{
  "openapi": "3.1.0",
  "info": {
    "title": "PROradius Invoicing",
    "version": "v1",
    "description": "The PROradius Invoicing public API (v1). Authenticate with an organization API key:\n`Authorization: Bearer <key>`. The key is bound to one organization, so the `Organization-Id`\nheader is not needed. Errors use `{\"status\": false, \"error\": {\"message\": \"...\", \"errors\": {...}}}`.\nv1 only receives additive changes. Guides: https://developers.invoicing.proradius.co"
  },
  "security": [
    {
      "apiKey": []
    },
    {
      "userToken": [],
      "organizationId": []
    }
  ],
  "paths": {
    "/v1/clients": {
      "get": {
        "operationId": "clients.index",
        "summary": "List clients",
        "tags": [
          "Clients"
        ],
        "parameters": [
          {
            "name": "pageIndex",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "columns[]",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "query",
            "in": "query",
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "filterData",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "include",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "orderBy",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "flat",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Filter parameters",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "enum": [
                "active",
                "inactive",
                null
              ]
            }
          },
          {
            "name": "date_from",
            "in": "query",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "date"
            }
          },
          {
            "name": "date_to",
            "in": "query",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "date"
            }
          },
          {
            "name": "has_balance",
            "in": "query",
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "service_id",
            "in": "query",
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "services_count[]",
            "in": "query",
            "schema": {
              "type": "array",
              "enum": [
                "none",
                "one",
                "multiple"
              ],
              "items": {
                "type": "string",
                "enum": [
                  "none",
                  "one",
                  "multiple"
                ]
              }
            }
          },
          {
            "name": "collector_id",
            "in": "query",
            "schema": {
              "type": [
                "integer",
                "null"
              ]
            }
          },
          {
            "name": "branch_id",
            "in": "query",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            }
          },
          {
            "name": "auto_invoice",
            "in": "query",
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "odometer",
            "in": "query",
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "due_day",
            "in": "query",
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "minimum": 1,
              "maximum": 31
            }
          },
          {
            "name": "unassigned",
            "in": "query",
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "unassigned_isp",
            "in": "query",
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "isp_id",
            "in": "query",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            }
          },
          {
            "name": "city",
            "in": "query",
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "zone",
            "in": "query",
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "building",
            "in": "query",
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "box",
            "in": "query",
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "reference",
            "in": "query",
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "code",
            "in": "query",
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "color_tag",
            "in": "query",
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "disjunctor",
            "in": "query",
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "agreed_payment_method[]",
            "in": "query",
            "schema": {
              "type": "array",
              "enum": [
                "cash",
                "collector",
                "whish",
                "omt",
                "bob",
                "bank_transfer",
                "in_shop",
                "check",
                "credit_card"
              ],
              "items": {
                "type": "string",
                "enum": [
                  "cash",
                  "collector",
                  "whish",
                  "omt",
                  "bob",
                  "bank_transfer",
                  "in_shop",
                  "check",
                  "credit_card"
                ]
              }
            }
          },
          {
            "name": "generator",
            "in": "query",
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "external_ref",
            "in": "query",
            "description": "Exact lookups for integrations: the client's own reference, or a phone in any format.",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "maxLength": 191
            }
          },
          {
            "name": "phone",
            "in": "query",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "maxLength": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Array of `ClientsResource`",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "allOf": [
                          {
                            "$ref": "#/components/schemas/ClientsResource"
                          },
                          {
                            "type": "object",
                            "required": [
                              "branch",
                              "isp_name",
                              "isp_id",
                              "isp_status",
                              "isp_expires_at"
                            ]
                          }
                        ]
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationException"
          },
          "403": {
            "$ref": "#/components/responses/AuthorizationException"
          },
          "422": {
            "$ref": "#/components/responses/ValidationException"
          }
        },
        "description": "**API key ability:** `clients:read`",
        "x-api-key-ability": "`clients:read`"
      },
      "post": {
        "operationId": "clients.store",
        "summary": "Create a client",
        "tags": [
          "Clients"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateClientRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "`SingleClientResource`",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/SingleClientResource"
                    },
                    {
                      "type": "object",
                      "required": [
                        "items"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationException"
          },
          "403": {
            "$ref": "#/components/responses/AuthorizationException"
          },
          "422": {
            "$ref": "#/components/responses/ValidationException"
          }
        },
        "description": "**API key ability:** `clients:create`",
        "x-api-key-ability": "`clients:create`"
      },
      "delete": {
        "operationId": "clients.delete",
        "summary": "Delete clients",
        "tags": [
          "Clients"
        ],
        "parameters": [
          {
            "name": "id[]",
            "in": "query",
            "schema": {
              "type": "array",
              "format": "uuid",
              "items": {
                "type": "string",
                "format": "uuid"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "type": "integer"
                    },
                    "impact": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "minItems": 0,
                      "maxItems": 0
                    },
                    "reversed_journal_entries": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "minItems": 0,
                      "maxItems": 0
                    },
                    "reversed_count": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "deleted",
                    "impact",
                    "reversed_journal_entries",
                    "reversed_count"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationException"
          },
          "403": {
            "$ref": "#/components/responses/AuthorizationException"
          },
          "422": {
            "$ref": "#/components/responses/ValidationException"
          }
        },
        "description": "**API key ability:** `clients:delete`",
        "x-api-key-ability": "`clients:delete`"
      }
    },
    "/v1/clients/{client}": {
      "get": {
        "operationId": "clients.show",
        "summary": "Get a client",
        "tags": [
          "Clients"
        ],
        "parameters": [
          {
            "name": "client",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "include",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "`SingleClientResource`",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/SingleClientResource"
                    },
                    {
                      "type": "object",
                      "required": [
                        "branch",
                        "collector",
                        "items",
                        "latest_check_in",
                        "generator",
                        "isp_account"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationException"
          },
          "403": {
            "$ref": "#/components/responses/AuthorizationException"
          },
          "422": {
            "$ref": "#/components/responses/ValidationException"
          }
        },
        "description": "**API key ability:** `clients:read`",
        "x-api-key-ability": "`clients:read`"
      },
      "put": {
        "operationId": "clients.update",
        "summary": "Update a client",
        "tags": [
          "Clients"
        ],
        "parameters": [
          {
            "name": "client",
            "in": "path",
            "required": true,
            "description": "The client UUID",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateClientRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "`SingleClientResource`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SingleClientResource"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationException"
          },
          "403": {
            "$ref": "#/components/responses/AuthorizationException"
          },
          "404": {
            "$ref": "#/components/responses/ModelNotFoundException"
          },
          "422": {
            "$ref": "#/components/responses/ValidationException"
          }
        },
        "description": "**API key ability:** `clients:update`",
        "x-api-key-ability": "`clients:update`"
      }
    },
    "/v1/ticket-boards": {
      "get": {
        "tags": [
          "Boards"
        ],
        "summary": "List boards",
        "description": "**API key ability:** `tickets:read`\n\nList boards I can open.\n\nColumn `tickets_count` and board `tickets_count` exclude archived tickets.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Board"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-api-key-ability": "`tickets:read`"
      }
    },
    "/v1/ticket-boards/{id}": {
      "get": {
        "tags": [
          "Boards"
        ],
        "summary": "Get a board with its tickets",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "name": "slim",
            "in": "query",
            "schema": {
              "type": "boolean"
            },
            "description": "Cards without comments/attachments arrays (comments_count/attachments_count stay)."
          },
          {
            "$ref": "#/components/parameters/Archived"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BoardDetail"
                }
              }
            }
          },
          "404": {
            "description": "Not found or not a member"
          }
        },
        "description": "**API key ability:** `tickets:read`\n\nBoard with its tickets.",
        "x-api-key-ability": "`tickets:read`"
      }
    },
    "/v1/ticket-job-types": {
      "get": {
        "tags": [
          "Job types"
        ],
        "summary": "List job types",
        "parameters": [
          {
            "name": "board_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "That board's types + org-wide ones."
          },
          {
            "name": "include_inactive",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/JobType"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "description": "**API key ability:** `tickets:read`\n\nJob types (tickets:read). Org-wide ones plus those of boards I can open..",
        "x-api-key-ability": "`tickets:read`"
      },
      "post": {
        "tags": [
          "Job types"
        ],
        "summary": "Create a job type",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JobTypeInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobType"
                }
              }
            }
          },
          "422": {
            "description": "Validation error, duplicate code, or unknown default item."
          }
        },
        "description": "**API key ability:** `tickets:update`\n\nCreate (tickets:update). `code` defaults to a slug of the name; unique per org (422)..",
        "x-api-key-ability": "`tickets:update`"
      }
    },
    "/v1/ticket-job-types/{id}": {
      "get": {
        "tags": [
          "Job types"
        ],
        "summary": "Get a job type",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobType"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "description": "**API key ability:** `tickets:read`\n\nOne job type (tickets:read).",
        "x-api-key-ability": "`tickets:read`"
      },
      "put": {
        "tags": [
          "Job types"
        ],
        "summary": "Update a job type",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JobTypeInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobType"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "description": "**API key ability:** `tickets:update`\n\nPartial update (tickets:update). Unsent fields stay; existing tickets keep their SLA/checklist..",
        "x-api-key-ability": "`tickets:update`"
      }
    },
    "/v1/ticket-technicians": {
      "get": {
        "tags": [
          "Scheduling"
        ],
        "summary": "List technicians",
        "parameters": [
          {
            "name": "board_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Technicians of this board (members with tickets:own). Default: every active org user who can take jobs."
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TechnicianProfile"
                  }
                }
              }
            }
          }
        },
        "description": "**API key ability:** `tickets:read`\n\nWho can take jobs, with weekly hours, current/upcoming time off and skills (tickets:read).",
        "x-api-key-ability": "`tickets:read`"
      }
    },
    "/v1/tickets": {
      "get": {
        "tags": [
          "Service jobs"
        ],
        "summary": "List service jobs",
        "parameters": [
          {
            "name": "board_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Unknown/inaccessible board → empty list."
          },
          {
            "name": "client_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Client uuid. Unknown → empty list."
          },
          {
            "name": "client_phone",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Or find the client by phone / ISP username / its external_ref (send one key). Unknown → empty list; ambiguous → 422 ClientLookupError."
          },
          {
            "name": "client_isp_username",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "client_external_ref",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "name": "external_ref",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 191
            },
            "description": "Your own reference (exact match). Combine with archived=1 to also search the archive."
          },
          {
            "name": "status_category",
            "in": "query",
            "schema": {
              "type": "string",
              "example": "new,in_progress"
            },
            "description": "One category or a comma list."
          },
          {
            "name": "assignee",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "User uuid in assigned_users."
          },
          {
            "name": "unassigned",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "overdue",
            "in": "query",
            "schema": {
              "type": "boolean"
            },
            "description": "due_date before today and in an open column."
          },
          {
            "$ref": "#/components/parameters/Archived"
          },
          {
            "name": "slim",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Exact column name (legacy)."
          },
          {
            "name": "priority",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "low",
                "medium",
                "high",
                "critical"
              ]
            }
          },
          {
            "name": "type",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "task",
                "bug",
                "support",
                "feature"
              ]
            }
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "technician_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Jobs of this technician."
          },
          {
            "name": "mine",
            "in": "query",
            "schema": {
              "type": "boolean"
            },
            "description": "My jobs (technician = me). tickets:own users always get only their own."
          },
          {
            "name": "job_type_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "updated_at",
                "due_date",
                "priority",
                "status",
                "scheduled_at",
                "sla_due_at"
              ]
            }
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ]
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "maximum": 100,
              "default": 15
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Ticket"
                      }
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  }
                }
              }
            }
          }
        },
        "description": "**API key ability:** `tickets:read`\n\nPaginated ticket list across the boards I can open.",
        "x-api-key-ability": "`tickets:read`"
      },
      "post": {
        "tags": [
          "Service jobs"
        ],
        "summary": "Create a service job",
        "description": "**API key ability:** `tickets:create` (plus `tickets:schedule` when `technician_id` is sent)\n\nCreate a ticket (tickets:create + member).\n\nCreated straight into a done column → resolved_at set; cancelled → closed_at set. Writes a `created` event\nand sends `ticket.created`. `created_via` is set by the server (api for API keys, mobile when the app sends\n`App-Platform`, else web).\n\n**Job type:** `job_type_id` fills priority (when not sent), `sla_due_at` (now + sla_hours) and `checklist_state`;\na job type with `requires_client` needs `client_id` (422). With `auto_assign` and no technician, the top\nsuggested technician is booked in their first free slot (08:00–18:00 org time, next days if full); nobody free\n→ stays unassigned. **Technician:** `technician_id` (+ optional window) follows the schedule rules (403 for\nAPI keys without tickets:schedule; 422 on overlap unless `override` + `override_reason` with tickets:dispatch).\n\n**Safe retries:** with `external_ref`, a second request with the same value (from anyone in the org) returns\nthe existing ticket with **200** and changes nothing. A new ticket answers **201**. If the ref belongs to a\ndeleted ticket or one on a board you can't open, the answer is **409**.\n\n**Client lookup (D11):** identify the client with ONE of `client_id` (uuid), `client_phone` (any format; both\nsides normalised the way the app stores Lebanese numbers), `client_isp_username` (the ISP account username) or\n`client_external_ref` (the client's own `external_ref`, set through the clients API). Scoped to the organization.\nNo match → 422 `client_not_found`; more than one → 422 `client_ambiguous` with the candidate client uuids;\ntwo keys at once → 422 `client_lookup_conflict`. See `ClientLookupError`.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "title",
                  "board_id"
                ],
                "properties": {
                  "title": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  },
                  "board_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "column_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Defaults to the first column."
                  },
                  "client_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "client_phone": {
                    "type": "string",
                    "maxLength": 50,
                    "description": "Client lookup by phone (instead of client_id)."
                  },
                  "client_isp_username": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Client lookup by ISP account username."
                  },
                  "client_external_ref": {
                    "type": "string",
                    "maxLength": 191,
                    "description": "Client lookup by the client's external_ref."
                  },
                  "priority": {
                    "type": "string",
                    "enum": [
                      "low",
                      "medium",
                      "high",
                      "critical"
                    ],
                    "description": "Required unless job_type_id is sent."
                  },
                  "type": {
                    "type": "string",
                    "enum": [
                      "task",
                      "bug",
                      "support",
                      "feature"
                    ],
                    "description": "Required unless job_type_id is sent (defaults to support)."
                  },
                  "due_date": {
                    "type": "string",
                    "format": "date"
                  },
                  "sla_hours": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 8760,
                    "nullable": true,
                    "description": "Hours from creation until the SLA is due. Not sent = the job type's sla_hours; null = no SLA."
                  },
                  "labels": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "job_type_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "technician_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "scheduled_at": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "scheduled_until": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "override": {
                    "type": "boolean"
                  },
                  "override_reason": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "assigned_user_ids": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    }
                  },
                  "linked_invoice_ids": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    }
                  },
                  "external_ref": {
                    "type": "string",
                    "maxLength": 191,
                    "description": "Your own id for this ticket, unique per organization."
                  }
                }
              },
              "examples": {
                "withExternalRef": {
                  "summary": "Create from a CRM with a retry-safe reference",
                  "value": {
                    "title": "No internet since this morning",
                    "board_id": "4c6e8a0b-1d3f-4a5c-9e7b-2f4a6c8e0b1d",
                    "client_id": "b8f2a1c4-7d39-4e52-9a06-1f4c8b3d5e27",
                    "priority": "high",
                    "type": "support",
                    "external_ref": "crm-48213"
                  }
                },
                "byClientPhone": {
                  "summary": "Create for a caller identified by phone",
                  "value": {
                    "title": "Router keeps rebooting",
                    "board_id": "4c6e8a0b-1d3f-4a5c-9e7b-2f4a6c8e0b1d",
                    "client_phone": "+961 70 123 456",
                    "priority": "medium",
                    "type": "support"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Replay: a ticket with this external_ref already exists; it is returned unchanged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TicketDetail"
                }
              }
            }
          },
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TicketDetail"
                }
              }
            }
          },
          "409": {
            "description": "external_ref is used by a deleted ticket or one on a board you cannot open."
          },
          "422": {
            "description": "Validation error, the target column is at its WIP limit, or the client lookup failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClientLookupError"
                }
              }
            }
          }
        },
        "x-api-key-ability": "`tickets:create` (plus `tickets:schedule` when `technician_id` is sent)"
      }
    },
    "/v1/tickets/{id}": {
      "get": {
        "tags": [
          "Service jobs"
        ],
        "summary": "Get a service job",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TicketDetail"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "description": "**API key ability:** `tickets:read`\n\nTicket detail.",
        "x-api-key-ability": "`tickets:read`"
      },
      "put": {
        "tags": [
          "Service jobs"
        ],
        "summary": "Update a service job",
        "description": "**API key ability:** `tickets:update`\n\nUpdate fields (title, description, priority, type, due_date, sla_hours, labels, client_id).\n\nOnly sent fields change. `sla_hours` sets the SLA again from the creation time (time spent in waiting columns\nstill counts as paused); null removes the SLA. SLA alerts re-arm when the new deadline is in the future.\nChanging `sla_hours` on a done or cancelled job answers 422 \"Reopen the job to change its SLA.\".",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "description": {
                    "type": "string",
                    "nullable": true
                  },
                  "client_id": {
                    "type": "string",
                    "format": "uuid",
                    "nullable": true
                  },
                  "priority": {
                    "type": "string",
                    "enum": [
                      "low",
                      "medium",
                      "high",
                      "critical"
                    ]
                  },
                  "type": {
                    "type": "string",
                    "enum": [
                      "task",
                      "bug",
                      "support",
                      "feature"
                    ]
                  },
                  "due_date": {
                    "type": "string",
                    "format": "date",
                    "nullable": true
                  },
                  "sla_hours": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 8760,
                    "nullable": true
                  },
                  "labels": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 50
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TicketDetail"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-api-key-ability": "`tickets:update`"
      },
      "delete": {
        "tags": [
          "Service jobs"
        ],
        "summary": "Delete a service job",
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "description": "**API key ability:** `tickets:delete`\n\nDelete (tickets:delete). Prefer archive..",
        "x-api-key-ability": "`tickets:delete`"
      }
    },
    "/v1/tickets/{id}/activity": {
      "get": {
        "tags": [
          "Service jobs"
        ],
        "summary": "Activity history",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "maximum": 100
            }
          },
          {
            "name": "include",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "events"
              ]
            },
            "description": "Adds `events` (ticket_events, newest first, max 200)."
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "total": {
                      "type": "integer"
                    },
                    "page": {
                      "type": "integer"
                    },
                    "per_page": {
                      "type": "integer"
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/TicketEvent"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "description": "**API key ability:** `tickets:read`\n\nActivity feed (newest first).",
        "x-api-key-ability": "`tickets:read`"
      }
    },
    "/v1/tickets/{id}/archive": {
      "post": {
        "tags": [
          "Service jobs"
        ],
        "summary": "Archive",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TicketDetail"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "description": "**API key ability:** `tickets:update`\n\nArchive (tickets:update + member). Idempotent; sends `ticket.archived` only when it actually archives..",
        "x-api-key-ability": "`tickets:update`"
      }
    },
    "/v1/tickets/{id}/cancel": {
      "post": {
        "tags": [
          "Completion"
        ],
        "summary": "Cancel the job",
        "description": "**API key ability:** `tickets:update`\n\nCancel with a reason (tickets:update + member; not tickets:own alone). Nothing is invoiced..\n\nMoves to the first cancelled column and sets closed_at + cancellation_reason. Already cancelled = 200, no change. Done jobs → 422. Sends ticket.cancelled.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "reason"
                ],
                "properties": {
                  "reason": {
                    "type": "string",
                    "maxLength": 1000
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompletionResult"
                }
              }
            }
          },
          "422": {
            "description": "Completed job, no Cancelled column, or WIP full."
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-api-key-ability": "`tickets:update`"
      }
    },
    "/v1/tickets/{id}/comments": {
      "post": {
        "tags": [
          "Service jobs"
        ],
        "summary": "Add a comment",
        "responses": {
          "201": {
            "description": "Created"
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "description": "**API key ability:** `tickets:update`\n\nAdd a comment (@mentions notify).",
        "x-api-key-ability": "`tickets:update`"
      }
    },
    "/v1/tickets/{id}/complete": {
      "post": {
        "tags": [
          "Completion"
        ],
        "summary": "Complete the job",
        "description": "**API key ability:** `tickets:complete` (plus `invoices:create` when it bills)\n\nComplete the job (tickets:update + member, or its technician with tickets:own; keys tickets:complete).\n\nOne transaction with the ticket row locked. done/partial: when the job type bills `on_completion` and items\nare sent, the invoice is created through the normal invoice pipeline (goods leave the technician's van stock\nwhen they hold any of the items), linked as `completion` (unique per ticket), an optional payment is recorded,\nthen the ticket moves to the first `done` column with `resolved_at`. `partial` + `invoice_now: false` keeps\nthe items for Create invoice later. `manual` billing saves the items only. `revisit` sends the job back to the\nUnassigned queue (technician + window cleared, `reason` required, no invoice); auto-assign job types rebook the\nfirst free slot. Any failure → 422 with the reason and nothing changes. Calling it again on a finished job\nanswers 200 with `completion.replayed: true` and the same invoice. Optional `Idempotency-Key` header.\nKeys completing a billable job also need `invoices:create`. Sends `ticket.completed` (done/partial) and the\n\"job completed\" customer message when enabled.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "outcome"
                ],
                "properties": {
                  "outcome": {
                    "type": "string",
                    "enum": [
                      "done",
                      "partial",
                      "revisit"
                    ]
                  },
                  "notes": {
                    "type": "string",
                    "maxLength": 5000
                  },
                  "reason": {
                    "type": "string",
                    "maxLength": 1000,
                    "description": "Required for revisit."
                  },
                  "reason_code": {
                    "type": "string",
                    "enum": [
                      "no_show",
                      "needs_parts",
                      "needs_time",
                      "customer_request",
                      "other"
                    ],
                    "description": "Optional (Phase 4) revisit code; no_show feeds the metrics no-show count."
                  },
                  "items": {
                    "type": "array",
                    "maxItems": 100,
                    "items": {
                      "$ref": "#/components/schemas/CompletionItemInput"
                    }
                  },
                  "checklist_state": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "required": [
                        "id",
                        "done"
                      ],
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "done": {
                          "type": "boolean"
                        }
                      }
                    }
                  },
                  "collect_payment": {
                    "$ref": "#/components/schemas/CollectPayment"
                  },
                  "notify_client": {
                    "type": "boolean",
                    "default": true
                  },
                  "invoice_now": {
                    "type": "boolean",
                    "description": "partial only; default true."
                  },
                  "create_follow_up": {
                    "type": "boolean",
                    "default": false,
                    "description": "Creates a linked follow-up job (needs tickets:create)."
                  }
                }
              },
              "example": {
                "outcome": "done",
                "notes": "Ran 60 m drop cable, speed test 48/20",
                "items": [
                  {
                    "item_uuid": "3f1c2b4a-5d6e-4f70-8a9b-0c1d2e3f4a5b",
                    "quantity": 1,
                    "mac": "A4:2B:B0:9C:11:7E"
                  }
                ],
                "collect_payment": {
                  "amount": 97,
                  "currency": "USD",
                  "method": "cash"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompletionResult"
                }
              }
            }
          },
          "403": {
            "description": "Not the technician / no access, key without tickets:complete, or billable job without invoices:create."
          },
          "422": {
            "description": "Invoice or payment failed (reason in the message), job closed/archived, no client, no Done column, WIP full."
          }
        },
        "x-api-key-ability": "`tickets:complete` (plus `invoices:create` when it bills)"
      }
    },
    "/v1/tickets/{id}/completion-preview": {
      "get": {
        "tags": [
          "Completion"
        ],
        "summary": "Completion preview",
        "description": "**API key ability:** `tickets:complete`\n\nWhat the Complete-job form starts with (same access as complete).\n\nSaved completion items, else the job type's default items, with the client's price and how many the technician holds in the van.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ticket_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "billing_mode": {
                      "type": "string",
                      "enum": [
                        "none",
                        "on_completion",
                        "manual"
                      ]
                    },
                    "client": {
                      "type": "object",
                      "nullable": true,
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        }
                      }
                    },
                    "technician": {
                      "type": "object",
                      "nullable": true,
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        }
                      }
                    },
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CompletionItemPreview"
                      }
                    },
                    "items_total": {
                      "type": "number"
                    },
                    "can_override_price": {
                      "type": "boolean",
                      "description": "invoices:override_price; without it the invoice uses catalog/client prices."
                    },
                    "client_message_channels": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "enum": [
                          "whatsapp",
                          "sms"
                        ]
                      },
                      "description": "Empty = the client gets no message."
                    },
                    "checklist_state": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "completion_invoice": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/CompletionInvoice"
                        }
                      ],
                      "nullable": true
                    }
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-api-key-ability": "`tickets:complete`"
      }
    },
    "/v1/tickets/{id}/create-invoice": {
      "post": {
        "tags": [
          "Completion"
        ],
        "summary": "Bill a completed job",
        "description": "**API key ability:** `tickets:update` and `invoices:create`\n\nInvoice the items saved at completion (manual billing or partial kept for later). Staff with tickets:update; keys also invoices:create..\n\nSame idempotency as completion: a second call returns the same invoice with completion.replayed = true. Optional Idempotency-Key.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "collect_payment": {
                    "$ref": "#/components/schemas/CollectPayment"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompletionResult"
                }
              }
            }
          },
          "422": {
            "description": "Not completed yet, billing_mode none, no items/client, or the invoice failed."
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-api-key-ability": "`tickets:update` and `invoices:create`"
      }
    },
    "/v1/tickets/{id}/move": {
      "put": {
        "tags": [
          "Service jobs"
        ],
        "summary": "Move to another column",
        "description": "**API key ability:** `tickets:update`\n\nMove to a column / reorder.\n\nEntering a done column sets resolved_at; entering cancelled sets closed_at; leaving done/cancelled\nfor an open column clears both (a `reopened` event). Respects column WIP limits (archived tickets don't count).\nA column change sends `ticket.status_changed`; reordering inside a column sends nothing.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "column_id"
                ],
                "properties": {
                  "column_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "column_order": {
                    "type": "integer"
                  },
                  "to_end": {
                    "type": "boolean"
                  }
                }
              },
              "examples": {
                "moveToDone": {
                  "summary": "Move to the board's Done column (take the id from GET /v1/ticket-boards/{id}, category done)",
                  "value": {
                    "column_id": "7e9a1c3d-5f2b-4d6e-8a0c-1b3d5f7a9c2e",
                    "to_end": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "column_id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "column_order": {
                      "type": "integer"
                    },
                    "status_category": {
                      "$ref": "#/components/schemas/Category"
                    },
                    "resolved_at": {
                      "type": "string",
                      "nullable": true
                    },
                    "closed_at": {
                      "type": "string",
                      "nullable": true
                    }
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-api-key-ability": "`tickets:update`"
      }
    },
    "/v1/tickets/{id}/schedule": {
      "post": {
        "tags": [
          "Scheduling"
        ],
        "summary": "Schedule a visit",
        "description": "**API key ability:** `tickets:schedule` (`override` also needs `tickets:dispatch`)\n\nSet technician + visit window (users tickets:update, keys tickets:schedule; board member).\n\nThe technician must be an active org user on the board (when it has a member list) with tickets:own\n(Technician role, or an owner who opted in). Moving the time of a job keeps its current technician. The visit\ncan't start in the past (5 min grace) unless the start stays the same (stretching a running visit). The technician's overlapping open jobs are locked (FOR UPDATE) and an overlap answers 422\nnaming them. Touching windows (10–12 then 12–13) are fine. `override: true` + `override_reason` books anyway\n(needs tickets:dispatch) and logs a `schedule_override` event. A ticket in a `new` column moves to the first\n`scheduled` column. The technician is added to `assigned_users`. Sends `ticket.scheduled`. Window ≤ 24 h.\nPhase 4: outside the technician's saved working hours, on time off, or missing a required skill of the job\ntype → 422 with the reasons; `override` books anyway and the event lists them under `availability`.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "technician_id",
                  "scheduled_at",
                  "scheduled_until"
                ],
                "properties": {
                  "technician_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "scheduled_at": {
                    "type": "string",
                    "format": "date-time",
                    "example": "2026-10-14T11:00:00Z"
                  },
                  "scheduled_until": {
                    "type": "string",
                    "format": "date-time",
                    "example": "2026-10-14T13:00:00Z"
                  },
                  "override": {
                    "type": "boolean"
                  },
                  "override_reason": {
                    "type": "string",
                    "maxLength": 500
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TicketDetail"
                }
              }
            }
          },
          "403": {
            "description": "No schedule permission, or override without tickets:dispatch."
          },
          "422": {
            "description": "Overlap, outside hours / time off / missing skills, technician not eligible, bad window, or the ticket is closed/archived."
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-api-key-ability": "`tickets:schedule` (`override` also needs `tickets:dispatch`)"
      }
    },
    "/v1/tickets/{id}/start": {
      "post": {
        "tags": [
          "Scheduling"
        ],
        "summary": "Start the job",
        "description": "**API key ability:** `tickets:update`\n\nStart the job (tickets:update + member, or the job's own technician with tickets:own).\n\nSets `started_at` once (repeat = no change) and moves new/scheduled/waiting → the first `in_progress` column if the board has one.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TicketDetail"
                }
              }
            }
          },
          "422": {
            "description": "Ticket is done/cancelled or archived."
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-api-key-ability": "`tickets:update`"
      }
    },
    "/v1/tickets/{id}/technician-suggestions": {
      "get": {
        "tags": [
          "Scheduling"
        ],
        "summary": "Suggest technicians",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "name": "scheduled_at",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Default the ticket window."
          },
          {
            "name": "scheduled_until",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Suggestions"
                }
              }
            }
          }
        },
        "description": "**API key ability:** `tickets:read`\n\nRanked technicians for this ticket (tickets:read).",
        "x-api-key-ability": "`tickets:read`"
      }
    },
    "/v1/tickets/{id}/unschedule": {
      "post": {
        "tags": [
          "Scheduling"
        ],
        "summary": "Clear the visit",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TicketDetail"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "description": "**API key ability:** `tickets:schedule`\n\nClear technician + window (back to Unassigned). A scheduled column moves back to the first new column. Idempotent..",
        "x-api-key-ability": "`tickets:schedule`"
      }
    },
    "/v1/webhooks": {
      "get": {
        "operationId": "webhook.index",
        "summary": "List webhook endpoints",
        "tags": [
          "Webhooks"
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": []
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationException"
          },
          "403": {
            "$ref": "#/components/responses/AuthorizationException"
          },
          "422": {
            "$ref": "#/components/responses/ValidationException"
          }
        },
        "description": "**API key ability:** `webhooks:read`",
        "x-api-key-ability": "`webhooks:read`"
      },
      "post": {
        "operationId": "webhook.store",
        "description": "**API key ability:** `webhooks:manage`, plus the read ability of every topic\n\nThe signing `secret` is returned only in this response and when rolling it.",
        "summary": "Create a webhook endpoint",
        "tags": [
          "Webhooks"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWebhookEndpointRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "`WebhookEndpointSecretResource`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointSecretResource"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationException"
          },
          "403": {
            "$ref": "#/components/responses/AuthorizationException"
          },
          "422": {
            "$ref": "#/components/responses/ValidationException"
          }
        },
        "x-api-key-ability": "`webhooks:manage`, plus the read ability of every topic"
      }
    },
    "/v1/webhooks/deliveries/{uuid}": {
      "get": {
        "operationId": "webhook.delivery",
        "summary": "Get a delivery with its signed payload",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "`WebhookDeliveryDetailResource`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryDetailResource"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationException"
          },
          "403": {
            "$ref": "#/components/responses/AuthorizationException"
          },
          "422": {
            "$ref": "#/components/responses/ValidationException"
          }
        },
        "description": "**API key ability:** `webhooks:read`",
        "x-api-key-ability": "`webhooks:read`"
      }
    },
    "/v1/webhooks/deliveries/{uuid}/resend": {
      "post": {
        "operationId": "webhook.resend",
        "summary": "Resend a delivery",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "`WebhookDeliveryDetailResource`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryDetailResource"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationException"
          },
          "403": {
            "$ref": "#/components/responses/AuthorizationException"
          },
          "422": {
            "$ref": "#/components/responses/ValidationException"
          }
        },
        "description": "**API key ability:** `webhooks:manage`",
        "x-api-key-ability": "`webhooks:manage`"
      }
    },
    "/v1/webhooks/topics": {
      "get": {
        "operationId": "webhook.topics",
        "summary": "List webhook topics and signing details",
        "tags": [
          "Webhooks"
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "api_version": {
                      "type": "string"
                    },
                    "signature_header": {
                      "type": "string",
                      "const": "X-PROradius-Signature"
                    },
                    "signature_tolerance_seconds": {
                      "type": "integer",
                      "const": 300
                    },
                    "topics": {
                      "type": "array",
                      "items": []
                    },
                    "delivery": {
                      "type": "object",
                      "properties": {
                        "max_attempts": {
                          "type": "integer",
                          "const": 6
                        },
                        "backoff_seconds": {
                          "type": "array",
                          "prefixItems": [
                            {
                              "type": "integer",
                              "const": 10
                            },
                            {
                              "type": "integer",
                              "const": 60
                            },
                            {
                              "type": "integer",
                              "const": 300
                            },
                            {
                              "type": "integer",
                              "const": 1800
                            },
                            {
                              "type": "integer",
                              "const": 7200
                            }
                          ],
                          "minItems": 5,
                          "maxItems": 5
                        },
                        "failure_threshold": {
                          "type": "integer"
                        },
                        "retention_days": {
                          "type": "integer"
                        },
                        "max_endpoints_per_org": {
                          "type": "integer"
                        },
                        "connect_timeout": {
                          "type": "integer"
                        },
                        "timeout": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "max_attempts",
                        "backoff_seconds",
                        "failure_threshold",
                        "retention_days",
                        "max_endpoints_per_org",
                        "connect_timeout",
                        "timeout"
                      ]
                    }
                  },
                  "required": [
                    "api_version",
                    "signature_header",
                    "signature_tolerance_seconds",
                    "topics",
                    "delivery"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationException"
          },
          "403": {
            "$ref": "#/components/responses/AuthorizationException"
          },
          "422": {
            "$ref": "#/components/responses/ValidationException"
          }
        },
        "description": "**API key ability:** `webhooks:read`",
        "x-api-key-ability": "`webhooks:read`"
      }
    },
    "/v1/webhooks/{uuid}": {
      "put": {
        "operationId": "webhook.update",
        "summary": "Update a webhook endpoint",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateWebhookEndpointRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "`WebhookEndpointResource`",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/WebhookEndpointResource"
                    },
                    {
                      "type": "object",
                      "required": [
                        "branch_id"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationException"
          },
          "403": {
            "$ref": "#/components/responses/AuthorizationException"
          },
          "422": {
            "$ref": "#/components/responses/ValidationException"
          }
        },
        "description": "**API key ability:** `webhooks:manage`, plus the read ability of every topic",
        "x-api-key-ability": "`webhooks:manage`, plus the read ability of every topic"
      },
      "delete": {
        "operationId": "webhook.destroy",
        "summary": "Delete a webhook endpoint",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "const": "Webhook endpoint deleted successfully"
                    }
                  },
                  "required": [
                    "message"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationException"
          },
          "403": {
            "$ref": "#/components/responses/AuthorizationException"
          },
          "422": {
            "$ref": "#/components/responses/ValidationException"
          }
        },
        "description": "**API key ability:** `webhooks:manage`",
        "x-api-key-ability": "`webhooks:manage`"
      }
    },
    "/v1/webhooks/{uuid}/deliveries": {
      "get": {
        "operationId": "webhook.deliveries",
        "summary": "List deliveries of an endpoint",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "delivered",
                "failed",
                "dropped"
              ]
            }
          },
          {
            "name": "topic",
            "in": "query",
            "description": "webhook.ping is a real stored topic but not a subscribable one,\nso the filter accepts it alongside the registry's list.",
            "schema": {
              "type": "string",
              "enum": [
                "invoice.created",
                "invoice.paid",
                "invoice.voided",
                "payment.created",
                "payment.deleted",
                "client.created",
                "client.updated",
                "ticket.created",
                "ticket.status_changed",
                "ticket.assigned",
                "ticket.archived",
                "ticket.scheduled",
                "ticket.completed",
                "ticket.cancelled",
                "webhook.ping"
              ]
            }
          },
          {
            "name": "date_from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "date_to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "topic",
                "status",
                "response_status",
                "duration_ms"
              ]
            }
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated set of `WebhookDeliveryResource`",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookDeliveryResource"
                      }
                    },
                    "links": {
                      "type": "object",
                      "properties": {
                        "first": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "last": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "prev": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "next": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "first",
                        "last",
                        "prev",
                        "next"
                      ]
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "current_page": {
                          "type": "integer",
                          "minimum": 1
                        },
                        "from": {
                          "type": [
                            "integer",
                            "null"
                          ],
                          "minimum": 1
                        },
                        "last_page": {
                          "type": "integer",
                          "minimum": 1
                        },
                        "links": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "url": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "label": {
                                "type": "string"
                              },
                              "active": {
                                "type": "boolean"
                              }
                            },
                            "required": [
                              "url",
                              "label",
                              "active"
                            ]
                          }
                        },
                        "path": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "per_page": {
                          "type": "integer",
                          "minimum": 0
                        },
                        "to": {
                          "type": [
                            "integer",
                            "null"
                          ],
                          "minimum": 1
                        },
                        "total": {
                          "type": "integer",
                          "minimum": 0
                        }
                      },
                      "required": [
                        "current_page",
                        "from",
                        "last_page",
                        "links",
                        "path",
                        "per_page",
                        "to",
                        "total"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "links",
                    "meta"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationException"
          },
          "403": {
            "$ref": "#/components/responses/AuthorizationException"
          },
          "422": {
            "$ref": "#/components/responses/ValidationException"
          }
        },
        "description": "**API key ability:** `webhooks:read`",
        "x-api-key-ability": "`webhooks:read`"
      }
    },
    "/v1/webhooks/{uuid}/roll-secret": {
      "post": {
        "operationId": "webhook.rollSecret",
        "summary": "Roll the signing secret",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "`WebhookEndpointSecretResource`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointSecretResource"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationException"
          },
          "403": {
            "$ref": "#/components/responses/AuthorizationException"
          },
          "422": {
            "$ref": "#/components/responses/ValidationException"
          }
        },
        "description": "**API key ability:** `webhooks:manage`",
        "x-api-key-ability": "`webhooks:manage`"
      }
    },
    "/v1/webhooks/{uuid}/test": {
      "post": {
        "operationId": "webhook.test",
        "summary": "Send a test delivery",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "`WebhookDeliveryDetailResource`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryDetailResource"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/AuthenticationException"
          },
          "403": {
            "$ref": "#/components/responses/AuthorizationException"
          },
          "422": {
            "$ref": "#/components/responses/ValidationException"
          }
        },
        "description": "**API key ability:** `webhooks:manage`",
        "x-api-key-ability": "`webhooks:manage`"
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "description": "Organization API key: `Authorization: Bearer <key>`. The key is bound to one organization, so no Organization-Id header is needed.",
        "scheme": "bearer"
      },
      "userToken": {
        "type": "http",
        "description": "Dashboard user token. Must be combined with the Organization-Id header.",
        "scheme": "bearer"
      },
      "organizationId": {
        "type": "apiKey",
        "description": "Organization the user token acts on. Ignored for API keys.",
        "in": "header",
        "name": "Organization-Id"
      }
    },
    "schemas": {
      "ClientAddressResource": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "zone": {
            "type": "string"
          },
          "street": {
            "type": "string"
          },
          "building": {
            "type": "string"
          },
          "box": {
            "type": "string"
          },
          "reference": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "external_ref": {
            "type": "string"
          },
          "color_tag": {
            "type": "string"
          },
          "disjunctor": {
            "type": "string"
          },
          "location": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "lat": {
                "type": "number"
              },
              "lng": {
                "type": "number"
              }
            },
            "required": [
              "lat",
              "lng"
            ]
          }
        },
        "required": [
          "name",
          "zone",
          "street",
          "building",
          "box",
          "reference",
          "code",
          "external_ref",
          "color_tag",
          "disjunctor",
          "location"
        ],
        "title": "ClientAddressResource"
      },
      "ClientsPaymetsResource": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "branch": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "code": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "name",
              "code"
            ]
          },
          "number": {
            "type": "string"
          },
          "hash": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "client": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "name"
            ]
          },
          "created_by": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              }
            },
            "required": [
              "name"
            ]
          },
          "invoice": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "number": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "number"
            ]
          },
          "amount": {
            "type": "string"
          },
          "currency": {
            "type": "string"
          },
          "method": {
            "type": "string"
          },
          "date": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "number",
          "hash",
          "type",
          "amount",
          "currency",
          "method",
          "date"
        ],
        "title": "ClientsPaymetsResource"
      },
      "ClientsResource": {
        "type": "object",
        "properties": {
          "id": {
            "type": [
              "string",
              "null"
            ]
          },
          "branch": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "code": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "name",
              "code"
            ]
          },
          "username": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "phone_number": {
            "type": "string"
          },
          "missing_phone": {
            "type": "boolean"
          },
          "missing_email": {
            "type": "boolean"
          },
          "balances": {
            "type": "string"
          },
          "address": {
            "type": "string"
          },
          "zone": {
            "type": "string"
          },
          "reference": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "external_ref": {
            "type": "string"
          },
          "color_tag": {
            "type": "string"
          },
          "disjunctor": {
            "type": "string"
          },
          "agreed_payment_method": {
            "type": "string"
          },
          "agreed_payment_method_label": {
            "type": "string"
          },
          "active": {
            "type": "boolean"
          },
          "auto_invoice": {
            "type": "boolean"
          },
          "odometer": {
            "type": "boolean"
          },
          "due_day": {
            "type": "string"
          },
          "discount": {
            "type": "string"
          },
          "discount_type": {
            "type": "string"
          },
          "collector_id": {
            "type": "string"
          },
          "collector_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          },
          "isp_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "isp_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "isp_status": {
            "type": [
              "string",
              "null"
            ]
          },
          "isp_expires_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "generator": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "zone": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "name",
              "zone"
            ]
          },
          "invoices": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "minItems": 0,
                "maxItems": 0
              }
            ]
          },
          "services": {
            "type": "string"
          },
          "wallet_balances": {
            "type": "string"
          },
          "last_invoice_due_date": {
            "type": "string"
          },
          "outstanding_balances": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "missing_phone",
          "missing_email",
          "address",
          "zone",
          "reference",
          "code",
          "external_ref",
          "color_tag",
          "disjunctor",
          "agreed_payment_method",
          "agreed_payment_method_label",
          "auto_invoice",
          "odometer",
          "due_day",
          "discount",
          "discount_type"
        ],
        "title": "ClientsResource"
      },
      "CreateClientRequest": {
        "type": "object",
        "properties": {
          "collector_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "receivable_account_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "branch_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "salutation": {
            "type": [
              "string",
              "null"
            ]
          },
          "username": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": [
              "string",
              "null"
            ],
            "format": "email"
          },
          "phone_number": {
            "type": [
              "string",
              "null"
            ]
          },
          "address": {
            "type": [
              "string",
              "null"
            ]
          },
          "city": {
            "type": [
              "string",
              "null"
            ]
          },
          "zone": {
            "type": [
              "string",
              "null"
            ]
          },
          "street": {
            "type": [
              "string",
              "null"
            ]
          },
          "country": {
            "type": [
              "string",
              "null"
            ]
          },
          "location": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            }
          },
          "balance": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            }
          },
          "due_day": {
            "type": [
              "integer",
              "null"
            ]
          },
          "active": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "enable_portal": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "auto_invoice": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "discount": {
            "type": [
              "number",
              "null"
            ],
            "minimum": 0
          },
          "discount_type": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "percentage",
              "fixed",
              null
            ]
          },
          "enable_odometer": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "odometer_value": {
            "type": [
              "number",
              "null"
            ],
            "minimum": 0
          },
          "opening_balance": {
            "type": [
              "number",
              "null"
            ]
          },
          "opening_balance_currency": {
            "type": [
              "string",
              "null"
            ]
          },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid"
                },
                "is_free": {
                  "type": [
                    "boolean",
                    "null"
                  ]
                },
                "price": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "minimum": 0
                },
                "display_price": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "minimum": 0
                },
                "quantity": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "maximum": 999999
                }
              },
              "required": [
                "id"
              ]
            },
            "uniqueItems": true
          },
          "preferred_language": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "en",
              "ar",
              null
            ]
          },
          "isp_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "isp_username": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 255
          },
          "generator_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "building": {
            "type": [
              "string",
              "null"
            ]
          },
          "box": {
            "type": [
              "string",
              "null"
            ]
          },
          "reference": {
            "type": [
              "string",
              "null"
            ]
          },
          "code": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 255
          },
          "external_ref": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 191
          },
          "color_tag": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 255
          },
          "disjunctor": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 255
          },
          "agreed_payment_method": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "cash",
              "collector",
              "whish",
              "omt",
              "bob",
              "bank_transfer",
              "in_shop",
              "check",
              "credit_card",
              null
            ]
          },
          "create_invoice_on_save": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "activation_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "required": [
          "username",
          "name"
        ],
        "title": "CreateClientRequest"
      },
      "CreateWebhookEndpointRequest": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "maxLength": 2048
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 255
          },
          "topics": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "invoice.created",
                "invoice.paid",
                "invoice.voided",
                "payment.created",
                "payment.deleted",
                "client.created",
                "client.updated",
                "ticket.created",
                "ticket.status_changed",
                "ticket.assigned",
                "ticket.archived",
                "ticket.scheduled",
                "ticket.completed",
                "ticket.cancelled"
              ]
            },
            "minItems": 1
          },
          "branch_id": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "url",
          "topics"
        ],
        "title": "CreateWebhookEndpointRequest"
      },
      "InvoiceStatus": {
        "type": "string",
        "enum": [
          "unpaid",
          "paid",
          "partial",
          "overdue",
          "cancelled",
          "voided",
          "written_off"
        ],
        "title": "InvoiceStatus"
      },
      "InvoicesResource": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "branch": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "code": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "name",
              "code"
            ]
          },
          "number": {
            "type": "string"
          },
          "client": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "address": {
                "type": "string"
              },
              "phone_number": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "name",
              "address"
            ]
          },
          "collector_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "services": {
            "type": "string"
          },
          "issue_date": {
            "type": "string"
          },
          "due_date": {
            "type": "string"
          },
          "discount": {
            "type": "string"
          },
          "discount_type": {
            "type": "string"
          },
          "sub_total": {
            "type": "string"
          },
          "total": {
            "type": "string"
          },
          "balance": {
            "type": "string"
          },
          "status": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/InvoiceStatus"
              },
              {
                "type": "string"
              }
            ]
          },
          "amount_paid": {
            "type": "number"
          },
          "balance_due": {
            "type": "string"
          },
          "currency": {
            "type": "string"
          },
          "is_due": {
            "type": "boolean"
          },
          "due_days": {
            "type": "string"
          },
          "voided_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "void_reason": {
            "type": "string"
          },
          "merged_from": {
            "type": [
              "string",
              "null"
            ]
          },
          "merged_into": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "number": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "number"
            ]
          },
          "written_off_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "write_off_amount": {
            "type": "string"
          },
          "write_off_reason": {
            "type": "string"
          },
          "cancelled_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "is_complimentary": {
            "type": "boolean"
          },
          "renew_isp_on_payment": {
            "type": "boolean"
          },
          "from_pos": {
            "type": "boolean"
          },
          "pos_sale": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "sale_type": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "register_id": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "sale_type",
              "register_id"
            ]
          }
        },
        "required": [
          "id",
          "number",
          "client",
          "issue_date",
          "due_date",
          "discount",
          "discount_type",
          "sub_total",
          "total",
          "balance",
          "status",
          "amount_paid",
          "balance_due",
          "currency",
          "is_due",
          "voided_at",
          "void_reason",
          "merged_from",
          "merged_into",
          "written_off_at",
          "write_off_amount",
          "write_off_reason",
          "cancelled_at",
          "is_complimentary",
          "renew_isp_on_payment",
          "from_pos"
        ],
        "title": "InvoicesResource"
      },
      "SingleClientResource": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "branch": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "code": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "name",
              "code"
            ]
          },
          "username": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "avatar": {
            "type": "string"
          },
          "phone_number": {
            "type": "string"
          },
          "external_ref": {
            "type": "string"
          },
          "missing_phone": {
            "type": "boolean"
          },
          "missing_email": {
            "type": "boolean"
          },
          "balances": [],
          "address": {
            "$ref": "#/components/schemas/ClientAddressResource"
          },
          "collector": {
            "type": "object",
            "properties": {
              "id": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "id",
              "name"
            ]
          },
          "collector_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "active": {
            "type": "boolean"
          },
          "due_day": {
            "type": "string"
          },
          "enable_portal": {
            "type": "boolean"
          },
          "auto_invoice": {
            "type": "boolean"
          },
          "discount": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "integer",
                "enum": [
                  0
                ]
              }
            ]
          },
          "discount_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "string",
                "enum": [
                  "percentage"
                ]
              }
            ]
          },
          "preferred_language": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "string",
                "enum": [
                  "en"
                ]
              }
            ]
          },
          "agreed_payment_method": {
            "type": "string"
          },
          "agreed_payment_method_label": {
            "type": "string"
          },
          "opening_balance": {
            "type": "string"
          },
          "opening_balance_currency": {
            "type": "string"
          },
          "has_opening_balance_invoice": {
            "type": "boolean"
          },
          "enable_odometer": {
            "type": "boolean"
          },
          "odometer_value": {
            "type": "number"
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          },
          "invoices_count": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "integer",
                "enum": [
                  0
                ]
              }
            ]
          },
          "payments_count": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "integer",
                "enum": [
                  0
                ]
              }
            ]
          },
          "deposits_count": {
            "type": "integer"
          },
          "check_ins_count": {
            "type": "integer"
          },
          "has_breaker": {
            "type": "boolean"
          },
          "deposits_enabled": {
            "type": "string"
          },
          "activity": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "data": {
                    "type": "string"
                  },
                  "loadable": {
                    "type": "string"
                  }
                },
                "required": [
                  "data",
                  "loadable"
                ]
              },
              {
                "type": "object",
                "properties": {
                  "data": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "minItems": 0,
                    "maxItems": 0
                  },
                  "loadable": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "data",
                  "loadable"
                ]
              }
            ]
          },
          "items": {
            "type": "string"
          },
          "latest_check_in": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "latitude": {
                "type": "number"
              },
              "longitude": {
                "type": "number"
              },
              "notes": {
                "type": "string"
              },
              "user": {
                "type": [
                  "object",
                  "null"
                ],
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  }
                },
                "required": [
                  "id",
                  "name"
                ]
              },
              "created_at": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "latitude",
              "longitude",
              "notes",
              "user",
              "created_at"
            ]
          },
          "generator": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "zone": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "name",
              "zone"
            ]
          },
          "isp_account": {
            "type": "object",
            "properties": {
              "isp_id": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "isp_name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "isp_username": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "status": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "last_synced_at": {
                "type": "string"
              },
              "last_renewed_at": {
                "type": "string"
              },
              "expires_at": {
                "type": "string"
              },
              "created_at": {
                "type": "string"
              }
            },
            "required": [
              "isp_id",
              "isp_name",
              "isp_username",
              "status",
              "last_synced_at",
              "last_renewed_at",
              "expires_at",
              "created_at"
            ]
          },
          "invoices": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/InvoicesResource"
            }
          },
          "payments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ClientsPaymetsResource"
            }
          },
          "statistic": {
            "type": "array",
            "prefixItems": [
              {
                "type": "object",
                "properties": {
                  "key": {
                    "type": "string",
                    "const": "invoices"
                  },
                  "label": {
                    "type": "string",
                    "const": "Invoice"
                  },
                  "value": {
                    "type": "string"
                  },
                  "growShrink": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "integer",
                        "enum": [
                          0
                        ]
                      }
                    ]
                  }
                },
                "required": [
                  "key",
                  "label",
                  "value",
                  "growShrink"
                ]
              },
              {
                "type": "object",
                "properties": {
                  "key": {
                    "type": "string",
                    "const": "payments"
                  },
                  "label": {
                    "type": "string",
                    "const": "Payment"
                  },
                  "value": {
                    "type": "string"
                  },
                  "growShrink": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "integer",
                        "enum": [
                          0
                        ]
                      }
                    ]
                  }
                },
                "required": [
                  "key",
                  "label",
                  "value",
                  "growShrink"
                ]
              },
              {
                "type": "object",
                "properties": {
                  "key": {
                    "type": "string",
                    "const": "overdue-invoices"
                  },
                  "label": {
                    "type": "string",
                    "const": "Overdue invoices"
                  },
                  "value": {
                    "type": "string"
                  },
                  "growShrink": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "integer",
                        "enum": [
                          0
                        ]
                      }
                    ]
                  }
                },
                "required": [
                  "key",
                  "label",
                  "value",
                  "growShrink"
                ]
              },
              {
                "type": "object",
                "properties": {
                  "key": {
                    "type": "string",
                    "const": "avg-time-to-pay"
                  },
                  "label": {
                    "type": "string",
                    "const": "Avg. days to pay"
                  },
                  "value": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "integer",
                        "enum": [
                          0
                        ]
                      }
                    ]
                  },
                  "growShrink": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "integer",
                        "enum": [
                          0
                        ]
                      }
                    ]
                  }
                },
                "required": [
                  "key",
                  "label",
                  "value",
                  "growShrink"
                ]
              }
            ],
            "minItems": 4,
            "maxItems": 4
          }
        },
        "required": [
          "id",
          "username",
          "name",
          "email",
          "avatar",
          "phone_number",
          "external_ref",
          "missing_phone",
          "missing_email",
          "balances",
          "address",
          "collector_id",
          "active",
          "due_day",
          "enable_portal",
          "auto_invoice",
          "discount",
          "discount_type",
          "preferred_language",
          "agreed_payment_method",
          "agreed_payment_method_label",
          "opening_balance",
          "opening_balance_currency",
          "has_opening_balance_invoice",
          "enable_odometer",
          "odometer_value",
          "created_at",
          "updated_at",
          "invoices_count",
          "payments_count",
          "statistic"
        ],
        "title": "SingleClientResource"
      },
      "UpdateClientRequest": {
        "type": "object",
        "properties": {
          "collector_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "receivable_account_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "branch_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "salutation": {
            "type": [
              "string",
              "null"
            ]
          },
          "username": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": [
              "string",
              "null"
            ],
            "format": "email"
          },
          "phone_number": {
            "type": [
              "string",
              "null"
            ]
          },
          "address": {
            "type": [
              "string",
              "null"
            ]
          },
          "city": {
            "type": [
              "string",
              "null"
            ]
          },
          "zone": {
            "type": [
              "string",
              "null"
            ]
          },
          "street": {
            "type": [
              "string",
              "null"
            ]
          },
          "country": {
            "type": [
              "string",
              "null"
            ]
          },
          "location": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            }
          },
          "balance": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            }
          },
          "due_day": {
            "type": [
              "integer",
              "null"
            ]
          },
          "active": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "enable_portal": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "auto_invoice": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "discount": {
            "type": [
              "number",
              "null"
            ],
            "minimum": 0
          },
          "discount_type": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "percentage",
              "fixed",
              null
            ]
          },
          "enable_odometer": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "odometer_value": {
            "type": [
              "number",
              "null"
            ],
            "minimum": 0
          },
          "opening_balance": {
            "type": [
              "number",
              "null"
            ]
          },
          "opening_balance_currency": {
            "type": [
              "string",
              "null"
            ]
          },
          "items": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid"
                },
                "is_free": {
                  "type": [
                    "boolean",
                    "null"
                  ]
                },
                "price": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "minimum": 0
                },
                "display_price": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "minimum": 0
                },
                "quantity": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "maximum": 999999
                }
              },
              "required": [
                "id"
              ]
            },
            "uniqueItems": true
          },
          "preferred_language": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "en",
              "ar",
              null
            ]
          },
          "isp_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "isp_username": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 255
          },
          "generator_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "building": {
            "type": [
              "string",
              "null"
            ]
          },
          "box": {
            "type": [
              "string",
              "null"
            ]
          },
          "reference": {
            "type": [
              "string",
              "null"
            ]
          },
          "code": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 255
          },
          "external_ref": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 191
          },
          "color_tag": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 255
          },
          "disjunctor": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 255
          },
          "agreed_payment_method": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "cash",
              "collector",
              "whish",
              "omt",
              "bob",
              "bank_transfer",
              "in_shop",
              "check",
              "credit_card",
              null
            ]
          },
          "cascade_collector_to_payable_invoices": {
            "type": "boolean"
          }
        },
        "required": [
          "username",
          "name"
        ],
        "title": "UpdateClientRequest"
      },
      "UpdateWebhookEndpointRequest": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "maxLength": 2048
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 255
          },
          "topics": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "invoice.created",
                "invoice.paid",
                "invoice.voided",
                "payment.created",
                "payment.deleted",
                "client.created",
                "client.updated",
                "ticket.created",
                "ticket.status_changed",
                "ticket.assigned",
                "ticket.archived",
                "ticket.scheduled",
                "ticket.completed",
                "ticket.cancelled"
              ]
            },
            "minItems": 1
          },
          "active": {
            "type": "boolean"
          },
          "branch_id": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "title": "UpdateWebhookEndpointRequest"
      },
      "WebhookDeliveryDetailResource": {
        "type": "array",
        "items": [],
        "title": "WebhookDeliveryDetailResource"
      },
      "WebhookDeliveryResource": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "event_id": {
            "type": "string"
          },
          "topic": {
            "type": "string"
          },
          "status": {
            "type": [
              "string",
              "null"
            ]
          },
          "attempt": {
            "type": "integer"
          },
          "response_status": {
            "type": "string"
          },
          "response_body": {
            "type": "string"
          },
          "error": {
            "type": "string"
          },
          "duration_ms": {
            "type": "string"
          },
          "next_attempt_at": {
            "type": "string"
          },
          "delivered_at": {
            "type": "string"
          },
          "created_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "event_id",
          "topic",
          "status",
          "attempt",
          "response_status",
          "response_body",
          "error",
          "duration_ms",
          "next_attempt_at",
          "delivered_at",
          "created_at"
        ],
        "title": "WebhookDeliveryResource"
      },
      "WebhookEndpointResource": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "topics": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "minItems": 0,
                "maxItems": 0
              }
            ]
          },
          "api_version": {
            "type": "string"
          },
          "active": {
            "type": "boolean"
          },
          "consecutive_failures": {
            "type": "integer"
          },
          "disabled_at": {
            "type": "string"
          },
          "disabled_reason": {
            "type": "string"
          },
          "branch_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_by_api_key": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "active": {
                "type": "boolean"
              }
            },
            "required": [
              "id",
              "name",
              "active"
            ]
          },
          "deliveries_count": {
            "type": "integer"
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "url",
          "description",
          "topics",
          "api_version",
          "active",
          "consecutive_failures",
          "disabled_at",
          "disabled_reason",
          "created_by_api_key",
          "created_at",
          "updated_at"
        ],
        "title": "WebhookEndpointResource"
      },
      "WebhookEndpointSecretResource": {
        "type": "array",
        "items": [],
        "title": "WebhookEndpointSecretResource"
      },
      "Board": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "columns": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Column"
            }
          },
          "members": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "labels": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "is_service_board": {
            "type": "boolean"
          },
          "portal_default": {
            "type": "boolean",
            "description": "Portal tickets without a job type board land here (one per org)."
          },
          "auto_archive_days": {
            "type": "integer",
            "nullable": true
          },
          "categories_guessed": {
            "type": "boolean",
            "description": "True while the column categories were guessed by the upgrade and no admin has saved the columns yet. False for new boards."
          },
          "tickets_count": {
            "type": "integer"
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          }
        }
      },
      "BoardDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Board"
          },
          {
            "type": "object",
            "properties": {
              "tickets": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Ticket"
                }
              }
            }
          }
        ]
      },
      "JobType": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "code": {
            "type": "string",
            "example": "installation"
          },
          "color": {
            "type": "string",
            "nullable": true
          },
          "icon": {
            "type": "string",
            "nullable": true
          },
          "board_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "null = every board."
          },
          "default_priority": {
            "type": "string",
            "enum": [
              "low",
              "medium",
              "high",
              "critical"
            ]
          },
          "sla_hours": {
            "type": "integer",
            "nullable": true
          },
          "duration_minutes": {
            "type": "integer",
            "nullable": true,
            "description": "Used for auto-assign slots (default 60)."
          },
          "checklist": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                }
              }
            }
          },
          "billing_mode": {
            "type": "string",
            "enum": [
              "none",
              "on_completion",
              "manual"
            ],
            "description": "none = free; on_completion = invoice when completed; manual = items saved, office presses Create invoice (Phase 3b)."
          },
          "default_items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "item_uuid": {
                  "type": "string"
                },
                "quantity": {
                  "type": "number"
                },
                "name": {
                  "type": "string",
                  "nullable": true
                },
                "type": {
                  "type": "string",
                  "nullable": true
                }
              }
            }
          },
          "required_skills": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Skill"
            },
            "description": "Phase 4: technicians must hold all of them (deleted skills drop out)."
          },
          "requires_client": {
            "type": "boolean"
          },
          "portal_visible": {
            "type": "boolean"
          },
          "auto_assign": {
            "type": "boolean"
          },
          "notify_client": {
            "type": "boolean",
            "description": "Customer messages for this job type (also needs the org setting). Default true."
          },
          "active": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "JobTypeInput": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 120,
            "description": "Required on create."
          },
          "code": {
            "type": "string",
            "pattern": "^[a-z0-9][a-z0-9_-]*$"
          },
          "color": {
            "type": "string"
          },
          "icon": {
            "type": "string"
          },
          "board_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "default_priority": {
            "type": "string",
            "enum": [
              "low",
              "medium",
              "high",
              "critical"
            ]
          },
          "sla_hours": {
            "type": "integer",
            "minimum": 1,
            "nullable": true
          },
          "duration_minutes": {
            "type": "integer",
            "minimum": 15,
            "maximum": 1440,
            "nullable": true
          },
          "checklist": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "billing_mode": {
            "type": "string",
            "enum": [
              "none",
              "on_completion",
              "manual"
            ]
          },
          "default_items": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "item_uuid"
              ],
              "properties": {
                "item_uuid": {
                  "type": "string",
                  "format": "uuid"
                },
                "quantity": {
                  "type": "number",
                  "default": 1
                }
              }
            }
          },
          "required_skills": {
            "type": "array",
            "maxItems": 20,
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "nullable": true,
            "description": "Skill ids; null or [] = none."
          },
          "requires_client": {
            "type": "boolean"
          },
          "portal_visible": {
            "type": "boolean"
          },
          "auto_assign": {
            "type": "boolean"
          },
          "notify_client": {
            "type": "boolean"
          },
          "active": {
            "type": "boolean"
          }
        }
      },
      "Ticket": {
        "type": "object",
        "description": "Card. `comments`/`attachments` are absent with ?slim=1.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "ticket_number": {
            "type": "string",
            "example": "TKT-0042"
          },
          "external_ref": {
            "type": "string",
            "nullable": true,
            "description": "Integrator reference, unique per organization."
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "board_id": {
            "type": "string",
            "format": "uuid"
          },
          "column_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "description": "Column name."
          },
          "status_category": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Category"
              }
            ],
            "nullable": true
          },
          "priority": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "column_order": {
            "type": "integer"
          },
          "labels": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "assigned_users": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "user_id": {
                  "type": "string"
                },
                "user_name": {
                  "type": "string"
                },
                "user_avatar": {
                  "type": "string",
                  "nullable": true
                }
              }
            }
          },
          "comments": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "attachments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Attachment"
            }
          },
          "comments_count": {
            "type": "integer"
          },
          "attachments_count": {
            "type": "integer"
          },
          "linked_invoices": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LinkedInvoice"
            }
          },
          "client": {
            "type": "object",
            "nullable": true,
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              }
            }
          },
          "created_by": {
            "type": "object",
            "nullable": true,
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              }
            }
          },
          "due_date": {
            "type": "string",
            "format": "date",
            "nullable": true
          },
          "is_overdue": {
            "type": "boolean"
          },
          "created_via": {
            "type": "string",
            "nullable": true,
            "enum": [
              "web",
              "mobile",
              "portal",
              "api",
              null
            ],
            "description": "Read-only. Null on tickets created before Oct 2026."
          },
          "api_key_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "Read-only. The API key that created the ticket."
          },
          "resolved_at": {
            "type": "string",
            "nullable": true
          },
          "closed_at": {
            "type": "string",
            "nullable": true
          },
          "archived_at": {
            "type": "string",
            "nullable": true
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          },
          "job_type_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "job_type": {
            "type": "object",
            "nullable": true,
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "code": {
                "type": "string"
              },
              "color": {
                "type": "string",
                "nullable": true
              },
              "icon": {
                "type": "string",
                "nullable": true
              },
              "billing_mode": {
                "type": "string"
              }
            }
          },
          "technician_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "technician": {
            "type": "object",
            "nullable": true,
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "avatar": {
                "type": "string",
                "nullable": true
              }
            }
          },
          "scheduled_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "UTC (Z)."
          },
          "scheduled_until": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "started_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "sla_due_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "sla_hours": {
            "type": "integer",
            "nullable": true,
            "description": "SLA length in hours from creation (paused time excluded); null = no SLA."
          },
          "sla_breached_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Set once by the hourly SLA check."
          },
          "sla_paused_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Set while in a waiting column (SLA clock paused)."
          },
          "sla_paused_seconds": {
            "type": "integer",
            "description": "Total paused time; sla_due_at is shifted by it."
          },
          "reminded_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Day-before customer reminder sent (cleared when the visit time changes)."
          },
          "sla_escalated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Phase 4: Owners were alerted (breach + owner_after_hours)."
          },
          "parent_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "Follow-up of this ticket."
          },
          "parent_ticket_number": {
            "type": "string",
            "nullable": true
          },
          "outcome": {
            "type": "string",
            "nullable": true,
            "enum": [
              "done",
              "partial",
              "revisit",
              null
            ]
          },
          "completion_items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CompletionItem"
            }
          },
          "cancellation_reason": {
            "type": "string",
            "nullable": true
          },
          "completion_notes": {
            "type": "string",
            "nullable": true
          },
          "checklist_state": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                },
                "done": {
                  "type": "boolean"
                },
                "done_at": {
                  "type": "string",
                  "nullable": true
                },
                "done_by": {
                  "type": "string",
                  "nullable": true
                }
              }
            }
          }
        }
      },
      "Pagination": {
        "type": "object",
        "properties": {
          "total": {
            "type": "integer"
          },
          "per_page": {
            "type": "integer"
          },
          "current_page": {
            "type": "integer"
          },
          "last_page": {
            "type": "integer"
          },
          "from": {
            "type": "integer",
            "nullable": true
          },
          "to": {
            "type": "integer",
            "nullable": true
          }
        }
      },
      "TicketDetail": {
        "$ref": "#/components/schemas/Ticket"
      },
      "ClientLookupError": {
        "type": "object",
        "properties": {
          "status": {
            "type": "boolean",
            "example": false
          },
          "error": {
            "type": "object",
            "properties": {
              "message": {
                "type": "string"
              },
              "reason": {
                "type": "string",
                "enum": [
                  "client_not_found",
                  "client_ambiguous",
                  "client_lookup_conflict"
                ]
              },
              "details": {
                "type": "object",
                "properties": {
                  "field": {
                    "type": "string",
                    "example": "client_phone"
                  },
                  "candidates": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "description": "client_ambiguous only: up to 10 client uuids (no other client data)."
                  },
                  "sent": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "client_lookup_conflict only."
                  }
                }
              }
            }
          }
        },
        "example": {
          "status": false,
          "error": {
            "message": "client_phone matches more than one client; send client_id instead.",
            "reason": "client_ambiguous",
            "details": {
              "field": "client_phone",
              "candidates": [
                "b8f2a1c4-7d39-4e52-9a06-1f4c8b3d5e27",
                "0d1e2f3a-4b5c-4d6e-8f70-8192a3b4c5d6"
              ]
            }
          }
        }
      },
      "Category": {
        "type": "string",
        "enum": [
          "new",
          "scheduled",
          "in_progress",
          "waiting",
          "done",
          "cancelled"
        ]
      },
      "TicketEvent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "type": {
            "type": "string",
            "enum": [
              "created",
              "moved",
              "assigned",
              "unassigned",
              "archived",
              "unarchived",
              "reopened"
            ]
          },
          "from": {
            "type": "string",
            "nullable": true,
            "description": "moved: column name; unassigned: user uuid; reopened: category."
          },
          "to": {
            "type": "string",
            "nullable": true
          },
          "meta": {
            "type": "object",
            "example": {
              "from_category": "in_progress",
              "to_category": "done"
            }
          },
          "actor": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "user",
                  "api_key",
                  "client",
                  "system"
                ]
              },
              "id": {
                "type": "string",
                "nullable": true
              },
              "name": {
                "type": "string"
              }
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "TechnicianProfile": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "avatar": {
            "type": "string",
            "nullable": true
          },
          "custom_hours": {
            "type": "boolean",
            "description": "false = no saved hours: manual booking any time, auto-assign 08:00–18:00."
          },
          "working_hours": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "weekday": {
                  "type": "integer",
                  "minimum": 1,
                  "maximum": 7,
                  "description": "1 = Monday … 7 = Sunday"
                },
                "start": {
                  "type": "string",
                  "example": "09:00"
                },
                "end": {
                  "type": "string",
                  "example": "17:00"
                }
              }
            }
          },
          "time_off": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TimeOff"
            },
            "description": "Current and upcoming."
          },
          "skills": {
            "type": "array",
            "items": {
              "allOf": [
                {
                  "$ref": "#/components/schemas/Skill"
                },
                {
                  "type": "object",
                  "properties": {
                    "level": {
                      "type": "integer",
                      "enum": [
                        1,
                        2,
                        3
                      ],
                      "description": "1 basic, 2 good, 3 expert"
                    }
                  }
                }
              ]
            }
          }
        }
      },
      "Suggestions": {
        "type": "object",
        "properties": {
          "window": {
            "type": "object",
            "nullable": true,
            "properties": {
              "scheduled_at": {
                "type": "string"
              },
              "scheduled_until": {
                "type": "string"
              }
            }
          },
          "duration_minutes": {
            "type": "integer"
          },
          "suggestions": {
            "type": "array",
            "description": "Best first. Hard rules: active org user, board member, tickets:own or tickets:update, all the job type's required_skills; with a window also inside saved working hours, not on time off, not busy. Score = (collector 20 + branch 30 + zone 25) × zone − 8 × jobs that day × load − min(30, 1.5 × km) × distance + skills_score × skills (org ranking_weights).",
            "items": {
              "type": "object",
              "properties": {
                "user": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "avatar": {
                      "type": "string",
                      "nullable": true
                    }
                  }
                },
                "score": {
                  "type": "number"
                },
                "jobs_that_day": {
                  "type": "integer"
                },
                "distance_km": {
                  "type": "number",
                  "nullable": true,
                  "description": "From the last GPS fix (≤ 24 h old) to the client pin."
                },
                "available": {
                  "type": "boolean"
                },
                "skills_score": {
                  "type": "number",
                  "nullable": true,
                  "description": "Phase 4: average level (1–3) over the required skills × 10; null when the job type requires none."
                },
                "reasons": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  },
                  "example": [
                    "Same branch",
                    "Covers Hosh",
                    "2 jobs that day",
                    "1.8 km away"
                  ]
                },
                "next_free_slot": {
                  "type": "object",
                  "nullable": true,
                  "description": "Only without a window: first free slot of the job duration inside the technician's working hours (default 08:00–18:00 org time), skipping time off, up to 7 days.",
                  "properties": {
                    "scheduled_at": {
                      "type": "string"
                    },
                    "scheduled_until": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "CompletionItemPreview": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CompletionItem"
          },
          {
            "type": "object",
            "properties": {
              "currency": {
                "type": "string",
                "nullable": true
              },
              "held_in_van": {
                "type": "number",
                "nullable": true,
                "description": "Goods held by the technician; null for services or no technician."
              },
              "source": {
                "type": "string",
                "enum": [
                  "saved",
                  "job_type"
                ]
              }
            }
          }
        ]
      },
      "CompletionInvoice": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "number": {
            "type": "string"
          },
          "total": {
            "type": "string"
          },
          "balance": {
            "type": "string"
          },
          "currency": {
            "type": "string"
          },
          "status": {
            "type": "string"
          }
        }
      },
      "CompletionItemInput": {
        "type": "object",
        "required": [
          "item_uuid",
          "quantity"
        ],
        "properties": {
          "item_uuid": {
            "type": "string",
            "format": "uuid"
          },
          "quantity": {
            "type": "number",
            "minimum": 0.01
          },
          "price": {
            "type": "number",
            "nullable": true,
            "description": "Used only with invoices:override_price; else the catalog/client price."
          },
          "serial": {
            "type": "string",
            "maxLength": 120
          },
          "mac": {
            "type": "string",
            "maxLength": 64
          }
        }
      },
      "CollectPayment": {
        "type": "object",
        "nullable": true,
        "required": [
          "amount"
        ],
        "properties": {
          "amount": {
            "type": "number",
            "minimum": 0.01
          },
          "currency": {
            "type": "string",
            "description": "Default = invoice currency."
          },
          "method": {
            "type": "string",
            "enum": [
              "cash",
              "whish",
              "omt",
              "bob",
              "bank_transfer"
            ],
            "default": "cash",
            "description": "Cash goes to the technician's wallet."
          },
          "exchange_rate": {
            "type": "number"
          }
        }
      },
      "CompletionResult": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Ticket"
          },
          {
            "type": "object",
            "properties": {
              "completion": {
                "type": "object",
                "properties": {
                  "replayed": {
                    "type": "boolean",
                    "description": "true = the job was already finished; nothing new was created."
                  },
                  "billing_mode": {
                    "type": "string",
                    "enum": [
                      "none",
                      "on_completion",
                      "manual"
                    ]
                  },
                  "invoice": {
                    "allOf": [
                      {
                        "$ref": "#/components/schemas/CompletionInvoice"
                      }
                    ],
                    "nullable": true
                  },
                  "payment_id": {
                    "type": "string",
                    "format": "uuid",
                    "nullable": true
                  },
                  "follow_up": {
                    "type": "object",
                    "nullable": true,
                    "properties": {
                      "id": {
                        "type": "string"
                      },
                      "ticket_number": {
                        "type": "string"
                      }
                    }
                  },
                  "client_notified": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        ]
      },
      "Column": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ColumnInput"
          },
          {
            "type": "object",
            "required": [
              "id",
              "name",
              "order",
              "category"
            ],
            "properties": {
              "tickets_count": {
                "type": "integer",
                "description": "Board list only."
              }
            }
          }
        ]
      },
      "Skill": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "color": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "Attachment": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "file_name": {
            "type": "string"
          },
          "file_path": {
            "type": "string"
          },
          "file_url": {
            "type": "string",
            "nullable": true,
            "description": "Signed 60-minute link for private files; public URL for files uploaded before Oct 2026."
          },
          "disk": {
            "type": "string",
            "enum": [
              "local",
              "public"
            ]
          },
          "file_size": {
            "type": "integer"
          },
          "mime_type": {
            "type": "string"
          },
          "uploaded_by": {
            "type": "string"
          },
          "uploaded_by_name": {
            "type": "string"
          },
          "created_at": {
            "type": "string"
          }
        }
      },
      "LinkedInvoice": {
        "type": "object",
        "description": "Read live from the invoice on every response.",
        "properties": {
          "invoice_id": {
            "type": "string",
            "format": "uuid"
          },
          "invoice_number": {
            "type": "string"
          },
          "total": {
            "type": "string"
          },
          "balance": {
            "type": "number"
          },
          "currency": {
            "type": "string",
            "example": "USD"
          },
          "status": {
            "type": "string"
          },
          "purpose": {
            "type": "string",
            "enum": [
              "manual",
              "completion"
            ]
          },
          "linked_by": {
            "type": "string",
            "nullable": true
          },
          "linked_at": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "CompletionItem": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CompletionItemInput"
          },
          {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              },
              "type": {
                "type": "string",
                "enum": [
                  "goods",
                  "service"
                ]
              }
            }
          }
        ]
      },
      "TimeOff": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "starts_on": {
            "type": "string",
            "format": "date"
          },
          "ends_on": {
            "type": "string",
            "format": "date",
            "description": "Inclusive (org-local dates)."
          },
          "reason": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "ColumnInput": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "order": {
            "type": "integer"
          },
          "color": {
            "type": "string",
            "example": "#10B981"
          },
          "wip_limit": {
            "type": "integer"
          },
          "category": {
            "$ref": "#/components/schemas/Category"
          }
        }
      },
      "WebhookEnvelope": {
        "type": "object",
        "required": [
          "id",
          "topic",
          "created_at",
          "api_version",
          "organization_id",
          "data"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Event id (`evt_` + uuid). Same across retries and endpoints; use it to de-duplicate."
          },
          "topic": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "api_version": {
            "type": "string",
            "description": "Payload version stamped on the endpoint when it was created."
          },
          "organization_id": {
            "type": "string",
            "format": "uuid"
          },
          "data": {
            "type": "object"
          }
        }
      },
      "WebhookTicketCreated": {
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "object",
                "properties": {
                  "ticket": {
                    "$ref": "#/components/schemas/WebhookTicket"
                  }
                }
              }
            }
          }
        ]
      },
      "WebhookTicket": {
        "type": "object",
        "description": "Ids and state only; ticket fields are read when the webhook is built, so re-fetch for details.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "ticket_number": {
            "type": "string"
          },
          "external_ref": {
            "type": "string",
            "nullable": true
          },
          "status": {
            "type": "string",
            "description": "Column name."
          },
          "status_category": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Category"
              }
            ],
            "nullable": true
          },
          "board_id": {
            "type": "string",
            "format": "uuid"
          },
          "client_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "created_via": {
            "type": "string",
            "nullable": true
          },
          "job_type": {
            "type": "string",
            "nullable": true,
            "description": "Job type code."
          },
          "technician_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "scheduled_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "sla_due_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "archived_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebhookTicketStatusChanged": {
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "object",
                "properties": {
                  "ticket": {
                    "$ref": "#/components/schemas/WebhookTicket"
                  },
                  "from": {
                    "type": "object",
                    "properties": {
                      "column": {
                        "type": "string"
                      },
                      "category": {
                        "$ref": "#/components/schemas/Category"
                      }
                    }
                  },
                  "to": {
                    "type": "object",
                    "properties": {
                      "column": {
                        "type": "string"
                      },
                      "category": {
                        "$ref": "#/components/schemas/Category"
                      }
                    }
                  }
                }
              }
            }
          }
        ]
      },
      "WebhookTicketAssigned": {
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "object",
                "properties": {
                  "ticket": {
                    "$ref": "#/components/schemas/WebhookTicket"
                  },
                  "assigned_user_ids": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "description": "Assignees now."
                  },
                  "added_user_ids": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    }
                  },
                  "removed_user_ids": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          }
        ]
      },
      "WebhookTicketArchived": {
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "object",
                "properties": {
                  "ticket": {
                    "$ref": "#/components/schemas/WebhookTicket"
                  },
                  "auto": {
                    "type": "boolean",
                    "description": "true = archived by the daily auto-archive job."
                  }
                }
              }
            }
          }
        ]
      },
      "WebhookTicketScheduled": {
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "object",
                "properties": {
                  "ticket": {
                    "$ref": "#/components/schemas/WebhookTicket"
                  },
                  "technician_id": {
                    "type": "string",
                    "format": "uuid",
                    "nullable": true
                  },
                  "scheduled_at": {
                    "type": "string",
                    "format": "date-time",
                    "nullable": true
                  },
                  "scheduled_until": {
                    "type": "string",
                    "format": "date-time",
                    "nullable": true
                  },
                  "auto": {
                    "type": "boolean"
                  },
                  "override": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        ]
      },
      "WebhookTicketCompleted": {
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "object",
                "properties": {
                  "ticket": {
                    "$ref": "#/components/schemas/WebhookTicket"
                  },
                  "outcome": {
                    "type": "string",
                    "enum": [
                      "done",
                      "partial"
                    ]
                  },
                  "invoice_id": {
                    "type": "string",
                    "format": "uuid",
                    "nullable": true
                  },
                  "resolved_at": {
                    "type": "string",
                    "format": "date-time",
                    "nullable": true
                  }
                }
              }
            }
          }
        ]
      },
      "WebhookTicketCancelled": {
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "object",
                "properties": {
                  "ticket": {
                    "$ref": "#/components/schemas/WebhookTicket"
                  },
                  "reason": {
                    "type": "string",
                    "nullable": true
                  },
                  "closed_at": {
                    "type": "string",
                    "format": "date-time",
                    "nullable": true
                  }
                }
              }
            }
          }
        ]
      }
    },
    "responses": {
      "AuthenticationException": {
        "description": "Unauthenticated",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "status": {
                  "type": "boolean",
                  "examples": [
                    false
                  ]
                },
                "error": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "description": "Error overview."
                    }
                  },
                  "required": [
                    "message"
                  ]
                }
              },
              "required": [
                "status",
                "error"
              ]
            }
          }
        }
      },
      "ValidationException": {
        "description": "Validation error",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "status": {
                  "type": "boolean",
                  "examples": [
                    false
                  ]
                },
                "error": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "description": "Errors overview."
                    },
                    "errors": {
                      "type": "object",
                      "description": "A detailed description of each field that failed validation.",
                      "additionalProperties": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    }
                  },
                  "required": [
                    "message",
                    "errors"
                  ]
                }
              },
              "required": [
                "status",
                "error"
              ]
            }
          }
        }
      },
      "AuthorizationException": {
        "description": "Authorization error",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "status": {
                  "type": "boolean",
                  "examples": [
                    false
                  ]
                },
                "error": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "description": "Error overview."
                    }
                  },
                  "required": [
                    "message"
                  ]
                }
              },
              "required": [
                "status",
                "error"
              ]
            }
          }
        }
      },
      "ModelNotFoundException": {
        "description": "Not found",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "status": {
                  "type": "boolean",
                  "examples": [
                    false
                  ]
                },
                "error": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "description": "Error overview."
                    }
                  },
                  "required": [
                    "message"
                  ]
                }
              },
              "required": [
                "status",
                "error"
              ]
            }
          }
        }
      }
    },
    "parameters": {
      "Id": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "Archived": {
        "name": "archived",
        "in": "query",
        "schema": {
          "type": "string",
          "enum": [
            "0",
            "1",
            "only"
          ]
        },
        "description": "Default hides archived tickets; 1 = include them; only = archived only."
      }
    }
  },
  "webhooks": {
    "invoice.created": {
      "post": {
        "summary": "Invoice created",
        "description": "Requires the `invoices:read` ability when the endpoint was created by an API key.",
        "tags": [
          "Webhooks"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEnvelope"
              },
              "example": {
                "id": "evt_1f0b6a3c-9d4e-4a1b-8c22-5f7e0d9a1234",
                "topic": "invoice.created",
                "created_at": "2026-09-06T12:00:00Z",
                "api_version": "2026-09-01",
                "organization_id": "7c2d1e8a-3b45-4f9c-a0d1-6e8b2f4a9c11",
                "data": {
                  "invoice": {
                    "id": "e3b1c7d2-5a64-4f80-9b13-2c8d5e7f1a90",
                    "number": "INV-001204",
                    "status": "paid",
                    "currency": "USD",
                    "total": 120,
                    "balance": 0,
                    "issue_date": "2026-09-01",
                    "due_date": "2026-09-15",
                    "client": {
                      "id": "b8f2a1c4-7d39-4e52-9a06-1f4c8b3d5e27",
                      "name": "Acme ISP"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery."
          }
        }
      }
    },
    "invoice.paid": {
      "post": {
        "summary": "Invoice fully paid",
        "description": "Requires the `invoices:read` ability when the endpoint was created by an API key.",
        "tags": [
          "Webhooks"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEnvelope"
              },
              "example": {
                "id": "evt_1f0b6a3c-9d4e-4a1b-8c22-5f7e0d9a1234",
                "topic": "invoice.paid",
                "created_at": "2026-09-06T12:00:00Z",
                "api_version": "2026-09-01",
                "organization_id": "7c2d1e8a-3b45-4f9c-a0d1-6e8b2f4a9c11",
                "data": {
                  "invoice": {
                    "id": "e3b1c7d2-5a64-4f80-9b13-2c8d5e7f1a90",
                    "number": "INV-001204",
                    "status": "paid",
                    "currency": "USD",
                    "total": 120,
                    "balance": 0,
                    "issue_date": "2026-09-01",
                    "due_date": "2026-09-15",
                    "client": {
                      "id": "b8f2a1c4-7d39-4e52-9a06-1f4c8b3d5e27",
                      "name": "Acme ISP"
                    }
                  },
                  "payment": {
                    "id": "a41d6f92-8c07-4b3e-95a2-0d7e6c1b8f43",
                    "amount": 120,
                    "currency": "USD",
                    "payment_method": "cash",
                    "date": "2026-09-06T09:12:44Z",
                    "client": {
                      "id": "b8f2a1c4-7d39-4e52-9a06-1f4c8b3d5e27",
                      "name": "Acme ISP"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery."
          }
        }
      }
    },
    "invoice.voided": {
      "post": {
        "summary": "Invoice voided",
        "description": "Requires the `invoices:read` ability when the endpoint was created by an API key.",
        "tags": [
          "Webhooks"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEnvelope"
              },
              "example": {
                "id": "evt_1f0b6a3c-9d4e-4a1b-8c22-5f7e0d9a1234",
                "topic": "invoice.voided",
                "created_at": "2026-09-06T12:00:00Z",
                "api_version": "2026-09-01",
                "organization_id": "7c2d1e8a-3b45-4f9c-a0d1-6e8b2f4a9c11",
                "data": {
                  "invoice": {
                    "id": "e3b1c7d2-5a64-4f80-9b13-2c8d5e7f1a90",
                    "number": "INV-001204",
                    "status": "paid",
                    "currency": "USD",
                    "total": 120,
                    "balance": 0,
                    "issue_date": "2026-09-01",
                    "due_date": "2026-09-15",
                    "client": {
                      "id": "b8f2a1c4-7d39-4e52-9a06-1f4c8b3d5e27",
                      "name": "Acme ISP"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery."
          }
        }
      }
    },
    "payment.created": {
      "post": {
        "summary": "Payment recorded",
        "description": "Requires the `client_payments:read` ability when the endpoint was created by an API key.",
        "tags": [
          "Webhooks"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEnvelope"
              },
              "example": {
                "id": "evt_1f0b6a3c-9d4e-4a1b-8c22-5f7e0d9a1234",
                "topic": "payment.created",
                "created_at": "2026-09-06T12:00:00Z",
                "api_version": "2026-09-01",
                "organization_id": "7c2d1e8a-3b45-4f9c-a0d1-6e8b2f4a9c11",
                "data": {
                  "payment": {
                    "id": "a41d6f92-8c07-4b3e-95a2-0d7e6c1b8f43",
                    "amount": 120,
                    "currency": "USD",
                    "payment_method": "cash",
                    "date": "2026-09-06T09:12:44Z",
                    "client": {
                      "id": "b8f2a1c4-7d39-4e52-9a06-1f4c8b3d5e27",
                      "name": "Acme ISP"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery."
          }
        }
      }
    },
    "payment.deleted": {
      "post": {
        "summary": "Payment deleted",
        "description": "Requires the `client_payments:read` ability when the endpoint was created by an API key.",
        "tags": [
          "Webhooks"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEnvelope"
              },
              "example": {
                "id": "evt_1f0b6a3c-9d4e-4a1b-8c22-5f7e0d9a1234",
                "topic": "payment.deleted",
                "created_at": "2026-09-06T12:00:00Z",
                "api_version": "2026-09-01",
                "organization_id": "7c2d1e8a-3b45-4f9c-a0d1-6e8b2f4a9c11",
                "data": {
                  "payment": {
                    "id": "a41d6f92-8c07-4b3e-95a2-0d7e6c1b8f43",
                    "amount": 120,
                    "currency": "USD",
                    "payment_method": "cash",
                    "date": "2026-09-06T09:12:44Z",
                    "client": {
                      "id": "b8f2a1c4-7d39-4e52-9a06-1f4c8b3d5e27",
                      "name": "Acme ISP"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery."
          }
        }
      }
    },
    "client.created": {
      "post": {
        "summary": "Client created",
        "description": "Requires the `clients:read` ability when the endpoint was created by an API key.",
        "tags": [
          "Webhooks"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEnvelope"
              },
              "example": {
                "id": "evt_1f0b6a3c-9d4e-4a1b-8c22-5f7e0d9a1234",
                "topic": "client.created",
                "created_at": "2026-09-06T12:00:00Z",
                "api_version": "2026-09-01",
                "organization_id": "7c2d1e8a-3b45-4f9c-a0d1-6e8b2f4a9c11",
                "data": {
                  "client": {
                    "id": "b8f2a1c4-7d39-4e52-9a06-1f4c8b3d5e27",
                    "username": "acme-isp",
                    "name": "Acme ISP",
                    "email": "billing@acme.example",
                    "phone_number": "+9613000000",
                    "active": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery."
          }
        }
      }
    },
    "client.updated": {
      "post": {
        "summary": "Client updated",
        "description": "Requires the `clients:read` ability when the endpoint was created by an API key.",
        "tags": [
          "Webhooks"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEnvelope"
              },
              "example": {
                "id": "evt_1f0b6a3c-9d4e-4a1b-8c22-5f7e0d9a1234",
                "topic": "client.updated",
                "created_at": "2026-09-06T12:00:00Z",
                "api_version": "2026-09-01",
                "organization_id": "7c2d1e8a-3b45-4f9c-a0d1-6e8b2f4a9c11",
                "data": {
                  "client": {
                    "id": "b8f2a1c4-7d39-4e52-9a06-1f4c8b3d5e27",
                    "username": "acme-isp",
                    "name": "Acme ISP",
                    "email": "billing@acme.example",
                    "phone_number": "+9613000000",
                    "active": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery."
          }
        }
      }
    },
    "ticket.created": {
      "post": {
        "summary": "Ticket created",
        "description": "Requires the `tickets:read` ability when the endpoint was created by an API key.",
        "tags": [
          "Webhooks"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookTicketCreated"
              },
              "example": {
                "id": "evt_1f0b6a3c-9d4e-4a1b-8c22-5f7e0d9a1234",
                "topic": "ticket.created",
                "created_at": "2026-09-06T12:00:00Z",
                "api_version": "2026-09-01",
                "organization_id": "7c2d1e8a-3b45-4f9c-a0d1-6e8b2f4a9c11",
                "data": {
                  "ticket": {
                    "id": "9a7c3e1f-2b4d-4e6f-8a1c-3d5e7f9b1c2d",
                    "ticket_number": "TKT-0123",
                    "external_ref": "crm-48213",
                    "status": "New",
                    "status_category": "new",
                    "board_id": "4c6e8a0b-1d3f-4a5c-9e7b-2f4a6c8e0b1d",
                    "client_id": "b8f2a1c4-7d39-4e52-9a06-1f4c8b3d5e27",
                    "created_via": "api",
                    "job_type": "installation",
                    "technician_id": null,
                    "scheduled_at": null,
                    "sla_due_at": "2026-10-15T09:00:00Z",
                    "archived_at": null,
                    "updated_at": "2026-10-13T09:15:00Z"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery."
          }
        }
      }
    },
    "ticket.status_changed": {
      "post": {
        "summary": "Ticket status changed",
        "description": "Requires the `tickets:read` ability when the endpoint was created by an API key.",
        "tags": [
          "Webhooks"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookTicketStatusChanged"
              },
              "example": {
                "id": "evt_1f0b6a3c-9d4e-4a1b-8c22-5f7e0d9a1234",
                "topic": "ticket.status_changed",
                "created_at": "2026-09-06T12:00:00Z",
                "api_version": "2026-09-01",
                "organization_id": "7c2d1e8a-3b45-4f9c-a0d1-6e8b2f4a9c11",
                "data": {
                  "ticket": {
                    "id": "9a7c3e1f-2b4d-4e6f-8a1c-3d5e7f9b1c2d",
                    "ticket_number": "TKT-0123",
                    "external_ref": "crm-48213",
                    "status": "Done",
                    "status_category": "done",
                    "board_id": "4c6e8a0b-1d3f-4a5c-9e7b-2f4a6c8e0b1d",
                    "client_id": "b8f2a1c4-7d39-4e52-9a06-1f4c8b3d5e27",
                    "created_via": "api",
                    "job_type": "installation",
                    "technician_id": null,
                    "scheduled_at": null,
                    "sla_due_at": "2026-10-15T09:00:00Z",
                    "archived_at": null,
                    "updated_at": "2026-10-13T09:15:00Z"
                  },
                  "from": {
                    "column": "In progress",
                    "category": "in_progress"
                  },
                  "to": {
                    "column": "Done",
                    "category": "done"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery."
          }
        }
      }
    },
    "ticket.assigned": {
      "post": {
        "summary": "Ticket assigned",
        "description": "Requires the `tickets:read` ability when the endpoint was created by an API key.",
        "tags": [
          "Webhooks"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookTicketAssigned"
              },
              "example": {
                "id": "evt_1f0b6a3c-9d4e-4a1b-8c22-5f7e0d9a1234",
                "topic": "ticket.assigned",
                "created_at": "2026-09-06T12:00:00Z",
                "api_version": "2026-09-01",
                "organization_id": "7c2d1e8a-3b45-4f9c-a0d1-6e8b2f4a9c11",
                "data": {
                  "ticket": {
                    "id": "9a7c3e1f-2b4d-4e6f-8a1c-3d5e7f9b1c2d",
                    "ticket_number": "TKT-0123",
                    "external_ref": "crm-48213",
                    "status": "New",
                    "status_category": "new",
                    "board_id": "4c6e8a0b-1d3f-4a5c-9e7b-2f4a6c8e0b1d",
                    "client_id": "b8f2a1c4-7d39-4e52-9a06-1f4c8b3d5e27",
                    "created_via": "api",
                    "job_type": "installation",
                    "technician_id": null,
                    "scheduled_at": null,
                    "sla_due_at": "2026-10-15T09:00:00Z",
                    "archived_at": null,
                    "updated_at": "2026-10-13T09:15:00Z"
                  },
                  "assigned_user_ids": [
                    "5d1e2f3a-4b5c-4d6e-8f70-1a2b3c4d5e6f"
                  ],
                  "added_user_ids": [
                    "5d1e2f3a-4b5c-4d6e-8f70-1a2b3c4d5e6f"
                  ],
                  "removed_user_ids": []
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery."
          }
        }
      }
    },
    "ticket.archived": {
      "post": {
        "summary": "Ticket archived",
        "description": "Requires the `tickets:read` ability when the endpoint was created by an API key.",
        "tags": [
          "Webhooks"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookTicketArchived"
              },
              "example": {
                "id": "evt_1f0b6a3c-9d4e-4a1b-8c22-5f7e0d9a1234",
                "topic": "ticket.archived",
                "created_at": "2026-09-06T12:00:00Z",
                "api_version": "2026-09-01",
                "organization_id": "7c2d1e8a-3b45-4f9c-a0d1-6e8b2f4a9c11",
                "data": {
                  "ticket": {
                    "id": "9a7c3e1f-2b4d-4e6f-8a1c-3d5e7f9b1c2d",
                    "ticket_number": "TKT-0123",
                    "external_ref": "crm-48213",
                    "status": "Done",
                    "status_category": "done",
                    "board_id": "4c6e8a0b-1d3f-4a5c-9e7b-2f4a6c8e0b1d",
                    "client_id": "b8f2a1c4-7d39-4e52-9a06-1f4c8b3d5e27",
                    "created_via": "api",
                    "job_type": "installation",
                    "technician_id": null,
                    "scheduled_at": null,
                    "sla_due_at": "2026-10-15T09:00:00Z",
                    "archived_at": "2026-10-13T03:40:00Z",
                    "updated_at": "2026-10-13T09:15:00Z"
                  },
                  "auto": true
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery."
          }
        }
      }
    },
    "ticket.scheduled": {
      "post": {
        "summary": "Ticket scheduled",
        "description": "Requires the `tickets:read` ability when the endpoint was created by an API key.",
        "tags": [
          "Webhooks"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookTicketScheduled"
              },
              "example": {
                "id": "evt_1f0b6a3c-9d4e-4a1b-8c22-5f7e0d9a1234",
                "topic": "ticket.scheduled",
                "created_at": "2026-09-06T12:00:00Z",
                "api_version": "2026-09-01",
                "organization_id": "7c2d1e8a-3b45-4f9c-a0d1-6e8b2f4a9c11",
                "data": {
                  "ticket": {
                    "id": "9a7c3e1f-2b4d-4e6f-8a1c-3d5e7f9b1c2d",
                    "ticket_number": "TKT-0123",
                    "external_ref": "crm-48213",
                    "status": "Scheduled",
                    "status_category": "scheduled",
                    "board_id": "4c6e8a0b-1d3f-4a5c-9e7b-2f4a6c8e0b1d",
                    "client_id": "b8f2a1c4-7d39-4e52-9a06-1f4c8b3d5e27",
                    "created_via": "api",
                    "job_type": "installation",
                    "technician_id": null,
                    "scheduled_at": null,
                    "sla_due_at": "2026-10-15T09:00:00Z",
                    "archived_at": null,
                    "updated_at": "2026-10-13T09:15:00Z"
                  },
                  "technician_id": "5d1e2f3a-4b5c-4d6e-8f70-1a2b3c4d5e6f",
                  "scheduled_at": "2026-10-14T11:00:00Z",
                  "scheduled_until": "2026-10-14T13:00:00Z",
                  "auto": false,
                  "override": false
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery."
          }
        }
      }
    },
    "ticket.completed": {
      "post": {
        "summary": "Ticket completed",
        "description": "Requires the `tickets:read` ability when the endpoint was created by an API key.",
        "tags": [
          "Webhooks"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookTicketCompleted"
              },
              "example": {
                "id": "evt_1f0b6a3c-9d4e-4a1b-8c22-5f7e0d9a1234",
                "topic": "ticket.completed",
                "created_at": "2026-09-06T12:00:00Z",
                "api_version": "2026-09-01",
                "organization_id": "7c2d1e8a-3b45-4f9c-a0d1-6e8b2f4a9c11",
                "data": {
                  "ticket": {
                    "id": "9a7c3e1f-2b4d-4e6f-8a1c-3d5e7f9b1c2d",
                    "ticket_number": "TKT-0123",
                    "external_ref": "crm-48213",
                    "status": "Done",
                    "status_category": "done",
                    "board_id": "4c6e8a0b-1d3f-4a5c-9e7b-2f4a6c8e0b1d",
                    "client_id": "b8f2a1c4-7d39-4e52-9a06-1f4c8b3d5e27",
                    "created_via": "api",
                    "job_type": "installation",
                    "technician_id": null,
                    "scheduled_at": null,
                    "sla_due_at": "2026-10-15T09:00:00Z",
                    "archived_at": null,
                    "updated_at": "2026-10-13T09:15:00Z"
                  },
                  "outcome": "done",
                  "invoice_id": "7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d",
                  "resolved_at": "2026-10-14T12:40:00Z"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery."
          }
        }
      }
    },
    "ticket.cancelled": {
      "post": {
        "summary": "Ticket cancelled",
        "description": "Requires the `tickets:read` ability when the endpoint was created by an API key.",
        "tags": [
          "Webhooks"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookTicketCancelled"
              },
              "example": {
                "id": "evt_1f0b6a3c-9d4e-4a1b-8c22-5f7e0d9a1234",
                "topic": "ticket.cancelled",
                "created_at": "2026-09-06T12:00:00Z",
                "api_version": "2026-09-01",
                "organization_id": "7c2d1e8a-3b45-4f9c-a0d1-6e8b2f4a9c11",
                "data": {
                  "ticket": {
                    "id": "9a7c3e1f-2b4d-4e6f-8a1c-3d5e7f9b1c2d",
                    "ticket_number": "TKT-0123",
                    "external_ref": "crm-48213",
                    "status": "Cancelled",
                    "status_category": "cancelled",
                    "board_id": "4c6e8a0b-1d3f-4a5c-9e7b-2f4a6c8e0b1d",
                    "client_id": "b8f2a1c4-7d39-4e52-9a06-1f4c8b3d5e27",
                    "created_via": "api",
                    "job_type": "installation",
                    "technician_id": null,
                    "scheduled_at": null,
                    "sla_due_at": "2026-10-15T09:00:00Z",
                    "archived_at": null,
                    "updated_at": "2026-10-13T09:15:00Z"
                  },
                  "reason": "Customer changed their mind",
                  "closed_at": "2026-10-14T09:15:00Z"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery."
          }
        }
      }
    },
    "webhook.ping": {
      "post": {
        "summary": "Test delivery",
        "description": "Sent by `POST /v1/webhooks/{uuid}/test`. Not subscribable; every endpoint can receive it.",
        "tags": [
          "Webhooks"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEnvelope"
              },
              "example": {
                "id": "evt_1f0b6a3c-9d4e-4a1b-8c22-5f7e0d9a1234",
                "topic": "webhook.ping",
                "created_at": "2026-09-06T12:00:00Z",
                "api_version": "2026-09-01",
                "organization_id": "7c2d1e8a-3b45-4f9c-a0d1-6e8b2f4a9c11",
                "data": {
                  "message": "This is a test delivery from PROradius.",
                  "endpoint_id": "3f9a2c1e-6b7d-4e8f-9a0b-1c2d3e4f5a6b"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the delivery."
          }
        }
      }
    }
  },
  "tags": [
    {
      "name": "Service jobs",
      "description": "Tickets and service jobs: create, read, update, move and archive. Needs the Ticketing add-on."
    },
    {
      "name": "Scheduling",
      "description": "Book a technician and a visit window, then start the job."
    },
    {
      "name": "Completion",
      "description": "Complete, bill or cancel a job."
    },
    {
      "name": "Job types",
      "description": "Templates that set priority, SLA, checklist and billing mode."
    },
    {
      "name": "Boards",
      "description": "Boards and their columns. Every job lives on a board."
    },
    {
      "name": "Clients",
      "description": "Customers of the organization."
    },
    {
      "name": "Webhooks",
      "description": "Endpoints, topics and deliveries. Events are signed with HMAC-SHA256."
    }
  ],
  "x-tagGroups": [
    {
      "name": "Service jobs",
      "tags": [
        "Service jobs",
        "Scheduling",
        "Completion",
        "Job types",
        "Boards"
      ]
    },
    {
      "name": "Clients",
      "tags": [
        "Clients"
      ]
    },
    {
      "name": "Webhooks",
      "tags": [
        "Webhooks"
      ]
    }
  ]
}
