openapi: 3.0.3 info: title: 'Shift Collect API Documentation' description: 'Welcome to the Shift Collect API - A RESTful API for managing locker bookings and account access.' version: 1.0.0 servers: - url: 'https://api.shiftcollect.com' tags: - name: Accounts description: '' - name: Authentication description: '' - name: Availability description: '' - name: 'Booking Tracking' description: '' - name: Bookings description: '' - name: Cabinets description: '' - name: 'Collection Schedules' description: '' - name: 'Despatch Centres' description: '' - name: Sites description: '' - name: 'Token Management' description: '' - name: 'User Management' description: '' - name: Webhooks description: '' components: securitySchemes: default: type: http scheme: bearer description: 'Generate API tokens using the `POST /v1/auth/token` endpoint. See the `Authentication` section below for more information.' security: - default: [] paths: /v1/accounts: get: summary: 'List the accounts the authenticated user belongs to.' operationId: listTheAccountsTheAuthenticatedUserBelongsTo description: "Returns every account that the authenticated user is a member of, including the\nmembership status, join date, and their role assignments scoped to each account." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: data: - id: 01ARZ3NDEKTSV4RRFFQ69G5FAW name: 'Acme Corp' slug: acme-corp role: owner properties: data: type: array example: - id: 01ARZ3NDEKTSV4RRFFQ69G5FAW name: 'Acme Corp' slug: acme-corp role: owner items: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAW name: type: string example: 'Acme Corp' slug: type: string example: acme-corp role: type: string example: owner 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - Accounts /v1/auth/token: post: summary: 'Generate API token from credentials.' operationId: generateAPITokenFromCredentials description: "Authenticates a user with email and password and returns an API token.\nThis is useful for programmatic access without needing to login via the SPA first.\nRequires Admin or Owner role in the specified account." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: token: 1|abcdefghijklmnopqrstuvwxyz1234567890 token_name: 'Production API Token' account_id: 01ARZ3NDEKTSV4RRFFQ69G5FAW user: id: 01ARZ3NDEKTSV4RRFFQ69G5FAW name: 'John Doe' email: user@example.com abilities: - '*' expires_at: '2025-12-31T23:59:59.000000Z' created_at: '2025-01-01T00:00:00.000000Z' message: 'API token generated successfully' properties: token: type: string example: 1|abcdefghijklmnopqrstuvwxyz1234567890 token_name: type: string example: 'Production API Token' account_id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAW user: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAW name: type: string example: 'John Doe' email: type: string example: user@example.com abilities: type: array example: - '*' items: type: string expires_at: type: string example: '2025-12-31T23:59:59.000000Z' created_at: type: string example: '2025-01-01T00:00:00.000000Z' message: type: string example: 'API token generated successfully' 403: description: '' content: application/json: schema: oneOf: - description: '' type: object example: message: 'This action is unauthorized. Only admins and owners can generate API tokens.' properties: message: type: string example: 'This action is unauthorized. Only admins and owners can generate API tokens.' - description: '' type: object example: message: 'User does not belong to the specified account.' properties: message: type: string example: 'User does not belong to the specified account.' 422: description: '' content: application/json: schema: oneOf: - description: '' type: object example: message: 'The given data was invalid.' errors: email: - 'The email field is required.' password: - 'The password field is required.' account_id: - 'The account id field is required.' expires_at: - 'The expires at must be a date after now.' properties: message: type: string example: 'The given data was invalid.' errors: type: object properties: email: type: array example: - 'The email field is required.' items: type: string password: type: array example: - 'The password field is required.' items: type: string account_id: type: array example: - 'The account id field is required.' items: type: string expires_at: type: array example: - 'The expires at must be a date after now.' items: type: string - description: '' type: object example: message: 'The given data was invalid.' errors: email: - 'These credentials do not match our records.' properties: message: type: string example: 'The given data was invalid.' errors: type: object properties: email: type: array example: - 'These credentials do not match our records.' items: type: string tags: - Authentication requestBody: required: true content: application/json: schema: type: object properties: email: type: string description: 'User email address' example: user@example.com nullable: false password: type: string description: 'User password' example: password123 nullable: false account_id: type: string description: 'Account ID (ULID) for which to generate the token' example: 01ARZ3NDEKTSV4RRFFQ69G5FAW nullable: false token_name: type: string description: 'Name for the token (optional, defaults to "API Token")' example: 'Production API Token' nullable: false expires_at: type: string description: 'Expiration date and time (ISO 8601). Must be in the future' example: '2025-12-31T23:59:59Z' nullable: false required: - email - password - account_id /v1/availability: get: summary: 'Get site availability for a date range.' operationId: getSiteAvailabilityForADateRange description: "Returns all active sites with availability information for the requested time window.\nSites are returned regardless of availability (sites with 0 available lockers are still included).\nAvailability is calculated from:\n- Hard reservations: locker_assignments that overlap with the requested period (fixed date/time reservations)\n- Soft reservations: booking_soft_reservations that overlap with the requested period (each counts as 1 locker, representing a best-guess estimate)\nEach site includes an array of available lockers with their dimensions and status.\nNote: Booking details are never included in the response to prevent data leakage between accounts." parameters: - in: query name: from description: 'Start date and time (ISO 8601). Must be a valid date.' example: '2025-01-15T09:00:00Z' required: true schema: type: string description: 'Start date and time (ISO 8601). Must be a valid date.' example: '2025-01-15T09:00:00Z' nullable: false - in: query name: to description: 'End date and time (ISO 8601). Must be after from. Must be a valid date. Must be a date after from.' example: '2025-01-20T17:00:00Z' required: true schema: type: string description: 'End date and time (ISO 8601). Must be after from. Must be a valid date. Must be a date after from.' example: '2025-01-20T17:00:00Z' nullable: false - in: query name: site_id description: 'Filter by specific site ID. Returns only the selected site with available lockers.' example: 01ARZ3NDEKTSV4RRFFQ69G5FAA required: false schema: type: string description: 'Filter by specific site ID. Returns only the selected site with available lockers.' example: 01ARZ3NDEKTSV4RRFFQ69G5FAA nullable: true - in: query name: per_page description: 'Number of sites per page (max 100). Must be at least 1. Must not be greater than 100.' example: 20 required: false schema: type: integer description: 'Number of sites per page (max 100). Must be at least 1. Must not be greater than 100.' example: 20 nullable: true - in: query name: latitude description: 'Latitude for sorting results by distance (must include longitude). Results will be sorted by distance ascending (closest first). This field is required when longitude is present. Must be between -90 and 90.' example: 50.376289 required: false schema: type: number description: 'Latitude for sorting results by distance (must include longitude). Results will be sorted by distance ascending (closest first). This field is required when longitude is present. Must be between -90 and 90.' example: 50.376289 nullable: true - in: query name: longitude description: 'Longitude for sorting results by distance (must include latitude). Results will be sorted by distance ascending (closest first). This field is required when latitude is present. Must be between -180 and 180.' example: -4.143841 required: false schema: type: number description: 'Longitude for sorting results by distance (must include latitude). Results will be sorted by distance ascending (closest first). This field is required when latitude is present. Must be between -180 and 180.' example: -4.143841 nullable: true responses: 200: description: '' content: application/json: schema: type: object example: data: - id: 01kc4dsqq7wa73jfrbek30zym2 name: 'Bailey Inc Site' address_line_1: '764 Ernser Parkways Suite 841' address_line_2: null city: Myaport postcode: '02042' county: null country: 'United Kingdom' latitude: -25.59289 longitude: -175.353288 access_instructions: null special_notes: 'Qui commodi incidunt iure odit. Et modi ipsum nostrum omnis autem et consequatur. Dolores enim non facere tempora.' height_restriction: null reserved_lockers: 0 available_lockers: 0 distance: null lockers: - name: T98 cabinet: 'Train Station' status: active dimensions: height: 36.98 width: 76.4 depth: 22.11 volume: 62466.76392 - id: 01kc4dsqqze313yw6ngk0dmkpm name: 'Dibbert Inc Site' address_line_1: '12438 Mariela Forest Suite 382' address_line_2: null city: Margarettaside postcode: '57468' county: Kendraburgh country: 'United Kingdom' latitude: -38.654828 longitude: 95.151071 access_instructions: 'Rem est esse sint aut. Sunt suscipit doloribus fugiat ut aut deserunt et. Neque recusandae et ipsam dolorem et ut dicta.' special_notes: null height_restriction: null reserved_lockers: 0 available_lockers: 0 distance: null lockers: - name: E15 cabinet: 'Residential Complex' status: unavailable dimensions: height: 37.89 width: 40.72 depth: 25.26 volume: 38973.169008 links: first: '/?page=1' last: '/?page=1' prev: null next: null meta: current_page: 1 from: 1 last_page: 1 links: - url: null label: '« Previous' page: null active: false - url: '/?page=1' label: '1' page: 1 active: true - url: null label: 'Next »' page: null active: false path: / per_page: 10 to: 2 total: 2 properties: data: type: array example: - id: 01kc4dsqq7wa73jfrbek30zym2 name: 'Bailey Inc Site' address_line_1: '764 Ernser Parkways Suite 841' address_line_2: null city: Myaport postcode: '02042' county: null country: 'United Kingdom' latitude: -25.59289 longitude: -175.353288 access_instructions: null special_notes: 'Qui commodi incidunt iure odit. Et modi ipsum nostrum omnis autem et consequatur. Dolores enim non facere tempora.' height_restriction: null reserved_lockers: 0 available_lockers: 0 distance: null lockers: - name: T98 cabinet: 'Train Station' status: active dimensions: height: 36.98 width: 76.4 depth: 22.11 volume: 62466.76392 - id: 01kc4dsqqze313yw6ngk0dmkpm name: 'Dibbert Inc Site' address_line_1: '12438 Mariela Forest Suite 382' address_line_2: null city: Margarettaside postcode: '57468' county: Kendraburgh country: 'United Kingdom' latitude: -38.654828 longitude: 95.151071 access_instructions: 'Rem est esse sint aut. Sunt suscipit doloribus fugiat ut aut deserunt et. Neque recusandae et ipsam dolorem et ut dicta.' special_notes: null height_restriction: null reserved_lockers: 0 available_lockers: 0 distance: null lockers: - name: E15 cabinet: 'Residential Complex' status: unavailable dimensions: height: 37.89 width: 40.72 depth: 25.26 volume: 38973.169008 items: type: object properties: id: type: string example: 01kc4dsqq7wa73jfrbek30zym2 name: type: string example: 'Bailey Inc Site' address_line_1: type: string example: '764 Ernser Parkways Suite 841' address_line_2: type: string example: null city: type: string example: Myaport postcode: type: string example: '02042' county: type: string example: null country: type: string example: 'United Kingdom' latitude: type: number example: -25.59289 longitude: type: number example: -175.353288 access_instructions: type: string example: null special_notes: type: string example: 'Qui commodi incidunt iure odit. Et modi ipsum nostrum omnis autem et consequatur. Dolores enim non facere tempora.' height_restriction: type: string example: null reserved_lockers: type: integer example: 0 available_lockers: type: integer example: 0 distance: type: string example: null lockers: type: array example: - name: T98 cabinet: 'Train Station' status: active dimensions: height: 36.98 width: 76.4 depth: 22.11 volume: 62466.76392 items: type: object properties: name: type: string example: T98 cabinet: type: string example: 'Train Station' status: type: string example: active dimensions: type: object properties: height: type: number example: 36.98 width: type: number example: 76.4 depth: type: number example: 22.11 volume: type: number example: 62466.76392 links: type: object properties: first: type: string example: '/?page=1' last: type: string example: '/?page=1' prev: type: string example: null next: type: string example: null meta: type: object properties: current_page: type: integer example: 1 from: type: integer example: 1 last_page: type: integer example: 1 links: type: array example: - url: null label: '« Previous' page: null active: false - url: '/?page=1' label: '1' page: 1 active: true - url: null label: 'Next »' page: null active: false items: type: object properties: url: type: string example: null label: type: string example: '« Previous' page: type: string example: null active: type: boolean example: false path: type: string example: / per_page: type: integer example: 10 to: type: integer example: 2 total: type: integer example: 2 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 422: description: '' content: application/json: schema: type: object example: message: 'The given data was invalid.' errors: from: - 'The from field is required.' to: - 'The to must be a date after from.' properties: message: type: string example: 'The given data was invalid.' errors: type: object properties: from: type: array example: - 'The from field is required.' items: type: string to: type: array example: - 'The to must be a date after from.' items: type: string tags: - Availability /v1/tracking/booking: post: summary: 'Track a booking by reference ID (public endpoint).' operationId: trackABookingByReferenceIDpublicEndpoint description: "Allows public users to track their booking using reference ID and email or phone verification.\nAt least one of email or phone must be provided." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: data: reference_id: BK65A3F2E1 status: confirmed locker_assignments: - locker_id: 01ARZ3NDEKTSV4RRFFQ69G5FAV locker_name: A1-01 cabinet: id: 01ARZ3NDEKTSV4RRFFQ69G5FAU name: 'Cabinet A1' status: active starts_at: '2025-01-15T09:00:00.000000Z' ends_at: '2025-01-20T17:00:00.000000Z' items_count: 3 items: - name: 'Item 1' quantity: 1 properties: data: type: object properties: reference_id: type: string example: BK65A3F2E1 status: type: string example: confirmed locker_assignments: type: array example: - locker_id: 01ARZ3NDEKTSV4RRFFQ69G5FAV locker_name: A1-01 cabinet: id: 01ARZ3NDEKTSV4RRFFQ69G5FAU name: 'Cabinet A1' status: active starts_at: '2025-01-15T09:00:00.000000Z' ends_at: '2025-01-20T17:00:00.000000Z' items: type: object properties: locker_id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAV locker_name: type: string example: A1-01 cabinet: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAU name: type: string example: 'Cabinet A1' status: type: string example: active starts_at: type: string example: '2025-01-15T09:00:00.000000Z' ends_at: type: string example: '2025-01-20T17:00:00.000000Z' items_count: type: integer example: 3 items: type: array example: - name: 'Item 1' quantity: 1 items: type: object properties: name: type: string example: 'Item 1' quantity: type: integer example: 1 404: description: '' content: application/json: schema: type: object example: message: 'Booking not found' properties: message: type: string example: 'Booking not found' 422: description: '' content: application/json: schema: type: object example: message: 'The given data was invalid.' properties: message: type: string example: 'The given data was invalid.' tags: - 'Booking Tracking' requestBody: required: true content: application/json: schema: type: object properties: reference_id: type: string description: 'The booking reference ID' example: BK691B2516D28B2 nullable: false email: type: string description: 'Customer email address for verification (required if phone is not provided)' example: customer@example.com nullable: false phone: type: string description: 'Customer phone number for verification (required if email is not provided)' example: '+447700900123' nullable: false required: - reference_id '/v1/tracking/{booking_id}/tracking': post: summary: 'Track a booking by ID (authenticated endpoint).' operationId: trackABookingByIDauthenticatedEndpoint description: 'Allows authenticated accounts to track their bookings.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: data: reference_id: BK65A3F2E1 status: confirmed locker_assignments: - locker_id: 01ARZ3NDEKTSV4RRFFQ69G5FAV locker_name: A1-01 cabinet: id: 01ARZ3NDEKTSV4RRFFQ69G5FAU name: 'Cabinet A1' status: active starts_at: '2025-01-15T09:00:00.000000Z' ends_at: '2025-01-20T17:00:00.000000Z' items_count: 3 items: - name: 'Item 1' quantity: 1 properties: data: type: object properties: reference_id: type: string example: BK65A3F2E1 status: type: string example: confirmed locker_assignments: type: array example: - locker_id: 01ARZ3NDEKTSV4RRFFQ69G5FAV locker_name: A1-01 cabinet: id: 01ARZ3NDEKTSV4RRFFQ69G5FAU name: 'Cabinet A1' status: active starts_at: '2025-01-15T09:00:00.000000Z' ends_at: '2025-01-20T17:00:00.000000Z' items: type: object properties: locker_id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAV locker_name: type: string example: A1-01 cabinet: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAU name: type: string example: 'Cabinet A1' status: type: string example: active starts_at: type: string example: '2025-01-15T09:00:00.000000Z' ends_at: type: string example: '2025-01-20T17:00:00.000000Z' items_count: type: integer example: 3 items: type: array example: - name: 'Item 1' quantity: 1 items: type: object properties: name: type: string example: 'Item 1' quantity: type: integer example: 1 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 404: description: '' content: application/json: schema: type: object example: message: 'Booking not found' properties: message: type: string example: 'Booking not found' tags: - 'Booking Tracking' parameters: - in: path name: booking_id description: 'The ID of the booking.' example: 01kc4drge0a29g6p1hxk9wn2kv required: true schema: type: string /v1/bookings: get: summary: 'Display a listing of bookings.' operationId: displayAListingOfBookings description: "Returns a paginated list of bookings for the current account context.\nBookings can be filtered by status." parameters: - in: query name: status description: 'Filter bookings by status' example: confirmed required: false schema: type: string description: 'Filter bookings by status' example: confirmed nullable: false - in: query name: per_page description: 'Number of items per page (max 100)' example: 20 required: false schema: type: integer description: 'Number of items per page (max 100)' example: 20 nullable: false - in: query name: page description: 'Page number' example: 1 required: false schema: type: integer description: 'Page number' example: 1 nullable: false responses: 200: description: '' content: application/json: schema: type: object example: data: - id: 01ARZ3NDEKTSV4RRFFQ69G5FAV reference_id: BK-2025-001 created_at: '2025-01-01T00:00:00.000000Z' updated_at: '2025-01-01T00:00:00.000000Z' status: id: 01ARZ3NDEKTSV4RRFFQ69G5FAX name: confirmed user: id: 01ARZ3NDEKTSV4RRFFQ69G5FAY name: 'John Doe' account: id: 01ARZ3NDEKTSV4RRFFQ69G5FAZ name: 'Acme Corp' service_product: id: 01ARZ3NDEKTSV4RRFFQ69G5FAX name: 'DC to Locker' items: [] status_history: [] pagination: current_page: 1 per_page: 15 total: 100 last_page: 7 from: 1 to: 15 has_more_pages: true links: first: 'http://example.com/api/v1/bookings?page=1' last: 'http://example.com/api/v1/bookings?page=7' prev: null next: 'http://example.com/api/v1/bookings?page=2' properties: data: type: array example: - id: 01ARZ3NDEKTSV4RRFFQ69G5FAV reference_id: BK-2025-001 created_at: '2025-01-01T00:00:00.000000Z' updated_at: '2025-01-01T00:00:00.000000Z' status: id: 01ARZ3NDEKTSV4RRFFQ69G5FAX name: confirmed user: id: 01ARZ3NDEKTSV4RRFFQ69G5FAY name: 'John Doe' account: id: 01ARZ3NDEKTSV4RRFFQ69G5FAZ name: 'Acme Corp' service_product: id: 01ARZ3NDEKTSV4RRFFQ69G5FAX name: 'DC to Locker' items: [] status_history: [] items: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAV reference_id: type: string example: BK-2025-001 created_at: type: string example: '2025-01-01T00:00:00.000000Z' updated_at: type: string example: '2025-01-01T00:00:00.000000Z' status: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAX name: type: string example: confirmed user: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAY name: type: string example: 'John Doe' account: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAZ name: type: string example: 'Acme Corp' service_product: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAX name: type: string example: 'DC to Locker' items: type: array example: [] status_history: type: array example: [] pagination: type: object properties: current_page: type: integer example: 1 per_page: type: integer example: 15 total: type: integer example: 100 last_page: type: integer example: 7 from: type: integer example: 1 to: type: integer example: 15 has_more_pages: type: boolean example: true links: type: object properties: first: type: string example: 'http://example.com/api/v1/bookings?page=1' last: type: string example: 'http://example.com/api/v1/bookings?page=7' prev: type: string example: null next: type: string example: 'http://example.com/api/v1/bookings?page=2' 400: description: '' content: application/json: schema: type: object example: message: 'No account context set' properties: message: type: string example: 'No account context set' 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: '' content: application/json: schema: type: object example: message: 'This action is unauthorized.' properties: message: type: string example: 'This action is unauthorized.' tags: - Bookings post: summary: 'Store a newly created booking.' operationId: storeANewlyCreatedBooking description: "Creates a new booking associated with the current account context and the authenticated user.\nThe booking will be processed according to the specified service product." parameters: [] responses: 201: description: '' content: application/json: schema: type: object example: message: 'Booking created successfully' booking_id: 01ARZ3NDEKTSV4RRFFQ69G5FAV properties: message: type: string example: 'Booking created successfully' booking_id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAV 400: description: '' content: application/json: schema: type: object example: message: 'No account context set' properties: message: type: string example: 'No account context set' 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: '' content: application/json: schema: type: object example: message: 'This action is unauthorized.' properties: message: type: string example: 'This action is unauthorized.' 422: description: '' content: application/json: schema: type: object example: message: 'The given data was invalid.' errors: delivery: - 'The delivery field is required.' collection.address_id: - 'The collection address id field is required when collection is present.' locker_reservation_window.site_id: - 'The locker reservation window site must match the delivery site.' properties: message: type: string example: 'The given data was invalid.' errors: type: object properties: delivery: type: array example: - 'The delivery field is required.' items: type: string collection.address_id: type: array example: - 'The collection address id field is required when collection is present.' items: type: string locker_reservation_window.site_id: type: array example: - 'The locker reservation window site must match the delivery site.' items: type: string tags: - Bookings requestBody: required: true content: application/json: schema: type: object properties: service_product_id: type: string description: "The ID of the service product that defines how the booking should be processed. If not provided, the account's default service product will be used." example: 01ARZ3NDEKTSV4RRFFQ69G5FAX nullable: false collection: type: object description: 'Collection details (required if service product requires collection)' example: [] nullable: false properties: address_id: type: string description: 'The address ID where items will be collected from' example: 01ARZ3NDEKTSV4RRFFQ69G5FAY nullable: false delivery: type: object description: 'Delivery details (always required)' example: [] nullable: false properties: site_id: type: string description: 'The site ID where items will be delivered (if to a locker site)' example: 01ARZ3NDEKTSV4RRFFQ69G5FAZ nullable: false address_id: type: string description: 'The address ID where items will be delivered (if to a custom address)' example: 01ARZ3NDEKTSV4RRFFQ69G5FAX nullable: false locker_reservation_window: type: object description: 'Locker reservation window (optional, not auto-created)' example: [] nullable: false properties: site_id: type: string description: 'The site ID for the locker reservation window (must match delivery.site_id if delivery is to a site)' example: 01ARZ3NDEKTSV4RRFFQ69G5FAZ nullable: false t_earliest_arrival: type: string description: 'Earliest arrival time (ISO 8601)' example: '2025-01-15T09:00:00Z' nullable: false t_latest_collection: type: string description: 'Latest collection time (ISO 8601)' example: '2025-01-22T17:00:00Z' nullable: false contacts: type: array description: 'Array of contacts to notify' example: - architecto items: type: string items: type: array description: 'Array of items to be stored in the booking' example: - architecto items: type: string authorisation_group_ids: type: array description: 'Array of authorisation group IDs' example: - 01ARZ3NDEKTSV4RRFFQ69G5FAY items: type: string locker_user_ids: type: array description: 'Array of locker user IDs' example: - 01ARZ3NDEKTSV4RRFFQ69G5FAZ items: type: string required: - delivery '/v1/bookings/{booking_id}': get: summary: 'Display the specified booking.' operationId: displayTheSpecifiedBooking description: "Returns detailed information about a specific booking. The booking\nmust belong to the current account context." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: data: id: 01ARZ3NDEKTSV4RRFFQ69G5FAV reference_id: BK-2025-001 created_at: '2025-01-01T00:00:00.000000Z' updated_at: '2025-01-01T00:00:00.000000Z' status: id: 01ARZ3NDEKTSV4RRFFQ69G5FAX name: confirmed user: id: 01ARZ3NDEKTSV4RRFFQ69G5FAY name: 'John Doe' account: id: 01ARZ3NDEKTSV4RRFFQ69G5FAZ name: 'Acme Corp' service_product: id: 01ARZ3NDEKTSV4RRFFQ69G5FAX name: 'DC to Locker' description: 'Transport from Dispatch Centre to Locker' items: - id: 01ARZ3NDEKTSV4RRFFQ69G5FAB name: 'Box of documents' description: 'Important business documents' weight: 5.5 height: 30 width: 40 depth: 50 volume: 60000 created_at: '2025-01-01T00:00:00.000000Z' updated_at: '2025-01-01T00:00:00.000000Z' status_history: [] properties: data: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAV reference_id: type: string example: BK-2025-001 created_at: type: string example: '2025-01-01T00:00:00.000000Z' updated_at: type: string example: '2025-01-01T00:00:00.000000Z' status: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAX name: type: string example: confirmed user: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAY name: type: string example: 'John Doe' account: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAZ name: type: string example: 'Acme Corp' service_product: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAX name: type: string example: 'DC to Locker' description: type: string example: 'Transport from Dispatch Centre to Locker' items: type: array example: - id: 01ARZ3NDEKTSV4RRFFQ69G5FAB name: 'Box of documents' description: 'Important business documents' weight: 5.5 height: 30 width: 40 depth: 50 volume: 60000 created_at: '2025-01-01T00:00:00.000000Z' updated_at: '2025-01-01T00:00:00.000000Z' items: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAB name: type: string example: 'Box of documents' description: type: string example: 'Important business documents' weight: type: number example: 5.5 height: type: integer example: 30 width: type: integer example: 40 depth: type: integer example: 50 volume: type: integer example: 60000 created_at: type: string example: '2025-01-01T00:00:00.000000Z' updated_at: type: string example: '2025-01-01T00:00:00.000000Z' status_history: type: array example: [] 400: description: '' content: application/json: schema: type: object example: message: 'No account context set' properties: message: type: string example: 'No account context set' 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 404: description: '' content: application/json: schema: type: object example: message: 'Booking not found' properties: message: type: string example: 'Booking not found' tags: - Bookings delete: summary: 'Cancel the specified booking.' operationId: cancelTheSpecifiedBooking description: "Cancels a booking, removing it from active status. The booking\nmust belong to the current account context." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: message: 'Booking cancelled' booking: id: 01ARZ3NDEKTSV4RRFFQ69G5FAV reference_id: BK-2025-001 created_at: '2025-01-01T00:00:00.000000Z' updated_at: '2025-01-01T00:00:00.000000Z' status: id: 01ARZ3NDEKTSV4RRFFQ69G5FAX name: cancelled user: null account: null items: [] status_history: [] properties: message: type: string example: 'Booking cancelled' booking: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAV reference_id: type: string example: BK-2025-001 created_at: type: string example: '2025-01-01T00:00:00.000000Z' updated_at: type: string example: '2025-01-01T00:00:00.000000Z' status: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAX name: type: string example: cancelled user: type: string example: null account: type: string example: null items: type: array example: [] status_history: type: array example: [] 400: description: '' content: application/json: schema: type: object example: message: 'No account context set' properties: message: type: string example: 'No account context set' 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 404: description: '' content: application/json: schema: type: object example: message: 'Booking not found' properties: message: type: string example: 'Booking not found' tags: - Bookings parameters: - in: path name: booking_id description: 'The ID of the booking.' example: 01kc4drge0a29g6p1hxk9wn2kv required: true schema: type: string - in: path name: booking description: 'The ID of the booking' example: 01ARZ3NDEKTSV4RRFFQ69G5FAV required: true schema: type: string '/v1/bookings/{booking_id}/authorisation': post: summary: 'Add or update booking authorisations.' operationId: addOrUpdateBookingAuthorisations description: "Adds or extends authorisation groups and locker users for an existing booking.\nThe booking must belong to the current account context." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: message: 'Authorisations updated' properties: message: type: string example: 'Authorisations updated' 400: description: '' content: application/json: schema: type: object example: message: 'No account context set' properties: message: type: string example: 'No account context set' 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 404: description: '' content: application/json: schema: type: object example: message: 'Booking not found' properties: message: type: string example: 'Booking not found' 422: description: '' content: application/json: schema: type: object example: message: 'The given data was invalid.' errors: authorisation_group_ids.0: - 'The selected authorisation group ids.0 is invalid.' properties: message: type: string example: 'The given data was invalid.' errors: type: object properties: authorisation_group_ids.0: type: array example: - 'The selected authorisation group ids.0 is invalid.' items: type: string tags: - Bookings requestBody: required: false content: application/json: schema: type: object properties: authorisation_group_ids: type: array description: 'Array of authorisation group IDs to add' example: - 01ARZ3NDEKTSV4RRFFQ69G5FAY items: type: string locker_user_ids: type: array description: 'Array of locker user IDs to add' example: - 01ARZ3NDEKTSV4RRFFQ69G5FAZ items: type: string parameters: - in: path name: booking_id description: 'The ID of the booking.' example: 01kc4drge0a29g6p1hxk9wn2kv required: true schema: type: string - in: path name: booking description: 'The ID of the booking' example: 01ARZ3NDEKTSV4RRFFQ69G5FAV required: true schema: type: string '/v1/bookings/{booking_id}/generate-codes': post: summary: 'Generate lock codes for booking lockers.' operationId: generateLockCodesForBookingLockers description: "Generates access codes for all lockers associated with a booking.\nThe booking must belong to the current account context." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: message: 'Lock codes generated' codes: - locker_id: 01ARZ3NDEKTSV4RRFFQ69G5FAC code: '1234' properties: message: type: string example: 'Lock codes generated' codes: type: array example: - locker_id: 01ARZ3NDEKTSV4RRFFQ69G5FAC code: '1234' items: type: object properties: locker_id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAC code: type: string example: '1234' 400: description: '' content: application/json: schema: type: object example: message: 'No account context set' properties: message: type: string example: 'No account context set' 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: '' content: application/json: schema: type: object example: message: 'This action is unauthorized.' properties: message: type: string example: 'This action is unauthorized.' 404: description: '' content: application/json: schema: type: object example: message: 'Booking not found' properties: message: type: string example: 'Booking not found' tags: - Bookings parameters: - in: path name: booking_id description: 'The ID of the booking.' example: 01kc4drge0a29g6p1hxk9wn2kv required: true schema: type: string - in: path name: booking description: 'The ID of the booking' example: 01ARZ3NDEKTSV4RRFFQ69G5FAV required: true schema: type: string '/v1/bookings/{booking_id}/send-booking-confirmation': post: summary: 'Send booking confirmation to customer.' operationId: sendBookingConfirmationToCustomer description: "Sends booking confirmation notification via email and SMS.\nThis includes any access codes if the booking has locker assignments." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: message: 'Booking confirmation sent successfully' email: sent: true recipient: customer@example.com sms: sent: true recipient: '+44 1234 567890' properties: message: type: string example: 'Booking confirmation sent successfully' email: type: object properties: sent: type: boolean example: true recipient: type: string example: customer@example.com sms: type: object properties: sent: type: boolean example: true recipient: type: string example: '+44 1234 567890' 400: description: '' content: application/json: schema: type: object example: message: 'No customer contact information available' properties: message: type: string example: 'No customer contact information available' 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: '' content: application/json: schema: type: object example: message: 'This action is unauthorized.' properties: message: type: string example: 'This action is unauthorized.' 404: description: '' content: application/json: schema: type: object example: message: 'Booking not found' properties: message: type: string example: 'Booking not found' tags: - Bookings parameters: - in: path name: booking_id description: 'The ID of the booking.' example: 01kc4drge0a29g6p1hxk9wn2kv required: true schema: type: string - in: path name: booking description: 'The ID of the booking' example: 01ARZ3NDEKTSV4RRFFQ69G5FAV required: true schema: type: string '/v1/bookings/{booking_id}/send-reminder': post: summary: 'Send booking reminder email.' operationId: sendBookingReminderEmail description: 'Sends a reminder email before the booking starts with all access codes.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: message: 'Reminder sent successfully' properties: message: type: string example: 'Reminder sent successfully' 400: description: '' content: application/json: schema: type: object example: message: 'No customer contact information available' properties: message: type: string example: 'No customer contact information available' 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: '' content: application/json: schema: type: object example: message: 'This action is unauthorized.' properties: message: type: string example: 'This action is unauthorized.' 404: description: '' content: application/json: schema: type: object example: message: 'Booking not found' properties: message: type: string example: 'Booking not found' tags: - Bookings parameters: - in: path name: booking_id description: 'The ID of the booking.' example: 01kc4drge0a29g6p1hxk9wn2kv required: true schema: type: string - in: path name: booking description: 'The ID of the booking' example: 01ARZ3NDEKTSV4RRFFQ69G5FAV required: true schema: type: string '/v1/bookings/{booking_id}/send-expiry-reminder': post: summary: 'Send expiry reminder email.' operationId: sendExpiryReminderEmail description: 'Sends a reminder email before the booking expires.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: message: 'Expiry reminder sent successfully' properties: message: type: string example: 'Expiry reminder sent successfully' 400: description: '' content: application/json: schema: type: object example: message: 'No customer contact information available' properties: message: type: string example: 'No customer contact information available' 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: '' content: application/json: schema: type: object example: message: 'This action is unauthorized.' properties: message: type: string example: 'This action is unauthorized.' 404: description: '' content: application/json: schema: type: object example: message: 'Booking not found' properties: message: type: string example: 'Booking not found' tags: - Bookings parameters: - in: path name: booking_id description: 'The ID of the booking.' example: 01kc4drge0a29g6p1hxk9wn2kv required: true schema: type: string - in: path name: booking description: 'The ID of the booking' example: 01ARZ3NDEKTSV4RRFFQ69G5FAV required: true schema: type: string '/v1/bookings/{booking_id}/send-cancellation-notice': post: summary: 'Send cancellation notice email.' operationId: sendCancellationNoticeEmail description: 'Sends a cancellation notice when a booking is cancelled.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: message: 'Cancellation notice sent successfully' properties: message: type: string example: 'Cancellation notice sent successfully' 400: description: '' content: application/json: schema: type: object example: message: 'No customer contact information available' properties: message: type: string example: 'No customer contact information available' 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: '' content: application/json: schema: type: object example: message: 'This action is unauthorized.' properties: message: type: string example: 'This action is unauthorized.' 404: description: '' content: application/json: schema: type: object example: message: 'Booking not found' properties: message: type: string example: 'Booking not found' tags: - Bookings requestBody: required: false content: application/json: schema: type: object properties: cancellation_reason: type: string description: 'Reason for cancellation' example: 'Customer request' nullable: false parameters: - in: path name: booking_id description: 'The ID of the booking.' example: 01kc4drge0a29g6p1hxk9wn2kv required: true schema: type: string - in: path name: booking description: 'The ID of the booking' example: 01ARZ3NDEKTSV4RRFFQ69G5FAV required: true schema: type: string /v1/cabinets: get: summary: 'Display a listing of cabinets.' operationId: displayAListingOfCabinets description: "Returns a list of cabinets with optional filtering by status, version, layout,\nmaintenance needs, or location. Cabinets include their lockers and arrangements." parameters: - in: query name: status description: 'Filter by cabinet status name' example: active required: false schema: type: string description: 'Filter by cabinet status name' example: active nullable: false - in: query name: version description: 'Filter by cabinet version' example: v2.0 required: false schema: type: string description: 'Filter by cabinet version' example: v2.0 nullable: false - in: query name: layout description: 'Filter by cabinet layout' example: standard required: false schema: type: string description: 'Filter by cabinet layout' example: standard nullable: false - in: query name: needs_maintenance description: 'Filter cabinets that need maintenance' example: true required: false schema: type: boolean description: 'Filter cabinets that need maintenance' example: true nullable: false - in: query name: latitude description: 'Latitude for location-based search (must include longitude and radius)' example: 51.5074 required: false schema: type: number description: 'Latitude for location-based search (must include longitude and radius)' example: 51.5074 nullable: false - in: query name: longitude description: 'Longitude for location-based search (must include latitude and radius)' example: -0.1278 required: false schema: type: number description: 'Longitude for location-based search (must include latitude and radius)' example: -0.1278 nullable: false - in: query name: radius description: 'Radius in kilometers for location-based search (must include latitude and longitude)' example: 10 required: false schema: type: number description: 'Radius in kilometers for location-based search (must include latitude and longitude)' example: 10 nullable: false responses: 200: description: '' content: application/json: schema: type: object example: data: - id: 01ARZ3NDEKTSV4RRFFQ69G5FAA name: 'Cabinet A1' site_id: 01ARZ3NDEKTSV4RRFFQ69G5FAW status: id: 01ARZ3NDEKTSV4RRFFQ69G5FAB name: active version: id: 01ARZ3NDEKTSV4RRFFQ69G5FAC version: v2.0 layout: standard lockers: [] properties: data: type: array example: - id: 01ARZ3NDEKTSV4RRFFQ69G5FAA name: 'Cabinet A1' site_id: 01ARZ3NDEKTSV4RRFFQ69G5FAW status: id: 01ARZ3NDEKTSV4RRFFQ69G5FAB name: active version: id: 01ARZ3NDEKTSV4RRFFQ69G5FAC version: v2.0 layout: standard lockers: [] items: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAA name: type: string example: 'Cabinet A1' site_id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAW status: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAB name: type: string example: active version: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAC version: type: string example: v2.0 layout: type: string example: standard lockers: type: array example: [] 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: '' content: application/json: schema: type: object example: message: 'This action is unauthorized.' properties: message: type: string example: 'This action is unauthorized.' tags: - Cabinets '/v1/cabinets/{id}': get: summary: 'Display the specified cabinet.' operationId: displayTheSpecifiedCabinet description: 'Returns detailed information about a specific cabinet, including its lockers and arrangements.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: data: id: 01ARZ3NDEKTSV4RRFFQ69G5FAA name: 'Cabinet A1' status: active total_active_lockers: 10 total_available_lockers: 5 site: site_id: 01ARZ3NDEKTSV4RRFFQ69G5FAW name: 'Downtown Location' lockers: [] properties: data: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAA name: type: string example: 'Cabinet A1' status: type: string example: active total_active_lockers: type: integer example: 10 total_available_lockers: type: integer example: 5 site: type: object properties: site_id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAW name: type: string example: 'Downtown Location' lockers: type: array example: [] 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: '' content: application/json: schema: type: object example: message: 'This action is unauthorized.' properties: message: type: string example: 'This action is unauthorized.' 404: description: '' content: application/json: schema: type: object example: message: 'Cabinet not found' properties: message: type: string example: 'Cabinet not found' tags: - Cabinets parameters: - in: path name: id description: 'The ID of the cabinet' example: 01ARZ3NDEKTSV4RRFFQ69G5FAA required: true schema: type: string /v1/collection-schedules: post: summary: 'Store a newly created collection schedule.' operationId: storeANewlyCreatedCollectionSchedule description: '' parameters: [] responses: 201: description: '' content: application/json: schema: type: object example: message: 'Collection schedule created successfully' data: id: 01ARZ3NDEKTSV4RRFFQ69G5FAW despatch_centre_id: 01ARZ3NDEKTSV4RRFFQ69G5FAX name: 'Weekday Morning Collection' collection_start_time: '08:00:00' collection_end_time: '10:00:00' days_of_week: - 0 - 1 - 2 - 3 - 4 is_active: true properties: message: type: string example: 'Collection schedule created successfully' data: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAW despatch_centre_id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAX name: type: string example: 'Weekday Morning Collection' collection_start_time: type: string example: '08:00:00' collection_end_time: type: string example: '10:00:00' days_of_week: type: array example: - 0 - 1 - 2 - 3 - 4 items: type: integer is_active: type: boolean example: true 400: description: '' content: application/json: schema: type: object example: message: 'No account context set' properties: message: type: string example: 'No account context set' 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: '' content: application/json: schema: type: object example: message: 'This action is unauthorized.' properties: message: type: string example: 'This action is unauthorized.' tags: - 'Collection Schedules' requestBody: required: true content: application/json: schema: type: object properties: despatch_centre_id: type: string description: 'The ID of the despatch centre' example: 01ARZ3NDEKTSV4RRFFQ69G5FAW nullable: false name: type: string description: 'Name of the collection schedule' example: 'Weekday Morning Collection' nullable: false description: type: string description: 'Description of the collection schedule' example: 'Eius et animi quos velit et.' nullable: false collection_start_time: type: string description: 'Collection start time (HH:mm:ss)' example: '08:00:00' nullable: false collection_end_time: type: string description: 'Collection end time (HH:mm:ss)' example: '10:00:00' nullable: false days_of_week: type: array description: 'Array of day numbers (0=Monday, 6=Sunday)' example: - 0 - 1 - 2 - 3 - 4 items: type: string effective_from: type: string description: 'Effective from date (ISO 8601)' example: '2025-01-01T00:00:00Z' nullable: false effective_until: type: string description: 'Effective until date (ISO 8601)' example: '2025-12-31T23:59:59Z' nullable: false is_active: type: boolean description: 'Whether the schedule is active' example: true nullable: false required: - despatch_centre_id - name - collection_start_time - collection_end_time - days_of_week /v1/despatch-centres: get: summary: 'Display a listing of despatch centres.' operationId: displayAListingOfDespatchCentres description: 'Returns a paginated list of despatch centres for the current account.' parameters: - in: query name: per_page description: 'Number of items per page (max 100)' example: 20 required: false schema: type: integer description: 'Number of items per page (max 100)' example: 20 nullable: false - in: query name: page description: 'Page number' example: 1 required: false schema: type: integer description: 'Page number' example: 1 nullable: false responses: 200: description: '' content: application/json: schema: type: object example: data: - id: 01ARZ3NDEKTSV4RRFFQ69G5FAW account_id: 01ARZ3NDEKTSV4RRFFQ69G5FAX name: 'Main Warehouse' description: 'Primary despatch centre' address_id: 01ARZ3NDEKTSV4RRFFQ69G5FAY address: id: 01ARZ3NDEKTSV4RRFFQ69G5FAY line_1: '123 Industrial Way' line_2: null city: London postcode: 'SW1A 1AA' latitude: 51.5074 longitude: -0.1278 access_instructions: 'Enter through main gate' special_notes: null contact_phone: '+44 20 1234 5678' contact_email: warehouse@example.com is_active: true pagination: current_page: 1 per_page: 50 total: 10 last_page: 1 properties: data: type: array example: - id: 01ARZ3NDEKTSV4RRFFQ69G5FAW account_id: 01ARZ3NDEKTSV4RRFFQ69G5FAX name: 'Main Warehouse' description: 'Primary despatch centre' address_id: 01ARZ3NDEKTSV4RRFFQ69G5FAY address: id: 01ARZ3NDEKTSV4RRFFQ69G5FAY line_1: '123 Industrial Way' line_2: null city: London postcode: 'SW1A 1AA' latitude: 51.5074 longitude: -0.1278 access_instructions: 'Enter through main gate' special_notes: null contact_phone: '+44 20 1234 5678' contact_email: warehouse@example.com is_active: true items: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAW account_id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAX name: type: string example: 'Main Warehouse' description: type: string example: 'Primary despatch centre' address_id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAY address: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAY line_1: type: string example: '123 Industrial Way' line_2: type: string example: null city: type: string example: London postcode: type: string example: 'SW1A 1AA' latitude: type: number example: 51.5074 longitude: type: number example: -0.1278 access_instructions: type: string example: 'Enter through main gate' special_notes: type: string example: null contact_phone: type: string example: '+44 20 1234 5678' contact_email: type: string example: warehouse@example.com is_active: type: boolean example: true pagination: type: object properties: current_page: type: integer example: 1 per_page: type: integer example: 50 total: type: integer example: 10 last_page: type: integer example: 1 400: description: '' content: application/json: schema: type: object example: message: 'No account context set' properties: message: type: string example: 'No account context set' 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: '' content: application/json: schema: type: object example: message: 'This action is unauthorized.' properties: message: type: string example: 'This action is unauthorized.' tags: - 'Despatch Centres' post: summary: 'Store a newly created despatch centre.' operationId: storeANewlyCreatedDespatchCentre description: '' parameters: [] responses: 201: description: '' content: application/json: schema: type: object example: message: 'Despatch centre created successfully' data: id: 01ARZ3NDEKTSV4RRFFQ69G5FAW name: 'Main Warehouse' properties: message: type: string example: 'Despatch centre created successfully' data: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAW name: type: string example: 'Main Warehouse' 400: description: '' content: application/json: schema: type: object example: message: 'No account context set' properties: message: type: string example: 'No account context set' 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: '' content: application/json: schema: type: object example: message: 'This action is unauthorized.' properties: message: type: string example: 'This action is unauthorized.' tags: - 'Despatch Centres' requestBody: required: true content: application/json: schema: type: object properties: name: type: string description: 'Name of the despatch centre' example: 'Main Warehouse' nullable: false description: type: string description: 'Description of the despatch centre' example: 'Primary despatch centre' nullable: false address_line_1: type: string description: 'First line of address' example: '123 Industrial Way' nullable: false address_line_2: type: string description: 'Second line of address' example: architecto nullable: false city: type: string description: City example: London nullable: false postcode: type: string description: Postcode example: 'SW1A 1AA' nullable: false county: type: string description: County example: 'Greater London' nullable: false country: type: string description: Country example: 'United Kingdom' nullable: false latitude: type: number description: Latitude example: 51.5074 nullable: false longitude: type: number description: Longitude example: -0.1278 nullable: false access_instructions: type: string description: 'Access instructions' example: architecto nullable: false special_notes: type: string description: 'Special notes' example: architecto nullable: false contact_phone: type: string description: 'Contact phone number' example: architecto nullable: false contact_email: type: string description: 'Contact email address' example: gbailey@example.net nullable: false is_active: type: boolean description: 'Whether the despatch centre is active' example: true nullable: false required: - name - address_line_1 - postcode '/v1/despatch-centres/{id}': get: summary: 'Display the specified despatch centre.' operationId: displayTheSpecifiedDespatchCentre description: '' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: data: id: 01ARZ3NDEKTSV4RRFFQ69G5FAW account_id: 01ARZ3NDEKTSV4RRFFQ69G5FAX name: 'Main Warehouse' description: 'Primary despatch centre' address_id: 01ARZ3NDEKTSV4RRFFQ69G5FAY address: id: 01ARZ3NDEKTSV4RRFFQ69G5FAY line_1: '123 Industrial Way' line_2: null city: London postcode: 'SW1A 1AA' latitude: 51.5074 longitude: -0.1278 access_instructions: 'Enter through main gate' special_notes: null contact_phone: '+44 20 1234 5678' contact_email: warehouse@example.com is_active: true properties: data: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAW account_id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAX name: type: string example: 'Main Warehouse' description: type: string example: 'Primary despatch centre' address_id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAY address: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAY line_1: type: string example: '123 Industrial Way' line_2: type: string example: null city: type: string example: London postcode: type: string example: 'SW1A 1AA' latitude: type: number example: 51.5074 longitude: type: number example: -0.1278 access_instructions: type: string example: 'Enter through main gate' special_notes: type: string example: null contact_phone: type: string example: '+44 20 1234 5678' contact_email: type: string example: warehouse@example.com is_active: type: boolean example: true 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: '' content: application/json: schema: type: object example: message: 'This action is unauthorized.' properties: message: type: string example: 'This action is unauthorized.' 404: description: '' content: application/json: schema: type: object example: message: 'Despatch centre not found' properties: message: type: string example: 'Despatch centre not found' tags: - 'Despatch Centres' put: summary: 'Update the specified despatch centre.' operationId: updateTheSpecifiedDespatchCentre description: '' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: message: 'Despatch centre updated successfully' data: id: 01ARZ3NDEKTSV4RRFFQ69G5FAW name: 'Main Warehouse' properties: message: type: string example: 'Despatch centre updated successfully' data: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAW name: type: string example: 'Main Warehouse' 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: '' content: application/json: schema: type: object example: message: 'This action is unauthorized.' properties: message: type: string example: 'This action is unauthorized.' 404: description: '' content: application/json: schema: type: object example: message: 'Despatch centre not found' properties: message: type: string example: 'Despatch centre not found' tags: - 'Despatch Centres' requestBody: required: false content: application/json: schema: type: object properties: name: type: string description: 'Must not be greater than 255 characters.' example: b nullable: false description: type: string description: 'Must not be greater than 1000 characters.' example: 'Et animi quos velit et fugiat.' nullable: true address_line_1: type: string description: 'Must not be greater than 255 characters.' example: d nullable: false address_line_2: type: string description: 'Must not be greater than 255 characters.' example: l nullable: true city: type: string description: 'Must not be greater than 255 characters.' example: j nullable: true postcode: type: string description: 'Must not be greater than 20 characters.' example: nikhwaykcmyuwpwl nullable: false county: type: string description: 'Must not be greater than 255 characters.' example: v nullable: true country: type: string description: 'Must not be greater than 255 characters.' example: q nullable: true latitude: type: number description: 'Must be between -90 and 90.' example: -90 nullable: true longitude: type: number description: 'Must be between -180 and 180.' example: -179 nullable: true access_instructions: type: string description: 'Must not be greater than 1000 characters.' example: s nullable: true special_notes: type: string description: 'Must not be greater than 1000 characters.' example: i nullable: true contact_phone: type: string description: 'Must not be greater than 50 characters.' example: t nullable: true contact_email: type: string description: 'Must be a valid email address. Must not be greater than 255 characters.' example: okeefe.isidro@example.org nullable: true is_active: type: boolean description: '' example: false nullable: true delete: summary: 'Remove the specified despatch centre.' operationId: removeTheSpecifiedDespatchCentre description: '' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: message: 'Despatch centre deleted successfully' properties: message: type: string example: 'Despatch centre deleted successfully' 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: '' content: application/json: schema: type: object example: message: 'This action is unauthorized.' properties: message: type: string example: 'This action is unauthorized.' 404: description: '' content: application/json: schema: type: object example: message: 'Despatch centre not found' properties: message: type: string example: 'Despatch centre not found' tags: - 'Despatch Centres' parameters: - in: path name: id description: 'The ID of the despatch centre' example: 01ARZ3NDEKTSV4RRFFQ69G5FAW required: true schema: type: string /v1/sites: get: summary: 'Display a listing of sites with search and pagination.' operationId: displayAListingOfSitesWithSearchAndPagination description: "Returns a paginated list of active sites. Supports location-based filtering\nto find sites within a specified radius of coordinates." parameters: - in: query name: latitude description: 'Latitude for location-based search (must include longitude and radius)' example: 51.5074 required: false schema: type: number description: 'Latitude for location-based search (must include longitude and radius)' example: 51.5074 nullable: false - in: query name: longitude description: 'Longitude for location-based search (must include latitude and radius)' example: -0.1278 required: false schema: type: number description: 'Longitude for location-based search (must include latitude and radius)' example: -0.1278 nullable: false - in: query name: radius description: 'Radius in kilometers for location-based search (must include latitude and longitude)' example: 10 required: false schema: type: number description: 'Radius in kilometers for location-based search (must include latitude and longitude)' example: 10 nullable: false - in: query name: per_page description: 'Number of items per page (max 100)' example: 20 required: false schema: type: integer description: 'Number of items per page (max 100)' example: 20 nullable: false - in: query name: page description: 'Page number' example: 1 required: false schema: type: integer description: 'Page number' example: 1 nullable: false responses: 200: description: '' content: application/json: schema: type: object example: data: - id: 01ARZ3NDEKTSV4RRFFQ69G5FAW name: 'Downtown Location' address_line_1: '123 Main St' address_line_2: null city: London postcode: 'SW1A 1AA' county: 'Greater London' country: 'United Kingdom' latitude: 51.5074 longitude: -0.1278 access_instructions: 'Enter through main entrance' special_notes: null height_restriction: 2.5 contact_phone: '+44 20 1234 5678' contact_email: downtown@example.com is_active: true distance: km: 2.5 mi: 1.55 site_access_codes: - name: 'Customer access code 1' code: AB12CD34 pagination: current_page: 1 per_page: 50 total: 25 last_page: 1 from: 1 to: 25 has_more_pages: false links: first: 'http://example.com/api/v1/sites?page=1' last: 'http://example.com/api/v1/sites?page=1' prev: null next: null properties: data: type: array example: - id: 01ARZ3NDEKTSV4RRFFQ69G5FAW name: 'Downtown Location' address_line_1: '123 Main St' address_line_2: null city: London postcode: 'SW1A 1AA' county: 'Greater London' country: 'United Kingdom' latitude: 51.5074 longitude: -0.1278 access_instructions: 'Enter through main entrance' special_notes: null height_restriction: 2.5 contact_phone: '+44 20 1234 5678' contact_email: downtown@example.com is_active: true distance: km: 2.5 mi: 1.55 site_access_codes: - name: 'Customer access code 1' code: AB12CD34 items: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAW name: type: string example: 'Downtown Location' address_line_1: type: string example: '123 Main St' address_line_2: type: string example: null city: type: string example: London postcode: type: string example: 'SW1A 1AA' county: type: string example: 'Greater London' country: type: string example: 'United Kingdom' latitude: type: number example: 51.5074 longitude: type: number example: -0.1278 access_instructions: type: string example: 'Enter through main entrance' special_notes: type: string example: null height_restriction: type: number example: 2.5 contact_phone: type: string example: '+44 20 1234 5678' contact_email: type: string example: downtown@example.com is_active: type: boolean example: true distance: type: object properties: km: type: number example: 2.5 mi: type: number example: 1.55 site_access_codes: type: array example: - name: 'Customer access code 1' code: AB12CD34 items: type: object properties: name: type: string example: 'Customer access code 1' code: type: string example: AB12CD34 pagination: type: object properties: current_page: type: integer example: 1 per_page: type: integer example: 50 total: type: integer example: 25 last_page: type: integer example: 1 from: type: integer example: 1 to: type: integer example: 25 has_more_pages: type: boolean example: false links: type: object properties: first: type: string example: 'http://example.com/api/v1/sites?page=1' last: type: string example: 'http://example.com/api/v1/sites?page=1' prev: type: string example: null next: type: string example: null 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: '' content: application/json: schema: type: object example: message: 'This action is unauthorized.' properties: message: type: string example: 'This action is unauthorized.' tags: - Sites '/v1/sites/{id}': get: summary: 'Display the specified site.' operationId: displayTheSpecifiedSite description: 'Returns detailed information about a specific site.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: data: id: 01ARZ3NDEKTSV4RRFFQ69G5FAW name: 'Downtown Location' address_line_1: '123 Main St' address_line_2: null city: London postcode: 'SW1A 1AA' county: 'Greater London' country: 'United Kingdom' latitude: 51.5074 longitude: -0.1278 access_instructions: 'Enter through main entrance' special_notes: null height_restriction: 2.5 contact_phone: '+44 20 1234 5678' contact_email: downtown@example.com is_active: true site_access_codes: - id: 01ARZ3NDEKTSV4RRFFQ69G5FBA name: 'Customer access code 1' code: AB12CD34 type: id: 01ARZ3NDEKTSV4RRFFQ69G5FBB name: customer properties: data: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAW name: type: string example: 'Downtown Location' address_line_1: type: string example: '123 Main St' address_line_2: type: string example: null city: type: string example: London postcode: type: string example: 'SW1A 1AA' county: type: string example: 'Greater London' country: type: string example: 'United Kingdom' latitude: type: number example: 51.5074 longitude: type: number example: -0.1278 access_instructions: type: string example: 'Enter through main entrance' special_notes: type: string example: null height_restriction: type: number example: 2.5 contact_phone: type: string example: '+44 20 1234 5678' contact_email: type: string example: downtown@example.com is_active: type: boolean example: true site_access_codes: type: array example: - id: 01ARZ3NDEKTSV4RRFFQ69G5FBA name: 'Customer access code 1' code: AB12CD34 type: id: 01ARZ3NDEKTSV4RRFFQ69G5FBB name: customer items: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FBA name: type: string example: 'Customer access code 1' code: type: string example: AB12CD34 type: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FBB name: type: string example: customer 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: '' content: application/json: schema: type: object example: message: 'This action is unauthorized.' properties: message: type: string example: 'This action is unauthorized.' 404: description: '' content: application/json: schema: type: object example: message: 'Site not found' properties: message: type: string example: 'Site not found' tags: - Sites parameters: - in: path name: id description: 'The ID of the site' example: 01ARZ3NDEKTSV4RRFFQ69G5FAW required: true schema: type: string /v1/tokens/generate: post: summary: 'Generate API token for account.' operationId: generateAPITokenForAccount description: "Creates a new API token for the authenticated user in the current account context.\nRequires Admin or Owner role in the current account." parameters: [] responses: 201: description: '' content: application/json: schema: type: object example: token: 1|abcdefghijklmnopqrstuvwxyz1234567890 token_name: 'Production API Token' account_id: 01ARZ3NDEKTSV4RRFFQ69G5FAW abilities: - '*' expires_at: '2025-12-31T23:59:59.000000Z' created_at: '2025-01-01T00:00:00.000000Z' message: 'API token generated successfully' properties: token: type: string example: 1|abcdefghijklmnopqrstuvwxyz1234567890 token_name: type: string example: 'Production API Token' account_id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAW abilities: type: array example: - '*' items: type: string expires_at: type: string example: '2025-12-31T23:59:59.000000Z' created_at: type: string example: '2025-01-01T00:00:00.000000Z' message: type: string example: 'API token generated successfully' 400: description: '' content: application/json: schema: type: object example: message: 'No account context set' properties: message: type: string example: 'No account context set' 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: '' content: application/json: schema: type: object example: message: 'This action is unauthorized.' properties: message: type: string example: 'This action is unauthorized.' 422: description: '' content: application/json: schema: type: object example: message: 'The given data was invalid.' errors: token_name: - 'The token name field is required.' expires_at: - 'The expires at must be a date after now.' properties: message: type: string example: 'The given data was invalid.' errors: type: object properties: token_name: type: array example: - 'The token name field is required.' items: type: string expires_at: type: array example: - 'The expires at must be a date after now.' items: type: string tags: - 'Token Management' requestBody: required: true content: application/json: schema: type: object properties: token_name: type: string description: 'Name for the token' example: 'Production API Token' nullable: false expires_at: type: string description: 'Expiration date and time (ISO 8601). Must be in the future' example: '2025-12-31T23:59:59Z' nullable: false required: - token_name /v1/tokens: get: summary: 'List API tokens for account.' operationId: listAPITokensForAccount description: "Returns all API tokens for the authenticated user in the current account context.\nRequires Admin or Owner role in the current account." parameters: - in: query name: search description: 'Search tokens by name' example: Production required: false schema: type: string description: 'Search tokens by name' example: Production nullable: false responses: 200: description: '' content: application/json: schema: type: object example: tokens: - id: 1 name: 'Production API Token' abilities: - '*' last_used_at: '2025-01-15T10:30:00.000000Z' created_at: '2025-01-01T00:00:00.000000Z' expires_at: '2025-12-31T23:59:59.000000Z' account_id: 01ARZ3NDEKTSV4RRFFQ69G5FAW total: 1 properties: tokens: type: array example: - id: 1 name: 'Production API Token' abilities: - '*' last_used_at: '2025-01-15T10:30:00.000000Z' created_at: '2025-01-01T00:00:00.000000Z' expires_at: '2025-12-31T23:59:59.000000Z' items: type: object properties: id: type: integer example: 1 name: type: string example: 'Production API Token' abilities: type: array example: - '*' items: type: string last_used_at: type: string example: '2025-01-15T10:30:00.000000Z' created_at: type: string example: '2025-01-01T00:00:00.000000Z' expires_at: type: string example: '2025-12-31T23:59:59.000000Z' account_id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAW total: type: integer example: 1 400: description: '' content: application/json: schema: type: object example: message: 'No account context set' properties: message: type: string example: 'No account context set' 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: '' content: application/json: schema: type: object example: message: 'This action is unauthorized.' properties: message: type: string example: 'This action is unauthorized.' tags: - 'Token Management' delete: summary: 'Revoke all API tokens for account.' operationId: revokeAllAPITokensForAccount description: "Revokes all API tokens for the authenticated user in the current account context.\nRequires Admin or Owner role in the current account." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: message: 'All API tokens revoked successfully' deleted_count: 5 properties: message: type: string example: 'All API tokens revoked successfully' deleted_count: type: integer example: 5 400: description: '' content: application/json: schema: type: object example: message: 'No account context set' properties: message: type: string example: 'No account context set' 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: '' content: application/json: schema: type: object example: message: 'This action is unauthorized.' properties: message: type: string example: 'This action is unauthorized.' tags: - 'Token Management' '/v1/tokens/{tokenId}': delete: summary: 'Revoke a specific API token.' operationId: revokeASpecificAPIToken description: 'Revokes a single API token by ID. Requires Admin or Owner role in the current account.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: message: 'API token revoked successfully' properties: message: type: string example: 'API token revoked successfully' 400: description: '' content: application/json: schema: type: object example: message: 'No account context set' properties: message: type: string example: 'No account context set' 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: '' content: application/json: schema: type: object example: message: 'This action is unauthorized.' properties: message: type: string example: 'This action is unauthorized.' 404: description: '' content: application/json: schema: type: object example: message: 'Token not found' properties: message: type: string example: 'Token not found' tags: - 'Token Management' parameters: - in: path name: tokenId description: 'The ID of the token to revoke' example: '1' required: true schema: type: string /v1/user: get: summary: 'Get the current authenticated user' operationId: getTheCurrentAuthenticatedUser description: "Returns information about the currently authenticated user, including all accounts they belong to,\ntheir roles in each account, and the current account context." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: data: id: 01ARZ3NDEKTSV4RRFFQ69G5FAV name: 'John Doe' email: john@example.com created_at: '2025-01-01T00:00:00.000000Z' is_active: true accounts: - id: 01ARZ3NDEKTSV4RRFFQ69G5FAW name: 'Acme Corp' slug: acme-corp is_active: true joined_at: '2025-01-01T00:00:00.000000Z' role: owner current_account: id: 01ARZ3NDEKTSV4RRFFQ69G5FAW name: 'Acme Corp' slug: acme-corp role: owner role: owner permissions: - bookings.view - account.manage_users properties: data: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAV name: type: string example: 'John Doe' email: type: string example: john@example.com created_at: type: string example: '2025-01-01T00:00:00.000000Z' is_active: type: boolean example: true accounts: type: array example: - id: 01ARZ3NDEKTSV4RRFFQ69G5FAW name: 'Acme Corp' slug: acme-corp is_active: true joined_at: '2025-01-01T00:00:00.000000Z' role: owner items: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAW name: type: string example: 'Acme Corp' slug: type: string example: acme-corp is_active: type: boolean example: true joined_at: type: string example: '2025-01-01T00:00:00.000000Z' role: type: string example: owner required: - id - name - is_active - role current_account: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAW name: type: string example: 'Acme Corp' slug: type: string example: acme-corp role: type: string example: owner required: - id - name - role role: type: string example: owner permissions: type: array example: - bookings.view - account.manage_users items: type: string required: - id - name - email - created_at - is_active - accounts - current_account - role - permissions 401: description: '' content: application/json: schema: type: object example: message: 'User not authenticated' properties: message: type: string example: 'User not authenticated' tags: - 'User Management' /v1/webhooks: get: summary: 'Display a listing of webhooks.' operationId: displayAListingOfWebhooks description: "Returns all webhooks for the authenticated user's account." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: data: - id: 01ARZ3NDEKTSV4RRFFQ69G5FAW account_id: 01ARZ3NDEKTSV4RRFFQ69G5FAX name: 'Production Webhook' description: 'Webhook for production events' url: 'https://example.com/webhook' secret: whsec_... event_types: - booking.created - booking.cancelled is_active: true created_at: '2024-01-01T00:00:00.000000Z' updated_at: '2024-01-01T00:00:00.000000Z' properties: data: type: array example: - id: 01ARZ3NDEKTSV4RRFFQ69G5FAW account_id: 01ARZ3NDEKTSV4RRFFQ69G5FAX name: 'Production Webhook' description: 'Webhook for production events' url: 'https://example.com/webhook' secret: whsec_... event_types: - booking.created - booking.cancelled is_active: true created_at: '2024-01-01T00:00:00.000000Z' updated_at: '2024-01-01T00:00:00.000000Z' items: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAW account_id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAX name: type: string example: 'Production Webhook' description: type: string example: 'Webhook for production events' url: type: string example: 'https://example.com/webhook' secret: type: string example: whsec_... event_types: type: array example: - booking.created - booking.cancelled items: type: string is_active: type: boolean example: true created_at: type: string example: '2024-01-01T00:00:00.000000Z' updated_at: type: string example: '2024-01-01T00:00:00.000000Z' 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: '' content: application/json: schema: type: object example: message: 'This action is unauthorized.' properties: message: type: string example: 'This action is unauthorized.' tags: - Webhooks post: summary: 'Create a new webhook.' operationId: createANewWebhook description: "Creates a webhook for the authenticated user's account. A unique secret will be generated automatically." parameters: [] responses: 201: description: '' content: application/json: schema: type: object example: data: id: 01ARZ3NDEKTSV4RRFFQ69G5FAW account_id: 01ARZ3NDEKTSV4RRFFQ69G5FAX name: 'Production Webhook' description: 'Webhook for production events' url: 'https://example.com/webhook' secret: whsec_... event_types: - booking.created - booking.cancelled is_active: true created_at: '2024-01-01T00:00:00.000000Z' updated_at: '2024-01-01T00:00:00.000000Z' properties: data: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAW account_id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAX name: type: string example: 'Production Webhook' description: type: string example: 'Webhook for production events' url: type: string example: 'https://example.com/webhook' secret: type: string example: whsec_... event_types: type: array example: - booking.created - booking.cancelled items: type: string is_active: type: boolean example: true created_at: type: string example: '2024-01-01T00:00:00.000000Z' updated_at: type: string example: '2024-01-01T00:00:00.000000Z' 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: '' content: application/json: schema: type: object example: message: 'This action is unauthorized.' properties: message: type: string example: 'This action is unauthorized.' 422: description: '' content: application/json: schema: type: object example: message: 'The given data was invalid.' properties: message: type: string example: 'The given data was invalid.' tags: - Webhooks requestBody: required: true content: application/json: schema: type: object properties: name: type: string description: 'Name of the webhook' example: 'Production Webhook' nullable: false description: type: string description: 'Description of the webhook' example: 'Webhook for production events' nullable: false url: type: string description: 'URL to send webhook events' example: 'https://example.com/webhook' nullable: false event_types: type: array description: 'Array of event types to subscribe to' example: - booking.created - booking.cancelled items: type: string is_active: type: boolean description: '' example: false nullable: true required: - name - url - event_types '/v1/webhooks/{webhook_id}': get: summary: 'Display the specified webhook.' operationId: displayTheSpecifiedWebhook description: 'Returns detailed information about a specific webhook.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: data: id: 01ARZ3NDEKTSV4RRFFQ69G5FAW account_id: 01ARZ3NDEKTSV4RRFFQ69G5FAX name: 'Production Webhook' description: 'Webhook for production events' url: 'https://example.com/webhook' secret: whsec_... event_types: - booking.created - booking.cancelled is_active: true created_at: '2024-01-01T00:00:00.000000Z' updated_at: '2024-01-01T00:00:00.000000Z' properties: data: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAW account_id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAX name: type: string example: 'Production Webhook' description: type: string example: 'Webhook for production events' url: type: string example: 'https://example.com/webhook' secret: type: string example: whsec_... event_types: type: array example: - booking.created - booking.cancelled items: type: string is_active: type: boolean example: true created_at: type: string example: '2024-01-01T00:00:00.000000Z' updated_at: type: string example: '2024-01-01T00:00:00.000000Z' 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: '' content: application/json: schema: type: object example: message: 'This action is unauthorized.' properties: message: type: string example: 'This action is unauthorized.' 404: description: '' content: application/json: schema: type: object example: message: 'Webhook not found' properties: message: type: string example: 'Webhook not found' tags: - Webhooks put: summary: 'Update the specified webhook.' operationId: updateTheSpecifiedWebhook description: "Updates a webhook's details." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: data: id: 01ARZ3NDEKTSV4RRFFQ69G5FAW account_id: 01ARZ3NDEKTSV4RRFFQ69G5FAX name: 'Updated Webhook' description: 'Updated description' url: 'https://example.com/webhook' secret: whsec_... event_types: - booking.created is_active: true created_at: '2024-01-01T00:00:00.000000Z' updated_at: '2024-01-01T00:00:00.000000Z' properties: data: type: object properties: id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAW account_id: type: string example: 01ARZ3NDEKTSV4RRFFQ69G5FAX name: type: string example: 'Updated Webhook' description: type: string example: 'Updated description' url: type: string example: 'https://example.com/webhook' secret: type: string example: whsec_... event_types: type: array example: - booking.created items: type: string is_active: type: boolean example: true created_at: type: string example: '2024-01-01T00:00:00.000000Z' updated_at: type: string example: '2024-01-01T00:00:00.000000Z' 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: '' content: application/json: schema: type: object example: message: 'This action is unauthorized.' properties: message: type: string example: 'This action is unauthorized.' 404: description: '' content: application/json: schema: type: object example: message: 'Webhook not found' properties: message: type: string example: 'Webhook not found' 422: description: '' content: application/json: schema: type: object example: message: 'The given data was invalid.' properties: message: type: string example: 'The given data was invalid.' tags: - Webhooks requestBody: required: false content: application/json: schema: type: object properties: name: type: string description: 'Name of the webhook' example: 'Updated Webhook' nullable: false description: type: string description: 'Description of the webhook' example: 'Updated description' nullable: false url: type: string description: 'URL to send webhook events' example: 'https://example.com/webhook' nullable: false event_types: type: array description: 'Array of event types to subscribe to' example: - booking.created items: type: string is_active: type: boolean description: 'Whether the webhook is active' example: true nullable: false delete: summary: 'Delete the specified webhook.' operationId: deleteTheSpecifiedWebhook description: 'Permanently deletes a webhook.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: message: 'Webhook deleted successfully' properties: message: type: string example: 'Webhook deleted successfully' 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. 403: description: '' content: application/json: schema: type: object example: message: 'This action is unauthorized.' properties: message: type: string example: 'This action is unauthorized.' 404: description: '' content: application/json: schema: type: object example: message: 'Webhook not found' properties: message: type: string example: 'Webhook not found' tags: - Webhooks parameters: - in: path name: webhook_id description: 'The ID of the webhook.' example: 01kc4dsnt4mwgg5n7mtd76r9yy required: true schema: type: string - in: path name: webhook description: 'The ID of the webhook' example: 01ARZ3NDEKTSV4RRFFQ69G5FAW required: true schema: type: string