{"openapi":"3.1.0","info":{"title":"Servicebay API","description":"The Servicebay API provides programmatic access to your organisation's data including \ncustomers, tickets, and calendar events.\n\n## Authentication\n\nAll API requests require authentication using an API key. Include your API key in the \n`X-API-Key` header with every request:\n\n```\nX-API-Key: sk_live_your_api_key_here\n```\n\nAPI keys are scoped to a single organisation. You can create and manage API keys from \nthe [Developer Dashboard](/develop).\n\n## Rate Limiting\n\nAPI requests are rate limited to **100 requests per minute** per API key. Rate limit \ninformation is included in response 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\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 parameters |\n| 401 | Unauthorized - Invalid or missing API key |\n| 403 | Forbidden - No access to this resource |\n| 404 | Not Found |\n| 429 | Too Many Requests - Rate limit exceeded |\n| 500 | Internal Server Error |\n","version":"1.0.0","contact":{"name":"Servicebay Support","url":"https://servicebay.io/support","email":"support@servicebay.io"}},"servers":[{"url":"https://developer.servicebay.io/api/v1","description":"Production API"},{"url":"http://localhost:3000/api/v1","description":"Local development"}],"security":[{"apiKey":[]}],"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":"API Keys","description":"API key management (requires Firebase Auth)"}],"paths":{"/organisations/{orgId}":{"get":{"tags":["Organisations"],"summary":"Get organisation details","description":"Retrieve details for the organisation associated with your API key.","operationId":"getOrganisation","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","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","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","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","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","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","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.","operationId":"deleteCustomer","parameters":[{"$ref":"#/components/parameters/orgId"},{"$ref":"#/components/parameters/customerId"}],"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"}}}},"/organisations/{orgId}/calendar-events":{"get":{"tags":["Calendar Events"],"summary":"List calendar events","description":"Retrieve a paginated list of calendar events.","operationId":"listCalendarEvents","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.","operationId":"createCalendarEvent","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"}}}},"/organisations/{orgId}/calendar-events/{eventId}":{"get":{"tags":["Calendar Events"],"summary":"Get calendar event","description":"Retrieve a specific calendar event by ID.","operationId":"getCalendarEvent","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.","operationId":"updateCalendarEvent","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"}}},"delete":{"tags":["Calendar Events"],"summary":"Delete calendar event","description":"Delete a calendar event.","operationId":"deleteCalendarEvent","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","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","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","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","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","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","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","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","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","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","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","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"}}}}}},"post":{"tags":["Inventory"],"summary":"Create inventory item","operationId":"createInventoryItem","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","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","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","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","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"}}}}}},"post":{"tags":["Quotes"],"summary":"Create quote","operationId":"createQuote","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","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","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","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","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"}}}}}},"post":{"tags":["Invoices"],"summary":"Create invoice","operationId":"createInvoice","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","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","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","responses":{"200":{"description":"Invoice deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessMessage"}}}},"404":{"$ref":"#/components/responses/NotFound"}}}}},"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"}},"parameters":{"orgId":{"name":"orgId","in":"path","required":true,"description":"Organisation ID","schema":{"type":"string"}},"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"}},"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 previous page","schema":{"type":"string"}}},"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 - No access to this resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimitExceeded":{"description":"Too Many Requests - Rate limit exceeded","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"}}},"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."},"userTermsOfServiceDocument":{"type":"string","description":"URL or path to a user-specific terms of service document."},"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"},"userTermsOfServiceDocument":{"type":"string"}}},"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"},"businessName":{"type":"string"},"businessTaxId":{"type":"string"},"addressLine1":{"type":"string"},"addressLine2":{"type":"string"},"city":{"type":"string"},"state":{"type":"string"},"zip":{"type":"string"},"country":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"devices":{"type":"array","description":"Opaque list of device references linked to this customer. Structure is not stable and may change.","items":{"type":"object","additionalProperties":true}}}},"CustomerCreate":{"type":"object","required":["firstName","lastName","email"],"properties":{"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"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"},"devices":{"type":"array","items":{"type":"object","additionalProperties":true}}}},"CustomerUpdate":{"type":"object","properties":{"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"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"},"devices":{"type":"array","items":{"type":"object","additionalProperties":true}}}},"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"}}},"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"}}},"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","description":"Opaque, unstructured list used by the Servicebay app for extra line items attached to the job.","items":{"type":"object","additionalProperties":true}},"messageRooms":{"description":"Opaque container for in-app message-room metadata linked to this job. Structure is not stable.","type":"object","additionalProperties":true}}},"TicketCreate":{"type":"object","required":["customerId","customerName"],"properties":{"status":{"type":"string","description":"Free-form status string. Common values used by the Servicebay app\nare `Open`, `In Progress`, and `Closed`, but any string is\naccepted.\n","default":"Open"},"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","items":{"type":"object","additionalProperties":true}},"messageRooms":{"type":"object","additionalProperties":true}}},"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","items":{"type":"object","additionalProperties":true}},"messageRooms":{"type":"object","additionalProperties":true}}},"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"]},"price":{"type":"number"},"priceTimeRate":{"type":"string","enum":["hour","day","week","month"]},"warranty":{"type":"boolean"},"warrantyDuration":{"type":"integer"},"warrantyPeriod":{"type":"string","enum":["day","week","month","year"]},"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"]},"price":{"type":"number"},"priceTimeRate":{"type":"string","enum":["hour","day","week","month"]},"warranty":{"type":"boolean"},"warrantyDuration":{"type":"integer"},"warrantyPeriod":{"type":"string","enum":["day","week","month","year"]},"quantity":{"type":"number"},"taxRateId":{"type":"string"},"index":{"type":"integer"}}},"ServiceUpdate":{"allOf":[{"$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"},"weight":{"type":"number"},"weightUnit":{"type":"string","enum":["g","kg","oz","lb"]},"stockCount":{"type":"integer"},"tracksStock":{"type":"boolean"},"warranty":{"type":"boolean"},"warrantyPeriod":{"type":"string","enum":["day","week","month","year"]},"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"},"weight":{"type":"number"},"weightUnit":{"type":"string","enum":["g","kg","oz","lb"]},"stockCount":{"type":"integer"},"tracksStock":{"type":"boolean"},"warranty":{"type":"boolean"},"warrantyPeriod":{"type":"string","enum":["day","week","month","year"]},"warrantyDuration":{"type":"integer"},"quantity":{"type":"number"},"taxRateId":{"type":"string"},"index":{"type":"integer"}}},"InventoryItemUpdate":{"allOf":[{"$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","properties":{"type":{"type":"string","enum":["percentage","fixed"]},"value":{"type":"number"},"reason":{"type":"string"}},"additionalProperties":true},"Quote":{"type":"object","properties":{"id":{"type":"string"},"index":{"type":"integer"},"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"},"viewedByCustomer":{"type":"boolean"},"viewedDate":{"type":"string","format":"date-time"},"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"},"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"}]},"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"},"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"},"balanceAmount":{"type":"number"},"balancePaid":{"type":"boolean"},"paid":{"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"},"viewedByCustomer":{"type":"boolean"},"viewedDate":{"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"}}},"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"},"services":{"type":"array","items":{"$ref":"#/components/schemas/LineItem"}},"inventoryItems":{"type":"array","items":{"$ref":"#/components/schemas/LineItem"}},"discount":{"$ref":"#/components/schemas/Discount"}}},"InvoiceUpdate":{"allOf":[{"$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"}}}}}}}}