{
  "openapi": "3.0.3",
  "info": {
    "title": "Listings API V1",
    "version": "1.0.0",
    "contact": {
      "name": "Bookable",
      "url": "https://www.bookabletech.com",
      "email": "hello@bookabletech.com"
    },
    "description": "## Overview\n\nThe Listings API V1 is a **venue-aggregated** discovery interface.\n\nThe response root carries `meta` and `listings[]`. Each entry in `listings[]`\nis a `ListingGroup` — one per operator (venue-group / chain), carrying a\n`groupName` and an `items[]` array.\n\nEach `item` represents a single venue (or a standalone event when no venue is\nknown): it carries the venue `name`, a `location`, and a `capabilities[]`\narray. Each entry in `capabilities[]` is a `Listing` with exactly **one**\ncapability (`table_reservation` or `event_ticket`), and carries its own\n`photos[]`. A venue that also hosts a ticketed event therefore yields a single\nitem with two capabilities — one for the venue, one for the event.\n\nAll bookable units (venue products, event ticket types, future capability\ntypes) are unified under a single `bookableProducts[]` array. Every entry is a\nsingle `Bookable` shape; capability-specific fields are nullable and the\nparent Listing's `capability` sets the context.\n\nTemporal information (venue opening hours, event occurrences, blackout\ndates) is unified under a single `availabilityOccurrence[]` field of `CalendarRule`s.\nBoth capabilities use the same shape.\n\nPre-order assets (packages, menus) are unified under a single `preorders`\ncontainer — applicable to either capability when the listing supports\npre-orders.\n\n## ID formats — two distinct identifiers, both CompositeId-encoded\n\n`Listing.id` (venue or event, as returned in `/v1/listings`) is 3 segments:\n`{VenueGroupId}|{RmsSlug}|{ResourceId}`. For a hybrid entity the event-side\nrow uses the EventExt's CompositeId (different `RmsSlug` + `ResourceId`) so\nthe two rows are unambiguous.\n\n`Bookable.compositeId` (a specific bookable product/ticket type — used in\n`bookableProducts[]`, and as the `compositeId` in `/v1/availabilities` and\n`/v1/orders`) is 4 segments: `{VenueGroupId}|{RmsSlug}|{ResourceId}|{AdditionalId}`.\nThese are two different identifiers for two different things, not two\ninterchangeable formats for the same one — a `Listing.id` never appears where\na `Bookable.compositeId` is expected, or vice versa.\n"
  },
  "servers": [
    {
      "url": "https://api.bookabletech.com",
      "description": "Live"
    },
    {
      "url": "https://api-sandbox.bookabletech.com",
      "description": "Sandbox"
    }
  ],
  "tags": [
    {
      "name": "Listings",
      "description": "Discover and retrieve bookable listings"
    },
    {
      "name": "Orders",
      "description": "Create and manage orders"
    }
  ],
  "paths": {
    "/v1/listings": {
      "get": {
        "operationId": "getListings",
        "summary": "Retrieve the full bookable catalogue (paginated, venue-aggregated)",
        "description": "Returns the entire bookable catalogue available to the caller, paginated and\nvenue-aggregated. Results are grouped by operator (`ListingGroup`); each group\ncarries its venues (`ListingItem`), and each venue carries one `Listing` per\ncapability it offers (`table_reservation`, `event_ticket`).\n\nA venue that also hosts a ticketed event therefore appears once, with two\nentries in its `capabilities[]` — one per capability. Optional query filters\n(capability, name, location, features, date, …) narrow the catalogue; with no\nfilters the whole catalogue is returned page by page.\n",
        "tags": [
          "Listings"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/CorrelationID"
          },
          {
            "$ref": "#/components/parameters/PartnerReference"
          },
          {
            "name": "capability",
            "in": "query",
            "required": false,
            "description": "Restrict results to a single capability. Venues are still returned\naggregated; only their matching capability entries are included.\n",
            "schema": {
              "type": "string",
              "enum": [
                "table_reservation",
                "event_ticket"
              ]
            },
            "example": "table_reservation"
          },
          {
            "name": "venueName",
            "in": "query",
            "required": false,
            "description": "Filter by listing name — partial, case-insensitive match.",
            "schema": {
              "type": "string",
              "minLength": 2,
              "maxLength": 100
            },
            "example": "dishoom"
          },
          {
            "name": "operatorName",
            "in": "query",
            "required": false,
            "description": "Filter by operator (venue-group / chain) name.",
            "schema": {
              "type": "string",
              "minLength": 2,
              "maxLength": 100
            },
            "example": "stonegate"
          },
          {
            "name": "city",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 2,
              "maxLength": 100
            },
            "example": "london"
          },
          {
            "name": "area",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 2,
              "maxLength": 100
            },
            "example": "shoreditch"
          },
          {
            "name": "features",
            "in": "query",
            "required": false,
            "description": "Filter by type / feature slugs (matched against `types`). Comma-separated list.",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              },
              "minItems": 1,
              "maxItems": 10
            },
            "style": "form",
            "explode": false,
            "example": [
              "dog_friendly",
              "live_music"
            ]
          },
          {
            "name": "date",
            "in": "query",
            "required": false,
            "description": "Filter listings that have availability on a specific date (YYYY-MM-DD).",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-06-15"
          },
          {
            "name": "fields",
            "in": "query",
            "required": false,
            "description": "Field selection using Google Fields syntax. Comma-separated list of top-level\nListing fields to include. When omitted, all fields are returned.\n",
            "schema": {
              "type": "string"
            },
            "example": "id,name,capability,location(lat,lng,city),bookableProducts(compositeId,name)"
          },
          {
            "name": "pageNumber",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          },
          {
            "name": "sortBy",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "default",
                "name",
                "city",
                "area",
                "relevance"
              ],
              "default": "default"
            }
          },
          {
            "$ref": "#/components/parameters/SortDirection"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of listings.",
            "headers": {
              "X-Correlation-ID": {
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Page"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "listings": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/ListingGroup"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "tableReservationListing": {
                    "$ref": "#/components/examples/TableReservationListingPage"
                  },
                  "eventTicketListing": {
                    "$ref": "#/components/examples/EventTicketListingPage"
                  },
                  "hybridListing": {
                    "$ref": "#/components/examples/HybridListingPage"
                  }
                }
              },
              "application/vnd.bookable.toon+json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Page"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "listings": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/ListingGroup"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "tableReservationListing": {
                    "$ref": "#/components/examples/TableReservationListingPage"
                  },
                  "eventTicketListing": {
                    "$ref": "#/components/examples/EventTicketListingPage"
                  },
                  "hybridListing": {
                    "$ref": "#/components/examples/HybridListingPage"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "default": {
            "$ref": "#/components/responses/InternalServerError"
          }
        },
        "security": [
          {
            "Live": [
              "listing:read"
            ]
          },
          {
            "Sandbox": [
              "listing:read"
            ]
          }
        ]
      }
    },
    "/v1/availabilities": {
      "post": {
        "operationId": "checkAvailabilities",
        "summary": "Check availability for multiple bookable products in one call",
        "description": "Batch availability check. Modelled as a **command** (POST), not a search.\n\nThe request carries root-level `date`, `quantity` and optional `time`, plus\na `bookableProducts[]` list. Each entry has a required `compositeId` and may\noverride `date`, `quantity` and `time`. When an entry omits any of those,\nthe root-level value is used.\n\n`quantity` carries the count for either capability, same as in `POST /v1/orders`\n— number of covers for a table reservation, number of tickets for an\nevent-ticket line.\n\nEvery entry must end up with `date` **and** `quantity` resolved (either from\nthe entry or the root). `time` is optional — event capabilities are queried\nby date alone; for table reservations it narrows the slot when supplied. An\nentry that cannot resolve `date` and `quantity` is reported as an error\nresult and does **not** block the others.\n\nSearches run independently: a failure on one `compositeId` yields an `error`\non that result only — all other results are returned normally. The response\ncarries one `AvailabilityResult` per requested `compositeId`, preserving\nrequest order.\n\nThere is no `404` response: an unknown/nonexistent `compositeId` is not a\nrequest-level failure — it's reported as an `error` on that entry's\n`AvailabilityResult`, same as any other per-entry failure (e.g. unresolved\n`date`/`quantity`), never as an HTTP-level not-found for the whole call.\n",
        "tags": [
          "Listings"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/CorrelationID"
          },
          {
            "$ref": "#/components/parameters/PartnerReference"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AvailabilitiesRequest"
              },
              "example": {
                "date": "2026-06-15",
                "quantity": 4,
                "time": "19:00",
                "bookableProducts": [
                  {
                    "compositeId": "29|CS|275cc44dd2e2496fba44857c9257443a|prod1"
                  },
                  {
                    "compositeId": "29|CS|275cc44dd2e2496fba44857c9257443a|prod2",
                    "quantity": 2,
                    "time": "20:00"
                  },
                  {
                    "compositeId": "29|CS|999|prod3"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "One result per requested `compositeId`. Each result carries either\n`availability` (success) or `error` (failure); never both.\n",
            "headers": {
              "X-Correlation-ID": {
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AvailabilitiesResponse"
                },
                "examples": {
                  "mixed": {
                    "$ref": "#/components/examples/AvailabilitiesResponseExample"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "default": {
            "$ref": "#/components/responses/InternalServerError"
          }
        },
        "security": [
          {
            "Live": [
              "listing:read"
            ]
          },
          {
            "Sandbox": [
              "listing:read"
            ]
          }
        ]
      }
    },
    "/v1/orders": {
      "post": {
        "operationId": "createOrder",
        "summary": "Create an order — one or more independent bookings, across any platform",
        "description": "Creates an order containing one or more bookings. Each item is resolved and\nbooked **independently** — there is no cross-item transaction. A failure on\none item (e.g. the venue/event on one platform is fully booked) does not\nblock or roll back the others. The response carries one `OrderItemResult`\nper requested item, preserving request order — mirroring how\n`POST /v1/availabilities` reports one result per `compositeId`.\n\nBecause every item is self-sufficient via its own `compositeId` (which embeds\n`VenueGroupId` + `RmsSlug`), a single order can span multiple venues and even\nmultiple RMS platforms (e.g. one item on Collins, another on Zonal) — there is\nno top-level `listingId` constraining the order to one platform.\n\nEach `OrderItem` is unified (no `capability` field, no `oneOf`) — `quantity`\ncarries the count for either capability (covers for a table reservation, ticket\ncount for an event-ticket line); `time` additionally applies to table\nreservations. Capability is resolved server-side from the `compositeId`'s RMS\nslug, not from which fields are populated. An order's items may mix\ncapabilities and platforms freely.\n",
        "tags": [
          "Orders"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/CorrelationID"
          },
          {
            "$ref": "#/components/parameters/PartnerReference"
          },
          {
            "$ref": "#/components/parameters/IntegrationSlug"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateOrderRequest"
              },
              "examples": {
                "tableReservation": {
                  "summary": "Create table reservations across two different platforms in one order",
                  "value": {
                    "items": [
                      {
                        "compositeId": "29|CO|275cc44dd2e2496fba44857c9257443a|e4d909c290d0fb1ca068ffaddf22cbd0",
                        "date": "2026-06-15",
                        "time": "19:30",
                        "duration": 90,
                        "quantity": 4,
                        "type": "book"
                      },
                      {
                        "compositeId": "41|ZO|9a1c20-5b7e-4c1a|8c2d4e60-9a1b-4f3c",
                        "date": "2026-06-15",
                        "time": "20:00",
                        "quantity": 2,
                        "type": "book"
                      }
                    ],
                    "customer": {
                      "firstName": "John",
                      "lastName": "Doe",
                      "email": "john.doe@example.com",
                      "phone": "+441234567890"
                    }
                  }
                },
                "eventTicket": {
                  "summary": "Purchase tickets for two ticket types on the same event date",
                  "value": {
                    "items": [
                      {
                        "compositeId": "29|TN|69f87ae8c7475734752555b4|69f87a8568063a182c46c198",
                        "date": "2026-07-19",
                        "quantity": 2
                      },
                      {
                        "compositeId": "29|TN|69f87ae8c7475734752555b4|69f87a97c74757172d362198",
                        "date": "2026-07-19",
                        "quantity": 1
                      }
                    ],
                    "customer": {
                      "firstName": "Jane",
                      "lastName": "Smith",
                      "email": "jane.smith@example.com",
                      "phone": "+441234567891"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "One result per requested item, in request order — every item succeeded.",
            "headers": {
              "X-Correlation-ID": {
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                },
                "examples": {
                  "tableReservation": {
                    "$ref": "#/components/examples/CreateOrderTableReservationResponseExample"
                  },
                  "eventTicket": {
                    "$ref": "#/components/examples/CreateOrderEventTicketResponseExample"
                  }
                }
              },
              "application/vnd.bookable.toon+json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          },
          "207": {
            "description": "One result per requested item, in request order. Each result carries\neither `booking` (success) or `error` (failure); never both. Returned\nwhenever one or more items failed — including when **every** item\nfailed — so a bulk success is never conflated with a partial or total\nfailure; check each result.\n",
            "headers": {
              "X-Correlation-ID": {
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                },
                "examples": {
                  "partialFailure": {
                    "$ref": "#/components/examples/CreateOrderPartialFailureExample"
                  }
                }
              },
              "application/vnd.bookable.toon+json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "default": {
            "$ref": "#/components/responses/InternalServerError"
          }
        },
        "security": [
          {
            "Live": [
              "order:create"
            ]
          },
          {
            "Sandbox": [
              "order:create"
            ]
          }
        ]
      }
    },
    "/v1/orders/{orderId}": {
      "patch": {
        "operationId": "updateOrder",
        "summary": "Update one or more bookings within an order",
        "description": "Partial update — each `OrderItemUpdate` only carries the fields being changed;\nanything omitted keeps its current value. Items are resolved and updated\n**independently**, same isolation model as `POST /v1/orders`: a failure on one\nitem does not block the others.\n\nCapability (table reservation vs. event ticket) is resolved server-side from the\nexisting booking, not from the request — every field below applies uniformly to\neither capability at the API level, even where the RMS-side effect currently\ndiffers (noted per field).\n\n`compositeId` moves the booking to a different bookable product — the same\nidentifier used everywhere else (`Bookable.compositeId`, the only thing taken\nfrom a listing's `bookableProducts[]`), not a ticket-specific field. Supported for\nboth capabilities: for event tickets it changes the ticket type (the\n`compositeId`'s 4th segment); for table reservations it changes the booked\nproduct/space. The new `compositeId` must reference the same venue group, RMS and\nvenue/event as the booking's current product — only the trailing product/ticket-type\nsegment may differ; a cross-venue or cross-event move is rejected (400 `ORDER-N-007`).\n\n`firstName`/`lastName`/`email`/`phone` update the guest's details, either capability.\n\nPreorders (table-reservation only in practice — event tickets have no preorder\nconcept, these fields are accepted but a no-op for them today): `preorders` is a\n**full replacement** of the current preorder set (omit to leave unchanged, send\nempty arrays to clear). `preorderChanges` is the incremental alternative — add or\nremove specific packages/menus without resending the rest; mutually exclusive with\n`preorders` on the same item (400 `ORDER-N-008`).\n",
        "tags": [
          "Orders"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/CorrelationID"
          },
          {
            "$ref": "#/components/parameters/PartnerReference"
          },
          {
            "name": "orderId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "ORD-9980140810"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrderUpdateRequest"
              },
              "examples": {
                "changeTicketType": {
                  "summary": "Move a ticket-type line to a different ticket type and date",
                  "value": {
                    "items": [
                      {
                        "bookingId": "1|TN|6a59f0a0f58eb1c0fa00d040",
                        "compositeId": "1|TN|6a2bbc0285bf210719631c44|6a2bbb580ed61600150618f7",
                        "date": "2027-02-22",
                        "notes": "Customer upgraded to Kids ticket"
                      }
                    ]
                  }
                },
                "rescheduleTable": {
                  "summary": "Change a table reservation's time and party size",
                  "value": {
                    "items": [
                      {
                        "bookingId": "1|CO|BKG-8841203|B",
                        "time": "20:00",
                        "quantity": 6
                      }
                    ]
                  }
                },
                "changeCustomerAndProduct": {
                  "summary": "Update the guest's name/phone and move a table reservation to a different product, same venue",
                  "value": {
                    "items": [
                      {
                        "bookingId": "29|CO|BKG-8841203|B",
                        "firstName": "Jonathan",
                        "phone": "+441234567899",
                        "compositeId": "29|CO|275cc44dd2e2496fba44857c9257443a|8c2d4e60-9a1b-4f3c-8d2e-2b3c4d5e6f70"
                      }
                    ]
                  }
                },
                "addPreorderPackage": {
                  "summary": "Add a preorder package to a table reservation without resending the rest of the preorders",
                  "value": {
                    "items": [
                      {
                        "bookingId": "29|CO|BKG-8841203|B",
                        "preorderChanges": {
                          "addPackages": [
                            {
                              "id": "3f9a1c20-5b7e-4c1a-9e2d-1a2b3c4d5e6f",
                              "quantity": 2
                            }
                          ]
                        }
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "One result per requested item, in request order — every item succeeded.",
            "headers": {
              "X-Correlation-ID": {
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                },
                "examples": {
                  "tableReservation": {
                    "$ref": "#/components/examples/UpdateOrderTableReservationResponseExample"
                  },
                  "eventTicket": {
                    "$ref": "#/components/examples/UpdateOrderEventTicketResponseExample"
                  },
                  "changeCustomerAndProduct": {
                    "$ref": "#/components/examples/UpdateOrderCustomerAndProductResponseExample"
                  },
                  "addPreorderPackage": {
                    "$ref": "#/components/examples/UpdateOrderAddPreorderResponseExample"
                  }
                }
              }
            }
          },
          "207": {
            "description": "One result per requested item, in request order. Each result carries\neither `booking` (success) or `error` (failure); never both. Returned\nwhenever one or more items failed — including when every item failed —\nso a full success is never conflated with a partial or total failure.\n",
            "headers": {
              "X-Correlation-ID": {
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                },
                "examples": {
                  "bookingNotFound": {
                    "$ref": "#/components/examples/UpdateOrderFailureExample"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/InternalServerError"
          }
        },
        "security": [
          {
            "Live": [
              "order:create"
            ]
          },
          {
            "Sandbox": [
              "order:create"
            ]
          }
        ]
      },
      "delete": {
        "operationId": "deleteOrder",
        "summary": "Cancel bookings within an order, or the entire order",
        "description": "Cancels the bookings listed in `bookingIds`. When `bookingIds` is omitted or\nempty, cancels **every** booking belonging to `orderId`. Each cancellation is\nindependent — one failure does not block the others.\n",
        "tags": [
          "Orders"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/CorrelationID"
          },
          {
            "$ref": "#/components/parameters/PartnerReference"
          },
          {
            "name": "orderId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "ORD-9980140810"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrderCancelRequest"
              },
              "examples": {
                "wholeOrder": {
                  "summary": "Cancel every booking in the order (empty/omitted body)",
                  "value": {}
                },
                "singleBooking": {
                  "summary": "Cancel one booking within the order",
                  "value": {
                    "bookingIds": [
                      "1|TN|423458"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "One result per cancelled item, in request order — every cancellation succeeded.",
            "headers": {
              "X-Correlation-ID": {
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                },
                "examples": {
                  "wholeOrder": {
                    "$ref": "#/components/examples/CancelOrderWholeResponseExample"
                  },
                  "singleBooking": {
                    "$ref": "#/components/examples/CancelOrderSingleBookingResponseExample"
                  }
                }
              }
            }
          },
          "207": {
            "description": "One result per cancelled item. Each result carries either `booking`\n(the now-cancelled booking) or `error` (failure); never both. Returned\nwhenever one or more cancellations failed — including when every one\nfailed — so a full success is never conflated with a partial or total\nfailure.\n",
            "headers": {
              "X-Correlation-ID": {
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                },
                "examples": {
                  "alreadyCancelled": {
                    "$ref": "#/components/examples/CancelOrderFailureResponseExample"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "default": {
            "$ref": "#/components/responses/InternalServerError"
          }
        },
        "security": [
          {
            "Live": [
              "order:create"
            ]
          },
          {
            "Sandbox": [
              "order:create"
            ]
          }
        ]
      }
    }
  },
  "components": {
    "parameters": {
      "CorrelationID": {
        "in": "header",
        "name": "X-Correlation-ID",
        "required": false,
        "description": "Optional ID for cross-system transaction tracking.",
        "schema": {
          "type": "string",
          "example": "11C46F5F-CDEF-4865-94B2-0EE0EDCC26DA"
        }
      },
      "PartnerReference": {
        "in": "header",
        "name": "X-Partner-Reference",
        "required": false,
        "description": "Required for Bookable Agents — identifies the partner on whose behalf the request is made.",
        "schema": {
          "type": "string",
          "example": "bottomlessbrunch.com"
        }
      },
      "SortDirection": {
        "in": "query",
        "name": "sortDirection",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "ASC",
            "DESC"
          ],
          "default": "ASC"
        }
      },
      "IntegrationSlug": {
        "in": "header",
        "name": "X-Booking-Source",
        "required": false,
        "description": "Identifies the source or channel through which the order was created.\nDefaults to \"api\" when not provided.\n",
        "schema": {
          "type": "string",
          "enum": [
            "email",
            "phone",
            "api",
            "webhook",
            "js-tag",
            "chatbot",
            "puller",
            "portal"
          ],
          "example": "api"
        }
      }
    },
    "schemas": {
      "Capability": {
        "type": "string",
        "description": "Identifies a booking capability.",
        "enum": [
          "table_reservation",
          "event_ticket"
        ],
        "example": "table_reservation"
      },
      "Location": {
        "type": "object",
        "nullable": true,
        "description": "Physical location. `null` for virtual listings (e.g. online events).",
        "properties": {
          "street": {
            "type": "string",
            "example": "1 Upper St Martin's Lane"
          },
          "area": {
            "type": "string",
            "description": "Neighbourhood(s), pipe-separated.",
            "example": "Covent Garden|Seven Dials"
          },
          "city": {
            "type": "string",
            "example": "London"
          },
          "postCode": {
            "type": "string",
            "example": "WC2H 9FB"
          },
          "lat": {
            "type": "number",
            "format": "double",
            "example": 51.513
          },
          "lng": {
            "type": "number",
            "format": "double",
            "example": -0.128
          },
          "gPlace": {
            "type": "string",
            "example": "ChIJN1t_tDeuEmsRUsoyG83frY4"
          }
        }
      },
      "AutoConfirmRule": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "format": "date",
            "nullable": true,
            "example": "2026-06-15"
          },
          "dateType": {
            "type": "string",
            "nullable": true,
            "example": "weekday"
          },
          "minPeople": {
            "type": "integer",
            "nullable": true,
            "example": 1
          },
          "maxPeople": {
            "type": "integer",
            "nullable": true,
            "example": 6
          },
          "timeFrom": {
            "type": "string",
            "pattern": "^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$",
            "nullable": true,
            "example": "12:00"
          },
          "timeTo": {
            "type": "string",
            "pattern": "^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$",
            "nullable": true,
            "example": "22:30"
          }
        }
      },
      "Package": {
        "type": "object",
        "required": [
          "id",
          "name",
          "price",
          "type"
        ],
        "properties": {
          "id": {
            "type": "string",
            "example": "3f9a1c20-5b7e-4c1a-9e2d-1a2b3c4d5e6f"
          },
          "name": {
            "type": "string",
            "example": "Sunday Roast"
          },
          "price": {
            "type": "number",
            "format": "double",
            "example": 28.5
          },
          "description": {
            "type": "string",
            "nullable": true,
            "example": "Slow-roasted beef, Yorkshire pudding, seasonal vegetables."
          },
          "type": {
            "type": "string",
            "example": "main"
          },
          "sub_type": {
            "type": "string",
            "nullable": true,
            "example": "roast"
          },
          "diet_types": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "example": [
              "gluten_free_option"
            ]
          },
          "allergens": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "example": [
              "gluten",
              "dairy"
            ]
          }
        }
      },
      "Menu": {
        "type": "object",
        "required": [
          "id",
          "name",
          "items"
        ],
        "properties": {
          "id": {
            "type": "string",
            "example": "b4e6f810-1c2d-4a3b-9c8d-3c4d5e6f7081"
          },
          "name": {
            "type": "string",
            "example": "Spring Tasting Menu"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "example": "Five-course seasonal tasting menu with optional wine pairing."
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MenuItem"
            }
          }
        }
      },
      "MenuItem": {
        "type": "object",
        "required": [
          "packageId"
        ],
        "properties": {
          "packageId": {
            "type": "string",
            "example": "c5f70921-2d3e-4b4c-8d9e-4d5e6f708192"
          },
          "name": {
            "type": "string",
            "nullable": true,
            "example": "Amuse Bouche"
          },
          "price": {
            "type": "number",
            "format": "float",
            "nullable": true,
            "example": 0
          },
          "description": {
            "type": "string",
            "nullable": true,
            "example": "Chef's seasonal selection."
          },
          "type": {
            "type": "string",
            "nullable": true,
            "example": "starter"
          },
          "subType": {
            "type": "string",
            "nullable": true,
            "example": "amuse"
          },
          "displayOrder": {
            "type": "integer",
            "nullable": true,
            "example": 1
          }
        }
      },
      "Preorders": {
        "type": "object",
        "nullable": true,
        "description": "Pre-order assets for a listing. Either capability MAY expose packages\nand/or menus that can be selected at booking time. `null` when the\nlisting does not support pre-orders.\n",
        "properties": {
          "packages": {
            "type": "array",
            "nullable": true,
            "items": {
              "$ref": "#/components/schemas/Package"
            }
          },
          "menus": {
            "type": "array",
            "nullable": true,
            "items": {
              "$ref": "#/components/schemas/Menu"
            }
          }
        }
      },
      "CalendarRuleType": {
        "type": "string",
        "description": "Type of calendar rule:\n- `date_range`: continuous date range\n- `recurring`: weekday/month pattern, no time\n- `time_based`: time window only, applies every day\n- `specific_dates`: explicit list of dates\n- `specific_dates_with_time`: explicit dates with time window\n- `date_range_with_time`: date range with time window\n- `recurring_with_time`: weekday/month pattern with time window\n",
        "enum": [
          "date_range",
          "recurring",
          "time_based",
          "specific_dates",
          "specific_dates_with_time",
          "date_range_with_time",
          "recurring_with_time"
        ],
        "example": "recurring_with_time"
      },
      "CalendarRule": {
        "type": "object",
        "description": "Unified temporal rule. Describes when a listing is available:\nvenue opening hours, event occurrences, blackout dates and exceptions.\nDiscriminated by `type`; rule-specific fields live under `occurrences`.\nRules of the same `type`, `status` and time window are aggregated into a\nsingle entry (recurring rules combine their `daysOfWeek`, specific-date\nrules combine their `dates`).\n",
        "required": [
          "type",
          "occurrences"
        ],
        "properties": {
          "type": {
            "$ref": "#/components/schemas/CalendarRuleType"
          },
          "name": {
            "type": "string",
            "nullable": true,
            "example": "Weekday dinner service"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "example": "Standard weekday opening hours, kitchen open until 21:30."
          },
          "status": {
            "type": "string",
            "enum": [
              "open",
              "closed"
            ],
            "default": "open",
            "description": "`open` → listing IS available during this rule.\n`closed` → listing IS NOT available during this rule (overrides\nan underlying `open` rule, e.g. a holiday closure).\n",
            "example": "open"
          },
          "notes": {
            "type": "string",
            "nullable": true,
            "example": "Last seating 21:30."
          },
          "occurrences": {
            "description": "Rule-specific payload — shape determined by `type`."
          }
        },
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "date_range": "#/components/schemas/DateRangeCalendarRule",
            "recurring": "#/components/schemas/RecurringCalendarRule",
            "time_based": "#/components/schemas/TimeBasedCalendarRule",
            "specific_dates": "#/components/schemas/SpecificDatesCalendarRule",
            "specific_dates_with_time": "#/components/schemas/SpecificDatesWithTimeCalendarRule",
            "date_range_with_time": "#/components/schemas/DateRangeWithTimeCalendarRule",
            "recurring_with_time": "#/components/schemas/RecurringWithTimeCalendarRule"
          }
        }
      },
      "DateRangeCalendarRule": {
        "description": "Calendar rule for a continuous date range. `type: date_range`.",
        "allOf": [
          {
            "$ref": "#/components/schemas/CalendarRule"
          },
          {
            "type": "object",
            "properties": {
              "occurrences": {
                "type": "object",
                "required": [
                  "startDate",
                  "endDate"
                ],
                "properties": {
                  "startDate": {
                    "type": "string",
                    "format": "date",
                    "description": "Start of the date range (inclusive).",
                    "example": "2026-06-01"
                  },
                  "endDate": {
                    "type": "string",
                    "format": "date",
                    "description": "End of the date range (inclusive).",
                    "example": "2026-08-31"
                  }
                }
              }
            }
          }
        ]
      },
      "RecurringCalendarRule": {
        "description": "Calendar rule for a recurring weekday/month pattern (no time). `type: recurring`.",
        "allOf": [
          {
            "$ref": "#/components/schemas/CalendarRule"
          },
          {
            "type": "object",
            "properties": {
              "occurrences": {
                "type": "object",
                "required": [
                  "daysOfWeek",
                  "months"
                ],
                "properties": {
                  "daysOfWeek": {
                    "type": "array",
                    "items": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 6
                    },
                    "description": "Weekdays the rule applies to (0=Sunday … 6=Saturday).",
                    "minItems": 1,
                    "maxItems": 7,
                    "example": [
                      4
                    ]
                  },
                  "months": {
                    "type": "array",
                    "items": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 12
                    },
                    "description": "Months the rule applies to (1=January … 12=December).",
                    "minItems": 1,
                    "maxItems": 12,
                    "example": [
                      6,
                      7,
                      8
                    ]
                  },
                  "ordinal": {
                    "type": "integer",
                    "nullable": true,
                    "minimum": -1,
                    "maximum": 5,
                    "description": "Restricts the rule to only the Nth occurrence of each matching\nweekday within the month (1=1st … 5=5th, -1=last). `null` (the\ndefault) means every occurrence of the weekday — a plain weekly\npattern. E.g. \"1st Thursday of the month\" → `daysOfWeek: [4]`,\n`ordinal: 1`.\n",
                    "example": 1
                  }
                }
              }
            }
          }
        ]
      },
      "TimeBasedCalendarRule": {
        "description": "Calendar rule for a daily time window. `type: time_based`.",
        "allOf": [
          {
            "$ref": "#/components/schemas/CalendarRule"
          },
          {
            "type": "object",
            "properties": {
              "occurrences": {
                "type": "object",
                "required": [
                  "startTime",
                  "endTime"
                ],
                "properties": {
                  "startTime": {
                    "type": "string",
                    "pattern": "^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$",
                    "description": "Start of the daily window (HH:mm, 24-hour).",
                    "example": "12:00"
                  },
                  "endTime": {
                    "type": "string",
                    "pattern": "^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$",
                    "description": "End of the daily window (HH:mm, 24-hour).",
                    "example": "23:00"
                  }
                }
              }
            }
          }
        ]
      },
      "SpecificDatesCalendarRule": {
        "description": "Calendar rule for an explicit list of dates. `type: specific_dates`.",
        "allOf": [
          {
            "$ref": "#/components/schemas/CalendarRule"
          },
          {
            "type": "object",
            "properties": {
              "occurrences": {
                "type": "object",
                "required": [
                  "dates"
                ],
                "properties": {
                  "dates": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "date"
                    },
                    "minItems": 1,
                    "description": "Explicit dates (YYYY-MM-DD) the rule applies to.",
                    "example": [
                      "2026-12-25",
                      "2026-12-26",
                      "2027-01-01"
                    ]
                  }
                }
              }
            }
          }
        ]
      },
      "SpecificDatesWithTimeCalendarRule": {
        "description": "Calendar rule for an explicit list of dates with a time window. `type: specific_dates_with_time`.",
        "allOf": [
          {
            "$ref": "#/components/schemas/CalendarRule"
          },
          {
            "type": "object",
            "properties": {
              "occurrences": {
                "type": "object",
                "required": [
                  "dates",
                  "startTime",
                  "endTime"
                ],
                "properties": {
                  "dates": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "date"
                    },
                    "minItems": 1,
                    "example": [
                      "2026-08-15"
                    ]
                  },
                  "startTime": {
                    "type": "string",
                    "pattern": "^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$",
                    "example": "20:00"
                  },
                  "endTime": {
                    "type": "string",
                    "pattern": "^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$",
                    "example": "23:30"
                  }
                }
              }
            }
          }
        ]
      },
      "DateRangeWithTimeCalendarRule": {
        "description": "Calendar rule for a date range with a daily time window. `type: date_range_with_time`.",
        "allOf": [
          {
            "$ref": "#/components/schemas/CalendarRule"
          },
          {
            "type": "object",
            "properties": {
              "occurrences": {
                "type": "object",
                "required": [
                  "startDate",
                  "endDate",
                  "startTime",
                  "endTime"
                ],
                "properties": {
                  "startDate": {
                    "type": "string",
                    "format": "date",
                    "example": "2026-06-01"
                  },
                  "endDate": {
                    "type": "string",
                    "format": "date",
                    "example": "2026-08-31"
                  },
                  "startTime": {
                    "type": "string",
                    "pattern": "^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$",
                    "example": "19:00"
                  },
                  "endTime": {
                    "type": "string",
                    "pattern": "^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$",
                    "example": "22:00"
                  }
                }
              }
            }
          }
        ]
      },
      "RecurringWithTimeCalendarRule": {
        "description": "Calendar rule for a recurring weekday/month pattern with a daily time window. `type: recurring_with_time`.",
        "allOf": [
          {
            "$ref": "#/components/schemas/CalendarRule"
          },
          {
            "type": "object",
            "properties": {
              "occurrences": {
                "type": "object",
                "required": [
                  "daysOfWeek",
                  "months",
                  "startTime",
                  "endTime"
                ],
                "properties": {
                  "daysOfWeek": {
                    "type": "array",
                    "items": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 6
                    },
                    "minItems": 1,
                    "maxItems": 7,
                    "example": [
                      1,
                      2,
                      3,
                      4,
                      5
                    ]
                  },
                  "months": {
                    "type": "array",
                    "items": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 12
                    },
                    "minItems": 1,
                    "maxItems": 12,
                    "example": [
                      1,
                      2,
                      3,
                      4,
                      5,
                      6,
                      7,
                      8,
                      9,
                      10,
                      11,
                      12
                    ]
                  },
                  "startTime": {
                    "type": "string",
                    "pattern": "^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$",
                    "example": "12:00"
                  },
                  "endTime": {
                    "type": "string",
                    "pattern": "^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$",
                    "example": "22:30"
                  },
                  "ordinal": {
                    "type": "integer",
                    "nullable": true,
                    "minimum": -1,
                    "maximum": 5,
                    "description": "Restricts the rule to only the Nth occurrence of each matching\nweekday within the month (1=1st … 5=5th, -1=last). `null` (the\ndefault) means every occurrence of the weekday — a plain weekly\npattern. E.g. \"1st Thursday of the month\" → `daysOfWeek: [4]`,\n`ordinal: 1`.\n",
                    "example": 1
                  }
                }
              }
            }
          }
        ]
      },
      "ListingGroup": {
        "type": "object",
        "description": "A group of listing items belonging to a single operator\n(venue-group / chain). Resolved from the VenueGroup referenced by the\nfirst segment of the CompositeId.\n",
        "required": [
          "groupName",
          "items"
        ],
        "properties": {
          "groupName": {
            "type": "string",
            "description": "Operator (venue-group / chain) display name.",
            "example": "Stonegate Group"
          },
          "items": {
            "type": "array",
            "description": "Venues (and standalone events) belonging to this operator.",
            "items": {
              "$ref": "#/components/schemas/ListingItem"
            }
          }
        }
      },
      "ListingItem": {
        "type": "object",
        "description": "A single venue, aggregating every capability offered there. `name` is the\nvenue name (or the event name when the event has no associated venue).\nA venue that also hosts a ticketed event yields two `capabilities`\nentries — one `table_reservation`, one `event_ticket`.\n",
        "required": [
          "name",
          "capabilities"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Venue name, or event name when there is no associated venue.",
            "example": "The Crown & Anchor"
          },
          "location": {
            "$ref": "#/components/schemas/Location"
          },
          "capabilities": {
            "type": "array",
            "description": "The bookable capabilities offered at this venue.",
            "items": {
              "$ref": "#/components/schemas/Listing"
            }
          }
        }
      },
      "Listing": {
        "type": "object",
        "description": "A single bookable capability — a venue's table reservations OR an event's\ntickets. Exactly one capability per entry.\n",
        "required": [
          "id",
          "name",
          "capability",
          "bookableProducts"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "CompositeId — `{VenueGroupId}|{RmsSlug}|{ResourceId}`.",
            "example": "29|CS|275cc44dd2e2496fba44857c9257443a"
          },
          "name": {
            "type": "string",
            "example": "The Crown & Anchor"
          },
          "operatorName": {
            "type": "string",
            "nullable": true,
            "description": "Operator (venue-group / chain) display name.",
            "example": "Stonegate Group"
          },
          "hostedBy": {
            "type": "string",
            "nullable": true,
            "description": "Name of the venue hosting this listing. Populated for `event_ticket`\nlistings whose event is associated with a physical venue (resolved\nfrom Collins); the venue's address is reflected in `location`.\n`null` when there is no associated venue (e.g. virtual events).\n",
            "example": "The Crown & Anchor"
          },
          "capability": {
            "$ref": "#/components/schemas/Capability"
          },
          "types": {
            "type": "array",
            "description": "Listing types and feature tag slugs, merged into a single list\n(e.g. venue categories like `pub`, `bar` plus feature tags like\n`dog_friendly`, `live_music`).\n",
            "items": {
              "type": "string"
            },
            "example": [
              "pub",
              "bar",
              "dog_friendly",
              "live_music"
            ]
          },
          "content": {
            "type": "string",
            "nullable": true,
            "example": "A traditional gastropub in the heart of Covent Garden, serving seasonal British food and an award-winning cask ale selection."
          },
          "faqs": {
            "type": "array",
            "nullable": true,
            "description": "Operator-managed public-facing FAQ list. Omitted/null when none are configured.\nFor an `event_ticket` listing this is inherited from the hosting venue (`hostedBy`)\nwhen one exists — events have no FAQ list of their own.\n",
            "items": {
              "$ref": "#/components/schemas/FaqItem"
            },
            "example": [
              {
                "question": "What is your cancellation policy?",
                "answer": "See our **cancellation policy** [here](https://example.com/policy)."
              }
            ]
          },
          "photos": {
            "type": "array",
            "description": "Photo URLs for this capability.",
            "items": {
              "type": "string"
            },
            "example": [
              "https://cdn.bookabletech.com/venues/29/photos/crown-anchor-front.jpg",
              "https://cdn.bookabletech.com/venues/29/photos/crown-anchor-dining.jpg"
            ]
          },
          "phoneNumber": {
            "type": "string",
            "nullable": true,
            "example": "+442079461234"
          },
          "website": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "example": "https://www.crown-and-anchor.example/"
          },
          "availabilityOccurrence": {
            "type": "array",
            "description": "Unified temporal description of the listing. Use `recurring_with_time`\nrules for weekly opening hours, `specific_dates*` for event dates or\nholiday closures, `date_range*` for seasonal availability, etc.\nMultiple rules may combine — `status: closed` overrides `status: open`.\nRules sharing the same `type`, `status` and time window are aggregated:\nrecurring rules combine their `daysOfWeek`, specific-date rules combine\ntheir `dates`.\n",
            "items": {
              "$ref": "#/components/schemas/CalendarRule"
            }
          },
          "preorders": {
            "$ref": "#/components/schemas/Preorders"
          },
          "bookableProducts": {
            "type": "array",
            "description": "All bookable units for this listing. Every entry is a `Bookable` —\na single unified shape. Capability-specific fields are populated\naccording to the row's `capability`.\n",
            "items": {
              "$ref": "#/components/schemas/Bookable"
            }
          }
        }
      },
      "Bookable": {
        "type": "object",
        "description": "Bookable unit for any capability. Common fields (`compositeId`, `name`,\n`availabilityOccurrenceOverrides`) always apply. Capability-specific fields are\nnullable: table-reservation fields (`timeInterval`, `category`,\n`preorders`, `deposit`, `autoConfirmRule`, `noAvailabilityAction`) are\npopulated when the parent `capability: table_reservation`; event-ticket\nfields (`price`, `capacity`, `visibility`) when `capability: event_ticket`.\n",
        "properties": {
          "compositeId": {
            "type": "string",
            "description": "CompositeId of the bookable unit.\n- table_reservation → `{VenueGroupId}|{RmsSlug}|{VenueId}|{ProductId}`\n- event_ticket → `{VenueGroupId}|{RmsSlug}|{EventId}|{TicketTypeId}`\n",
            "example": "29|CS|275cc44dd2e2496fba44857c9257443a|e4d909c290d0fb1ca068ffaddf22cbd0"
          },
          "name": {
            "type": "string",
            "example": "Dining Room"
          },
          "timeInterval": {
            "type": "integer",
            "nullable": true,
            "example": 30
          },
          "category": {
            "type": "string",
            "nullable": true,
            "example": "Dinner"
          },
          "spaces": {
            "type": "array",
            "nullable": true,
            "description": "Spaces/areas available within this bookable product.",
            "items": {
              "$ref": "#/components/schemas/Space"
            }
          },
          "preorders": {
            "$ref": "#/components/schemas/ProductPreorders",
            "nullable": true
          },
          "deposit": {
            "$ref": "#/components/schemas/BookableDeposit",
            "nullable": true
          },
          "autoConfirmRule": {
            "$ref": "#/components/schemas/AutoConfirmRule",
            "nullable": true
          },
          "noAvailabilityAction": {
            "type": "string",
            "nullable": true,
            "example": "waitlist"
          },
          "price": {
            "$ref": "#/components/schemas/Price",
            "nullable": true
          },
          "capacity": {
            "$ref": "#/components/schemas/Capacity",
            "nullable": true
          },
          "visibility": {
            "type": "string",
            "nullable": true,
            "example": "on_sale"
          },
          "availabilityOccurrenceOverrides": {
            "type": "array",
            "nullable": true,
            "description": "Bookable-scoped `CalendarRule` entries that refine or restrict the\nlisting-level `availabilityOccurrence` for this specific bookable unit (event\nsessions, exceptional dates, closures, …). Same shape as\n`Listing.availabilityOccurrence`; `status: closed` overrides `status: open`.\n",
            "items": {
              "$ref": "#/components/schemas/CalendarRule"
            }
          }
        }
      },
      "Price": {
        "type": "object",
        "nullable": true,
        "description": "Monetary amount with currency.",
        "required": [
          "amount",
          "currency"
        ],
        "properties": {
          "amount": {
            "type": "number",
            "format": "double",
            "example": 25
          },
          "currency": {
            "type": "string",
            "description": "ISO 4217 currency code.",
            "example": "GBP"
          }
        }
      },
      "Capacity": {
        "type": "object",
        "nullable": true,
        "description": "Capacity for a ticket type.",
        "properties": {
          "max": {
            "type": "integer",
            "nullable": true,
            "description": "Maximum capacity.",
            "example": 300
          },
          "remaining": {
            "type": "integer",
            "nullable": true,
            "description": "Remaining capacity.",
            "example": 142
          }
        }
      },
      "ProductDepositRule": {
        "type": "object",
        "nullable": true,
        "properties": {
          "perAdult": {
            "type": "number",
            "format": "float",
            "nullable": true,
            "example": 10
          },
          "perChild": {
            "type": "number",
            "format": "float",
            "nullable": true,
            "example": 5
          },
          "perBooking": {
            "type": "number",
            "format": "float",
            "nullable": true,
            "example": null
          }
        }
      },
      "ProductPreorders": {
        "type": "object",
        "nullable": true,
        "description": "Pre-order configuration for the bookable unit.\n",
        "properties": {
          "required": {
            "type": "boolean",
            "description": "Whether a pre-order is required to complete the booking.",
            "example": true
          },
          "requiredType": {
            "type": "string",
            "nullable": true,
            "enum": [
              "package",
              "menu",
              "any"
            ],
            "description": "Type of asset the pre-order must reference.\nOnly meaningful when `required: true` — otherwise `null`.\n",
            "example": "package"
          },
          "packageIds": {
            "type": "array",
            "nullable": true,
            "items": {
              "type": "string"
            },
            "example": [
              "3f9a1c20-5b7e-4c1a-9e2d-1a2b3c4d5e6f",
              "8c2d4e60-9a1b-4f3c-8d2e-2b3c4d5e6f70"
            ]
          },
          "menuIds": {
            "type": "array",
            "nullable": true,
            "items": {
              "type": "string"
            },
            "example": [
              "b4e6f810-1c2d-4a3b-9c8d-3c4d5e6f7081"
            ]
          }
        }
      },
      "BookableDeposit": {
        "type": "object",
        "nullable": true,
        "description": "Deposit configuration for the bookable unit.",
        "properties": {
          "required": {
            "type": "boolean",
            "description": "Whether a deposit is required to confirm the booking.",
            "example": true
          },
          "rule": {
            "$ref": "#/components/schemas/ProductDepositRule",
            "nullable": true
          }
        }
      },
      "Space": {
        "type": "object",
        "description": "A space or area available within a bookable product (read-only).",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32"
          },
          "spaceName": {
            "type": "string",
            "nullable": true
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "floorLocation": {
            "type": "integer",
            "format": "int32",
            "nullable": true,
            "description": "Floor number (-10 to +10; 0 = ground floor)."
          },
          "facilities": {
            "type": "array",
            "nullable": true,
            "description": "Facilities available in the space.",
            "items": {
              "$ref": "#/components/schemas/SpaceFacility"
            }
          },
          "capacityStanding": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CapacityRange"
              }
            ],
            "nullable": true
          },
          "capacitySeated": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CapacityRange"
              }
            ],
            "nullable": true
          },
          "capacityCabaret": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CapacityRange"
              }
            ],
            "nullable": true
          },
          "capacityTheatre": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CapacityRange"
              }
            ],
            "nullable": true
          },
          "capacityBoardroom": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CapacityRange"
              }
            ],
            "nullable": true
          },
          "capacityClassroom": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CapacityRange"
              }
            ],
            "nullable": true
          },
          "capacityUShape": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CapacityRange"
              }
            ],
            "nullable": true
          },
          "capacityBanquet": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CapacityRange"
              }
            ],
            "nullable": true
          },
          "capacityReception": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CapacityRange"
              }
            ],
            "nullable": true
          },
          "policies": {
            "allOf": [
              {
                "$ref": "#/components/schemas/SpacePoliciesMap"
              }
            ],
            "nullable": true
          }
        }
      },
      "AvailabilitiesRequest": {
        "type": "object",
        "description": "Batch availability command. Root-level `date`, `quantity` and `time` act\nas defaults inherited by every entry in `bookableProducts` that omits them.\nEach entry must resolve `date` and `quantity` (from itself or the root) to\nbe searched; `time` is optional.\n",
        "required": [
          "bookableProducts"
        ],
        "properties": {
          "date": {
            "type": "string",
            "format": "date",
            "nullable": true,
            "description": "Default booking date (YYYY-MM-DD), inherited by entries that omit it.",
            "example": "2026-06-15"
          },
          "quantity": {
            "type": "integer",
            "minimum": 1,
            "nullable": true,
            "description": "Default quantity, inherited by entries that omit it — same field as\n`OrderItem.quantity`. For a `table_reservation` bookable, quantity is\nthe number of people (covers); for an `event_ticket` bookable, quantity\nis the number of tickets.\n",
            "example": 4
          },
          "time": {
            "type": "string",
            "pattern": "^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$",
            "nullable": true,
            "description": "Optional default start time (HH:mm), inherited by entries that omit it.",
            "example": "19:00"
          },
          "bookableProducts": {
            "type": "array",
            "minItems": 1,
            "maxItems": 100,
            "description": "Bookable products to check. One result is returned per entry.",
            "items": {
              "$ref": "#/components/schemas/AvailabilityProductRequest"
            }
          }
        }
      },
      "AvailabilityProductRequest": {
        "type": "object",
        "description": "A single availability query. `compositeId` is required; `date`, `quantity`\nand `time` are optional overrides — when omitted, the root-level value is used.\n",
        "required": [
          "compositeId"
        ],
        "properties": {
          "compositeId": {
            "type": "string",
            "description": "CompositeId of the bookable product to check.",
            "example": "29|CS|275cc44dd2e2496fba44857c9257443a|e4d909c290d0fb1ca068ffaddf22cbd0"
          },
          "date": {
            "type": "string",
            "format": "date",
            "nullable": true,
            "description": "Overrides the root `date` for this entry.",
            "example": "2026-06-15"
          },
          "quantity": {
            "type": "integer",
            "minimum": 1,
            "nullable": true,
            "description": "Overrides the root `quantity` for this entry — number of people for a\n`table_reservation` bookable, number of tickets for an `event_ticket` bookable.\n",
            "example": 2
          },
          "time": {
            "type": "string",
            "pattern": "^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$",
            "nullable": true,
            "description": "Overrides the root `time` for this entry.",
            "example": "20:00"
          }
        }
      },
      "AvailabilitiesResponse": {
        "type": "object",
        "required": [
          "results"
        ],
        "properties": {
          "results": {
            "type": "array",
            "description": "One result per requested `compositeId`, in request order.",
            "items": {
              "$ref": "#/components/schemas/AvailabilityResult"
            }
          }
        }
      },
      "AvailabilityResult": {
        "type": "object",
        "description": "Outcome for a single `compositeId`. Exactly one of `availability` or `error`\nis populated: `availability` on success, `error` on failure (including an\nentry that could not resolve `date` and `quantity`).\n",
        "required": [
          "compositeId"
        ],
        "properties": {
          "compositeId": {
            "type": "string",
            "description": "The `compositeId` this result refers to.",
            "example": "29|CS|275cc44dd2e2496fba44857c9257443a|e4d909c290d0fb1ca068ffaddf22cbd0"
          },
          "availability": {
            "$ref": "#/components/schemas/Availability",
            "nullable": true
          },
          "error": {
            "$ref": "#/components/schemas/ServerError",
            "nullable": true
          }
        }
      },
      "Availability": {
        "type": "object",
        "description": "Availability for a single bookable product. Mirrors the BookingApi AvailabilityResponse.",
        "properties": {
          "name": {
            "type": "string",
            "nullable": true,
            "description": "Name of the available booking option.",
            "example": "Dinner"
          },
          "deposit": {
            "type": "number",
            "format": "float",
            "nullable": true,
            "description": "Deposit amount required for the booking.",
            "example": 10
          },
          "policy": {
            "type": "string",
            "nullable": true,
            "description": "General policy details regarding the booking."
          },
          "autoConfirmRule": {
            "$ref": "#/components/schemas/AutoConfirmRule",
            "nullable": true
          },
          "cancellationPolicy": {
            "type": "string",
            "nullable": true,
            "description": "Terms and conditions for cancelling the booking."
          },
          "times": {
            "type": "array",
            "nullable": true,
            "items": {
              "$ref": "#/components/schemas/AvailabilityTime"
            }
          },
          "noAvailabilityReason": {
            "type": "string",
            "nullable": true,
            "description": "Populated only when `times` is empty — human-readable reason."
          },
          "noAvailabilityCode": {
            "type": "string",
            "nullable": true,
            "description": "Populated only when `times` is empty. Machine-readable code. Known values:\n`NO_AVAILABILITY`, `NO_ELIGIBLE_PRODUCTS`, `FILTERED_BY_OPERATOR_RULES`,\n`FILTERED_BY_CAPACITY`. Treat unknown values as a generic no-availability condition.\n"
          }
        }
      },
      "AvailabilityType": {
        "type": "string",
        "nullable": true,
        "description": "How a time slot can be handled. `book` = instant confirmation; `request` =\nmanual approval via enquiry.\n",
        "enum": [
          "book",
          "request"
        ],
        "example": "request"
      },
      "AvailabilityTime": {
        "type": "object",
        "properties": {
          "time": {
            "type": "string",
            "nullable": true,
            "description": "Available time slot (HH:mm).",
            "example": "18:00"
          },
          "duration": {
            "type": "integer",
            "nullable": true,
            "description": "Duration in minutes.",
            "example": 90
          },
          "type": {
            "$ref": "#/components/schemas/AvailabilityType"
          },
          "requestReason": {
            "type": "string",
            "nullable": true,
            "description": "Present only when `type` is `request`. Why the slot requires manual approval.\nKnown values: `fully_booked`, `exceeds_auto_confirm`, `request_only`.\nHandle unknown values gracefully.\n"
          },
          "product": {
            "$ref": "#/components/schemas/AvailabilityProduct",
            "nullable": true
          },
          "preOrderItems": {
            "$ref": "#/components/schemas/AvailabilityPreorderItems",
            "nullable": true
          },
          "unavailableReasons": {
            "type": "array",
            "nullable": true,
            "description": "Present only when `includeUnavailable=true` and the slot was filtered out.",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "AvailabilityProduct": {
        "type": "object",
        "nullable": true,
        "description": "Product info and applicable space policies for a time slot.",
        "properties": {
          "id": {
            "type": "string",
            "description": "CompositeId of the product."
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "spaces": {
            "type": "array",
            "nullable": true,
            "description": "Spaces associated with this product, with policies pre-filtered to the slot.",
            "items": {
              "$ref": "#/components/schemas/AvailabilitySpace"
            }
          }
        }
      },
      "AvailabilitySpace": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "Unique identifier of the space."
          },
          "spaceName": {
            "type": "string",
            "nullable": true
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "floorLocation": {
            "type": "integer",
            "nullable": true,
            "description": "Floor number (0 = ground floor)."
          },
          "facilities": {
            "type": "array",
            "nullable": true,
            "items": {
              "$ref": "#/components/schemas/SpaceFacility"
            }
          },
          "capacityStanding": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CapacityRange"
              }
            ],
            "nullable": true
          },
          "capacitySeated": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CapacityRange"
              }
            ],
            "nullable": true
          },
          "capacityCabaret": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CapacityRange"
              }
            ],
            "nullable": true
          },
          "capacityTheatre": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CapacityRange"
              }
            ],
            "nullable": true
          },
          "capacityBoardroom": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CapacityRange"
              }
            ],
            "nullable": true
          },
          "capacityClassroom": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CapacityRange"
              }
            ],
            "nullable": true
          },
          "capacityUShape": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CapacityRange"
              }
            ],
            "nullable": true
          },
          "capacityBanquet": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CapacityRange"
              }
            ],
            "nullable": true
          },
          "capacityReception": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CapacityRange"
              }
            ],
            "nullable": true
          },
          "policies": {
            "$ref": "#/components/schemas/AvailabilitySpacePolicies",
            "nullable": true
          }
        }
      },
      "AvailabilitySpacePolicies": {
        "type": "object",
        "description": "Space policies pre-filtered to the requested date and time slot.",
        "properties": {
          "minimumSpend": {
            "type": "array",
            "nullable": true,
            "description": "Minimum spend entries applicable to this slot (override wins).",
            "items": {
              "type": "object",
              "properties": {
                "label": {
                  "type": "string",
                  "nullable": true
                },
                "spendValue": {
                  "type": "integer",
                  "nullable": true,
                  "description": "Minimum spend in pence (GBP)."
                }
              }
            }
          },
          "under18s": {
            "type": "object",
            "nullable": true,
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "until": {
                "type": "string",
                "nullable": true
              }
            }
          },
          "occasionTypes": {
            "type": "object",
            "nullable": true,
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "values": {
                "type": "array",
                "nullable": true,
                "items": {
                  "$ref": "#/components/schemas/OccasionType"
                }
              }
            }
          },
          "promotedEvents": {
            "type": "object",
            "nullable": true,
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "notes": {
                "type": "string",
                "nullable": true
              }
            }
          },
          "accessibility": {
            "type": "object",
            "nullable": true,
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "accessible": {
                "type": "boolean",
                "nullable": true
              },
              "notes": {
                "type": "string",
                "nullable": true
              }
            }
          },
          "servesFood": {
            "type": "object",
            "nullable": true,
            "properties": {
              "enabled": {
                "type": "boolean"
              }
            }
          }
        }
      },
      "AvailabilityPreorderItems": {
        "type": "object",
        "nullable": true,
        "description": "Which packages and menus are available for this availability result.",
        "properties": {
          "packageIds": {
            "type": "array",
            "nullable": true,
            "description": "Package IDs available when `allowedPackages` is `set`.",
            "items": {
              "type": "string"
            }
          },
          "allowedPackages": {
            "type": "string",
            "nullable": true,
            "enum": [
              "none",
              "all",
              "set"
            ],
            "description": "`none`: no packages; `all`: all packages; `set`: only `packageIds`."
          },
          "menuIds": {
            "type": "array",
            "nullable": true,
            "description": "Menu IDs available when `allowedMenus` is `set`.",
            "items": {
              "type": "string"
            }
          },
          "allowedMenus": {
            "type": "string",
            "nullable": true,
            "enum": [
              "none",
              "all",
              "set"
            ],
            "description": "`none`: no menus; `all`: all menus; `set`: only `menuIds`."
          }
        }
      },
      "Customer": {
        "type": "object",
        "required": [
          "firstName",
          "lastName",
          "email",
          "phone"
        ],
        "properties": {
          "firstName": {
            "type": "string",
            "example": "John"
          },
          "lastName": {
            "type": "string",
            "example": "Doe"
          },
          "email": {
            "type": "string",
            "format": "email",
            "example": "john.doe@example.com"
          },
          "phone": {
            "type": "string",
            "description": "E.164 format.",
            "example": "+441234567890"
          },
          "dateOfBirth": {
            "type": "string",
            "format": "date",
            "nullable": true
          }
        }
      },
      "PreorderContainer": {
        "type": "object",
        "description": "Pre-order items attached to a table reservation.",
        "properties": {
          "packages": {
            "type": "array",
            "nullable": true,
            "items": {
              "$ref": "#/components/schemas/PreorderPackageRequest"
            }
          },
          "menus": {
            "type": "array",
            "nullable": true,
            "items": {
              "$ref": "#/components/schemas/PreorderMenuRequest"
            }
          }
        }
      },
      "PreorderPackageRequest": {
        "type": "object",
        "required": [
          "id",
          "quantity"
        ],
        "properties": {
          "id": {
            "type": "string",
            "example": "3f9a1c20-5b7e-4c1a-9e2d-1a2b3c4d5e6f"
          },
          "quantity": {
            "type": "integer",
            "minimum": 1,
            "default": 1,
            "example": 2
          }
        }
      },
      "PreorderMenuRequest": {
        "type": "object",
        "required": [
          "id",
          "quantity"
        ],
        "properties": {
          "id": {
            "type": "string",
            "example": "b4e6f810-1c2d-4a3b-9c8d-3c4d5e6f7081"
          },
          "quantity": {
            "type": "integer",
            "minimum": 1,
            "default": 1,
            "example": 4
          },
          "items": {
            "type": "array",
            "nullable": true,
            "items": {
              "$ref": "#/components/schemas/MenuItemSelection"
            }
          }
        }
      },
      "MenuItemSelection": {
        "type": "object",
        "required": [
          "id",
          "quantity"
        ],
        "properties": {
          "id": {
            "type": "string",
            "example": "c5f70921-2d3e-4b4c-8d9e-4d5e6f708192"
          },
          "quantity": {
            "type": "integer",
            "minimum": 1,
            "default": 1,
            "example": 3
          }
        }
      },
      "PreorderChanges": {
        "type": "object",
        "description": "Incremental preorder change for `OrderItemUpdate` — add or remove specific\npackages/menus without resending the full current list. Mutually exclusive\nwith `preorders` on the same item (400 `ORDER-N-008` if both are present).\nAn id appearing in both an \"add\" list and its matching \"remove\" list in the\nsame request is rejected (400 `ORDER-N-009`) rather than silently resolved.\n",
        "properties": {
          "addPackages": {
            "type": "array",
            "nullable": true,
            "description": "Packages to add. If a package with the same `id` is already on the\nbooking, this replaces its quantity (upsert), matching legacy's\n`/preorders/packages/{id}/quantity` behavior — it does not add a\nduplicate line or increment the existing quantity.\n",
            "items": {
              "$ref": "#/components/schemas/PreorderPackageRequest"
            }
          },
          "removePackageIds": {
            "type": "array",
            "nullable": true,
            "items": {
              "type": "string"
            }
          },
          "addMenus": {
            "type": "array",
            "nullable": true,
            "description": "Menus to add. If a menu with the same `id` is already on the booking,\nthis replaces its quantity and its full `items` selection (upsert) —\nthere's no separate operation to change one item within an existing\nmenu; resend that menu's full `items` list here to change it.\n",
            "items": {
              "$ref": "#/components/schemas/PreorderMenuRequest"
            }
          },
          "removeMenuIds": {
            "type": "array",
            "nullable": true,
            "items": {
              "type": "string"
            }
          }
        }
      },
      "CreateOrderRequest": {
        "description": "Create-order request. No `capability`/`oneOf` split — every item is one\n`OrderItem`, unified (same pattern as `Bookable`/`BookingResult`):\ncapability is resolved server-side from each item's `compositeId` RMS slug,\nnot from which fields are populated. An order's items may mix capabilities\nand even RMS platforms; each is booked independently.\n",
        "allOf": [
          {
            "$ref": "#/components/schemas/CreateOrderRequestBase"
          },
          {
            "type": "object",
            "required": [
              "items"
            ],
            "properties": {
              "items": {
                "type": "array",
                "minItems": 1,
                "description": "One item per booking to create.",
                "items": {
                  "$ref": "#/components/schemas/OrderItem"
                }
              }
            }
          }
        ]
      },
      "CreateOrderRequestBase": {
        "type": "object",
        "description": "No `listingId` — every item carries its own `compositeId`, self-sufficient\n(embeds `VenueGroupId` + `RmsSlug`), so a single order's items may span\nmultiple listings and even multiple RMS platforms.\n",
        "required": [
          "customer"
        ],
        "properties": {
          "customer": {
            "$ref": "#/components/schemas/Customer"
          },
          "partnerOrderId": {
            "type": "string",
            "nullable": true,
            "description": "Optional external reference for cross-system tracking."
          },
          "notes": {
            "type": "string",
            "nullable": true
          },
          "adminNotes": {
            "type": "array",
            "nullable": true,
            "items": {
              "type": "string"
            },
            "description": "Internal notes visible to venue operators only."
          },
          "marketingConsent": {
            "type": "boolean",
            "nullable": true
          }
        }
      },
      "OrderItem": {
        "type": "object",
        "description": "A single booking to create within an order. Common fields (including\n`notes` and `partnerBookingId`) always apply; `time`/`duration`/`type`/\n`preorders`/`spaceId`/`depositAmount` apply to table reservations only.\nCapability is resolved server-side from the `compositeId`'s RMS slug — not\ninferred from which fields are populated. There is no `sessionId`: `date`\nidentifies the event occurrence directly.\n",
        "required": [
          "compositeId",
          "date",
          "quantity"
        ],
        "properties": {
          "compositeId": {
            "type": "string",
            "description": "CompositeId of the bookable product.\n- table_reservation → `{VenueGroupId}|{RmsSlug}|{VenueId}|{ProductId}`\n- event_ticket → `{VenueGroupId}|{RmsSlug}|{EventId}|{TicketTypeId}`\n",
            "example": "29|CO|275cc44dd2e2496fba44857c9257443a|e4d909c290d0fb1ca068ffaddf22cbd0"
          },
          "date": {
            "type": "string",
            "format": "date",
            "example": "2026-06-15"
          },
          "quantity": {
            "type": "integer",
            "minimum": 1,
            "description": "Covers for a table reservation, or ticket count for an event-ticket line.\n",
            "example": 4
          },
          "notes": {
            "type": "string",
            "nullable": true,
            "description": "Free-text note or special request for the booking. Applies to either\ncapability — table reservation notes or an event-ticket purchase comment.\n",
            "example": "Birthday celebration"
          },
          "partnerBookingId": {
            "type": "string",
            "nullable": true,
            "description": "Optional external reference supplied by the caller, used to cross-link\nthis booking with records in another system. Applies to either capability.\n",
            "example": "ext-ref-123"
          },
          "commission": {
            "type": "number",
            "format": "double",
            "nullable": true,
            "description": "Partner commission for this booking. Currently wired through only for\n`event_ticket` (Tonic's `partner_commission`) — behaviour for\n`table_reservation` (Collins/Zonal) is not yet defined.\n",
            "example": 2.5
          },
          "time": {
            "type": "string",
            "nullable": true,
            "pattern": "^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$",
            "example": "19:30"
          },
          "duration": {
            "type": "integer",
            "nullable": true,
            "description": "Duration in minutes.",
            "example": 90
          },
          "type": {
            "type": "string",
            "nullable": true,
            "enum": [
              "book",
              "request"
            ],
            "description": "Must match the availability slot type returned for this time.",
            "example": "book"
          },
          "preorders": {
            "$ref": "#/components/schemas/PreorderContainer",
            "nullable": true
          },
          "spaceId": {
            "type": "integer",
            "nullable": true,
            "description": "Specific space/area to book, overriding automatic selection by the RMS.\nObtain valid ids from `AvailabilityResult.availability.times[].product.spaces[].id`\nin the `POST /v1/availabilities` response for this `compositeId`/`date`/`time` —\nnot from `Bookable.spaces[]`, which is the unfiltered listing-level list.\n",
            "example": 12
          },
          "depositAmount": {
            "type": "number",
            "format": "double",
            "nullable": true,
            "description": "Deposit amount to charge for this booking. When provided, a payment is\ntaken from the RMS for this exact amount; when omitted, none is taken.\n",
            "example": 10
          },
          "unitPriceAmount": {
            "type": "number",
            "format": "double",
            "nullable": true,
            "example": 25
          },
          "priceCurrency": {
            "type": "string",
            "nullable": true,
            "example": "GBP"
          }
        }
      },
      "Order": {
        "type": "object",
        "description": "Canonical response for any created order, regardless of capability.\nOrder-level fields are always present; per-item outcomes are in `results[]` —\neach requested item is resolved independently, so a single order can be\npartially confirmed (e.g. one item's platform is fully booked while others\nsucceed). There is no order-wide `status`; check each result.\n",
        "required": [
          "id",
          "customer",
          "createdAt",
          "results"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Platform-generated unique order identifier.",
            "example": "ORD-9980140810"
          },
          "partnerOrderId": {
            "type": "string",
            "nullable": true
          },
          "customer": {
            "$ref": "#/components/schemas/Customer"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-04-21T14:22:00Z"
          },
          "results": {
            "type": "array",
            "description": "One result per requested item, in request order.",
            "items": {
              "$ref": "#/components/schemas/OrderItemResult"
            }
          }
        }
      },
      "OrderItemResult": {
        "type": "object",
        "description": "Outcome for a single requested order item. Exactly one of `booking` or\n`error` is populated: `booking` on success, `error` on failure. Mirrors\n`AvailabilityResult`'s per-item success-xor-error shape.\n",
        "required": [
          "compositeId",
          "date"
        ],
        "properties": {
          "compositeId": {
            "type": "string",
            "description": "The `compositeId` this result refers to — the product for a\ntable-reservation item, or the ticket-type line for an event-ticket line.\n",
            "example": "29|CO|275cc44dd2e2496fba44857c9257443a|e4d909c290d0fb1ca068ffaddf22cbd0"
          },
          "date": {
            "type": "string",
            "format": "date",
            "description": "The date this result refers to.",
            "example": "2026-06-15"
          },
          "booking": {
            "$ref": "#/components/schemas/BookingResult",
            "nullable": true
          },
          "error": {
            "$ref": "#/components/schemas/ServerError",
            "nullable": true
          }
        }
      },
      "BookingResult": {
        "type": "object",
        "description": "Confirmed booking detail for a single order item. Common fields (including\n`quantity` — covers or ticket count) always apply; `time`/`duration`/\n`preorders` apply to table reservations only, `unitPriceAmount`/\n`priceCurrency` to event tickets only. Check `capability` to know which.\n",
        "required": [
          "id",
          "capability",
          "status",
          "quantity"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Booking CompositeId assigned by the platform — the `bookingId` to pass\nback in `OrderItemUpdate.bookingId` / `OrderCancelRequest.bookingIds`\nfor a subsequent `PATCH`/`DELETE /v1/orders/{orderId}` call. Opaque and\nplatform-specific in shape — e.g. Collins/Zonal append a booking-type\nflag (`B`/`R`) as a 4th segment, Tonic uses a plain 3-segment purchase\nreference. Never equal to the `compositeId` that was booked (a different\nresource — the booking itself vs. the product/ticket type); treat it as\nan opaque token and round-trip it exactly as received.\n",
            "example": "29|CO|BKG-8841203|B"
          },
          "capability": {
            "$ref": "#/components/schemas/Capability"
          },
          "reference": {
            "type": "string",
            "nullable": true,
            "description": "Human-readable reference (e.g. DMN-9980140810).",
            "example": "DMN-9980140810"
          },
          "operatorOrderId": {
            "type": "string",
            "nullable": true,
            "description": "Booking reference assigned by the operator's RMS (Collins, Zonal, Tonic, etc.)."
          },
          "status": {
            "type": "string",
            "enum": [
              "Pending",
              "InProgress",
              "Confirmed",
              "Cancelled",
              "Deleted",
              "Lost"
            ],
            "example": "Confirmed"
          },
          "productName": {
            "type": "string",
            "nullable": true
          },
          "quantity": {
            "type": "integer",
            "description": "Covers for a table reservation, or ticket count for an event-ticket line.",
            "example": 2
          },
          "notes": {
            "type": "string",
            "nullable": true,
            "description": "Free-text note or special request for the booking. Applies to either\ncapability — table reservation notes or an event-ticket purchase comment.\n",
            "example": "Birthday celebration"
          },
          "partnerBookingId": {
            "type": "string",
            "nullable": true,
            "description": "External reference supplied by the caller at creation time, used to\ncross-link this booking with records in another system. Applies to\neither capability.\n",
            "example": "ext-ref-123"
          },
          "time": {
            "type": "string",
            "nullable": true,
            "pattern": "^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$",
            "example": "19:30"
          },
          "duration": {
            "type": "integer",
            "nullable": true
          },
          "preorders": {
            "$ref": "#/components/schemas/PreorderContainer",
            "nullable": true
          },
          "spaceId": {
            "type": "integer",
            "nullable": true,
            "description": "Space/area booked — either the requested `OrderItem.spaceId` or the\none assigned by the RMS. Matches an id from\n`AvailabilityResult.availability.times[].product.spaces[].id`.\n",
            "example": 12
          },
          "depositAmount": {
            "type": "number",
            "format": "double",
            "nullable": true,
            "description": "Deposit amount charged for this booking, when applicable.",
            "example": 10
          },
          "unitPriceAmount": {
            "type": "number",
            "format": "double",
            "nullable": true,
            "example": 25
          },
          "priceCurrency": {
            "type": "string",
            "nullable": true,
            "example": "GBP"
          }
        }
      },
      "OrderUpdateRequest": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "minItems": 1,
            "description": "One entry per booking to update, within this order.",
            "items": {
              "$ref": "#/components/schemas/OrderItemUpdate"
            }
          }
        }
      },
      "OrderItemUpdate": {
        "type": "object",
        "description": "Partial update for a single booking. Only populated fields are changed —\nanything omitted keeps its current value. Capability is resolved server-side\nfrom the existing booking (looked up via `bookingId`), not from the request.\n",
        "required": [
          "bookingId"
        ],
        "properties": {
          "bookingId": {
            "type": "string",
            "description": "The booking's platform id — `BookingResult.id` from the create/update/cancel response.",
            "example": "1|TN|423458"
          },
          "notes": {
            "type": "string",
            "nullable": true,
            "description": "Internal note. Table reservation → booking notes; event ticket → Tonic purchase comment.",
            "example": "Customer upgraded to Pay ticket"
          },
          "firstName": {
            "type": "string",
            "nullable": true,
            "description": "Guest first name. Applies to either capability.",
            "example": "John"
          },
          "lastName": {
            "type": "string",
            "nullable": true,
            "description": "Guest last name. Applies to either capability.",
            "example": "Doe"
          },
          "email": {
            "type": "string",
            "format": "email",
            "nullable": true,
            "description": "Guest email address. Applies to either capability.",
            "example": "john.doe@example.com"
          },
          "phone": {
            "type": "string",
            "nullable": true,
            "description": "Guest phone number, E.164 format. Applies to either capability.",
            "example": "+441234567890"
          },
          "commission": {
            "type": "number",
            "format": "double",
            "nullable": true,
            "description": "Partner commission for this booking. Currently wired through for\n`table_reservation` (Collins) on update — `event_ticket` (Tonic) only\nsupports commission on create today, not on update.\n",
            "example": 2.5
          },
          "date": {
            "type": "string",
            "format": "date",
            "nullable": true,
            "example": "2026-06-15"
          },
          "time": {
            "type": "string",
            "nullable": true,
            "pattern": "^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$",
            "example": "20:00"
          },
          "duration": {
            "type": "integer",
            "nullable": true,
            "example": 90
          },
          "quantity": {
            "type": "integer",
            "minimum": 1,
            "nullable": true,
            "description": "New covers count for a table reservation, or new ticket count for an\nevent-ticket line. For event tickets: a **decrease** is processed as a\npartial refund of the difference; an **increase** is rejected with 400\n(`EVENT-N-003`) — Tonic has no way to add tickets to an existing purchase,\ncreate a new order item instead.\n",
            "example": 6
          },
          "preorders": {
            "$ref": "#/components/schemas/PreorderContainer",
            "nullable": true
          },
          "preorderChanges": {
            "$ref": "#/components/schemas/PreorderChanges",
            "nullable": true
          },
          "compositeId": {
            "type": "string",
            "nullable": true,
            "description": "Full CompositeId of the bookable product to move this booking to — same\nshape and meaning as `Bookable.compositeId` (the only identifier taken\nfrom a listing's `bookableProducts[]`), not a ticket-specific field.\n\nSupported for both capabilities: for event tickets, moves to a different\nticket type on the same event (the compositeId's 4th segment); for table\nreservations, moves to a different bookable product/space on the same\nvenue. Optionally combined with `date` in the same operation — Tonic has\nno separate \"change date only\" call.\n\nThe new compositeId must reference the same venue group, RMS, and\nvenue/event as the booking's current product — only the trailing\nproduct/ticket-type segment (`AdditionalId`) may differ. A cross-venue\nor cross-event compositeId is rejected with 400 (`ORDER-N-007`).\n",
            "example": "1|TN|6a2bbc0285bf210719631c44|6a2bbb580ed61600150618f7"
          }
        }
      },
      "OrderCancelRequest": {
        "type": "object",
        "description": "Cancellation scope for `DELETE /v1/orders/{orderId}`. Omit entirely to cancel the whole order.",
        "properties": {
          "bookingIds": {
            "type": "array",
            "nullable": true,
            "description": "Booking ids to cancel. Omitted or empty → cancel every booking in the order.",
            "items": {
              "type": "string"
            },
            "example": [
              "1|TN|423458"
            ]
          }
        }
      },
      "ServerError": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "format": "uri",
            "description": "A URI reference [rfc9457] that identifies the problem type. This specification encourages that, when dereferenced, it provides human-readable documentation for the problem type (e.g., using HTML [W3C.REC-html5-20141028]). When this member is not present, its value is assumed to be \"about:blank\"."
          },
          "title": {
            "type": "string",
            "description": "A short, human-readable summary of the problem type. It SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization."
          },
          "status": {
            "type": "integer",
            "format": "int32",
            "description": "The HTTP status code [rfc9457, Section 3.1.12] generated by the origin server for this occurrence of the problem."
          },
          "detail": {
            "type": "string",
            "description": "A human-readable explanation specific to this occurrence of the problem."
          },
          "code": {
            "type": "string",
            "description": "Error code in the format RESOURCE-X-NNN where X is R (retryable) or N (non-retryable). See ErrorCatalog.md for all error codes.",
            "example": "BOOK-N-001"
          },
          "isRetryable": {
            "type": "boolean",
            "description": "Indicates whether the error is retryable. If true, the request may succeed if retried. If false, the request will fail again with the same input."
          },
          "traceId": {
            "type": "string",
            "description": "Request trace identifier for debugging and correlation purposes.",
            "example": "0HNJ2BG2TU3BU:00000001"
          }
        },
        "required": [
          "title",
          "status",
          "code",
          "isRetryable"
        ]
      },
      "Page": {
        "type": "object",
        "properties": {
          "meta": {
            "type": "object",
            "properties": {
              "currentPage": {
                "type": "integer",
                "description": "The current page number based on `limit` and `offset`."
              },
              "pageSize": {
                "type": "integer",
                "description": "The number of items returned per page."
              },
              "totalItems": {
                "type": "integer",
                "description": "The total number of items available."
              },
              "totalPages": {
                "type": "integer",
                "description": "The total number of pages."
              }
            }
          }
        }
      },
      "FaqItem": {
        "type": "object",
        "description": "Single FAQ entry. `question`/`answer` are plain strings and may contain markdown syntax; the server does not parse or sanitize it — rendering happens client-side.\n",
        "properties": {
          "question": {
            "type": "string",
            "nullable": true,
            "example": "What is your cancellation policy?"
          },
          "answer": {
            "type": "string",
            "nullable": true,
            "example": "See our **cancellation policy** [here](https://example.com/policy)."
          }
        }
      },
      "SpaceFacility": {
        "type": "string",
        "description": "Facilities available in a space.",
        "enum": [
          "Stage",
          "Private Bar",
          "Private Toilets",
          "Soundproof",
          "Own Street Entrance",
          "Fixed Seating",
          "Outside Space",
          "Can Be Decorated",
          "DJ Stand",
          "Suitable for Meetings",
          "Wheelchair Accessible",
          "Accessible Toilets",
          "Projector",
          "Screen / TV",
          "Microphone / PA",
          "Laptop Connection",
          "Own Sound System",
          "HDMI / AV",
          "In-House Lighting",
          "Sports TV",
          "Bring Own DJ",
          "Serves Food",
          "External Catering Permitted",
          "Draft Beer",
          "Cash Bar",
          "Can Bring Own Cake",
          "Tea/Coffee Facilities",
          "Cloakroom",
          "Smoking Area",
          "Wifi Available",
          "Pet Friendly",
          "Parking",
          "Air Conditioning"
        ]
      },
      "CapacityRange": {
        "type": "object",
        "description": "Min/max capacity range; both bounds are optional.",
        "properties": {
          "min": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "max": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          }
        }
      },
      "MinimumSpendDateRange": {
        "type": "object",
        "description": "Explicit date interval (inclusive, ISO 8601). Does not recur.",
        "properties": {
          "from": {
            "type": "string",
            "format": "date"
          },
          "to": {
            "type": "string",
            "format": "date"
          }
        }
      },
      "MinimumSpendTimeRange": {
        "type": "object",
        "description": "Time window of the booking start time (HH:MM, inclusive, Europe/London).",
        "properties": {
          "from": {
            "type": "string",
            "example": "18:00"
          },
          "to": {
            "type": "string",
            "example": "23:59"
          }
        }
      },
      "MinimumSpendConditions": {
        "type": "object",
        "description": "Conditions that must all be satisfied for the rule to apply (AND logic).\nAn empty object means the rule applies without restriction.\n",
        "properties": {
          "daysOfWeek": {
            "type": "array",
            "nullable": true,
            "description": "Days of the week (1=Monday, 7=Sunday). Absent means all days.",
            "items": {
              "type": "integer",
              "format": "int32"
            }
          },
          "months": {
            "type": "array",
            "nullable": true,
            "description": "Calendar months (1=January, 12=December). Absent means all months.",
            "items": {
              "type": "integer",
              "format": "int32"
            }
          },
          "dateRange": {
            "allOf": [
              {
                "$ref": "#/components/schemas/MinimumSpendDateRange"
              }
            ],
            "nullable": true
          },
          "timeRange": {
            "allOf": [
              {
                "$ref": "#/components/schemas/MinimumSpendTimeRange"
              }
            ],
            "nullable": true
          }
        }
      },
      "MinimumSpendRuleBase": {
        "type": "object",
        "properties": {
          "label": {
            "type": "string",
            "nullable": true
          },
          "conditions": {
            "$ref": "#/components/schemas/MinimumSpendConditions"
          },
          "spendValue": {
            "type": "integer",
            "format": "int32",
            "nullable": true,
            "description": "Minimum spend amount in pence (GBP)."
          },
          "notes": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "MinimumSpendOverrideBase": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "format": "date",
            "description": "The specific calendar date. Also serves as the URL key."
          },
          "label": {
            "type": "string",
            "nullable": true
          },
          "spendValue": {
            "type": "integer",
            "format": "int32",
            "nullable": true,
            "description": "Minimum spend amount in pence (GBP)."
          },
          "timeRange": {
            "allOf": [
              {
                "$ref": "#/components/schemas/MinimumSpendTimeRange"
              }
            ],
            "nullable": true,
            "description": "Optional time window (Europe/London) the override applies to. Absent means the override covers the whole date. Outside the window, normal rules apply."
          }
        }
      },
      "MinimumSpendPolicyResponse": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "rules": {
            "type": "array",
            "description": "Weekly recurring minimum spend rules. Empty array means none configured.",
            "items": {
              "$ref": "#/components/schemas/MinimumSpendRuleBase"
            }
          },
          "overrides": {
            "type": "array",
            "description": "Date-specific minimum spend overrides. Empty array means none configured.",
            "items": {
              "$ref": "#/components/schemas/MinimumSpendOverrideBase"
            }
          }
        }
      },
      "OccasionType": {
        "type": "string",
        "description": "Allowed occasion types for a space.",
        "enum": [
          "Christmas Party",
          "Corporate Event",
          "Engagement Party",
          "Funeral/Wake",
          "Summer Party",
          "Wedding Party",
          "Winter Party",
          "Work Get Together",
          "Working Breakfast",
          "Working Lunch",
          "Working Dinner",
          "Promoted Event"
        ]
      },
      "OccasionTypesPolicyResponse": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "values": {
            "type": "array",
            "nullable": true,
            "description": "Allowed occasion types.",
            "items": {
              "$ref": "#/components/schemas/OccasionType"
            }
          }
        }
      },
      "Under18sPolicyResponse": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "allowed": {
            "type": "boolean",
            "nullable": true,
            "description": "Whether under-18s are permitted (`true`) or prohibited (`false`) in this space.\n`null` means the policy has not been explicitly set.\n`allowed` must not be `true` when `enabled` is `false`.\n"
          },
          "until": {
            "type": "string",
            "nullable": true,
            "description": "Cutoff time for under-18s, e.g. \"21:00\"."
          }
        }
      },
      "PromotedEventsPolicyResponse": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "allowed": {
            "type": "boolean",
            "nullable": true,
            "description": "Whether promoted events are permitted (`true`) or prohibited (`false`) in this space.\n`null` means the policy has not been explicitly set.\n`allowed` must not be `true` when `enabled` is `false`.\n"
          },
          "notes": {
            "type": "string",
            "nullable": true,
            "description": "Optional notes about promoted events at this space."
          }
        }
      },
      "AccessibilityPolicyResponse": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "accessible": {
            "type": "boolean",
            "nullable": true
          },
          "notes": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "ServesFoodPolicyResponse": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "allowed": {
            "type": "boolean",
            "nullable": true,
            "description": "Whether the space serves food (`true`) or does not (`false`).\n`null` means the policy has not been explicitly set.\n`allowed` must not be `true` when `enabled` is `false`.\n"
          }
        }
      },
      "SpacePoliciesMap": {
        "type": "object",
        "description": "All policies for a space, keyed by policy type. An empty/default object means\nthat policy has not been configured for this space yet.\n",
        "properties": {
          "minimumSpend": {
            "$ref": "#/components/schemas/MinimumSpendPolicyResponse"
          },
          "occasionTypes": {
            "$ref": "#/components/schemas/OccasionTypesPolicyResponse"
          },
          "under18s": {
            "$ref": "#/components/schemas/Under18sPolicyResponse"
          },
          "promotedEvents": {
            "$ref": "#/components/schemas/PromotedEventsPolicyResponse"
          },
          "accessibility": {
            "$ref": "#/components/schemas/AccessibilityPolicyResponse"
          },
          "servesFood": {
            "$ref": "#/components/schemas/ServesFoodPolicyResponse"
          }
        }
      },
      "ClientError": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "format": "uri",
            "description": "A URI reference [rfc9457] that identifies the problem type. This specification encourages that, when dereferenced, it provides human-readable documentation for the problem type (e.g., using HTML [W3C.REC-html5-20141028]). When this member is not present, its value is assumed to be \"about:blank\"."
          },
          "title": {
            "type": "string",
            "description": "A short, human-readable summary of the problem type. It SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization."
          },
          "status": {
            "type": "integer",
            "format": "int32",
            "description": "The HTTP status code [rfc9457, Section 3.1.12] generated by the origin server for this occurrence of the problem."
          },
          "detail": {
            "type": "string",
            "description": "A human-readable explanation specific to this occurrence of the problem."
          },
          "code": {
            "type": "string",
            "description": "Error code in the format RESOURCE-X-NNN where X is R (retryable) or N (non-retryable). See ErrorCatalog.md for all error codes.",
            "example": "VALID-N-001"
          },
          "isRetryable": {
            "type": "boolean",
            "description": "Indicates whether the error is retryable. If true, the request may succeed if retried. If false, the request will fail again with the same input."
          },
          "traceId": {
            "type": "string",
            "description": "Request trace identifier for debugging and correlation purposes.",
            "example": "0HNJ2BG2TU3BU:00000001"
          },
          "errors": {
            "type": "object",
            "nullable": true,
            "additionalProperties": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "description": "Validation errors dictionary mapping field names to arrays of error messages. Only present for validation errors (VALID-N-001).",
            "example": {
              "Date": [
                "Availability date cannot be in the past."
              ],
              "EndTime": [
                "EndTime must be after StartTime."
              ]
            }
          }
        },
        "required": [
          "title",
          "status",
          "code",
          "isRetryable"
        ]
      }
    },
    "examples": {
      "CreateOrderTableReservationResponseExample": {
        "summary": "Both items booked successfully (matches the `tableReservation` request example, spanning two platforms)",
        "value": {
          "id": "ORD-8841203A",
          "partnerOrderId": null,
          "customer": {
            "firstName": "John",
            "lastName": "Doe",
            "email": "john.doe@example.com",
            "phone": "+441234567890"
          },
          "createdAt": "2026-06-15T09:12:44Z",
          "results": [
            {
              "compositeId": "29|CO|275cc44dd2e2496fba44857c9257443a|e4d909c290d0fb1ca068ffaddf22cbd0",
              "date": "2026-06-15",
              "booking": {
                "id": "29|CO|BKG-8841203|B",
                "capability": "table_reservation",
                "reference": "DMN-8841203",
                "operatorOrderId": "8841203",
                "status": "Confirmed",
                "productName": "Dining Room",
                "quantity": 4,
                "notes": null,
                "partnerBookingId": null,
                "time": "19:30",
                "duration": 90,
                "preorders": null,
                "spaceId": 12,
                "depositAmount": 10
              },
              "error": null
            },
            {
              "compositeId": "41|ZO|9a1c20-5b7e-4c1a|8c2d4e60-9a1b-4f3c",
              "date": "2026-06-15",
              "booking": {
                "id": "41|ZO|EVT-77210|B",
                "capability": "table_reservation",
                "reference": null,
                "operatorOrderId": "77210",
                "status": "Confirmed",
                "productName": "Roof Terrace",
                "quantity": 2,
                "notes": null,
                "partnerBookingId": null,
                "time": "20:00",
                "duration": 120,
                "preorders": null,
                "spaceId": null,
                "depositAmount": null
              },
              "error": null
            }
          ]
        }
      },
      "CreateOrderEventTicketResponseExample": {
        "summary": "Both ticket-type lines booked successfully (matches the `eventTicket` request example, same event/date)",
        "value": {
          "id": "ORD-F55BCDC2",
          "partnerOrderId": null,
          "customer": {
            "firstName": "Jane",
            "lastName": "Smith",
            "email": "jane.smith@example.com",
            "phone": "+441234567891"
          },
          "createdAt": "2026-07-17T07:55:58Z",
          "results": [
            {
              "compositeId": "29|TN|69f87ae8c7475734752555b4|69f87a8568063a182c46c198",
              "date": "2026-07-19",
              "booking": {
                "id": "29|TN|6a59e00dca03551cc60dc839",
                "capability": "event_ticket",
                "reference": null,
                "operatorOrderId": "426071",
                "status": "Confirmed",
                "productName": null,
                "quantity": 2,
                "notes": null,
                "partnerBookingId": null,
                "unitPriceAmount": 25,
                "priceCurrency": "GBP"
              },
              "error": null
            },
            {
              "compositeId": "29|TN|69f87ae8c7475734752555b4|69f87a97c74757172d362198",
              "date": "2026-07-19",
              "booking": {
                "id": "29|TN|6a59e00eca03551cc60dc840",
                "capability": "event_ticket",
                "operatorOrderId": "427896",
                "status": "Confirmed",
                "quantity": 1,
                "unitPriceAmount": 50,
                "priceCurrency": "GBP"
              },
              "error": null
            }
          ]
        }
      },
      "CreateOrderPartialFailureExample": {
        "summary": "One item booked, the other failed independently — 207 because at least one item failed",
        "value": {
          "id": "ORD-6B21F9A0",
          "partnerOrderId": null,
          "customer": {
            "firstName": "John",
            "lastName": "Doe",
            "email": "john.doe@example.com",
            "phone": "+441234567890"
          },
          "createdAt": "2026-06-15T09:12:44Z",
          "results": [
            {
              "compositeId": "29|CO|275cc44dd2e2496fba44857c9257443a|e4d909c290d0fb1ca068ffaddf22cbd0",
              "date": "2026-06-15",
              "booking": {
                "id": "29|CO|BKG-8841204|B",
                "capability": "table_reservation",
                "reference": "DMN-8841204",
                "operatorOrderId": "8841204",
                "status": "Confirmed",
                "productName": "Dining Room",
                "quantity": 4,
                "time": "19:30",
                "duration": 90,
                "spaceId": 12,
                "depositAmount": 10
              },
              "error": null
            },
            {
              "compositeId": "29|TN|69f87ae8c7475734752555b4|69f87a97c74757172d362198",
              "date": "2026-07-19",
              "booking": null,
              "error": {
                "title": "Bad request",
                "status": 409,
                "code": "BOOK-N-014",
                "isRetryable": false,
                "detail": "This ticket type is sold out for the requested date."
              }
            }
          ]
        }
      },
      "UpdateOrderEventTicketResponseExample": {
        "summary": "Ticket-type line moved to a new ticket type and date (matches the `changeTicketType` request example)",
        "value": {
          "id": "ORD-9980140810",
          "customer": {
            "firstName": "Jane",
            "lastName": "Smith",
            "email": "jane.smith@example.com",
            "phone": "+441234567891"
          },
          "createdAt": "2027-01-10T11:45:03Z",
          "results": [
            {
              "compositeId": "1|TN|6a59f0a0f58eb1c0fa00d040",
              "date": "2027-02-22",
              "booking": {
                "id": "1|TN|6a59f0a0f58eb1c0fa00d040",
                "capability": "event_ticket",
                "operatorOrderId": "429321",
                "status": "Confirmed",
                "quantity": 2,
                "notes": "Customer upgraded to Kids ticket"
              },
              "error": null
            }
          ]
        }
      },
      "UpdateOrderTableReservationResponseExample": {
        "summary": "Table reservation's time and party size changed (matches the `rescheduleTable` request example)",
        "value": {
          "id": "ORD-9980140810",
          "customer": {
            "firstName": "John",
            "lastName": "Doe",
            "email": "john.doe@example.com",
            "phone": "+441234567890"
          },
          "createdAt": "2026-06-10T08:30:00Z",
          "results": [
            {
              "compositeId": "1|CO|BKG-8841203|B",
              "date": "2026-06-15",
              "booking": {
                "id": "1|CO|BKG-8841203|B",
                "capability": "table_reservation",
                "reference": "DMN-1002",
                "operatorOrderId": "BKG-8841203",
                "status": "Confirmed",
                "productName": "Dining Room",
                "quantity": 6,
                "time": "20:00",
                "duration": 90,
                "spaceId": 12,
                "depositAmount": 10
              },
              "error": null
            }
          ]
        }
      },
      "UpdateOrderCustomerAndProductResponseExample": {
        "summary": "Guest name/phone changed and the reservation moved to a different product on the same venue (matches the `changeCustomerAndProduct` request example)",
        "value": {
          "id": "ORD-9980140810",
          "customer": {
            "firstName": "Jonathan",
            "lastName": "Doe",
            "email": "john.doe@example.com",
            "phone": "+441234567899"
          },
          "createdAt": "2026-06-10T08:30:00Z",
          "results": [
            {
              "compositeId": "29|CO|BKG-8841203|B",
              "date": "2026-06-15",
              "booking": {
                "id": "29|CO|BKG-8841203|B",
                "capability": "table_reservation",
                "reference": "DMN-1002",
                "operatorOrderId": "BKG-8841203",
                "status": "Confirmed",
                "productName": "Set Lunch Room",
                "quantity": 4,
                "time": "19:30",
                "duration": 90,
                "spaceId": null,
                "depositAmount": null
              },
              "error": null
            }
          ]
        }
      },
      "UpdateOrderAddPreorderResponseExample": {
        "summary": "Preorder package added without resending the rest of the preorders (matches the `addPreorderPackage` request example)",
        "value": {
          "id": "ORD-9980140810",
          "customer": {
            "firstName": "John",
            "lastName": "Doe",
            "email": "john.doe@example.com",
            "phone": "+441234567890"
          },
          "createdAt": "2026-06-10T08:30:00Z",
          "results": [
            {
              "compositeId": "29|CO|BKG-8841203|B",
              "date": "2026-06-15",
              "booking": {
                "id": "29|CO|BKG-8841203|B",
                "capability": "table_reservation",
                "reference": "DMN-1002",
                "operatorOrderId": "BKG-8841203",
                "status": "Confirmed",
                "productName": "Dining Room",
                "quantity": 4,
                "time": "19:30",
                "duration": 90,
                "preorders": {
                  "packages": [
                    {
                      "id": "3f9a1c20-5b7e-4c1a-9e2d-1a2b3c4d5e6f",
                      "quantity": 2
                    }
                  ]
                },
                "spaceId": 12,
                "depositAmount": 10
              },
              "error": null
            }
          ]
        }
      },
      "UpdateOrderFailureExample": {
        "summary": "Booking not found — a stale, mistyped or already-cancelled bookingId was supplied",
        "value": {
          "id": "ORD-9980140810",
          "customer": {
            "firstName": "",
            "lastName": "",
            "email": "",
            "phone": ""
          },
          "createdAt": "2027-01-10T11:45:03Z",
          "results": [
            {
              "compositeId": "1|TN|999999",
              "date": "0001-01-01",
              "booking": null,
              "error": {
                "title": "Bad request",
                "status": 404,
                "code": "ORDER-N-404",
                "isRetryable": false,
                "detail": "Booking not found: 1|TN|999999"
              }
            }
          ]
        }
      },
      "CancelOrderWholeResponseExample": {
        "summary": "Entire order cancelled (empty/omitted request body cancels every booking in it)",
        "value": {
          "id": "ORD-9980140810",
          "customer": {
            "firstName": "John",
            "lastName": "Doe",
            "email": "john.doe@example.com",
            "phone": "+441234567890"
          },
          "createdAt": "2026-06-15T09:12:44Z",
          "results": [
            {
              "compositeId": "29|CO|BKG-8841203|B",
              "date": "2026-06-15",
              "booking": {
                "id": "29|CO|BKG-8841203|B",
                "capability": "table_reservation",
                "reference": "DMN-8841203",
                "operatorOrderId": "8841203",
                "status": "Cancelled",
                "productName": "Dining Room",
                "quantity": 4,
                "spaceId": 12,
                "depositAmount": 10
              },
              "error": null
            },
            {
              "compositeId": "41|ZO|EVT-77210|B",
              "date": "2026-06-15",
              "booking": {
                "id": "41|ZO|EVT-77210|B",
                "capability": "table_reservation",
                "operatorOrderId": "77210",
                "status": "Cancelled",
                "productName": "Roof Terrace",
                "quantity": 2
              },
              "error": null
            }
          ]
        }
      },
      "CancelOrderSingleBookingResponseExample": {
        "summary": "Single booking cancelled within the order (matches the `singleBooking` request example)",
        "value": {
          "id": "ORD-9980140810",
          "customer": {
            "firstName": "Jane",
            "lastName": "Smith",
            "email": "jane.smith@example.com",
            "phone": "+441234567891"
          },
          "createdAt": "2027-01-10T11:45:03Z",
          "results": [
            {
              "compositeId": "1|TN|423458",
              "date": "2027-02-22",
              "booking": {
                "id": "1|TN|423458",
                "capability": "event_ticket",
                "operatorOrderId": "427896",
                "status": "Cancelled",
                "quantity": 1
              },
              "error": null
            }
          ]
        }
      },
      "CancelOrderFailureResponseExample": {
        "summary": "Booking already cancelled — the RMS-side refund fails independently",
        "value": {
          "id": "ORD-9980140810",
          "customer": {
            "firstName": "Jane",
            "lastName": "Smith",
            "email": "jane.smith@example.com",
            "phone": "+441234567891"
          },
          "createdAt": "2027-01-10T11:45:03Z",
          "results": [
            {
              "compositeId": "1|TN|423458",
              "date": "2027-02-22",
              "booking": null,
              "error": {
                "title": "Bad request",
                "status": 404,
                "code": "BOOK-N-020",
                "isRetryable": false,
                "detail": "No tickets found on the Tonic purchase for this ticket type — it may already be cancelled."
              }
            }
          ]
        }
      },
      "AvailabilitiesResponseExample": {
        "summary": "Mixed batch — two successes and one isolated error",
        "value": {
          "results": [
            {
              "compositeId": "29|CS|275cc44dd2e2496fba44857c9257443a|prod1",
              "availability": {
                "name": "Dinner",
                "deposit": 10,
                "policy": "Please arrive on time.",
                "cancellationPolicy": "Cancel 48h before or a fee applies.",
                "times": [
                  {
                    "time": "19:00",
                    "duration": 90,
                    "type": "book",
                    "product": {
                      "id": "29|CS|275cc44dd2e2496fba44857c9257443a|prod1",
                      "name": "Dining Room"
                    }
                  }
                ]
              },
              "error": null
            },
            {
              "compositeId": "29|CS|275cc44dd2e2496fba44857c9257443a|prod2",
              "availability": {
                "name": "Bar",
                "times": [
                  {
                    "time": "20:00",
                    "duration": 90,
                    "type": "request",
                    "requestReason": "exceeds_auto_confirm",
                    "product": {
                      "id": "29|CS|275cc44dd2e2496fba44857c9257443a|prod2",
                      "name": "Bar Area"
                    }
                  }
                ]
              },
              "error": null
            },
            {
              "compositeId": "29|CS|999|prod3",
              "availability": null,
              "error": {
                "title": "Bad request",
                "status": 400,
                "code": "AVAIL-N-001",
                "isRetryable": false,
                "detail": "Missing date or quantity — cannot run availability for this item."
              }
            }
          ]
        }
      },
      "TableReservationListingPage": {
        "summary": "Single-page result containing a venue with table reservations",
        "value": {
          "meta": {
            "currentPage": 1,
            "pageSize": 20,
            "totalItems": 1,
            "totalPages": 1
          },
          "listings": [
            {
              "groupName": "Stonegate Group",
              "items": [
                {
                  "name": "The Crown & Anchor",
                  "location": {
                    "street": "1 Upper St Martin's Lane",
                    "area": "Covent Garden|Seven Dials",
                    "city": "London",
                    "postCode": "WC2H 9FB",
                    "lat": 51.513,
                    "lng": -0.128,
                    "gPlace": "ChIJN1t_tDeuEmsRUsoyG83frY4"
                  },
                  "capabilities": [
                    {
                      "id": "29|CS|275cc44dd2e2496fba44857c9257443a",
                      "name": "The Crown & Anchor",
                      "operatorName": "Stonegate Group",
                      "capability": "table_reservation",
                      "types": [
                        "pub",
                        "bar",
                        "dog_friendly",
                        "live_music"
                      ],
                      "content": "A traditional gastropub in the heart of Covent Garden, serving seasonal British food and an award-winning cask ale selection.",
                      "photos": [
                        "https://cdn.bookabletech.com/venues/29/photos/crown-anchor-front.jpg",
                        "https://cdn.bookabletech.com/venues/29/photos/crown-anchor-dining.jpg"
                      ],
                      "phoneNumber": "+442079461234",
                      "website": "https://www.crown-and-anchor.example/",
                      "availabilityOccurrence": [
                        {
                          "name": "Weekday service",
                          "description": "Mon–Fri kitchen hours.",
                          "type": "recurring_with_time",
                          "occurrences": {
                            "daysOfWeek": [
                              1,
                              2,
                              3,
                              4,
                              5
                            ],
                            "months": [
                              1,
                              2,
                              3,
                              4,
                              5,
                              6,
                              7,
                              8,
                              9,
                              10,
                              11,
                              12
                            ],
                            "startTime": "12:00",
                            "endTime": "22:30"
                          },
                          "status": "open",
                          "notes": "Last seating 21:30."
                        },
                        {
                          "name": "Weekend service",
                          "description": "Sat–Sun extended hours.",
                          "type": "recurring_with_time",
                          "occurrences": {
                            "daysOfWeek": [
                              0,
                              6
                            ],
                            "months": [
                              1,
                              2,
                              3,
                              4,
                              5,
                              6,
                              7,
                              8,
                              9,
                              10,
                              11,
                              12
                            ],
                            "startTime": "11:00",
                            "endTime": "23:00"
                          },
                          "status": "open",
                          "notes": "Brunch from 11:00."
                        },
                        {
                          "name": "Christmas closure",
                          "description": "Closed Christmas Day and Boxing Day.",
                          "type": "specific_dates",
                          "occurrences": {
                            "dates": [
                              "2026-12-25",
                              "2026-12-26"
                            ]
                          },
                          "status": "closed",
                          "notes": "Reopen 27 Dec at normal hours."
                        }
                      ],
                      "preorders": {
                        "packages": [
                          {
                            "id": "3f9a1c20-5b7e-4c1a-9e2d-1a2b3c4d5e6f",
                            "name": "Sunday Roast",
                            "price": 28.5,
                            "description": "Slow-roasted beef, Yorkshire pudding, seasonal vegetables.",
                            "type": "main",
                            "sub_type": "roast",
                            "diet_types": [
                              "gluten_free_option"
                            ],
                            "allergens": [
                              "gluten",
                              "dairy"
                            ]
                          },
                          {
                            "id": "8c2d4e60-9a1b-4f3c-8d2e-2b3c4d5e6f70",
                            "name": "Set Lunch",
                            "price": 18,
                            "description": "Two courses from the set lunch menu.",
                            "type": "set",
                            "sub_type": "lunch",
                            "diet_types": [
                              "vegetarian_option"
                            ],
                            "allergens": [
                              "gluten"
                            ]
                          }
                        ],
                        "menus": [
                          {
                            "id": "b4e6f810-1c2d-4a3b-9c8d-3c4d5e6f7081",
                            "name": "Spring Tasting Menu",
                            "description": "Five-course seasonal tasting menu with optional wine pairing.",
                            "items": [
                              {
                                "packageId": "c5f70921-2d3e-4b4c-8d9e-4d5e6f708192",
                                "name": "Amuse Bouche",
                                "price": 0,
                                "description": "Chef's seasonal selection.",
                                "type": "starter",
                                "subType": "amuse",
                                "displayOrder": 1
                              },
                              {
                                "packageId": "d6081a32-3e4f-4c5d-9eaf-5e6f708192a3",
                                "name": "Heritage Beetroot",
                                "price": 0,
                                "description": "Whipped goat's curd, walnut, sherry vinegar.",
                                "type": "starter",
                                "subType": "cold",
                                "displayOrder": 2
                              }
                            ]
                          }
                        ]
                      },
                      "bookableProducts": [
                        {
                          "compositeId": "29|CS|275cc44dd2e2496fba44857c9257443a|e4d909c290d0fb1ca068ffaddf22cbd0",
                          "name": "Dining Room",
                          "timeInterval": 30,
                          "category": "Dinner",
                          "preorders": {
                            "required": true,
                            "requiredType": "package",
                            "packageIds": [
                              "3f9a1c20-5b7e-4c1a-9e2d-1a2b3c4d5e6f",
                              "8c2d4e60-9a1b-4f3c-8d2e-2b3c4d5e6f70"
                            ],
                            "menuIds": [
                              "b4e6f810-1c2d-4a3b-9c8d-3c4d5e6f7081"
                            ]
                          },
                          "deposit": {
                            "required": true,
                            "rule": {
                              "perAdult": 10,
                              "perChild": 5,
                              "perBooking": null
                            }
                          },
                          "autoConfirmRule": {
                            "date": "2026-06-15",
                            "dateType": "weekday",
                            "minPeople": 1,
                            "maxPeople": 6,
                            "timeFrom": "12:00",
                            "timeTo": "22:30"
                          },
                          "noAvailabilityAction": "waitlist",
                          "availabilityOccurrenceOverrides": [
                            {
                              "name": "Christmas closure",
                              "description": "This product is unavailable over Christmas.",
                              "type": "specific_dates",
                              "occurrences": {
                                "dates": [
                                  "2026-12-25",
                                  "2026-12-26"
                                ]
                              },
                              "status": "closed",
                              "notes": "Set menu only on reopening."
                            }
                          ]
                        }
                      ]
                    }
                  ]
                }
              ]
            }
          ]
        }
      },
      "EventTicketListingPage": {
        "summary": "Single-page result containing an event with ticketed sessions",
        "value": {
          "meta": {
            "currentPage": 1,
            "pageSize": 20,
            "totalItems": 1,
            "totalPages": 1
          },
          "listings": [
            {
              "groupName": "Stonegate Live",
              "items": [
                {
                  "name": "The Crown & Anchor",
                  "location": {
                    "street": "1 Upper St Martin's Lane",
                    "area": "Covent Garden|Seven Dials",
                    "city": "London",
                    "postCode": "WC2H 9FB",
                    "lat": 51.513,
                    "lng": -0.128,
                    "gPlace": "ChIJN1t_tDeuEmsRUsoyG83frY4"
                  },
                  "capabilities": [
                    {
                      "id": "29|TN|evt_summer_2026",
                      "name": "Summer Live Sessions",
                      "operatorName": "Stonegate Live",
                      "hostedBy": "The Crown & Anchor",
                      "capability": "event_ticket",
                      "types": [
                        "live_music",
                        "concert",
                        "outdoor"
                      ],
                      "content": "A weekly outdoor live music series running every Thursday throughout summer, headlined by emerging UK artists.",
                      "photos": [
                        "https://cdn.bookabletech.com/events/evt_summer_2026/poster.jpg"
                      ],
                      "phoneNumber": null,
                      "website": "https://www.stonegate-live.example/summer-2026",
                      "availabilityOccurrence": [
                        {
                          "name": "Weekly Thursday show",
                          "description": "Every Thursday June through August.",
                          "type": "recurring_with_time",
                          "occurrences": {
                            "daysOfWeek": [
                              4
                            ],
                            "months": [
                              6,
                              7,
                              8
                            ],
                            "startTime": "19:00",
                            "endTime": "22:00"
                          },
                          "status": "open",
                          "notes": "Doors 18:30, support act 19:00."
                        },
                        {
                          "name": "Special headline night",
                          "description": "One-off headline performance on 15 August.",
                          "type": "specific_dates_with_time",
                          "occurrences": {
                            "dates": [
                              "2026-08-15"
                            ],
                            "startTime": "20:00",
                            "endTime": "23:30"
                          },
                          "status": "open",
                          "notes": "Headline act announced separately."
                        },
                        {
                          "name": "Next occurrence",
                          "description": "Next upcoming show.",
                          "type": "specific_dates_with_time",
                          "occurrences": {
                            "dates": [
                              "2026-06-18"
                            ],
                            "startTime": "19:00",
                            "endTime": "22:00"
                          },
                          "status": "open"
                        },
                        {
                          "name": "Final occurrence",
                          "description": "Final scheduled show.",
                          "type": "specific_dates_with_time",
                          "occurrences": {
                            "dates": [
                              "2026-08-27"
                            ],
                            "startTime": "19:00",
                            "endTime": "22:00"
                          },
                          "status": "open"
                        }
                      ],
                      "preorders": null,
                      "bookableProducts": [
                        {
                          "compositeId": "29|TN|evt_summer_2026|tt_standard",
                          "name": "Standard",
                          "price": {
                            "amount": 25,
                            "currency": "GBP"
                          },
                          "capacity": {
                            "max": 300,
                            "remaining": 142
                          },
                          "visibility": "on_sale",
                          "availabilityOccurrenceOverrides": [
                            {
                              "name": "Session 2026-06-18",
                              "description": "Scheduled session for this ticket type.",
                              "type": "specific_dates_with_time",
                              "occurrences": {
                                "dates": [
                                  "2026-06-18"
                                ],
                                "startTime": "19:00",
                                "endTime": "22:00"
                              },
                              "status": "open",
                              "notes": "availabilityStatus=available"
                            },
                            {
                              "name": "Session 2026-06-25",
                              "description": "Scheduled session for this ticket type.",
                              "type": "specific_dates_with_time",
                              "occurrences": {
                                "dates": [
                                  "2026-06-25"
                                ],
                                "startTime": "19:00",
                                "endTime": "22:00"
                              },
                              "status": "open",
                              "notes": "availabilityStatus=limited"
                            }
                          ]
                        }
                      ]
                    }
                  ]
                }
              ]
            }
          ]
        }
      },
      "HybridListingPage": {
        "summary": "Single venue offering both capabilities (table reservation + ticketed event)",
        "value": {
          "meta": {
            "currentPage": 1,
            "pageSize": 20,
            "totalItems": 1,
            "totalPages": 1
          },
          "listings": [
            {
              "groupName": "Stonegate Group",
              "items": [
                {
                  "name": "The Crown & Anchor",
                  "location": {
                    "street": "1 Upper St Martin's Lane",
                    "area": "Covent Garden|Seven Dials",
                    "city": "London",
                    "postCode": "WC2H 9FB",
                    "lat": 51.513,
                    "lng": -0.128,
                    "gPlace": "ChIJN1t_tDeuEmsRUsoyG83frY4"
                  },
                  "capabilities": [
                    {
                      "id": "29|CS|275cc44dd2e2496fba44857c9257443a",
                      "name": "The Crown & Anchor",
                      "operatorName": "Stonegate Group",
                      "capability": "table_reservation",
                      "types": [
                        "pub",
                        "bar",
                        "dog_friendly",
                        "live_music"
                      ],
                      "content": "A traditional gastropub in the heart of Covent Garden.",
                      "photos": [
                        "https://cdn.bookabletech.com/venues/29/photos/crown-anchor-front.jpg"
                      ],
                      "phoneNumber": "+442079461234",
                      "website": "https://www.crown-and-anchor.example/",
                      "availabilityOccurrence": [
                        {
                          "name": "Weekday service",
                          "type": "recurring_with_time",
                          "occurrences": {
                            "daysOfWeek": [
                              1,
                              2,
                              3,
                              4,
                              5
                            ],
                            "months": [
                              1,
                              2,
                              3,
                              4,
                              5,
                              6,
                              7,
                              8,
                              9,
                              10,
                              11,
                              12
                            ],
                            "startTime": "12:00",
                            "endTime": "22:30"
                          },
                          "status": "open"
                        }
                      ],
                      "preorders": {
                        "packages": [
                          {
                            "id": "3f9a1c20-5b7e-4c1a-9e2d-1a2b3c4d5e6f",
                            "name": "Sunday Roast",
                            "price": 28.5,
                            "type": "main",
                            "sub_type": "roast",
                            "diet_types": [
                              "gluten_free_option"
                            ],
                            "allergens": [
                              "gluten",
                              "dairy"
                            ]
                          }
                        ],
                        "menus": [
                          {
                            "id": "b4e6f810-1c2d-4a3b-9c8d-3c4d5e6f7081",
                            "name": "Spring Tasting Menu",
                            "items": [
                              {
                                "packageId": "c5f70921-2d3e-4b4c-8d9e-4d5e6f708192",
                                "name": "Amuse Bouche",
                                "price": 0,
                                "type": "starter",
                                "displayOrder": 1
                              }
                            ]
                          }
                        ]
                      },
                      "bookableProducts": [
                        {
                          "compositeId": "29|CS|275cc44dd2e2496fba44857c9257443a|e4d909c290d0fb1ca068ffaddf22cbd0",
                          "name": "Dining Room",
                          "timeInterval": 30,
                          "category": "Dinner",
                          "preorders": {
                            "required": true,
                            "requiredType": "package",
                            "packageIds": [
                              "3f9a1c20-5b7e-4c1a-9e2d-1a2b3c4d5e6f"
                            ],
                            "menuIds": [
                              "b4e6f810-1c2d-4a3b-9c8d-3c4d5e6f7081"
                            ]
                          }
                        }
                      ]
                    },
                    {
                      "id": "29|TN|evt_summer_2026",
                      "name": "Summer Live Sessions",
                      "operatorName": "Stonegate Group",
                      "hostedBy": "The Crown & Anchor",
                      "capability": "event_ticket",
                      "types": [
                        "live_music",
                        "concert",
                        "outdoor"
                      ],
                      "content": "A weekly outdoor live music series every Thursday through summer.",
                      "photos": [
                        "https://cdn.bookabletech.com/events/evt_summer_2026/poster.jpg"
                      ],
                      "phoneNumber": null,
                      "website": "https://www.stonegate-live.example/summer-2026",
                      "availabilityOccurrence": [
                        {
                          "name": "Weekly Thursday show",
                          "type": "recurring_with_time",
                          "occurrences": {
                            "daysOfWeek": [
                              4
                            ],
                            "months": [
                              6,
                              7,
                              8
                            ],
                            "startTime": "19:00",
                            "endTime": "22:00"
                          },
                          "status": "open"
                        }
                      ],
                      "preorders": null,
                      "bookableProducts": [
                        {
                          "compositeId": "29|TN|evt_summer_2026|tt_standard",
                          "name": "Standard",
                          "price": {
                            "amount": 25,
                            "currency": "GBP"
                          },
                          "capacity": {
                            "max": 300,
                            "remaining": 142
                          },
                          "visibility": "on_sale"
                        }
                      ]
                    }
                  ]
                }
              ]
            }
          ]
        }
      }
    },
    "securitySchemes": {
      "Live": {
        "type": "oauth2",
        "description": "OAuth 2.0 client credentials (Auth0) — Live.",
        "flows": {
          "clientCredentials": {
            "tokenUrl": "https://auth.bookabletech.com/oauth/token",
            "scopes": {
              "listing:read": "Read access to listings.",
              "order:create": "Permission to create orders.",
              "order:read": "Read access to orders.",
              "order:update": "Permission to update orders.",
              "order:delete": "Permission to cancel orders."
            }
          }
        }
      },
      "Sandbox": {
        "type": "oauth2",
        "description": "OAuth 2.0 client credentials (Auth0) — Sandbox.",
        "flows": {
          "clientCredentials": {
            "tokenUrl": "https://auth-sandbox.bookabletech.com/oauth/token",
            "scopes": {
              "listing:read": "Read access to listings.",
              "order:create": "Permission to create orders.",
              "order:read": "Read access to orders.",
              "order:update": "Permission to update orders.",
              "order:delete": "Permission to cancel orders."
            }
          }
        }
      }
    },
    "headers": {
      "RateLimitLimit": {
        "description": "Maximum number of requests allowed per window.",
        "schema": {
          "type": "integer"
        },
        "example": 200
      },
      "RateLimitRemaining": {
        "description": "Number of requests remaining in the current window.",
        "schema": {
          "type": "integer"
        },
        "example": 150
      },
      "RateLimitReset": {
        "description": "Unix timestamp (seconds since epoch) when the current rate-limit window resets.",
        "schema": {
          "type": "integer",
          "format": "int64"
        },
        "example": 1741651200
      }
    },
    "responses": {
      "InternalServerError": {
        "description": "Internal Server Error - An unexpected error occurred",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ServerError"
            },
            "example": {
              "type": "https://tools.ietf.org/html/rfc9110#section-15.6.1",
              "title": "Internal Server Error",
              "status": 500,
              "detail": "An unexpected error occurred while processing the request",
              "code": "SYS-N-001",
              "isRetryable": false,
              "traceId": "0HNJ2BG2TU3BU:00000007"
            }
          },
          "text/toon": {
            "schema": {
              "$ref": "#/components/schemas/ServerError"
            },
            "example": "type: \"https://tools.ietf.org/html/rfc9110#section-15.6.1\"\ntitle: Internal Server Error\nstatus: 500\ndetail: An unexpected error occurred while processing the request\ncode: SYS-N-001\nisRetryable: false\ntraceId: \"0HNJ2BG2TU3BU:00000007\"\n"
          }
        }
      },
      "BadRequest": {
        "description": "Bad Request - The request was invalid or cannot be served",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ClientError"
            },
            "example": {
              "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
              "title": "Validation Failed",
              "status": 400,
              "detail": "One or more validation errors occurred.",
              "code": "VALID-N-001",
              "isRetryable": false,
              "traceId": "0HNJ2BG2TU3BU:00000001",
              "errors": {
                "Date": [
                  "Availability date cannot be in the past."
                ]
              }
            }
          },
          "text/toon": {
            "schema": {
              "$ref": "#/components/schemas/ClientError"
            },
            "example": "type: \"https://tools.ietf.org/html/rfc9110#section-15.5.1\"\ntitle: Validation Failed\nstatus: 400\ndetail: One or more validation errors occurred.\ncode: VALID-N-001\nisRetryable: false\ntraceId: \"0HNJ2BG2TU3BU:00000001\"\nerrors.Date[1]: \"Availability date cannot be in the past.\"\n"
          }
        }
      },
      "Unauthorized": {
        "description": "Unauthorized - Authentication is required",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ClientError"
            },
            "example": {
              "type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
              "title": "Invalid User Credentials",
              "status": 401,
              "detail": "The provided credentials are invalid",
              "code": "USER-N-003",
              "isRetryable": false,
              "traceId": "0HNJ2BG2TU3BU:00000002"
            }
          },
          "text/toon": {
            "schema": {
              "$ref": "#/components/schemas/ClientError"
            },
            "example": "type: \"https://tools.ietf.org/html/rfc9110#section-15.5.5\"\ntitle: Invalid User Credentials\nstatus: 401\ndetail: The provided credentials are invalid\ncode: USER-N-003\nisRetryable: false\ntraceId: \"0HNJ2BG2TU3BU:00000002\"\n"
          }
        }
      },
      "Forbidden": {
        "description": "Forbidden - The request is understood but access is denied",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ClientError"
            },
            "example": {
              "type": "https://tools.ietf.org/html/rfc9110#section-15.5.4",
              "title": "Venue Not Mapped to Partner",
              "status": 403,
              "detail": "The requested venue is not mapped to the current partner",
              "code": "PMAP-N-001",
              "isRetryable": false,
              "traceId": "0HNJ2BG2TU3BU:00000003"
            }
          },
          "text/toon": {
            "schema": {
              "$ref": "#/components/schemas/ClientError"
            },
            "example": "type: \"https://tools.ietf.org/html/rfc9110#section-15.5.4\"\ntitle: Venue Not Mapped to Partner\nstatus: 403\ndetail: The requested venue is not mapped to the current partner\ncode: PMAP-N-001\nisRetryable: false\ntraceId: \"0HNJ2BG2TU3BU:00000003\"\n"
          }
        }
      },
      "TooManyRequests": {
        "description": "Too Many Requests - Rate limit exceeded. Retry after the window specified in the Retry-After header.",
        "headers": {
          "Retry-After": {
            "description": "Number of seconds to wait before retrying the request.",
            "schema": {
              "type": "integer"
            },
            "example": 60
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ClientError"
            },
            "example": {
              "type": "https://tools.ietf.org/html/rfc6585#section-4",
              "title": "Rate Limit Exceeded",
              "status": 429,
              "detail": "Too many requests have been made in a short period. Please wait and retry.",
              "code": "RATE-R-001",
              "isRetryable": true,
              "traceId": "0HNJ2BG2TU3BU:00000006"
            }
          },
          "text/toon": {
            "schema": {
              "$ref": "#/components/schemas/ClientError"
            },
            "example": "type: \"https://tools.ietf.org/html/rfc6585#section-4\"\ntitle: Rate Limit Exceeded\nstatus: 429\ndetail: Too many requests have been made in a short period. Please wait and retry.\ncode: RATE-R-001\nisRetryable: true\ntraceId: \"0HNJ2BG2TU3BU:00000006\"\n"
          }
        }
      },
      "ServiceUnavailable": {
        "description": "Service Unavailable - The server is temporarily unavailable",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ServerError"
            },
            "example": {
              "type": "https://api.bookabletech.com/problems/service-unavailable",
              "title": "Service Unavailable",
              "status": 503,
              "detail": "The server is temporarily unavailable. Please try again later",
              "code": "SYS-R-503",
              "isRetryable": true
            }
          },
          "text/toon": {
            "schema": {
              "$ref": "#/components/schemas/ServerError"
            },
            "example": "type: \"https://api.bookabletech.com/problems/service-unavailable\"\ntitle: Service Unavailable\nstatus: 503\ndetail: The server is temporarily unavailable. Please try again later\ncode: SYS-R-503\nisRetryable: true\n"
          }
        }
      },
      "NotFound": {
        "description": "Not Found - The requested resource was not found",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ClientError"
            },
            "example": {
              "type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
              "title": "Venue Not Found",
              "status": 404,
              "detail": "The requested venue could not be found",
              "code": "VENUE-N-001",
              "isRetryable": false,
              "traceId": "0HNJ2BG2TU3BU:00000004"
            }
          },
          "text/toon": {
            "schema": {
              "$ref": "#/components/schemas/ClientError"
            },
            "example": "type: \"https://tools.ietf.org/html/rfc9110#section-15.5.5\"\ntitle: Venue Not Found\nstatus: 404\ndetail: The requested venue could not be found\ncode: VENUE-N-001\nisRetryable: false\ntraceId: \"0HNJ2BG2TU3BU:00000004\"\n"
          }
        }
      }
    }
  }
}