{"openapi":"3.0.3","info":{"title":"Servicebay API","description":"The Servicebay API provides programmatic access to an organisation's\ncustomers, jobs, catalogue, quotes, invoices, calendar, recurring\nagreements, and compliance forms.\n\n## Authentication\n\nREST accepts `X-API-Key: sk_live_…` or an OAuth 2.1 access token\n(`Authorization: Bearer …`). Tokens are audience-bound to\n`https://oauth.servicebay.io/mcp`; this API accepts that audience.\nDiscover the authorization server from\n`/.well-known/oauth-protected-resource` (RFC 9728). PKCE S256 is\nrequired. The `resource` parameter is optional and defaults to the MCP\nresource; REST origin aliases are canonicalised.\n\nAPI keys are scoped (`entity:read|write|delete` or bundles\n`read` / `write` / `full`), may expire, and declare `allowedUses`\n(`rest`, `mcp`). Manage them from the [Developer Dashboard](/develop)\n(Firebase bearer + TOTP).\n\n## Rate Limiting\n\n**100 requests per minute** per API key and per OAuth grant. Production\nrequires Upstash Redis — missing configuration returns **503**. Headers:\n\n- `X-RateLimit-Limit`: Maximum requests per minute\n- `X-RateLimit-Remaining`: Remaining requests in the current window\n- `X-RateLimit-Reset`: Unix timestamp when the rate limit resets\n- `Retry-After`: Seconds until the window resets (on **429** only)\n\n## Errors\n\nThe API uses standard HTTP status codes to indicate success or failure:\n\n| Status Code | Description |\n|-------------|-------------|\n| 200 | Success |\n| 201 | Created |\n| 400 | Bad Request — invalid JSON, `limit`, ISO date, path id, or `startAfter` |\n| 401 | Unauthorized — invalid or missing credential |\n| 403 | Forbidden — wrong org, insufficient scope, use/IP not allowed, or not Pro/trial |\n| 404 | Not Found |\n| 409 | Conflict — form gates, series shape, quote already invoiced, occurrence rules |\n| 413 | Payload Too Large - Request body exceeds 1 MB |\n| 415 | Unsupported Media Type - `Content-Type` must be `application/json` |\n| 429 | Too Many Requests - Rate limit exceeded |\n| 500 | Internal Server Error |\n| 503 | Service Unavailable - Temporary outage; retry with backoff |\n\n`5xx` error bodies include a `requestId` to quote to support.\n\n### Pro subscription required\n\nThe API is a **Pro** feature. An organisation qualifies when entitlement\nis `pro` **or** in-app `trial`. Others return **403** with:\n\n```json\n{\n  \"success\": false,\n  \"error\": \"This organisation does not have an active Pro subscription. Upgrade to Pro to use the Servicebay API.\"\n}\n```\n","version":"1.0.0","contact":{"name":"Servicebay Support","url":"https://servicebay.io/support","email":"support@servicebay.io"},"license":{"name":"Proprietary","url":"https://servicebay.io/terms"}},"servers":[{"url":"https://developer.servicebay.io/api/v1","description":"Production API"},{"url":"http://localhost:3000/api/v1","description":"Local development"}],"security":[{"apiKey":[]},{"oauth2":[]}],"tags":[{"name":"Organisations","description":"Organisation management endpoints"},{"name":"Customers","description":"Customer management and lookup endpoints"},{"name":"Tickets","description":"Service jobs (a.k.a. tickets) — create, schedule, and update jobs"},{"name":"Services","description":"Reusable service templates (pricing, warranty defaults)"},{"name":"Inventory","description":"Stock items and parts catalogue"},{"name":"Quotes","description":"Customer quotes"},{"name":"Invoices","description":"Customer invoices"},{"name":"Calendar Events","description":"Calendar events — standalone or linked to a job"},{"name":"Devices","description":"Customer devices/assets (subcollection of a customer)"},{"name":"Payments","description":"Payments and refunds recorded against invoices"},{"name":"Stations","description":"Workstations/bays that jobs can be assigned to"},{"name":"Tax Rates","description":"Tax rates used on services, inventory, quotes, and invoices"},{"name":"Job Statuses","description":"Configurable job status values (a.k.a. ticket statuses)"},{"name":"Messages","description":"Job timeline messages"},{"name":"Recurring","description":"Recurring service agreements and occurrence actions"},{"name":"Categories","description":"Inventory and customer-asset categories"},{"name":"Forms","description":"Read-only compliance forms, rules, and submissions"},{"name":"Members","description":"Organisation members (read-only)"},{"name":"API Keys","description":"API key management (requires Firebase Auth)"},{"name":"OAuth","description":"Authorization-server endpoints hosted at https://oauth.servicebay.io"}],"paths":{"/organisations/{orgId}":{"get":{"tags":["Organisations"],"summary":"Get organisation details","description":"Retrieve details for the organisation associated with your API key.","operationId":"getOrganisation","security":[{"apiKey":[]},{"oauth2":["organisation:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"}],"responses":{"200":{"description":"Organisation details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganisationResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"tags":["Organisations"],"summary":"Update organisation","description":"Update organisation details.","operationId":"updateOrganisation","security":[{"apiKey":[]},{"oauth2":["organisation:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganisationUpdate"}}}},"responses":{"200":{"description":"Updated organisation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganisationResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/organisations/{orgId}/customers":{"get":{"tags":["Customers"],"summary":"List customers","description":"Retrieve a paginated list of customers for the organisation.","operationId":"listCustomers","security":[{"apiKey":[]},{"oauth2":["customers:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/startAfter"},{"name":"search","in":"query","description":"Search customers by name, email, or business name","schema":{"type":"string"}}],"responses":{"200":{"description":"List of customers","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Customers"],"summary":"Create customer","description":"Create a new customer in the organisation.","operationId":"createCustomer","security":[{"apiKey":[]},{"oauth2":["customers:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerCreate"},"example":{"firstName":"John","lastName":"Doe","email":"john.doe@example.com","phone":"+1234567890","businessName":"Acme Corp"}}}},"responses":{"201":{"description":"Created customer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/organisations/{orgId}/customers/lookup":{"get":{"tags":["Customers"],"summary":"Look up customer by phone or email","description":"Server-side exact-match customer lookup. Provide `phone`, `email`, or\nboth. Returns up to 10 matches per identifier (deduplicated). Designed\nfor customer-facing intake forms that need to find an existing record\nbefore booking a job.\n\nReturns `404` when no customer matches.\n","operationId":"lookupCustomer","security":[{"apiKey":[]},{"oauth2":["customers:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"name":"phone","in":"query","description":"Exact phone number to match","schema":{"type":"string"}},{"name":"email","in":"query","description":"Exact email address to match","schema":{"type":"string","format":"email"}}],"responses":{"200":{"description":"One or more matching customers","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"matches":{"type":"array","items":{"$ref":"#/components/schemas/Customer"}},"count":{"type":"integer"}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/organisations/{orgId}/customers/{customerId}":{"get":{"tags":["Customers"],"summary":"Get customer","description":"Retrieve a specific customer by ID.","operationId":"getCustomer","security":[{"apiKey":[]},{"oauth2":["customers:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/customerId"}],"responses":{"200":{"description":"Customer details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"tags":["Customers"],"summary":"Update customer","description":"Update an existing customer.","operationId":"updateCustomer","security":[{"apiKey":[]},{"oauth2":["customers:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/customerId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerUpdate"}}}},"responses":{"200":{"description":"Updated customer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Customers"],"summary":"Delete customer","description":"Delete a customer from the organisation. Default `cascade=true` also\ndeletes devices, jobs, and those jobs' calendar events. When cascade\nwould delete jobs, the credential must include both `customers:delete`\nand `tickets:delete` (otherwise **403** `insufficient_scope`).\n`cascade=false` returns **409** `CUSTOMER_HAS_TICKETS` if jobs exist.\n","operationId":"deleteCustomer","security":[{"apiKey":[]},{"oauth2":["customers:delete","tickets:delete"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/customerId"},{"name":"cascade","in":"query","required":false,"schema":{"type":"boolean","default":true},"description":"When true, delete the customer's jobs and devices as well."}],"responses":{"200":{"description":"Customer deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessMessage"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/organisations/{orgId}/calendar-events":{"get":{"tags":["Calendar Events"],"summary":"List calendar events","description":"Retrieve a paginated list of calendar events.","operationId":"listCalendarEvents","security":[{"apiKey":[]},{"oauth2":["calendar:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/startAfter"},{"name":"from","in":"query","description":"Filter events starting from this date (ISO 8601)","schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","description":"Filter events ending before this date (ISO 8601)","schema":{"type":"string","format":"date-time"}},{"name":"assignedToId","in":"query","description":"Filter by assigned user ID","schema":{"type":"string"}},{"name":"ticketId","in":"query","description":"Filter by associated ticket ID","schema":{"type":"string"}}],"responses":{"200":{"description":"List of calendar events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalendarEventListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Calendar Events"],"summary":"Create calendar event","description":"Create a new calendar event. If `ticketId` is set, the ticket must not\nalready have a linked event (one event per job — prefer the jobs API\nfor schedule changes). A conflict returns **409**.\n","operationId":"createCalendarEvent","security":[{"apiKey":[]},{"oauth2":["calendar:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalendarEventCreate"},"example":{"title":"Service Appointment","from":"2025-01-15T10:00:00Z","to":"2025-01-15T11:00:00Z","allDay":false,"assignedToId":"user123","ticketId":"1"}}}},"responses":{"201":{"description":"Created calendar event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalendarEventResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/organisations/{orgId}/calendar-events/{eventId}":{"get":{"tags":["Calendar Events"],"summary":"Get calendar event","description":"Retrieve a specific calendar event by ID.","operationId":"getCalendarEvent","security":[{"apiKey":[]},{"oauth2":["calendar:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/eventId"}],"responses":{"200":{"description":"Calendar event details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalendarEventResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"tags":["Calendar Events"],"summary":"Update calendar event","description":"Update an existing calendar event. Re-linking to a `ticketId` that\nalready has a different event returns **409**.\n","operationId":"updateCalendarEvent","security":[{"apiKey":[]},{"oauth2":["calendar:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/eventId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalendarEventUpdate"}}}},"responses":{"200":{"description":"Updated calendar event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalendarEventResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}},"delete":{"tags":["Calendar Events"],"summary":"Delete calendar event","description":"Delete a calendar event.","operationId":"deleteCalendarEvent","security":[{"apiKey":[]},{"oauth2":["calendar:delete"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/eventId"}],"responses":{"200":{"description":"Calendar event deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessMessage"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/organisations/{orgId}/tickets":{"get":{"tags":["Tickets"],"summary":"List tickets","description":"Retrieve a paginated list of tickets.","operationId":"listTickets","security":[{"apiKey":[]},{"oauth2":["tickets:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/startAfter"},{"name":"status","in":"query","description":"Filter by ticket status","schema":{"type":"string","enum":["Open","In Progress","Closed"]}},{"name":"customerId","in":"query","description":"Filter by customer ID","schema":{"type":"string"}},{"name":"assignedTechnician","in":"query","description":"Filter by assigned technician ID","schema":{"type":"string"}}],"responses":{"200":{"description":"List of tickets","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TicketListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Tickets"],"summary":"Create ticket","description":"Create a new service ticket.","operationId":"createTicket","security":[{"apiKey":[]},{"oauth2":["tickets:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TicketCreate"},"example":{"customerId":"customer123","customerName":"John Doe","customerEmail":"john@example.com","serviceRequired":"Device Repair","status":"Open"}}}},"responses":{"201":{"description":"Created ticket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TicketResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/organisations/{orgId}/tickets/{ticketId}":{"get":{"tags":["Tickets"],"summary":"Get ticket","description":"Retrieve a specific ticket by ID.","operationId":"getTicket","security":[{"apiKey":[]},{"oauth2":["tickets:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/ticketId"}],"responses":{"200":{"description":"Ticket details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TicketResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"tags":["Tickets"],"summary":"Update ticket","description":"Update an existing ticket.","operationId":"updateTicket","security":[{"apiKey":[]},{"oauth2":["tickets:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/ticketId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TicketUpdate"}}}},"responses":{"200":{"description":"Updated ticket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TicketResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Tickets"],"summary":"Delete ticket","description":"Delete a ticket.","operationId":"deleteTicket","security":[{"apiKey":[]},{"oauth2":["tickets:delete"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/ticketId"}],"responses":{"200":{"description":"Ticket deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessMessage"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/organisations/{orgId}/services":{"get":{"tags":["Services"],"summary":"List services","description":"Retrieve a paginated list of service templates.","operationId":"listServices","security":[{"apiKey":[]},{"oauth2":["services:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/startAfter"},{"name":"search","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"List of services","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Services"],"summary":"Create service","operationId":"createService","security":[{"apiKey":[]},{"oauth2":["services:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceCreate"}}}},"responses":{"201":{"description":"Created service","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/organisations/{orgId}/services/{serviceId}":{"parameters":[{"$ref":"#/components/parameters/orgId"},{"name":"serviceId","in":"path","required":true,"schema":{"type":"string"}}],"get":{"tags":["Services"],"summary":"Get service","operationId":"getService","security":[{"apiKey":[]},{"oauth2":["services:read"]}],"responses":{"200":{"description":"Service details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"tags":["Services"],"summary":"Update service","operationId":"updateService","security":[{"apiKey":[]},{"oauth2":["services:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUpdate"}}}},"responses":{"200":{"description":"Updated service","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Services"],"summary":"Delete service","operationId":"deleteService","security":[{"apiKey":[]},{"oauth2":["services:delete"]}],"responses":{"200":{"description":"Service deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessMessage"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/organisations/{orgId}/inventory":{"get":{"tags":["Inventory"],"summary":"List inventory items","operationId":"listInventory","security":[{"apiKey":[]},{"oauth2":["inventory:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/startAfter"},{"name":"categoryId","in":"query","schema":{"type":"string"}},{"name":"sku","in":"query","description":"Exact SKU lookup","schema":{"type":"string"}},{"name":"search","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"List of inventory items","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Inventory"],"summary":"Create inventory item","operationId":"createInventoryItem","security":[{"apiKey":[]},{"oauth2":["inventory:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryItemCreate"}}}},"responses":{"201":{"description":"Created inventory item","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryItemResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/organisations/{orgId}/inventory/{itemId}":{"parameters":[{"$ref":"#/components/parameters/orgId"},{"name":"itemId","in":"path","required":true,"schema":{"type":"string"}}],"get":{"tags":["Inventory"],"summary":"Get inventory item","operationId":"getInventoryItem","security":[{"apiKey":[]},{"oauth2":["inventory:read"]}],"responses":{"200":{"description":"Inventory item details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryItemResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"tags":["Inventory"],"summary":"Update inventory item","operationId":"updateInventoryItem","security":[{"apiKey":[]},{"oauth2":["inventory:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryItemUpdate"}}}},"responses":{"200":{"description":"Updated inventory item","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryItemResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Inventory"],"summary":"Delete inventory item","operationId":"deleteInventoryItem","security":[{"apiKey":[]},{"oauth2":["inventory:delete"]}],"responses":{"200":{"description":"Inventory item deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessMessage"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/organisations/{orgId}/quotes":{"get":{"tags":["Quotes"],"summary":"List quotes","operationId":"listQuotes","security":[{"apiKey":[]},{"oauth2":["quotes:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/startAfter"},{"name":"customerId","in":"query","schema":{"type":"string"}},{"name":"ticketId","in":"query","schema":{"type":"string"}},{"name":"accepted","in":"query","schema":{"type":"boolean"}}],"responses":{"200":{"description":"List of quotes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Quotes"],"summary":"Create quote","operationId":"createQuote","security":[{"apiKey":[]},{"oauth2":["quotes:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteCreate"}}}},"responses":{"201":{"description":"Created quote","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/organisations/{orgId}/quotes/{quoteId}":{"parameters":[{"$ref":"#/components/parameters/orgId"},{"name":"quoteId","in":"path","required":true,"schema":{"type":"string"}}],"get":{"tags":["Quotes"],"summary":"Get quote","operationId":"getQuote","security":[{"apiKey":[]},{"oauth2":["quotes:read"]}],"responses":{"200":{"description":"Quote details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteResponse"}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"tags":["Quotes"],"summary":"Update quote","operationId":"updateQuote","security":[{"apiKey":[]},{"oauth2":["quotes:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteUpdate"}}}},"responses":{"200":{"description":"Updated quote","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteResponse"}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Quotes"],"summary":"Delete quote","operationId":"deleteQuote","security":[{"apiKey":[]},{"oauth2":["quotes:delete"]}],"responses":{"200":{"description":"Quote deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessMessage"}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/organisations/{orgId}/invoices":{"get":{"tags":["Invoices"],"summary":"List invoices","operationId":"listInvoices","security":[{"apiKey":[]},{"oauth2":["invoices:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/startAfter"},{"name":"customerId","in":"query","schema":{"type":"string"}},{"name":"ticketId","in":"query","schema":{"type":"string"}},{"name":"paid","in":"query","schema":{"type":"boolean"}}],"responses":{"200":{"description":"List of invoices","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Invoices"],"summary":"Create invoice","operationId":"createInvoice","security":[{"apiKey":[]},{"oauth2":["invoices:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceCreate"}}}},"responses":{"201":{"description":"Created invoice","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/organisations/{orgId}/invoices/{invoiceId}":{"parameters":[{"$ref":"#/components/parameters/orgId"},{"name":"invoiceId","in":"path","required":true,"schema":{"type":"string"}}],"get":{"tags":["Invoices"],"summary":"Get invoice","operationId":"getInvoice","security":[{"apiKey":[]},{"oauth2":["invoices:read"]}],"responses":{"200":{"description":"Invoice details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceResponse"}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"tags":["Invoices"],"summary":"Update invoice","operationId":"updateInvoice","security":[{"apiKey":[]},{"oauth2":["invoices:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceUpdate"}}}},"responses":{"200":{"description":"Updated invoice","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceResponse"}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Invoices"],"summary":"Delete invoice","operationId":"deleteInvoice","security":[{"apiKey":[]},{"oauth2":["invoices:delete"]}],"responses":{"200":{"description":"Invoice deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessMessage"}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/organisations/{orgId}/customers/{customerId}/devices":{"get":{"tags":["Devices"],"summary":"List customer devices","description":"List the devices/assets belonging to a customer, newest first.","operationId":"listDevices","security":[{"apiKey":[]},{"oauth2":["devices:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/customerId"}],"responses":{"200":{"description":"List of devices","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"tags":["Devices"],"summary":"Create customer device","description":"Add a device/asset to a customer.","operationId":"createDevice","security":[{"apiKey":[]},{"oauth2":["devices:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/customerId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceCreate"},"example":{"type":"Laptop","brand":"Dell","make":"XPS","model":"13 9310","identifier":"SN-12345"}}}},"responses":{"201":{"description":"Created device","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/organisations/{orgId}/customers/{customerId}/devices/{deviceId}":{"get":{"tags":["Devices"],"summary":"Get customer device","operationId":"getDevice","security":[{"apiKey":[]},{"oauth2":["devices:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/customerId"},{"$ref":"#/components/parameters/deviceId"}],"responses":{"200":{"description":"Device","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"tags":["Devices"],"summary":"Update customer device","description":"Update a device. Changes to the type/name are propagated to any job\nthat references this device (the denormalised `customerDeviceType` /\n`customerDeviceName` fields).\n","operationId":"updateDevice","security":[{"apiKey":[]},{"oauth2":["devices:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/customerId"},{"$ref":"#/components/parameters/deviceId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceUpdate"}}}},"responses":{"200":{"description":"Updated device","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Devices"],"summary":"Delete customer device","description":"Delete a device. The `deviceId` reference is cleared from any job that used it.","operationId":"deleteDevice","security":[{"apiKey":[]},{"oauth2":["devices:delete"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/customerId"},{"$ref":"#/components/parameters/deviceId"}],"responses":{"200":{"description":"Device deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessMessage"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/organisations/{orgId}/payments":{"get":{"tags":["Payments"],"summary":"List payments","description":"List payments, optionally filtered by invoice, newest first.","operationId":"listPayments","security":[{"apiKey":[]},{"oauth2":["payments:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/startAfter"},{"name":"invoiceId","in":"query","description":"Only return payments for this invoice","schema":{"type":"string"}}],"responses":{"200":{"description":"List of payments","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentListResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Payments"],"summary":"Record a payment","description":"Record a payment (or a refund, using a negative `amount`) against an\ninvoice. The invoice's paid/deposit/balance flags are recalculated\nautomatically. The referenced invoice must exist.\n","operationId":"createPayment","security":[{"apiKey":[]},{"oauth2":["payments:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentCreate"},"example":{"invoiceId":"abc123","amount":150,"paymentMethod":"card","notes":"Paid in full"}}}},"responses":{"201":{"description":"Created payment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/organisations/{orgId}/payments/{paymentId}":{"get":{"tags":["Payments"],"summary":"Get payment","operationId":"getPayment","security":[{"apiKey":[]},{"oauth2":["payments:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/paymentId"}],"responses":{"200":{"description":"Payment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"tags":["Payments"],"summary":"Update payment","description":"Update a manual payment. The parent invoice's paid status is\nrecalculated. Payments linked to Stripe cannot be modified (`409`).\n","operationId":"updatePayment","security":[{"apiKey":[]},{"oauth2":["payments:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/paymentId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentUpdate"}}}},"responses":{"200":{"description":"Updated payment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}},"delete":{"tags":["Payments"],"summary":"Delete payment","description":"Delete a manual payment. The parent invoice's paid status is\nrecalculated. Payments linked to Stripe cannot be deleted (`409`).\n","operationId":"deletePayment","security":[{"apiKey":[]},{"oauth2":["payments:delete"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/paymentId"}],"responses":{"200":{"description":"Payment deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessMessage"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/organisations/{orgId}/stations":{"get":{"tags":["Stations"],"summary":"List stations","operationId":"listStations","security":[{"apiKey":[]},{"oauth2":["stations:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"}],"responses":{"200":{"description":"List of stations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StationListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Stations"],"summary":"Create station","operationId":"createStation","security":[{"apiKey":[]},{"oauth2":["stations:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StationCreate"},"example":{"name":"Bench 1","index":0,"capacity":1}}}},"responses":{"201":{"description":"Created station","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StationResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/organisations/{orgId}/stations/{stationId}":{"get":{"tags":["Stations"],"summary":"Get station","operationId":"getStation","security":[{"apiKey":[]},{"oauth2":["stations:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/stationId"}],"responses":{"200":{"description":"Station","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StationResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"tags":["Stations"],"summary":"Update station","operationId":"updateStation","security":[{"apiKey":[]},{"oauth2":["stations:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/stationId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StationUpdate"}}}},"responses":{"200":{"description":"Updated station","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StationResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Stations"],"summary":"Delete station","description":"Delete a station. Blocked (`409`) while any active (non-closed) job is assigned to it.","operationId":"deleteStation","security":[{"apiKey":[]},{"oauth2":["stations:delete"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/stationId"}],"responses":{"200":{"description":"Station deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessMessage"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/organisations/{orgId}/tax-rates":{"get":{"tags":["Tax Rates"],"summary":"List tax rates","operationId":"listTaxRates","security":[{"apiKey":[]},{"oauth2":["tax-rates:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"}],"responses":{"200":{"description":"List of tax rates","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaxRateListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Tax Rates"],"summary":"Create tax rate","description":"Create a tax rate. Setting `defaultEnabled` clears the default flag on all other rates.","operationId":"createTaxRate","security":[{"apiKey":[]},{"oauth2":["tax-rates:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaxRateCreate"},"example":{"name":"GST","rate":10,"isInclusive":false,"defaultEnabled":true}}}},"responses":{"201":{"description":"Created tax rate","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaxRateResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/organisations/{orgId}/tax-rates/{taxRateId}":{"get":{"tags":["Tax Rates"],"summary":"Get tax rate","operationId":"getTaxRate","security":[{"apiKey":[]},{"oauth2":["tax-rates:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/taxRateId"}],"responses":{"200":{"description":"Tax rate","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaxRateResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"tags":["Tax Rates"],"summary":"Update tax rate","description":"Update a tax rate. Setting `defaultEnabled` clears the default flag on all other rates.","operationId":"updateTaxRate","security":[{"apiKey":[]},{"oauth2":["tax-rates:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/taxRateId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaxRateUpdate"}}}},"responses":{"200":{"description":"Updated tax rate","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaxRateResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Tax Rates"],"summary":"Delete tax rate","operationId":"deleteTaxRate","security":[{"apiKey":[]},{"oauth2":["tax-rates:delete"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/taxRateId"}],"responses":{"200":{"description":"Tax rate deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessMessage"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/organisations/{orgId}/ticket-statuses":{"get":{"tags":["Job Statuses"],"summary":"List job statuses","operationId":"listTicketStatuses","security":[{"apiKey":[]},{"oauth2":["ticket-statuses:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"}],"responses":{"200":{"description":"List of job statuses","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TicketStatusListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Job Statuses"],"summary":"Create job status","description":"Create a custom job status. API-created statuses are always `type: custom`.","operationId":"createTicketStatus","security":[{"apiKey":[]},{"oauth2":["ticket-statuses:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TicketStatusCreate"},"example":{"name":"Awaiting Parts","color":4283215696,"index":4}}}},"responses":{"201":{"description":"Created job status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TicketStatusResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/organisations/{orgId}/ticket-statuses/{statusId}":{"get":{"tags":["Job Statuses"],"summary":"Get job status","operationId":"getTicketStatus","security":[{"apiKey":[]},{"oauth2":["ticket-statuses:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/statusId"}],"responses":{"200":{"description":"Job status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TicketStatusResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"tags":["Job Statuses"],"summary":"Update job status","description":"Update a job status. `type` cannot be changed via the API.","operationId":"updateTicketStatus","security":[{"apiKey":[]},{"oauth2":["ticket-statuses:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/statusId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TicketStatusUpdate"}}}},"responses":{"200":{"description":"Updated job status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TicketStatusResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Job Statuses"],"summary":"Delete job status","description":"Delete a custom job status. Built-in (`type: default`) statuses\ncannot be deleted (`400`), and a status in use by any job cannot be\ndeleted (`409`).\n","operationId":"deleteTicketStatus","security":[{"apiKey":[]},{"oauth2":["ticket-statuses:delete"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/statusId"}],"responses":{"200":{"description":"Job status deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessMessage"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/organisations/{orgId}/tickets/{ticketId}/services":{"get":{"tags":["Tickets"],"summary":"List job service lines","operationId":"listTicketServices","security":[{"apiKey":[]},{"oauth2":["tickets:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/ticketId"}],"responses":{"200":{"description":"Service lines"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"tags":["Tickets"],"summary":"Add a service line to a job","operationId":"createTicketService","security":[{"apiKey":[]},{"oauth2":["tickets:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/ticketId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceLine"}}}},"responses":{"201":{"description":"Created line"},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/organisations/{orgId}/tickets/{ticketId}/services/{lineId}":{"get":{"tags":["Tickets"],"summary":"Get a job service line","operationId":"getTicketService","security":[{"apiKey":[]},{"oauth2":["tickets:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/ticketId"},{"name":"lineId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Service line"},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"tags":["Tickets"],"summary":"Update a job service line","operationId":"updateTicketService","security":[{"apiKey":[]},{"oauth2":["tickets:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/ticketId"},{"name":"lineId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceLine"}}}},"responses":{"200":{"description":"Updated line"},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Tickets"],"summary":"Delete a job service line","operationId":"deleteTicketService","security":[{"apiKey":[]},{"oauth2":["tickets:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/ticketId"},{"name":"lineId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Deleted"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/organisations/{orgId}/tickets/{ticketId}/inventory":{"get":{"tags":["Tickets"],"summary":"List job inventory lines","operationId":"listTicketInventory","security":[{"apiKey":[]},{"oauth2":["tickets:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/ticketId"}],"responses":{"200":{"description":"Inventory lines"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"tags":["Tickets"],"summary":"Add an inventory line to a job","operationId":"createTicketInventory","security":[{"apiKey":[]},{"oauth2":["tickets:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/ticketId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryLine"}}}},"responses":{"201":{"description":"Created line"},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/organisations/{orgId}/tickets/{ticketId}/inventory/{lineId}":{"get":{"tags":["Tickets"],"summary":"Get a job inventory line","operationId":"getTicketInventory","security":[{"apiKey":[]},{"oauth2":["tickets:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/ticketId"},{"name":"lineId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Inventory line"},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"tags":["Tickets"],"summary":"Update a job inventory line","operationId":"updateTicketInventory","security":[{"apiKey":[]},{"oauth2":["tickets:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/ticketId"},{"name":"lineId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryLine"}}}},"responses":{"200":{"description":"Updated line"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Tickets"],"summary":"Delete a job inventory line","operationId":"deleteTicketInventory","security":[{"apiKey":[]},{"oauth2":["tickets:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/ticketId"},{"name":"lineId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Deleted"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/organisations/{orgId}/tickets/{ticketId}/discount":{"get":{"tags":["Tickets"],"summary":"Get job discount","operationId":"getTicketDiscount","security":[{"apiKey":[]},{"oauth2":["tickets:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/ticketId"}],"responses":{"200":{"description":"Discount or null"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"put":{"tags":["Tickets"],"summary":"Set job discount","operationId":"putTicketDiscount","security":[{"apiKey":[]},{"oauth2":["tickets:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/ticketId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Discount"}}}},"responses":{"200":{"description":"Written discount"},"400":{"$ref":"#/components/responses/BadRequest"}}},"delete":{"tags":["Tickets"],"summary":"Remove job discount","operationId":"deleteTicketDiscount","security":[{"apiKey":[]},{"oauth2":["tickets:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/ticketId"}],"responses":{"200":{"description":"Removed"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/organisations/{orgId}/tickets/{ticketId}/totals":{"get":{"tags":["Tickets"],"summary":"Compute job totals","operationId":"getTicketTotals","security":[{"apiKey":[]},{"oauth2":["tickets:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/ticketId"}],"responses":{"200":{"description":"Computed totals"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/organisations/{orgId}/tickets/{ticketId}/signature":{"get":{"tags":["Tickets"],"summary":"Get job signature","operationId":"getTicketSignature","security":[{"apiKey":[]},{"oauth2":["tickets:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/ticketId"}],"responses":{"200":{"description":"Signature document"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"put":{"tags":["Tickets"],"summary":"Set job signature","operationId":"putTicketSignature","security":[{"apiKey":[]},{"oauth2":["tickets:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/ticketId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"signature":{"type":"string","nullable":true,"maxLength":400000}}}}}},"responses":{"200":{"description":"Updated signature"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/organisations/{orgId}/tickets/{ticketId}/messages":{"get":{"tags":["Messages"],"summary":"List job messages","operationId":"listTicketMessages","security":[{"apiKey":[]},{"oauth2":["messages:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/ticketId"}],"responses":{"200":{"description":"Messages listed oldest first"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Messages"],"summary":"Create a job message","operationId":"createTicketMessage","security":[{"apiKey":[]},{"oauth2":["messages:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/ticketId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageCreate"}}}},"responses":{"201":{"description":"Created message"},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/organisations/{orgId}/tickets/{ticketId}/messages/{messageId}":{"get":{"tags":["Messages"],"summary":"Get a message","operationId":"getTicketMessage","security":[{"apiKey":[]},{"oauth2":["messages:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/ticketId"},{"name":"messageId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Message"},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"tags":["Messages"],"summary":"Update a non-system message","operationId":"updateTicketMessage","security":[{"apiKey":[]},{"oauth2":["messages:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/ticketId"},{"name":"messageId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Updated"},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Messages"],"summary":"Delete a message","operationId":"deleteTicketMessage","security":[{"apiKey":[]},{"oauth2":["messages:delete"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/ticketId"},{"name":"messageId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Deleted"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/organisations/{orgId}/invoices/{invoiceId}/reminders":{"get":{"tags":["Invoices"],"summary":"List invoice payment reminders","operationId":"listInvoiceReminders","security":[{"apiKey":[]},{"oauth2":["invoices:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/invoiceId"}],"responses":{"200":{"description":"Reminders"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"tags":["Invoices"],"summary":"Create an invoice reminder","operationId":"createInvoiceReminder","security":[{"apiKey":[]},{"oauth2":["invoices:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/invoiceId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceReminderWrite"}}}},"responses":{"201":{"description":"Created"},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/organisations/{orgId}/invoices/{invoiceId}/reminders/{reminderId}":{"get":{"tags":["Invoices"],"summary":"Get an invoice reminder","operationId":"getInvoiceReminder","security":[{"apiKey":[]},{"oauth2":["invoices:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/invoiceId"},{"name":"reminderId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Reminder"},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"tags":["Invoices"],"summary":"Update reminder trigger/days (does not write nextSendAt)","operationId":"updateInvoiceReminder","security":[{"apiKey":[]},{"oauth2":["invoices:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/invoiceId"},{"name":"reminderId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Updated"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Invoices"],"summary":"Delete an invoice reminder","operationId":"deleteInvoiceReminder","security":[{"apiKey":[]},{"oauth2":["invoices:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/invoiceId"},{"name":"reminderId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Deleted"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/organisations/{orgId}/quotes/{quoteId}/convert":{"post":{"tags":["Quotes"],"summary":"Convert a quote to an invoice","operationId":"convertQuote","security":[{"apiKey":[]},{"oauth2":["quotes:write","invoices:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/quoteId"},{"name":"force","in":"query","schema":{"type":"boolean"}}],"responses":{"201":{"description":"Created invoice"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/organisations/{orgId}/quotes/{quoteId}/share-link":{"post":{"tags":["Quotes"],"summary":"Mint a public view link for a quote","operationId":"createQuoteShareLink","security":[{"apiKey":[]},{"oauth2":["quotes:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/quoteId"},{"name":"markSent","in":"query","schema":{"type":"boolean","default":true}}],"responses":{"201":{"description":"Share link"},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/organisations/{orgId}/quotes/{quoteId}/share-link/{tokenId}":{"delete":{"tags":["Quotes"],"summary":"Revoke a quote share link","operationId":"deleteQuoteShareLink","security":[{"apiKey":[]},{"oauth2":["quotes:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/quoteId"},{"name":"tokenId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Deleted"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/organisations/{orgId}/invoices/{invoiceId}/share-link":{"post":{"tags":["Invoices"],"summary":"Mint a public view link for an invoice","operationId":"createInvoiceShareLink","security":[{"apiKey":[]},{"oauth2":["invoices:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/invoiceId"},{"name":"markSent","in":"query","schema":{"type":"boolean","default":true}}],"responses":{"201":{"description":"Share link"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/organisations/{orgId}/invoices/{invoiceId}/share-link/{tokenId}":{"delete":{"tags":["Invoices"],"summary":"Revoke an invoice share link","operationId":"deleteInvoiceShareLink","security":[{"apiKey":[]},{"oauth2":["invoices:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/invoiceId"},{"name":"tokenId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Deleted"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/organisations/{orgId}/inventory-categories":{"get":{"tags":["Categories"],"summary":"List inventory categories","operationId":"listInventoryCategories","security":[{"apiKey":[]},{"oauth2":["categories:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"}],"responses":{"200":{"description":"Categories ordered by index"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Categories"],"summary":"Create an inventory category","operationId":"createInventoryCategory","security":[{"apiKey":[]},{"oauth2":["categories:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"}],"responses":{"201":{"description":"Created"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/organisations/{orgId}/inventory-categories/{categoryId}":{"get":{"tags":["Categories"],"summary":"Get an inventory category","operationId":"getInventoryCategory","security":[{"apiKey":[]},{"oauth2":["categories:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"name":"categoryId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Category"},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"tags":["Categories"],"summary":"Update an inventory category","operationId":"updateInventoryCategory","security":[{"apiKey":[]},{"oauth2":["categories:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"name":"categoryId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Updated"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Categories"],"summary":"Delete an inventory category","operationId":"deleteInventoryCategory","security":[{"apiKey":[]},{"oauth2":["categories:delete"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"name":"categoryId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Deleted"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/organisations/{orgId}/asset-categories":{"get":{"tags":["Categories"],"summary":"List customer-asset categories","operationId":"listAssetCategories","security":[{"apiKey":[]},{"oauth2":["categories:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"}],"responses":{"200":{"description":"Categories"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Categories"],"summary":"Create an asset category","operationId":"createAssetCategory","security":[{"apiKey":[]},{"oauth2":["categories:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"}],"responses":{"201":{"description":"Created"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/organisations/{orgId}/asset-categories/{categoryId}":{"get":{"tags":["Categories"],"summary":"Get an asset category","operationId":"getAssetCategory","security":[{"apiKey":[]},{"oauth2":["categories:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"name":"categoryId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Category"},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"tags":["Categories"],"summary":"Update an asset category","operationId":"updateAssetCategory","security":[{"apiKey":[]},{"oauth2":["categories:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"name":"categoryId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Updated"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"delete":{"tags":["Categories"],"summary":"Delete an asset category","operationId":"deleteAssetCategory","security":[{"apiKey":[]},{"oauth2":["categories:delete"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"name":"categoryId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Deleted"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/organisations/{orgId}/members":{"get":{"tags":["Members"],"summary":"List organisation members (read-only projection)","operationId":"listMembers","security":[{"apiKey":[]},{"oauth2":["members:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"}],"responses":{"200":{"description":"Members"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/organisations/{orgId}/form-templates":{"get":{"tags":["Forms"],"summary":"List form templates","operationId":"listFormTemplates","security":[{"apiKey":[]},{"oauth2":["forms:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"}],"responses":{"200":{"description":"Templates"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/organisations/{orgId}/form-templates/{templateId}":{"get":{"tags":["Forms"],"summary":"Get a form template","operationId":"getFormTemplate","security":[{"apiKey":[]},{"oauth2":["forms:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"name":"templateId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Template"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/organisations/{orgId}/form-templates/{templateId}/versions":{"get":{"tags":["Forms"],"summary":"List published form versions","operationId":"listFormVersions","security":[{"apiKey":[]},{"oauth2":["forms:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"name":"templateId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Versions"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/organisations/{orgId}/form-templates/{templateId}/versions/{versionId}":{"get":{"tags":["Forms"],"summary":"Get a form version","operationId":"getFormVersion","security":[{"apiKey":[]},{"oauth2":["forms:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"name":"templateId","in":"path","required":true,"schema":{"type":"string"}},{"name":"versionId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Version"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/organisations/{orgId}/form-templates/{templateId}/versions/{versionId}/translations/{locale}":{"get":{"tags":["Forms"],"summary":"Get a form translation","operationId":"getFormTranslation","security":[{"apiKey":[]},{"oauth2":["forms:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"name":"templateId","in":"path","required":true,"schema":{"type":"string"}},{"name":"versionId","in":"path","required":true,"schema":{"type":"string"}},{"name":"locale","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Translation"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/organisations/{orgId}/form-rules":{"get":{"tags":["Forms"],"summary":"List form attach rules","operationId":"listFormRules","security":[{"apiKey":[]},{"oauth2":["forms:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"}],"responses":{"200":{"description":"Rules"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/organisations/{orgId}/form-submissions":{"get":{"tags":["Forms"],"summary":"List form submissions","operationId":"listFormSubmissions","security":[{"apiKey":[]},{"oauth2":["forms:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"name":"ticketId","in":"query","schema":{"type":"string"}},{"name":"isOpen","in":"query","schema":{"type":"boolean"}},{"name":"customerItemId","in":"query","schema":{"type":"string"}},{"name":"include","in":"query","schema":{"type":"string","enum":["audit"]}}],"responses":{"200":{"description":"Submissions"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/organisations/{orgId}/form-submissions/{submissionId}":{"get":{"tags":["Forms"],"summary":"Get a form submission","operationId":"getFormSubmission","security":[{"apiKey":[]},{"oauth2":["forms:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"name":"submissionId","in":"path","required":true,"schema":{"type":"string"}},{"name":"include","in":"query","schema":{"type":"string","enum":["audit"]}}],"responses":{"200":{"description":"Submission"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/organisations/{orgId}/form-submissions/{submissionId}/signatures":{"get":{"tags":["Forms"],"summary":"List form submission signatures","operationId":"listFormSignatures","security":[{"apiKey":[]},{"oauth2":["forms:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"name":"submissionId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Signatures"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/organisations/{orgId}/form-submissions/{submissionId}/events":{"get":{"tags":["Forms"],"summary":"List form submission events","operationId":"listFormEvents","security":[{"apiKey":[]},{"oauth2":["forms:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"name":"submissionId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Events"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/organisations/{orgId}/recurring-schedules":{"get":{"tags":["Recurring"],"summary":"List recurring schedules","operationId":"listRecurringSchedules","security":[{"apiKey":[]},{"oauth2":["recurring-schedules:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"name":"customerId","in":"query","schema":{"type":"string"}},{"name":"status","in":"query","schema":{"type":"string"}},{"name":"assetId","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Schedules"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Recurring"],"summary":"Create a recurring schedule","operationId":"createRecurringSchedule","security":[{"apiKey":[]},{"oauth2":["recurring-schedules:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"}],"responses":{"201":{"description":"Created"},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/organisations/{orgId}/recurring-schedules/{scheduleId}":{"get":{"tags":["Recurring"],"summary":"Get a recurring schedule","operationId":"getRecurringSchedule","security":[{"apiKey":[]},{"oauth2":["recurring-schedules:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"name":"scheduleId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Schedule"},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"tags":["Recurring"],"summary":"Update a recurring schedule","description":"Series-shape changes require `?resync=thisAndFuture` or return 409 SERIES_SHAPE_CHANGE.","operationId":"updateRecurringSchedule","security":[{"apiKey":[]},{"oauth2":["recurring-schedules:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"name":"scheduleId","in":"path","required":true,"schema":{"type":"string"}},{"name":"resync","in":"query","schema":{"type":"string","enum":["thisAndFuture"]}}],"responses":{"200":{"description":"Updated"},"409":{"$ref":"#/components/responses/Conflict"}}},"delete":{"tags":["Recurring"],"summary":"Delete an unused schedule","operationId":"deleteRecurringSchedule","security":[{"apiKey":[]},{"oauth2":["recurring-schedules:delete"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"name":"scheduleId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Deleted"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/organisations/{orgId}/recurring-schedules/{scheduleId}/pause":{"post":{"tags":["Recurring"],"summary":"Pause a schedule","operationId":"pauseRecurringSchedule","security":[{"apiKey":[]},{"oauth2":["recurring-schedules:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"name":"scheduleId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Paused"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/organisations/{orgId}/recurring-schedules/{scheduleId}/resume":{"post":{"tags":["Recurring"],"summary":"Resume a schedule","operationId":"resumeRecurringSchedule","security":[{"apiKey":[]},{"oauth2":["recurring-schedules:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"name":"scheduleId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Resumed"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/organisations/{orgId}/recurring-schedules/{scheduleId}/end":{"post":{"tags":["Recurring"],"summary":"End a schedule","operationId":"endRecurringSchedule","security":[{"apiKey":[]},{"oauth2":["recurring-schedules:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"name":"scheduleId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Ended"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/organisations/{orgId}/recurring-schedules/{scheduleId}/resync":{"post":{"tags":["Recurring"],"summary":"Resync future occurrences","operationId":"resyncRecurringSchedule","security":[{"apiKey":[]},{"oauth2":["recurring-schedules:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"name":"scheduleId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Resync result"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/organisations/{orgId}/recurring-schedules/{scheduleId}/generate":{"post":{"tags":["Recurring"],"summary":"Generate due occurrences now","operationId":"generateRecurringSchedule","security":[{"apiKey":[]},{"oauth2":["recurring-schedules:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"name":"scheduleId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Generation counts"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/organisations/{orgId}/recurring-schedules/{scheduleId}/occurrences":{"get":{"tags":["Recurring"],"summary":"List occurrences","operationId":"listRecurringOccurrences","security":[{"apiKey":[]},{"oauth2":["recurring-schedules:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"name":"scheduleId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Occurrences"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/organisations/{orgId}/recurring-schedules/{scheduleId}/occurrences/{index}/skip":{"post":{"tags":["Recurring"],"summary":"Skip an occurrence","operationId":"skipOccurrence","security":[{"apiKey":[]},{"oauth2":["recurring-schedules:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"name":"scheduleId","in":"path","required":true,"schema":{"type":"string"}},{"name":"index","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Skipped"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/organisations/{orgId}/recurring-schedules/{scheduleId}/occurrences/{index}/move":{"post":{"tags":["Recurring"],"summary":"Move an occurrence","operationId":"moveOccurrence","security":[{"apiKey":[]},{"oauth2":["recurring-schedules:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"name":"scheduleId","in":"path","required":true,"schema":{"type":"string"}},{"name":"index","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Moved"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/organisations/{orgId}/recurring-schedules/{scheduleId}/occurrences/{index}/resize":{"post":{"tags":["Recurring"],"summary":"Resize an occurrence","operationId":"resizeOccurrence","security":[{"apiKey":[]},{"oauth2":["recurring-schedules:write"]}],"parameters":[{"$ref":"#/components/parameters/orgId"},{"name":"scheduleId","in":"path","required":true,"schema":{"type":"string"}},{"name":"index","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Resized"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/organisations/{orgId}/recurring-presets":{"get":{"tags":["Recurring"],"summary":"List global recurring presets","operationId":"listRecurringPresets","security":[{"apiKey":[]},{"oauth2":["recurring-schedules:read"]}],"parameters":[{"$ref":"#/components/parameters/orgId"}],"responses":{"200":{"description":"Presets"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/api-keys":{"get":{"tags":["API Keys"],"summary":"List API keys","operationId":"listApiKeys","security":[{"bearerAuth":[]}],"parameters":[{"name":"organisationId","in":"query","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,128}$"}}],"responses":{"200":{"description":"API keys for the organisation (secrets are never returned)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyListResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimitExceeded"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}},"post":{"tags":["API Keys"],"summary":"Create an API key","description":"Defaults: scopes `[read]`, `allowedUses` `[rest, mcp]`, expiry 90 days.\nThe plaintext key is returned once. Max 50 active keys per organisation.\nRequires a Firebase ID token with TOTP and an active Pro/trial admin.\n","operationId":"createApiKey","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyCreate"}}}},"responses":{"201":{"description":"Created. Store `data.key` now — it is not shown again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyCreatedResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"429":{"$ref":"#/components/responses/RateLimitExceeded"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/api-keys/{keyId}":{"parameters":[{"$ref":"#/components/parameters/keyId"}],"get":{"tags":["API Keys"],"summary":"Get API key metadata","operationId":"getApiKey","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Key metadata (no secret)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["API Keys"],"summary":"Update an API key","operationId":"updateApiKey","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyUpdate"}}}},"responses":{"200":{"description":"Updated key metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"}}},"delete":{"tags":["API Keys"],"summary":"Revoke an API key","description":"Soft-revoke. Sets active to false and records revokedAt and revokedBy.","operationId":"revokeApiKey","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessMessage"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api-keys/{keyId}/rotate":{"post":{"tags":["API Keys"],"summary":"Rotate an API key","description":"Mints a new key with the same name, scopes, allowlist, and uses.\n`graceMinutes` (0–1440) keeps the previous key valid until that\ninstant; 0 revokes it immediately.\n","operationId":"rotateApiKey","security":[{"bearerAuth":[]}],"parameters":[{"$ref":"#/components/parameters/keyId"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"graceMinutes":{"type":"integer","minimum":0,"maximum":1440,"default":0}}}}}},"responses":{"200":{"description":"New plaintext key. Store `data.key` now.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyRotatedResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/revoke":{"servers":[{"url":"https://oauth.servicebay.io"}],"post":{"tags":["OAuth"],"summary":"Revoke an access or refresh token","description":"RFC 7009 token revocation. Always returns **200** when the request is\nwell-formed, even if the token is unknown or already revoked.\nConfidential clients should authenticate. `POST /token` with `token`\nand no `grant_type` remains accepted for compatibility.\n","operationId":"revokeOAuthToken","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["token"],"properties":{"token":{"type":"string"},"token_type_hint":{"type":"string","enum":["access_token","refresh_token"]}}}}}},"responses":{"200":{"description":"Token revoked or already invalid."},"400":{"description":"Malformed revocation request."},"405":{"description":"Method not allowed. Use POST."}}}}},"components":{"securitySchemes":{"apiKey":{"type":"apiKey","in":"header","name":"X-API-Key","description":"API key for authentication. Get your key from the Developer Dashboard."},"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Firebase ID token for dashboard authentication"},"oauth2":{"type":"oauth2","description":"OAuth 2.1 authorization-code flow. PKCE S256 is mandatory for every client.         Discover this API from https://developer.servicebay.io/.well-known/oauth-protected-resource (RFC 9728). The `resource` parameter is optional and defaults to https://oauth.servicebay.io/mcp; REST origin aliases are canonicalised to that value. Scope v2: `write` does not imply `delete` (legacy grants with scopeVersion 1 still do). Revoke tokens at `https://oauth.servicebay.io/revoke` (RFC 7009), advertised as `revocation_endpoint` on the authorization-server metadata. See /docs/oauth.","flows":{"authorizationCode":{"authorizationUrl":"https://oauth.servicebay.io/authorize","tokenUrl":"https://oauth.servicebay.io/token","refreshUrl":"https://oauth.servicebay.io/token","scopes":{"organisation:read":"Read the organisation profile","organisation:write":"Create and update the organisation profile","tickets:read":"Read jobs (tickets)","tickets:write":"Create and update jobs","tickets:delete":"Delete jobs (also deletes the linked calendar event)","customers:read":"Read customers","customers:write":"Create and update customers","customers:delete":"Delete customers. Default cascade also deletes their jobs and requires tickets:delete when jobs exist.","devices:read":"Read customer devices","devices:write":"Create and update customer devices","devices:delete":"Delete customer devices","services:read":"Read the service catalogue","services:write":"Create and update services","services:delete":"Delete services","inventory:read":"Read inventory","inventory:write":"Create and update inventory","inventory:delete":"Delete inventory","quotes:read":"Read quotes","quotes:write":"Create and update quotes","quotes:delete":"Delete quotes","invoices:read":"Read invoices","invoices:write":"Create and update invoices","invoices:delete":"Delete invoices","payments:read":"Read payments","payments:write":"Create and update payments","payments:delete":"Delete payments (re-opens the invoice balance)","calendar:read":"Read calendar events","calendar:write":"Create and update calendar events","calendar:delete":"Delete calendar events","stations:read":"Read stations","stations:write":"Create and update stations","stations:delete":"Delete stations","tax-rates:read":"Read tax rates","tax-rates:write":"Create and update tax rates","tax-rates:delete":"Delete tax rates","ticket-statuses:read":"Read job status values","ticket-statuses:write":"Create and update job status values","ticket-statuses:delete":"Delete job status values","messages:read":"Read job messages","messages:write":"Create and update job messages","messages:delete":"Delete job messages","recurring-schedules:read":"Read recurring schedules and presets","recurring-schedules:write":"Create and update recurring schedules","recurring-schedules:delete":"Delete recurring schedules","categories:read":"Read inventory and asset categories","categories:write":"Create and update categories","categories:delete":"Delete categories","forms:read":"Read form templates, rules, and submissions","members:read":"Read organisation members","read":"Read all data in the organisation","write":"Read and write all data (does not include delete)","full":"Full access to every resource, including delete","offline_access":"Request a refresh token (accepted; refresh tokens are always issued)"}}}}},"parameters":{"orgId":{"name":"orgId","in":"path","required":true,"description":"Organisation ID","schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,128}$"}},"keyId":{"name":"keyId","in":"path","required":true,"description":"API key document id","schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,128}$"}},"customerId":{"name":"customerId","in":"path","required":true,"description":"Customer ID","schema":{"type":"string"}},"eventId":{"name":"eventId","in":"path","required":true,"description":"Calendar event ID","schema":{"type":"string"}},"ticketId":{"name":"ticketId","in":"path","required":true,"description":"Ticket ID","schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,128}$"}},"invoiceId":{"name":"invoiceId","in":"path","required":true,"description":"Invoice ID","schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,128}$"}},"quoteId":{"name":"quoteId","in":"path","required":true,"description":"Quote ID","schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,128}$"}},"deviceId":{"name":"deviceId","in":"path","required":true,"description":"Customer device ID","schema":{"type":"string"}},"paymentId":{"name":"paymentId","in":"path","required":true,"description":"Payment ID","schema":{"type":"string"}},"stationId":{"name":"stationId","in":"path","required":true,"description":"Station ID","schema":{"type":"string"}},"taxRateId":{"name":"taxRateId","in":"path","required":true,"description":"Tax rate ID","schema":{"type":"string"}},"statusId":{"name":"statusId","in":"path","required":true,"description":"Job status ID","schema":{"type":"string"}},"limit":{"name":"limit","in":"query","description":"Maximum number of items to return (max 100)","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},"startAfter":{"name":"startAfter","in":"query","description":"Cursor for pagination — ID of the last item from the previous page (`[A-Za-z0-9_-]{1,128}`).","schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,128}$","maxLength":128}}},"responses":{"BadRequest":{"description":"Bad Request - Invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"Forbidden — one of:\n- API key / token is valid but not scoped to this organisation\n- OAuth grant lacks the required `entity:action` scope\n- Organisation is not on an active Pro subscription (see error body)\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"wrongOrg":{"summary":"Cross-organisation access","value":{"success":false,"error":"You do not have access to this organisation"}},"insufficientScope":{"summary":"OAuth missing scope","value":{"success":false,"error":"Insufficient scope. This request requires 'invoices:write'."}},"proRequired":{"summary":"Pro subscription required","value":{"success":false,"error":"This organisation does not have an active Pro subscription. Upgrade to Pro to use the Servicebay API."}}}}}},"NotFound":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimitExceeded":{"description":"Too Many Requests - Rate limit exceeded","headers":{"Retry-After":{"description":"Seconds until the rate-limit window resets.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Conflict":{"description":"Conflict - The request could not be completed because the resource is in use or managed elsewhere","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"PayloadTooLarge":{"description":"Payload Too Large - Request body exceeds 1 MB","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UnsupportedMediaType":{"description":"Unsupported Media Type - Content-Type must be application/json","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServiceUnavailable":{"description":"Service Unavailable - Temporary outage; retry with backoff","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"An error occurred"},"requestId":{"type":"string","description":"Quote this to support. Present on 5xx and many 4xx responses."},"code":{"type":"string","description":"Machine-readable error code when the status alone is ambiguous.","enum":["insufficient_scope","unknown_resource","use_not_allowed","ip_not_allowed","FORM_GATE_CREATE","FORM_GATE_TRANSITION","FORM_GATE_DELETE","FORM_GATE_INVOICE","SERIES_SHAPE_CHANGE","QUOTE_ALREADY_INVOICED","SCHEDULE_IN_USE","OCCURRENCE_WORKED","OCCURRENCE_NOT_GENERATED","CUSTOMER_HAS_TICKETS","RECURRING_VISIT","LAST_STATUS","STATUS_IN_USE","STATION_IN_USE","CALENDAR_EVENT_EXISTS","PAYMENT_ACCOUNTING_MANAGED"]},"requiredScopes":{"type":"array","description":"Present on `insufficient_scope`. Scopes that would authorize the request.","items":{"type":"string"}},"data":{"type":"object","description":"Extra context for 409 gate failures (e.g. `{gate, outstanding}` or `{ticketIds}`).","additionalProperties":true}}},"ApiKey":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"organisationId":{"type":"string"},"createdBy":{"type":"string"},"createdAt":{"type":"string","format":"date-time","nullable":true},"lastUsedAt":{"type":"string","format":"date-time","nullable":true},"lastUsedIp":{"type":"string","nullable":true},"requestCount":{"type":"integer"},"active":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time","nullable":true},"revokedAt":{"type":"string","format":"date-time","nullable":true},"revokedBy":{"type":"string","nullable":true},"scopes":{"type":"array","items":{"type":"string"}},"scopeVersion":{"type":"integer","enum":[1,2]},"allowedUses":{"type":"array","items":{"type":"string","enum":["rest","mcp"]}},"ipAllowlist":{"type":"array","items":{"type":"string"}},"keyPrefix":{"type":"string","nullable":true},"legacy":{"type":"boolean"}}},"ApiKeyCreate":{"type":"object","required":["name","organisationId"],"properties":{"name":{"type":"string","minLength":1,"maxLength":80},"organisationId":{"type":"string"},"description":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"},"default":["read"]},"allowedUses":{"type":"array","items":{"type":"string","enum":["rest","mcp"]},"default":["rest","mcp"]},"ipAllowlist":{"type":"array","items":{"type":"string"}},"expiresAt":{"type":"string","format":"date-time","description":"Must be in the future and at most 1 year from now. Mutually exclusive with expiresInDays."},"expiresInDays":{"type":"integer","enum":[30,90,365],"nullable":true,"description":"Day preset. `null` means the key never expires."}}},"ApiKeyUpdate":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"description":{"type":"string","nullable":true},"scopes":{"type":"array","items":{"type":"string"}},"allowedUses":{"type":"array","items":{"type":"string","enum":["rest","mcp"]}},"ipAllowlist":{"type":"array","nullable":true,"items":{"type":"string"}},"expiresAt":{"type":"string","format":"date-time","nullable":true},"active":{"type":"boolean"}}},"ApiKeyResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/ApiKey"}}},"ApiKeyListResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/ApiKey"}}}},"ApiKeyCreatedResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"string"},"key":{"type":"string","description":"Plaintext secret. Shown once."},"keyPrefix":{"type":"string"},"name":{"type":"string"},"organisationId":{"type":"string"},"createdBy":{"type":"string"},"expiresAt":{"type":"string","format":"date-time","nullable":true},"scopes":{"type":"array","items":{"type":"string"}},"allowedUses":{"type":"array","items":{"type":"string"}},"scopeVersion":{"type":"integer"},"message":{"type":"string"}}}}},"ApiKeyRotatedResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"string"},"key":{"type":"string"},"keyPrefix":{"type":"string"},"previousKeyId":{"type":"string"},"previousExpiresAt":{"type":"string","format":"date-time","nullable":true},"message":{"type":"string"}}}}},"SuccessMessage":{"type":"object","required":["success","data"],"properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"message":{"type":"string","example":"Operation completed successfully"}}}}},"Pagination":{"type":"object","properties":{"limit":{"type":"integer"},"hasMore":{"type":"boolean"},"nextCursor":{"type":"string","nullable":true}}},"Organisation":{"type":"object","description":"Organisation profile. Note: the `members` map and `teamAccessCode` field\nare persisted in Firestore but deliberately stripped from API responses\nfor privacy — they do not appear here.\n","properties":{"id":{"type":"string"},"name":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":"string"},"phoneCountryCode":{"type":"string","description":"ISO country code for the phone number (e.g. `AU`)."},"phoneCountryDialCode":{"type":"string","description":"International dial code for the phone number (e.g. `+61`)."},"website":{"type":"string","format":"uri"},"addressLine1":{"type":"string"},"addressLine2":{"type":"string"},"city":{"type":"string"},"state":{"type":"string"},"zip":{"type":"string"},"country":{"type":"string"},"noPhysicalLocation":{"type":"boolean","description":"Set when the organisation has no physical premises (e.g. mobile-only operators)."},"taxId":{"type":"string"},"taxIdLabel":{"type":"string","description":"Label shown alongside `taxId` on invoices and quotes (e.g. `ABN`, `VAT`)."},"registrationNumber":{"type":"string"},"registrationNumberLabel":{"type":"string","description":"Label shown alongside `registrationNumber` (e.g. `ACN`, `Company No.`)."},"defaultInvoiceMessage":{"type":"string","description":"Default message prefilled on new invoices."},"defaultInvoicePaymentAdvice":{"type":"string","description":"Default payment advice prefilled on new invoices."},"defaultInvoiceTerms":{"type":"string","description":"Default terms prefilled on new invoices."},"defaultQuoteMessage":{"type":"string","description":"Default message prefilled on new quotes."},"defaultQuoteTerms":{"type":"string","description":"Default terms prefilled on new quotes."},"termsOfServiceDocument":{"type":"string","description":"URL or path to the organisation-level terms of service document."},"defaultInvoiceRemindersEnabled":{"type":"boolean","description":"Whether new invoices default to having payment reminders enabled."},"defaultInvoiceReminders":{"type":"array","description":"Default set of invoice payment reminders applied to new invoices.","items":{"type":"object","additionalProperties":true}},"defaultQuoteReplyToEnabled":{"type":"boolean"},"defaultQuoteReplyToEmail":{"type":"string","format":"email"},"defaultInvoiceReplyToEnabled":{"type":"boolean"},"defaultInvoiceReplyToEmail":{"type":"string","format":"email"},"defaultTicketReplyToEnabled":{"type":"boolean"},"defaultTicketReplyToEmail":{"type":"string","format":"email"},"timezone":{"type":"string"},"latitude":{"type":"number","nullable":true},"longitude":{"type":"number","nullable":true},"formUnitSystem":{"type":"string","nullable":true,"enum":["metric","imperial"]},"formGateStatuses":{"type":"object","properties":{"start":{"type":"array","items":{"type":"string"}},"completion":{"type":"array","items":{"type":"string"}}}},"defaultRecurringLeadDays":{"type":"integer","nullable":true},"defaultRecurringStatus":{"type":"string","nullable":true},"recurringExpiryHorizonDays":{"type":"integer","nullable":true},"stripeDefaultCurrency":{"type":"string","readOnly":true,"description":"Read-only. Default 3-letter ISO currency for Stripe customer payments."},"onboardingComplete":{"type":"boolean","description":"Read-only. Whether the organisation has finished onboarding."},"customerAssetLabel":{"type":"string","description":"Read-only. Label the organisation uses for a customer's devices/assets."},"createdAt":{"type":"string","format":"date-time"}}},"OrganisationUpdate":{"type":"object","properties":{"name":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":"string"},"phoneCountryCode":{"type":"string"},"phoneCountryDialCode":{"type":"string"},"website":{"type":"string"},"addressLine1":{"type":"string"},"addressLine2":{"type":"string"},"city":{"type":"string"},"state":{"type":"string"},"zip":{"type":"string"},"country":{"type":"string"},"noPhysicalLocation":{"type":"boolean"},"taxId":{"type":"string"},"taxIdLabel":{"type":"string"},"registrationNumber":{"type":"string"},"registrationNumberLabel":{"type":"string"},"defaultInvoiceMessage":{"type":"string"},"defaultInvoicePaymentAdvice":{"type":"string"},"defaultInvoiceTerms":{"type":"string"},"defaultQuoteMessage":{"type":"string"},"defaultQuoteTerms":{"type":"string"},"termsOfServiceDocument":{"type":"string"},"defaultInvoiceRemindersEnabled":{"type":"boolean"},"defaultInvoiceReminders":{"type":"array","items":{"type":"object","additionalProperties":true}},"defaultQuoteReplyToEnabled":{"type":"boolean"},"defaultQuoteReplyToEmail":{"type":"string","format":"email"},"defaultInvoiceReplyToEnabled":{"type":"boolean"},"defaultInvoiceReplyToEmail":{"type":"string","format":"email"},"defaultTicketReplyToEnabled":{"type":"boolean"},"defaultTicketReplyToEmail":{"type":"string","format":"email"},"timezone":{"type":"string","description":"IANA time zone (e.g. Australia/Sydney)"},"latitude":{"type":"number","nullable":true},"longitude":{"type":"number","nullable":true},"formUnitSystem":{"type":"string","nullable":true,"enum":["metric","imperial"]},"formGateStatuses":{"type":"object","properties":{"start":{"type":"array","items":{"type":"string"}},"completion":{"type":"array","items":{"type":"string"}}}},"defaultRecurringLeadDays":{"type":"integer","nullable":true},"defaultRecurringStatus":{"type":"string","nullable":true},"recurringExpiryHorizonDays":{"type":"integer","nullable":true}}},"OrganisationResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Organisation"}}},"Customer":{"type":"object","properties":{"id":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":"string"},"secondaryPhone":{"type":"string"},"businessName":{"type":"string"},"businessTaxId":{"type":"string"},"addressLine1":{"type":"string"},"addressLine2":{"type":"string"},"city":{"type":"string"},"state":{"type":"string"},"zip":{"type":"string"},"country":{"type":"string"},"latitude":{"type":"number"},"longitude":{"type":"number"},"notes":{"type":"string"},"customerType":{"type":"string","enum":["residential","business"]},"preferredContactMethod":{"type":"string","enum":["phone","sms","email"]},"createdAt":{"type":"string","format":"date-time"}}},"CustomerCreate":{"type":"object","required":["firstName"],"properties":{"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":"string"},"secondaryPhone":{"type":"string"},"businessName":{"type":"string"},"businessTaxId":{"type":"string"},"addressLine1":{"type":"string"},"addressLine2":{"type":"string"},"city":{"type":"string"},"state":{"type":"string"},"zip":{"type":"string"},"country":{"type":"string"},"latitude":{"type":"number"},"longitude":{"type":"number"},"notes":{"type":"string"},"customerType":{"type":"string"},"preferredContactMethod":{"type":"string"}}},"CustomerUpdate":{"type":"object","properties":{"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":"string"},"secondaryPhone":{"type":"string"},"businessName":{"type":"string"},"businessTaxId":{"type":"string"},"addressLine1":{"type":"string"},"addressLine2":{"type":"string"},"city":{"type":"string"},"state":{"type":"string"},"zip":{"type":"string"},"country":{"type":"string"},"latitude":{"type":"number"},"longitude":{"type":"number"},"notes":{"type":"string"},"customerType":{"type":"string"},"preferredContactMethod":{"type":"string"}}},"CustomerResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Customer"}}},"CustomerListResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"customers":{"type":"array","items":{"$ref":"#/components/schemas/Customer"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}}},"CalendarEvent":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"notes":{"type":"string"},"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"},"allDay":{"type":"boolean"},"assignedTo":{"type":"string"},"assignedToId":{"type":"string"},"ticketId":{"type":"string"},"ticketLocation":{"type":"string"},"color":{"type":"integer"},"serviceRequest":{"type":"string","description":"Copied from the linked job's serviceRequired on calendar sync."}}},"CalendarEventCreate":{"type":"object","required":["title","from","to"],"properties":{"title":{"type":"string"},"description":{"type":"string"},"notes":{"type":"string"},"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"},"allDay":{"type":"boolean","default":false},"assignedTo":{"type":"string"},"assignedToId":{"type":"string"},"ticketId":{"type":"string"},"ticketLocation":{"type":"string"},"color":{"type":"integer"},"serviceRequest":{"type":"string"}}},"CalendarEventUpdate":{"type":"object","properties":{"title":{"type":"string"},"description":{"type":"string"},"notes":{"type":"string"},"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"},"allDay":{"type":"boolean"},"assignedTo":{"type":"string"},"assignedToId":{"type":"string"},"ticketId":{"type":"string"},"ticketLocation":{"type":"string"},"color":{"type":"integer"}}},"CalendarEventResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/CalendarEvent"}}},"CalendarEventListResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/CalendarEvent"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}}},"Ticket":{"type":"object","properties":{"id":{"type":"string"},"ticketId":{"type":"integer","description":"Sequential numeric job/ticket ID, auto-assigned on create."},"status":{"type":"string","description":"Free-form status string. The Servicebay app commonly uses\n`Open`, `In Progress`, and `Closed`, but any string is accepted\nso integrators can define their own workflow states.\n","default":"Open"},"timestamp":{"type":"string","format":"date-time"},"ticketClosedTimestamp":{"type":"string","format":"date-time","nullable":true},"customerId":{"type":"string"},"customerName":{"type":"string"},"customerEmail":{"type":"string","format":"email"},"customerPhone":{"type":"string"},"customerDeviceName":{"type":"string"},"customerDeviceType":{"type":"string"},"deviceId":{"type":"string"},"assignedTechnician":{"type":"string"},"serviceRequired":{"type":"string"},"serviceNotes":{"type":"string"},"serviceTime":{"type":"string","format":"date-time"},"endTime":{"type":"string","format":"date-time"},"serviceAddress":{"type":"string"},"serviceLocation":{"type":"string","enum":["instore","offsite","remote"],"description":"Where the job is performed. instore = on-premises, offsite = at the customer's address, remote = handled remotely."},"warrantyRepair":{"type":"boolean"},"alternativeCustomerAddress":{"type":"boolean"},"additionalItems":{"type":"array","maxItems":200,"description":"Extra note strings attached to the job (matches the app's additionalItems list).","items":{"type":"string","maxLength":500}},"stationId":{"type":"string","description":"ID of the workstation/bay this job is assigned to (see Stations)."},"serviceLatitude":{"type":"number","readOnly":true},"serviceLongitude":{"type":"number","readOnly":true},"warrantyTicketId":{"type":"integer"},"warrantyTicketServiceRequest":{"type":"string"},"imageUrls":{"type":"array","items":{"type":"string"},"readOnly":true},"imageStoragePaths":{"type":"array","items":{"type":"string"},"readOnly":true},"videoUrl":{"type":"string","readOnly":true},"videoStoragePath":{"type":"string","readOnly":true},"videoThumbnailUrl":{"type":"string","readOnly":true},"openRequiredFormCount":{"type":"integer","readOnly":true},"openStartFormCount":{"type":"integer","readOnly":true},"openInvoiceFormCount":{"type":"integer","readOnly":true},"recurringScheduleId":{"type":"string","readOnly":true},"occurrenceIndex":{"type":"integer","readOnly":true},"generatedAt":{"type":"string","format":"date-time","readOnly":true},"detachedFromSeries":{"type":"boolean","readOnly":true}}},"TicketCreate":{"type":"object","required":["customerId","customerName"],"properties":{"status":{"type":"string","description":"Optional. When omitted, the organisation's lowest-index job status\nis used. Must be a known `ticketStatuses` name when provided.\n"},"customerId":{"type":"string"},"customerName":{"type":"string"},"customerEmail":{"type":"string","format":"email"},"customerPhone":{"type":"string"},"customerDeviceName":{"type":"string"},"customerDeviceType":{"type":"string"},"deviceId":{"type":"string"},"assignedTechnician":{"type":"string"},"serviceRequired":{"type":"string"},"serviceNotes":{"type":"string"},"serviceTime":{"type":"string","format":"date-time"},"endTime":{"type":"string","format":"date-time"},"serviceAddress":{"type":"string"},"serviceLocation":{"type":"string","enum":["instore","offsite","remote"],"description":"Where the job is performed."},"warrantyRepair":{"type":"boolean","default":false},"alternativeCustomerAddress":{"type":"boolean","default":false},"additionalItems":{"type":"array","maxItems":200,"description":"Extra note strings attached to the job.","items":{"type":"string","maxLength":500}},"stationId":{"type":"string","description":"ID of the workstation/bay this job is assigned to (see Stations)."}}},"TicketUpdate":{"type":"object","properties":{"status":{"type":"string","description":"Free-form status string (e.g. `Open`, `In Progress`, `Closed`)."},"customerName":{"type":"string"},"customerEmail":{"type":"string","format":"email"},"customerPhone":{"type":"string"},"customerDeviceName":{"type":"string"},"customerDeviceType":{"type":"string"},"assignedTechnician":{"type":"string"},"serviceRequired":{"type":"string"},"serviceNotes":{"type":"string"},"serviceTime":{"type":"string","format":"date-time"},"endTime":{"type":"string","format":"date-time"},"serviceAddress":{"type":"string"},"serviceLocation":{"type":"string","enum":["instore","offsite","remote"],"description":"Where the job is performed."},"warrantyRepair":{"type":"boolean"},"alternativeCustomerAddress":{"type":"boolean"},"additionalItems":{"type":"array","maxItems":200,"description":"Extra note strings attached to the job.","items":{"type":"string","maxLength":500}},"stationId":{"type":"string","description":"ID of the workstation/bay this job is assigned to (see Stations)."}}},"TicketResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Ticket"}}},"TicketListResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"tickets":{"type":"array","items":{"$ref":"#/components/schemas/Ticket"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}}},"Service":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"notes":{"type":"string"},"priceType":{"type":"string","enum":["fixed","rate","variable","unset"]},"price":{"type":"number"},"costPrice":{"type":"number"},"priceTimeRate":{"type":"string","enum":["hour","day","week","month","year"]},"warranty":{"type":"boolean"},"warrantyDuration":{"type":"integer"},"warrantyPeriod":{"type":"string","enum":["days","weeks","months","years",""]},"quantity":{"type":"number"},"taxRateId":{"type":"string"},"index":{"type":"integer"},"createdAt":{"type":"string","format":"date-time"}}},"ServiceCreate":{"type":"object","required":["title"],"properties":{"title":{"type":"string"},"description":{"type":"string"},"notes":{"type":"string"},"priceType":{"type":"string","enum":["fixed","rate","variable","unset"]},"price":{"type":"number"},"costPrice":{"type":"number"},"priceTimeRate":{"type":"string","enum":["hour","day","week","month","year"]},"warranty":{"type":"boolean"},"warrantyDuration":{"type":"integer"},"warrantyPeriod":{"type":"string","enum":["days","weeks","months","years",""]},"quantity":{"type":"number"},"taxRateId":{"type":"string"},"index":{"type":"integer"}}},"ServiceUpdate":{"$ref":"#/components/schemas/ServiceCreate"},"ServiceResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Service"}}},"ServiceListResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"services":{"type":"array","items":{"$ref":"#/components/schemas/Service"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}}},"InventoryItem":{"type":"object","properties":{"id":{"type":"string"},"itemName":{"type":"string"},"description":{"type":"string"},"categoryId":{"type":"string"},"gtin":{"type":"string"},"sku":{"type":"string"},"price":{"type":"number"},"costPrice":{"type":"number"},"weight":{"type":"number"},"weightUnit":{"type":"string","enum":["grams","kilograms","ounces","pounds"]},"stockCount":{"type":"integer"},"tracksStock":{"type":"boolean"},"warranty":{"type":"boolean"},"warrantyPeriod":{"type":"string","enum":["days","weeks","months","years",""]},"warrantyDuration":{"type":"integer"},"quantity":{"type":"number"},"taxRateId":{"type":"string"},"index":{"type":"integer"},"createdAt":{"type":"string","format":"date-time"}}},"InventoryItemCreate":{"type":"object","required":["itemName"],"properties":{"itemName":{"type":"string"},"description":{"type":"string"},"categoryId":{"type":"string"},"gtin":{"type":"string"},"sku":{"type":"string"},"price":{"type":"number"},"costPrice":{"type":"number"},"weight":{"type":"number"},"weightUnit":{"type":"string","enum":["grams","kilograms","ounces","pounds"]},"stockCount":{"type":"integer"},"tracksStock":{"type":"boolean"},"warranty":{"type":"boolean"},"warrantyPeriod":{"type":"string","enum":["days","weeks","months","years",""]},"warrantyDuration":{"type":"integer"},"quantity":{"type":"number"},"taxRateId":{"type":"string"},"index":{"type":"integer"}}},"InventoryItemUpdate":{"$ref":"#/components/schemas/InventoryItemCreate"},"InventoryItemResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/InventoryItem"}}},"InventoryListResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/InventoryItem"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}}},"LineItem":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"price":{"type":"number"},"quantity":{"type":"number"},"taxRateId":{"type":"string"}},"additionalProperties":true},"Discount":{"type":"object","required":["isPercentage","value"],"properties":{"isPercentage":{"type":"boolean","description":"true = percentage of subtotal; false = fixed amount"},"value":{"type":"number","minimum":0}},"additionalProperties":false},"Quote":{"type":"object","properties":{"id":{"type":"string"},"index":{"type":"integer","readOnly":true},"ticketId":{"type":"string"},"customerId":{"type":"string"},"customerName":{"type":"string"},"title":{"type":"string"},"message":{"type":"string"},"terms":{"type":"string"},"totalPrice":{"type":"number"},"depositRequest":{"type":"boolean"},"depositAmount":{"type":"number"},"depositDueDays":{"type":"integer"},"balanceAmount":{"type":"number"},"balanceDueDays":{"type":"integer"},"dueDays":{"type":"integer"},"expirationDays":{"type":"integer"},"expirationDate":{"type":"string","format":"date-time"},"neverExpires":{"type":"boolean"},"accepted":{"type":"boolean"},"invoiced":{"type":"boolean"},"sent":{"type":"boolean"},"viewedByCustomer":{"type":"boolean","readOnly":true},"viewedDate":{"type":"string","format":"date-time","readOnly":true},"acceptedDate":{"type":"string","format":"date-time"},"invoicedDate":{"type":"string","format":"date-time"},"sentDate":{"type":"string","format":"date-time"},"createdOn":{"type":"string","format":"date-time"},"services":{"type":"array","items":{"$ref":"#/components/schemas/LineItem"}},"inventoryItems":{"type":"array","items":{"$ref":"#/components/schemas/LineItem"}},"discount":{"$ref":"#/components/schemas/Discount"}}},"QuoteCreate":{"type":"object","required":["customerId"],"properties":{"ticketId":{"type":"string"},"customerId":{"type":"string"},"customerName":{"type":"string"},"title":{"type":"string"},"message":{"type":"string"},"terms":{"type":"string"},"totalPrice":{"type":"number"},"depositRequest":{"type":"boolean"},"depositAmount":{"type":"number"},"depositDueDays":{"type":"integer"},"balanceAmount":{"type":"number"},"balanceDueDays":{"type":"integer"},"dueDays":{"type":"integer"},"expirationDays":{"type":"integer"},"expirationDate":{"type":"string","format":"date-time"},"neverExpires":{"type":"boolean"},"sent":{"type":"boolean"},"services":{"type":"array","items":{"$ref":"#/components/schemas/LineItem"}},"inventoryItems":{"type":"array","items":{"$ref":"#/components/schemas/LineItem"}},"discount":{"$ref":"#/components/schemas/Discount"}}},"QuoteUpdate":{"allOf":[{"$ref":"#/components/schemas/QuoteCreate"},{"type":"object","properties":{"accepted":{"type":"boolean"},"invoiced":{"type":"boolean"},"acceptedDate":{"type":"string","format":"date-time","nullable":true},"invoicedDate":{"type":"string","format":"date-time","nullable":true},"sentDate":{"type":"string","format":"date-time","nullable":true}}}]},"QuoteResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Quote"}}},"QuoteListResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"quotes":{"type":"array","items":{"$ref":"#/components/schemas/Quote"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}}},"Invoice":{"type":"object","properties":{"id":{"type":"string"},"index":{"type":"integer","readOnly":true},"ticketId":{"type":"string"},"customerId":{"type":"string"},"customerName":{"type":"string"},"title":{"type":"string"},"message":{"type":"string"},"terms":{"type":"string"},"paymentAdvice":{"type":"string"},"totalPrice":{"type":"number"},"depositRequested":{"type":"boolean"},"depositAmount":{"type":"number"},"depositPaid":{"type":"boolean","readOnly":true},"balanceAmount":{"type":"number"},"balancePaid":{"type":"boolean","readOnly":true},"paid":{"type":"boolean","readOnly":true},"sent":{"type":"boolean"},"remindersEnabled":{"type":"boolean"},"dueDate":{"type":"string","format":"date-time"},"depositDueDate":{"type":"string","format":"date-time"},"balanceDueDate":{"type":"string","format":"date-time"},"invoiceDate":{"type":"string","format":"date-time"},"createdOn":{"type":"string","format":"date-time"},"sentDate":{"type":"string","format":"date-time"},"paidDate":{"type":"string","format":"date-time","readOnly":true},"viewedByCustomer":{"type":"boolean","readOnly":true},"viewedDate":{"type":"string","format":"date-time","readOnly":true},"services":{"type":"array","items":{"$ref":"#/components/schemas/LineItem"}},"inventoryItems":{"type":"array","items":{"$ref":"#/components/schemas/LineItem"}},"discount":{"$ref":"#/components/schemas/Discount"}}},"InvoiceCreate":{"type":"object","required":["customerId"],"properties":{"ticketId":{"type":"string"},"customerId":{"type":"string"},"customerName":{"type":"string"},"title":{"type":"string"},"message":{"type":"string"},"terms":{"type":"string"},"paymentAdvice":{"type":"string"},"totalPrice":{"type":"number"},"depositRequested":{"type":"boolean"},"depositAmount":{"type":"number"},"balanceAmount":{"type":"number"},"dueDate":{"type":"string","format":"date-time"},"depositDueDate":{"type":"string","format":"date-time"},"balanceDueDate":{"type":"string","format":"date-time"},"invoiceDate":{"type":"string","format":"date-time"},"remindersEnabled":{"type":"boolean"},"sent":{"type":"boolean"},"services":{"type":"array","items":{"$ref":"#/components/schemas/LineItem"}},"inventoryItems":{"type":"array","items":{"$ref":"#/components/schemas/LineItem"}},"discount":{"$ref":"#/components/schemas/Discount"}}},"InvoiceUpdate":{"$ref":"#/components/schemas/InvoiceCreate"},"InvoiceResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Invoice"}}},"InvoiceListResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"invoices":{"type":"array","items":{"$ref":"#/components/schemas/Invoice"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}}},"Device":{"type":"object","description":"A customer's device/asset. Open schema — beyond the fixed fields below,\nany additional keys sent on create/update are stored and returned as-is\n(used for custom attributes like a serial/identifier).\n","additionalProperties":true,"properties":{"id":{"type":"string"},"type":{"type":"string"},"brand":{"type":"string"},"make":{"type":"string"},"model":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}},"DeviceCreate":{"type":"object","additionalProperties":true,"properties":{"type":{"type":"string"},"brand":{"type":"string"},"make":{"type":"string"},"model":{"type":"string"}}},"DeviceUpdate":{"$ref":"#/components/schemas/DeviceCreate"},"DeviceResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Device"}}},"DeviceListResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"devices":{"type":"array","items":{"$ref":"#/components/schemas/Device"}}}}}},"Payment":{"type":"object","properties":{"id":{"type":"string"},"invoiceId":{"type":"string"},"amount":{"type":"number","description":"Payment amount. Negative values represent a refund."},"paymentDate":{"type":"string","format":"date-time"},"paymentMethod":{"type":"string","description":"Payment method. Writable values are the manual methods; `stripe`/`stripeRefund` are set only by Stripe."},"sendReceipt":{"type":"boolean","description":"Metadata only — the API does not send receipt emails."},"notes":{"type":"string"},"stripePaymentIntentId":{"type":"string","description":"Read-only. Present when the payment originated from Stripe."},"stripeRefundId":{"type":"string","description":"Read-only. Present when the payment is a Stripe refund."}}},"PaymentCreate":{"type":"object","required":["invoiceId","amount"],"properties":{"invoiceId":{"type":"string"},"amount":{"type":"number","description":"Negative to record a refund."},"paymentDate":{"type":"string","format":"date-time"},"paymentMethod":{"type":"string","enum":["card","cash","eft","cheque","other"]},"sendReceipt":{"type":"boolean"},"notes":{"type":"string"}}},"PaymentUpdate":{"type":"object","properties":{"amount":{"type":"number"},"paymentDate":{"type":"string","format":"date-time"},"paymentMethod":{"type":"string","enum":["card","cash","eft","cheque","other"]},"sendReceipt":{"type":"boolean"},"notes":{"type":"string"}}},"PaymentResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Payment"}}},"PaymentListResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"payments":{"type":"array","items":{"$ref":"#/components/schemas/Payment"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}}},"Station":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"index":{"type":"integer"},"capacity":{"type":"integer"}}},"StationCreate":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"index":{"type":"integer"},"capacity":{"type":"integer"}}},"StationUpdate":{"type":"object","properties":{"name":{"type":"string"},"index":{"type":"integer"},"capacity":{"type":"integer"}}},"StationResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Station"}}},"StationListResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"stations":{"type":"array","items":{"$ref":"#/components/schemas/Station"}}}}}},"TaxRate":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"rate":{"type":"number"},"isInclusive":{"type":"boolean"},"defaultEnabled":{"type":"boolean","description":"Only one tax rate per organisation may be the default."}}},"TaxRateCreate":{"type":"object","required":["name","rate"],"properties":{"name":{"type":"string"},"rate":{"type":"number"},"isInclusive":{"type":"boolean"},"defaultEnabled":{"type":"boolean"}}},"TaxRateUpdate":{"type":"object","properties":{"name":{"type":"string"},"rate":{"type":"number"},"isInclusive":{"type":"boolean"},"defaultEnabled":{"type":"boolean"}}},"TaxRateResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/TaxRate"}}},"TaxRateListResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"taxRates":{"type":"array","items":{"$ref":"#/components/schemas/TaxRate"}}}}}},"TicketStatus":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"color":{"type":"integer","description":"Packed ARGB32 colour integer."},"index":{"type":"integer"},"type":{"type":"string","description":"`default` for the four built-in statuses, `custom` for user-created ones. Built-in statuses cannot be deleted."}}},"TicketStatusCreate":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"color":{"type":"integer"},"index":{"type":"integer"}}},"TicketStatusUpdate":{"type":"object","properties":{"name":{"type":"string"},"color":{"type":"integer"},"index":{"type":"integer"}}},"TicketStatusResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/TicketStatus"}}},"TicketStatusListResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"ticketStatuses":{"type":"array","items":{"$ref":"#/components/schemas/TicketStatus"}}}}}},"ServiceLine":{"type":"object","required":["title","price"],"properties":{"title":{"type":"string"},"description":{"type":"string"},"notes":{"type":"string"},"priceType":{"type":"string","enum":["fixed","rate","variable","unset"]},"price":{"type":"number"},"costPrice":{"type":"number"},"priceTimeRate":{"type":"string","enum":["hour","day","week","month","year"]},"warranty":{"type":"boolean"},"warrantyDuration":{"type":"integer"},"warrantyPeriod":{"type":"string","enum":["days","weeks","months","years",""]},"quantity":{"type":"integer"},"index":{"type":"integer","nullable":true},"taxRateId":{"type":"string","nullable":true}}},"InventoryLine":{"type":"object","required":["itemName","price"],"properties":{"itemName":{"type":"string"},"description":{"type":"string"},"categoryId":{"type":"string","nullable":true},"gtin":{"type":"string"},"sku":{"type":"string"},"price":{"type":"number"},"costPrice":{"type":"number"},"weight":{"type":"number"},"weightUnit":{"type":"string","enum":["grams","kilograms","ounces","pounds"]},"stockCount":{"type":"integer"},"tracksStock":{"type":"boolean","nullable":true},"warranty":{"type":"boolean"},"warrantyPeriod":{"type":"string","enum":["days","weeks","months","years",""]},"warrantyDuration":{"type":"integer"},"quantity":{"type":"integer"},"index":{"type":"integer","nullable":true},"taxRateId":{"type":"string","nullable":true}}},"MessageCreate":{"type":"object","required":["messageText"],"properties":{"messageText":{"type":"string","maxLength":10000},"messageCategory":{"type":"string","enum":["information","important","critical"]},"messageType":{"type":"string","enum":["internal_message","customer_message"]},"mentionedUserIds":{"type":"array","items":{"type":"string"}}}},"InvoiceReminderWrite":{"type":"object","required":["trigger","days"],"properties":{"trigger":{"type":"string","enum":["beforeDueDate","onDueDate","afterDueDate"]},"days":{"type":"integer","minimum":0,"maximum":365}}}}}}