{
 "openapi": "3.0.3",
 "info": {
  "title": "Bramble PSA API",
  "version": "2026-11-13",
  "description": "Bramble PSA: tickets and their messages, notes and attachments; queues; customers and contacts (shared with Atlas); categories and types; agreements; and your own signature. Works with an API key. PSA settings (statuses, SLAs, workflows, templates, procedures) are in the [Admin Centre API](/apps/admin/api/psa).\n"
 },
 "servers": [
  {
   "url": "https://{org}.brambleit.cloud/api",
   "variables": {
    "org": {
     "default": "your-org"
    }
   }
  },
  {
   "url": "https://{org}.brambleit.cloud/psa",
   "variables": {
    "org": {
     "default": "your-org"
    }
   }
  }
 ],
 "components": {
  "securitySchemes": {
   "apiKey": {
    "type": "apiKey",
    "in": "header",
    "name": "X-API-Key"
   },
   "session": {
    "type": "apiKey",
    "in": "cookie",
    "name": "sso_session"
   },
   "bearer": {
    "type": "http",
    "scheme": "bearer",
    "bearerFormat": "JWT"
   }
  }
 },
 "tags": [
  {
   "name": "Tickets",
   "description": "Searching and listing tickets, one ticket with its conversation, creating, updating, bulk changes, replies and notes, and attachments."
  },
  {
   "name": "Queues",
   "description": "Queues, the agents who work them, and each queue's statuses, ticket types and reply templates."
  },
  {
   "name": "Customers",
   "description": "Customers (organisations), their agreements, and their links to RMM sites and to a Bramble organisation."
  },
  {
   "name": "Contacts",
   "description": "People at customers."
  },
  {
   "name": "Categories",
   "description": "Ticket categories and subcategories."
  },
  {
   "name": "PSA settings",
   "description": "PSA configuration for the organisation, and your own preferences and email signature."
  }
 ],
 "paths": {
  "/v1/app/psa/check": {
   "get": {
    "tags": [
     "Tickets"
    ],
    "summary": "Check PSA app access",
    "operationId": "get-v1-app-psa-check",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "ok": {
           "type": "boolean"
          },
          "user": {
           "type": "object",
           "properties": {
            "id": {
             "type": "integer"
            },
            "roles": {
             "type": "array",
             "items": {}
            }
           }
          }
         }
        }
       }
      }
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/psa/agents": {
   "get": {
    "tags": [
     "Queues"
    ],
    "summary": "List agents (tenant users)",
    "operationId": "get-v1-app-psa-agents",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "agents": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "id": {
              "type": "integer"
             },
             "first_name": {
              "type": "string",
              "nullable": true
             },
             "last_name": {
              "type": "string",
              "nullable": true
             },
             "email": {
              "type": "string"
             }
            }
           }
          }
         }
        }
       }
      }
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/psa/queues": {
   "get": {
    "tags": [
     "Queues"
    ],
    "summary": "List queues for tenant (inc",
    "operationId": "get-v1-app-psa-queues",
    "description": "List queues for tenant (inc. parent/child hierarchy info)\n\nRequires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "queues": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "restricted": {
              "type": "boolean"
             }
            }
           }
          }
         }
        }
       }
      }
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "tags": [
     "Queues"
    ],
    "summary": "Create a queue (set parent_id for sub-queue)",
    "operationId": "post-v1-app-psa-queues",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "queue": {}
         }
        }
       }
      }
     },
     "400": {
      "description": "name is required"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "name": {
          "type": "string"
         },
         "parent_id": {
          "type": "integer"
         },
         "email_address": {},
         "imap_host": {},
         "imap_port": {},
         "imap_user": {},
         "imap_pass": {
          "type": "array",
          "items": {}
         },
         "imap_tls": {
          "type": "array",
          "items": {}
         },
         "smtp_host": {},
         "smtp_port": {},
         "smtp_user": {},
         "smtp_pass": {
          "type": "array",
          "items": {}
         },
         "smtp_from": {}
        },
        "required": [
         "name"
        ]
       }
      }
     }
    }
   }
  },
  "/v1/app/psa/queues/{id}": {
   "post": {
    "tags": [
     "Queues"
    ],
    "summary": "Update a queue",
    "operationId": "post-v1-app-psa-queues-id",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "queue": {}
         }
        }
       }
      }
     },
     "400": {
      "description": "Queue cannot be its own parent"
     },
     "404": {
      "description": "Queue not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "name": {
          "type": "string"
         },
         "parent_id": {
          "type": "string"
         },
         "email_address": {},
         "imap_host": {},
         "imap_port": {},
         "imap_user": {},
         "imap_pass": {
          "type": "array",
          "items": {}
         },
         "imap_tls": {
          "type": "array",
          "items": {}
         },
         "smtp_host": {},
         "smtp_port": {},
         "smtp_user": {},
         "smtp_pass": {
          "type": "array",
          "items": {}
         },
         "smtp_from": {},
         "is_active": {
          "type": "boolean"
         }
        }
       }
      }
     }
    }
   }
  },
  "/v1/app/psa/queues/{id}/delete": {
   "post": {
    "tags": [
     "Queues"
    ],
    "summary": "Delete a queue (also removes sub-queues via FK cascade)",
    "operationId": "post-v1-app-psa-queues-id-delete",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "success": {
           "type": "boolean"
          }
         }
        }
       }
      }
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/psa/queues/{id}/test-imap": {
   "post": {
    "tags": [
     "Queues"
    ],
    "summary": "Test IMAP connection for a specific queue",
    "operationId": "post-v1-app-psa-queues-id-test-imap",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "success": {
           "type": "boolean"
          },
          "inbox": {
           "type": "object",
           "properties": {
            "messages": {
             "type": "array",
             "items": {}
            },
            "unseen": {}
           }
          }
         }
        }
       }
      }
     },
     "400": {
      "description": "IMAP not configured on this queue"
     },
     "404": {
      "description": "Queue not found"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/psa/customers": {
   "get": {
    "tags": [
     "Customers"
    ],
    "summary": "List customers",
    "operationId": "get-v1-app-psa-customers",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "customers": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "id": {
              "type": "integer"
             },
             "tenant_id": {
              "type": "integer"
             },
             "name": {
              "type": "string"
             },
             "domain": {
              "type": "string",
              "nullable": true
             },
             "phone": {
              "type": "string",
              "nullable": true
             },
             "address": {
              "type": "string",
              "nullable": true
             },
             "notes": {
              "type": "string",
              "nullable": true
             },
             "account_manager_id": {
              "type": "integer",
              "nullable": true
             },
             "created_at": {
              "type": "string",
              "format": "date-time",
              "nullable": true
             },
             "updated_at": {
              "type": "string",
              "format": "date-time",
              "nullable": true
             },
             "status": {
              "type": "string"
             },
             "org_type": {
              "type": "string",
              "nullable": true
             },
             "short_name": {
              "type": "string",
              "nullable": true
             },
             "website": {
              "type": "string",
              "nullable": true
             },
             "alert_note": {
              "type": "string",
              "nullable": true
             },
             "primary_contact_id": {
              "type": "integer",
              "nullable": true
             },
             "logo_file_id": {
              "type": "integer",
              "nullable": true
             },
             "bramble_tenant_id": {
              "type": "integer",
              "nullable": true
             },
             "customer_type_id": {
              "type": "integer",
              "nullable": true
             },
             "contact_count": {
              "type": "boolean"
             },
             "open_ticket_count": {
              "type": "boolean"
             }
            }
           }
          }
         }
        }
       }
      }
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "tags": [
     "Customers"
    ],
    "summary": "Create customer",
    "operationId": "post-v1-app-psa-customers",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "customer": {}
         }
        }
       }
      }
     },
     "400": {
      "description": "name is required"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "name": {
          "type": "string"
         },
         "domain": {
          "type": "string"
         },
         "phone": {},
         "address": {},
         "notes": {
          "type": "array",
          "items": {}
         },
         "account_manager_id": {
          "type": "integer"
         }
        },
        "required": [
         "name"
        ]
       }
      }
     }
    }
   }
  },
  "/v1/app/psa/customers/{id}": {
   "post": {
    "tags": [
     "Customers"
    ],
    "summary": "Update customer",
    "operationId": "post-v1-app-psa-customers-id",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "customer": {}
         }
        }
       }
      }
     },
     "404": {
      "description": "Customer not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "name": {
          "type": "string"
         },
         "domain": {
          "type": "string"
         },
         "phone": {},
         "address": {},
         "notes": {
          "type": "array",
          "items": {}
         },
         "account_manager_id": {
          "type": "integer"
         }
        }
       }
      }
     }
    }
   }
  },
  "/v1/app/psa/customers/{id}/delete": {
   "post": {
    "tags": [
     "Customers"
    ],
    "summary": "Delete customer",
    "operationId": "post-v1-app-psa-customers-id-delete",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "success": {
           "type": "boolean"
          }
         }
        }
       }
      }
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/psa/customers/{id}/contacts": {
   "get": {
    "tags": [
     "Customers"
    ],
    "summary": "Contacts for a customer",
    "operationId": "get-v1-app-psa-customers-id-contacts",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "contacts": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "id": {
              "type": "integer"
             },
             "tenant_id": {
              "type": "integer"
             },
             "customer_id": {
              "type": "integer",
              "nullable": true
             },
             "first_name": {
              "type": "string"
             },
             "last_name": {
              "type": "string"
             },
             "email": {
              "type": "string",
              "nullable": true
             },
             "phone": {
              "type": "string",
              "nullable": true
             },
             "job_title": {
              "type": "string",
              "nullable": true
             },
             "notes": {
              "type": "string",
              "nullable": true
             },
             "created_at": {
              "type": "string",
              "format": "date-time",
              "nullable": true
             },
             "updated_at": {
              "type": "string",
              "format": "date-time",
              "nullable": true
             },
             "mobile": {
              "type": "string",
              "nullable": true
             },
             "contact_type": {
              "type": "string",
              "nullable": true
             },
             "location_id": {
              "type": "integer",
              "nullable": true
             },
             "is_important": {
              "type": "boolean"
             }
            }
           }
          }
         }
        }
       }
      }
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/psa/customers/{id}/tickets": {
   "get": {
    "tags": [
     "Customers"
    ],
    "summary": "Tickets for a customer",
    "operationId": "get-v1-app-psa-customers-id-tickets",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "tickets": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "id": {
              "type": "integer"
             },
             "subject": {
              "type": "string"
             },
             "status": {
              "type": "string",
              "enum": [
               "open",
               "pending",
               "on-hold",
               "closed"
              ],
              "nullable": true
             },
             "priority": {
              "type": "string",
              "enum": [
               "low",
               "medium",
               "high",
               "critical"
              ],
              "nullable": true
             },
             "updated_at": {
              "type": "string",
              "format": "date-time",
              "nullable": true
             }
            }
           }
          }
         }
        }
       }
      }
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/psa/contacts": {
   "get": {
    "tags": [
     "Contacts"
    ],
    "summary": "List contacts",
    "operationId": "get-v1-app-psa-contacts",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "contacts": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "id": {
              "type": "integer"
             },
             "tenant_id": {
              "type": "integer"
             },
             "customer_id": {
              "type": "integer",
              "nullable": true
             },
             "first_name": {
              "type": "string"
             },
             "last_name": {
              "type": "string"
             },
             "email": {
              "type": "string",
              "nullable": true
             },
             "phone": {
              "type": "string",
              "nullable": true
             },
             "job_title": {
              "type": "string",
              "nullable": true
             },
             "notes": {
              "type": "string",
              "nullable": true
             },
             "created_at": {
              "type": "string",
              "format": "date-time",
              "nullable": true
             },
             "updated_at": {
              "type": "string",
              "format": "date-time",
              "nullable": true
             },
             "mobile": {
              "type": "string",
              "nullable": true
             },
             "contact_type": {
              "type": "string",
              "nullable": true
             },
             "location_id": {
              "type": "integer",
              "nullable": true
             },
             "is_important": {
              "type": "boolean"
             },
             "customer_name": {
              "type": "string"
             }
            }
           }
          }
         }
        }
       }
      }
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "tags": [
     "Contacts"
    ],
    "summary": "Create contact",
    "operationId": "post-v1-app-psa-contacts",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "contact": {}
         }
        }
       }
      }
     },
     "400": {
      "description": "first_name and last_name required"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "first_name": {
          "type": "string"
         },
         "last_name": {
          "type": "string"
         },
         "email": {
          "type": "string"
         },
         "phone": {},
         "job_title": {
          "type": "string"
         },
         "notes": {
          "type": "array",
          "items": {}
         },
         "customer_id": {
          "type": "integer"
         }
        },
        "required": [
         "first_name",
         "last_name"
        ]
       }
      }
     }
    }
   }
  },
  "/v1/app/psa/contacts/{id}": {
   "post": {
    "tags": [
     "Contacts"
    ],
    "summary": "Update contact",
    "operationId": "post-v1-app-psa-contacts-id",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "contact": {}
         }
        }
       }
      }
     },
     "404": {
      "description": "Contact not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "first_name": {
          "type": "string"
         },
         "last_name": {
          "type": "string"
         },
         "email": {
          "type": "string"
         },
         "phone": {},
         "job_title": {
          "type": "string"
         },
         "notes": {
          "type": "array",
          "items": {}
         },
         "customer_id": {
          "type": "integer"
         }
        }
       }
      }
     }
    }
   }
  },
  "/v1/app/psa/contacts/{id}/delete": {
   "post": {
    "tags": [
     "Contacts"
    ],
    "summary": "Delete contact",
    "operationId": "post-v1-app-psa-contacts-id-delete",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "success": {
           "type": "boolean"
          }
         }
        }
       }
      }
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/psa/tickets": {
   "get": {
    "tags": [
     "Tickets"
    ],
    "summary": "List tickets for tenant",
    "operationId": "get-v1-app-psa-tickets",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [
     {
      "name": "view",
      "in": "query",
      "required": false,
      "schema": {}
     },
     {
      "name": "q",
      "in": "query",
      "required": false,
      "schema": {}
     },
     {
      "name": "queue_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "customer_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "priority",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string",
       "enum": [
        "low",
        "medium",
        "high",
        "critical"
       ]
      }
     },
     {
      "name": "type_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "category_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "status_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "tickets": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "id": {
              "type": "integer"
             },
             "tenant_id": {
              "type": "integer"
             },
             "queue_id": {
              "type": "integer",
              "nullable": true
             },
             "customer_id": {
              "type": "integer",
              "nullable": true
             },
             "contact_id": {
              "type": "integer",
              "nullable": true
             },
             "reply_to_email": {
              "type": "string",
              "nullable": true
             },
             "cc_emails": {
              "type": "object",
              "nullable": true
             },
             "assigned_to": {
              "type": "integer",
              "nullable": true
             },
             "subject": {
              "type": "string"
             },
             "status": {
              "type": "string",
              "enum": [
               "open",
               "pending",
               "on-hold",
               "closed"
              ],
              "nullable": true
             },
             "priority": {
              "type": "string",
              "enum": [
               "low",
               "medium",
               "high",
               "critical"
              ],
              "nullable": true
             },
             "source": {
              "type": "string",
              "enum": [
               "manual",
               "email",
               "api"
              ],
              "nullable": true
             },
             "email_message_id": {
              "type": "string",
              "nullable": true
             },
             "is_unread": {
              "type": "integer",
              "nullable": true
             },
             "closed_at": {
              "type": "string",
              "format": "date-time",
              "nullable": true
             },
             "created_at": {
              "type": "string",
              "format": "date-time",
              "nullable": true
             },
             "updated_at": {
              "type": "string",
              "format": "date-time",
              "nullable": true
             },
             "type_id": {
              "type": "integer",
              "nullable": true
             },
             "category_id": {
              "type": "integer",
              "nullable": true
             },
             "subcategory_id": {
              "type": "integer",
              "nullable": true
             },
             "status_id": {
              "type": "integer",
              "nullable": true
             },
             "status_changed_at": {
              "type": "string",
              "format": "date-time",
              "nullable": true
             },
             "status_reminded_at": {
              "type": "string",
              "format": "date-time",
              "nullable": true
             },
             "sla_policy_id": {
              "type": "integer",
              "nullable": true
             },
             "sla_response_due": {
              "type": "string",
              "format": "date-time",
              "nullable": true
             },
             "sla_resolution_due": {
              "type": "string",
              "format": "date-time",
              "nullable": true
             },
             "sla_response_warn": {
              "type": "string",
              "format": "date-time",
              "nullable": true
             },
             "sla_resolution_warn": {
              "type": "string",
              "format": "date-time",
              "nullable": true
             },
             "sla_responded_at": {
              "type": "string",
              "format": "date-time",
              "nullable": true
             },
             "sla_paused_at": {
              "type": "string",
              "format": "date-time",
              "nullable": true
             },
             "sla_paused_mins": {
              "type": "integer"
             },
             "sla_response_breached": {
              "type": "boolean"
             },
             "sla_resolution_breached": {
              "type": "boolean"
             },
             "sla_flags": {
              "type": "integer"
             },
             "queue_name": {
              "type": "string"
             },
             "customer_name": {
              "type": "string"
             },
             "contact_name": {
              "type": "string"
             },
             "assigned_name": {
              "type": "string"
             }
            }
           }
          }
         }
        }
       }
      }
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "tags": [
     "Tickets"
    ],
    "summary": "Create a ticket",
    "operationId": "post-v1-app-psa-tickets",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "ticket": {}
         }
        }
       }
      }
     },
     "400": {
      "description": "subject, body and queue_id required"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "type_id": {
          "type": "integer"
         },
         "category_id": {
          "type": "integer"
         },
         "subcategory_id": {
          "type": "integer"
         },
         "subject": {},
         "queue_id": {
          "type": "number"
         },
         "customer_id": {
          "type": "integer"
         },
         "contact_id": {
          "type": "integer"
         },
         "priority": {},
         "assigned_to": {},
         "body_html": {},
         "body": {}
        },
        "required": [
         "subject",
         "queue_id"
        ]
       }
      }
     }
    }
   }
  },
  "/v1/app/psa/tickets/{id}": {
   "get": {
    "tags": [
     "Tickets"
    ],
    "summary": "Get a single ticket with messages and activity",
    "operationId": "get-v1-app-psa-tickets-id",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "ticket": {},
          "messages": {
           "type": "array",
           "items": {}
          },
          "activity": {}
         }
        }
       }
      }
     },
     "404": {
      "description": "Ticket not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "tags": [
     "Tickets"
    ],
    "summary": "Update ticket fields",
    "operationId": "post-v1-app-psa-tickets-id",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "ticket": {}
         }
        }
       }
      }
     },
     "400": {
      "description": "Unknown status"
     },
     "404": {
      "description": "Ticket not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "type_id": {
          "type": "integer"
         },
         "category_id": {
          "type": "integer"
         },
         "subcategory_id": {
          "type": "integer"
         },
         "status_id": {
          "type": "number"
         },
         "status": {
          "type": "string"
         },
         "queue_id": {
          "type": "number"
         },
         "subject": {},
         "reply_to_email": {
          "type": "string"
         },
         "cc_emails": {
          "type": "string",
          "format": "email"
         },
         "assigned_to": {
          "type": "number"
         },
         "key": {
          "type": "string"
         }
        },
        "required": [
         "subject"
        ]
       }
      }
     }
    }
   }
  },
  "/v1/app/psa/tickets/bulk": {
   "post": {
    "tags": [
     "Tickets"
    ],
    "summary": "Bulk update tickets (close, set_status, set_type, set_category, set_priority, assign)",
    "operationId": "post-v1-app-psa-tickets-bulk",
    "description": "Bulk update tickets (close, set_status, set_type, set_category, set_priority, assign). set_status takes a status id as value. Closing (close, or a status in the Closed group) skips tickets without a type and category and reports them as skipped.\n\nRequires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "updated": {
           "type": "integer"
          },
          "skipped": {}
         }
        }
       }
      }
     },
     "400": {
      "description": "action and ticket_ids[] required"
     },
     "404": {
      "description": "No matching tickets found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "action": {
          "type": "string"
         },
         "ticket_ids": {
          "type": "array",
          "items": {}
         },
         "value": {
          "type": "number",
          "enum": [
           "low",
           "medium",
           "high",
           "critical"
          ]
         }
        },
        "required": [
         "action",
         "ticket_ids"
        ]
       }
      }
     }
    }
   }
  },
  "/v1/app/psa/tickets/{id}/delete": {
   "post": {
    "tags": [
     "Tickets"
    ],
    "summary": "Delete ticket",
    "operationId": "post-v1-app-psa-tickets-id-delete",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "success": {
           "type": "boolean"
          }
         }
        }
       }
      }
     },
     "404": {
      "description": "Ticket not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/psa/tickets/{id}/messages": {
   "post": {
    "tags": [
     "Tickets"
    ],
    "summary": "Add a message or internal note to a ticket",
    "operationId": "post-v1-app-psa-tickets-id-messages",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "number",
       "format": "email"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "message": {
           "type": "string"
          }
         }
        }
       }
      }
     },
     "400": {
      "description": "Write a message first"
     },
     "404": {
      "description": "Ticket not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "type": {
          "type": "string"
         },
         "body_html": {},
         "body": {},
         "attachments": {
          "type": "array",
          "items": {}
         },
         "status_id": {
          "type": "integer"
         },
         "status": {
          "type": "string"
         },
         "to": {
          "type": "string",
          "format": "email"
         },
         "cc": {
          "type": "string",
          "format": "email"
         },
         "is_resolution": {
          "type": "boolean"
         }
        }
       }
      }
     }
    }
   }
  },
  "/v1/app/psa/statuses": {
   "get": {
    "tags": [
     "Queues"
    ],
    "summary": "List email templates",
    "operationId": "get-v1-app-psa-statuses",
    "description": "List email templates. Read-only — template management has moved to BRM-Admin's PSA > Templates tab.\n\nRequires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "statuses": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "id": {
              "type": "integer"
             },
             "name": {
              "type": "string"
             },
             "group_key": {
              "type": "string"
             },
             "color": {},
             "is_active": {
              "type": "boolean"
             },
             "is_default": {
              "type": "boolean"
             }
            }
           }
          }
         }
        }
       }
      }
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/psa/types": {
   "get": {
    "tags": [
     "Queues"
    ],
    "summary": "List ticket types",
    "operationId": "get-v1-app-psa-types",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "types": {
           "type": "array",
           "items": {}
          }
         }
        }
       }
      }
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/psa/me/signature": {
   "get": {
    "tags": [
     "PSA settings"
    ],
    "summary": "Your own email signature (PSA v2, ticket #57): added under every reply you send",
    "operationId": "get-v1-app-psa-me-signature",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "signature_html": {}
         }
        }
       }
      }
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   },
   "put": {
    "tags": [
     "PSA settings"
    ],
    "summary": "Set your email signature",
    "operationId": "put-v1-app-psa-me-signature",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "signature_html": {}
         }
        }
       }
      }
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "signature_html": {
          "description": "The signature (HTML)."
         }
        }
       }
      }
     }
    }
   }
  },
  "/v1/app/psa/templates": {
   "get": {
    "tags": [
     "Queues"
    ],
    "summary": "List reply templates",
    "operationId": "get-v1-app-psa-templates",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "templates": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "id": {
              "type": "integer"
             },
             "tenant_id": {
              "type": "integer"
             },
             "name": {
              "type": "string"
             },
             "subject": {
              "type": "string",
              "nullable": true
             },
             "body": {
              "type": "string"
             },
             "category": {
              "type": "string",
              "nullable": true
             },
             "is_active": {
              "type": "integer",
              "nullable": true
             },
             "created_at": {
              "type": "string",
              "format": "date-time",
              "nullable": true
             },
             "updated_at": {
              "type": "string",
              "format": "date-time",
              "nullable": true
             }
            }
           }
          }
         }
        }
       }
      }
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/psa/config": {
   "get": {
    "tags": [
     "PSA settings"
    ],
    "summary": "Get tenant PSA config",
    "operationId": "get-v1-app-psa-config",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "config": {}
         }
        }
       }
      }
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "tags": [
     "PSA settings"
    ],
    "summary": "Save tenant PSA config (upsert)",
    "operationId": "post-v1-app-psa-config",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "success": {
           "type": "boolean"
          }
         }
        }
       }
      }
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "smtp_host": {},
         "smtp_port": {},
         "smtp_user": {},
         "smtp_pass": {
          "type": "array",
          "items": {}
         },
         "smtp_from": {},
         "smtp_from_name": {
          "type": "string"
         },
         "imap_host": {},
         "imap_port": {},
         "imap_user": {},
         "imap_pass": {
          "type": "array",
          "items": {}
         },
         "imap_tls": {
          "type": "array",
          "items": {}
         },
         "default_queue_id": {
          "type": "integer"
         },
         "ticket_prefix": {},
         "brand_logo_url": {
          "type": "string"
         },
         "brand_color": {},
         "brand_footer": {},
         "brand_footer_html": {},
         "brand_signature_html": {},
         "quote_previous": {
          "type": "array",
          "items": {}
         }
        }
       }
      }
     }
    }
   }
  },
  "/v1/app/psa/config/test-smtp": {
   "post": {
    "tags": [
     "PSA settings"
    ],
    "summary": "Send a test email via configured SMTP",
    "operationId": "post-v1-app-psa-config-test-smtp",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "success": {
           "type": "boolean"
          }
         }
        }
       }
      }
     },
     "400": {
      "description": "SMTP not configured"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "to": {}
        }
       }
      }
     }
    }
   }
  },
  "/v1/app/psa/config/email-preview": {
   "post": {
    "tags": [
     "PSA settings"
    ],
    "summary": "Email preview for BRM-Admin → PSA → Branding: the saved settings with any unsaved changes from the form on top (nothing is stored)",
    "operationId": "post-v1-app-psa-config-email-preview",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "html": {}
         }
        }
       }
      }
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "use_org": {},
         "quote_previous": {
          "type": "boolean"
         }
        }
       }
      }
     }
    }
   }
  },
  "/v1/app/psa/attachments/{id}": {
   "get": {
    "tags": [
     "Tickets"
    ],
    "summary": "Download/view an attachment by DB id",
    "operationId": "get-v1-app-psa-attachments-id",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "File, page or redirect"
     },
     "403": {
      "description": "Forbidden"
     },
     "404": {
      "description": "Attachment not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/psa/tickets/{id}/attachments": {
   "get": {
    "tags": [
     "Tickets"
    ],
    "summary": "List attachments for a ticket",
    "operationId": "get-v1-app-psa-tickets-id-attachments",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "attachments": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "id": {
              "type": "integer"
             },
             "ticket_id": {
              "type": "integer"
             },
             "message_id": {
              "type": "integer",
              "nullable": true
             },
             "filename": {
              "type": "string"
             },
             "mime_type": {
              "type": "string",
              "nullable": true
             },
             "size_bytes": {
              "type": "integer",
              "nullable": true
             },
             "created_at": {
              "type": "string",
              "format": "date-time",
              "nullable": true
             }
            }
           }
          }
         }
        }
       }
      }
     },
     "404": {
      "description": "Ticket not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/psa/config/poller-status": {
   "get": {
    "tags": [
     "PSA settings"
    ],
    "summary": "Get IMAP poller status (interval, last run, results)",
    "operationId": "get-v1-app-psa-config-poller-status",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "poller": {
           "type": "string"
          }
         }
        }
       }
      }
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/psa/categories": {
   "get": {
    "tags": [
     "Categories"
    ],
    "summary": "List categories (flat, with parent_id)",
    "operationId": "get-v1-app-psa-categories",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [
     {
      "name": "queue_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "categories": {
           "type": "array",
           "items": {}
          }
         }
        }
       }
      }
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "tags": [
     "Categories"
    ],
    "summary": "Create category",
    "operationId": "post-v1-app-psa-categories",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "category": {
           "type": "object",
           "properties": {
            "id": {
             "type": "integer"
            },
            "tenant_id": {
             "type": "integer"
            },
            "parent_id": {
             "type": "integer",
             "nullable": true
            },
            "name": {
             "type": "string"
            },
            "created_at": {
             "type": "string",
             "format": "date-time",
             "nullable": true
            }
           }
          }
         }
        }
       }
      }
     },
     "400": {
      "description": "name is required"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "name": {
          "type": "string"
         },
         "parent_id": {
          "type": "integer"
         }
        },
        "required": [
         "name"
        ]
       }
      }
     }
    }
   }
  },
  "/v1/app/psa/categories/{id}": {
   "post": {
    "tags": [
     "Categories"
    ],
    "summary": "Update category",
    "operationId": "post-v1-app-psa-categories-id",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "category": {
           "type": "object",
           "properties": {
            "id": {
             "type": "integer"
            },
            "tenant_id": {
             "type": "integer"
            },
            "parent_id": {
             "type": "integer",
             "nullable": true
            },
            "name": {
             "type": "string"
            },
            "created_at": {
             "type": "string",
             "format": "date-time",
             "nullable": true
            }
           }
          }
         }
        }
       }
      }
     },
     "404": {
      "description": "Category not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "name": {
          "type": "string"
         },
         "parent_id": {
          "type": "integer"
         }
        }
       }
      }
     }
    }
   }
  },
  "/v1/app/psa/categories/{id}/delete": {
   "post": {
    "tags": [
     "Categories"
    ],
    "summary": "Delete category",
    "operationId": "post-v1-app-psa-categories-id-delete",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "success": {
           "type": "boolean"
          }
         }
        }
       }
      }
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/psa/queues/{id}/categories": {
   "get": {
    "tags": [
     "Queues"
    ],
    "summary": "Get category IDs assigned to a queue",
    "operationId": "get-v1-app-psa-queues-id-categories",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "category_ids": {
           "type": "array",
           "items": {
            "type": "integer"
           }
          }
         }
        }
       }
      }
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "tags": [
     "Queues"
    ],
    "summary": "Set categories for a queue (replaces all)",
    "operationId": "post-v1-app-psa-queues-id-categories",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "success": {
           "type": "boolean"
          }
         }
        }
       }
      }
     },
     "404": {
      "description": "Queue not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "category_ids": {
          "type": "array",
          "items": {}
         }
        }
       }
      }
     }
    }
   }
  },
  "/v1/app/psa/config/poll-now": {
   "post": {
    "tags": [
     "PSA settings"
    ],
    "summary": "Trigger an immediate IMAP poll",
    "operationId": "post-v1-app-psa-config-poll-now",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "message": {
           "type": "string"
          }
         }
        }
       }
      }
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/psa/config/test-imap": {
   "post": {
    "tags": [
     "PSA settings"
    ],
    "summary": "Test global IMAP connection",
    "operationId": "post-v1-app-psa-config-test-imap",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "success": {
           "type": "boolean"
          },
          "inbox": {
           "type": "object",
           "properties": {
            "messages": {
             "type": "array",
             "items": {}
            },
            "unseen": {}
           }
          }
         }
        }
       }
      }
     },
     "400": {
      "description": "IMAP not configured"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/psa/customers/{id}/devices": {
   "get": {
    "tags": [
     "Customers"
    ],
    "summary": "════════════════════════════════════════════════════════════════════════════════ CUSTOMER ↔ RMM DEVICES  (RMM-license gated) ════════════════════════════════…",
    "operationId": "get-v1-app-psa-customers-id-devices",
    "description": "════════════════════════════════════════════════════════════════════════════════ CUSTOMER ↔ RMM DEVICES  (RMM-license gated) ════════════════════════════════════════════════════════════════════════════════ Reuses bramble_rmm.sites.client_id (added by BRM-Schemas/2026-08-02_rmm_site_client_scoping.sql for the client-portal \"your devices\" feature — see v1-appPortal.js GET /devices for the same join) rather than a new per-device table: a customer is tagged by linking one or more RMM sites to it, and every device at a linked site counts as that customer's. Previously only settable from BRM-Admin's RMM site editor (v1-admin.js POST/PUT /rmm/sites) with no PSA-side UI at all.\n\nRequires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA. Licence: RMM.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "sites": {
           "type": "array",
           "items": {}
          },
          "devices": {
           "type": "array",
           "items": {}
          }
         }
        }
       }
      }
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/psa/rmm-sites": {
   "get": {
    "tags": [
     "Customers"
    ],
    "summary": "RMM sites (to link to customers)",
    "operationId": "get-v1-app-psa-rmm-sites",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA. Licence: RMM.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "sites": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "id": {
              "type": "integer"
             },
             "site_name": {
              "type": "string"
             },
             "client_id": {
              "type": "integer",
              "nullable": true
             }
            }
           }
          }
         }
        }
       }
      }
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/psa/customers/{id}/link-site": {
   "post": {
    "tags": [
     "Customers"
    ],
    "summary": "Link a customer to an RMM site",
    "operationId": "post-v1-app-psa-customers-id-link-site",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA. Licence: RMM.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "success": {
           "type": "boolean"
          }
         }
        }
       }
      }
     },
     "400": {
      "description": "site_id required"
     },
     "404": {
      "description": "Customer not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "site_id": {
          "type": "integer",
          "description": "The RMM site."
         }
        },
        "required": [
         "site_id"
        ]
       }
      }
     }
    }
   }
  },
  "/v1/app/psa/customers/{id}/links": {
   "get": {
    "tags": [
     "Customers"
    ],
    "summary": "One customer record (ticket #85, services/customerLinks.js): the RMM sites and the customer's own Bramble organisation linked to a PSA customer, plus what co…",
    "operationId": "get-v1-app-psa-customers-id-links",
    "description": "One customer record (ticket #85, services/customerLinks.js): the RMM sites and the customer's own Bramble organisation linked to a PSA customer, plus what could be linked (with suggestions by name).\n\nRequires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {}
       }
      }
     },
     "500": {
      "description": "Internal Server Error"
     },
     "err.status": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "message": {
           "type": "string"
          }
         }
        }
       }
      }
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/psa/customers/{id}/agreement": {
   "get": {
    "tags": [
     "Customers"
    ],
    "summary": "A customer's agreement",
    "operationId": "get-v1-app-psa-customers-id-agreement",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "tags": [
     "Customers"
    ],
    "summary": "Add an agreement line",
    "operationId": "post-v1-app-psa-customers-id-agreement",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/psa/customers/{id}/agreement/{lineId}": {
   "put": {
    "tags": [
     "Customers"
    ],
    "summary": "Update an agreement line",
    "operationId": "put-v1-app-psa-customers-id-agreement-lineid",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "lineId",
      "in": "path",
      "required": true,
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "tags": [
     "Customers"
    ],
    "summary": "Remove an agreement line",
    "operationId": "delete-v1-app-psa-customers-id-agreement-lineid",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "lineId",
      "in": "path",
      "required": true,
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/psa/customers/{id}/bramble-tenant": {
   "put": {
    "tags": [
     "Customers"
    ],
    "summary": "Link a customer to its Bramble organisation",
    "operationId": "put-v1-app-psa-customers-id-bramble-tenant",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "number"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {}
       }
      }
     },
     "500": {
      "description": "Internal Server Error"
     },
     "err.status": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "message": {
           "type": "string"
          }
         }
        }
       }
      }
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "tenant_id": {
          "type": "integer",
          "description": "The customer's Bramble organisation (for MSPs managing them as a partner)."
         }
        }
       }
      }
     }
    }
   }
  },
  "/v1/app/psa/customers/{id}/unlink-site": {
   "post": {
    "tags": [
     "Customers"
    ],
    "summary": "Unlink a customer from an RMM site",
    "operationId": "post-v1-app-psa-customers-id-unlink-site",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: PSA. Licence: RMM.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "success": {
           "type": "boolean"
          }
         }
        }
       }
      }
     },
     "400": {
      "description": "site_id required"
     },
     "404": {
      "description": "Site not found or not linked to this customer"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "site_id": {
          "type": "integer"
         }
        },
        "required": [
         "site_id"
        ]
       }
      }
     }
    }
   }
  }
 }
}