All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Listings API v1.0.0
- New venue-aggregated discovery API.
GET /v1/listingsreturns the bookable catalogue grouped by operator (ListingGroup→groupName+items[]), each item a single venue (ListingItem) carrying alocationand acapabilities[]array ofListings — one entry per capability (table_reservation,event_ticket). A venue that also hosts a ticketed event appears once, with two capability entries. - All bookable units (venue products, ticket types) are unified under a single
Bookableshape inbookableProducts[]; capability-specific fields are nullable, with context set by the parentListing.capability. - Temporal data (opening hours, event occurrences, blackout dates) is unified under
availabilityOccurrence[]— a singleCalendarRulemodel shared by both capabilities, discriminated bytype(date_range,recurring,time_based,specific_dates, and time-window variants of each). - Pre-order assets (packages, menus) are unified under a single
preorderscontainer, applicable to either capability. - Two distinct, non-interchangeable ID formats, both CompositeId-encoded:
Listing.id(3 segments —{VenueGroupId}|{RmsSlug}|{ResourceId}) vs.Bookable.compositeId(4 segments, adds{AdditionalId}), the latter used inbookableProducts[]and ascompositeIdin/v1/availabilitiesand/v1/orders. POST /v1/availabilities: batch availability check across multiplecompositeIds in one call. Modelled as a command, not a search — root-leveldate/quantity/timeact as defaults inherited by each entry. Searches run independently: a failure on onecompositeIdis reported as anerroron that entry's result only (never a404for the whole call); other results return normally.POST /v1/orders: create an order of one or more independent bookings, each resolved and booked separately — a failure on one item does not block or roll back the others. Items are unified (nocapability/oneOf); capability and platform are resolved server-side from each item'scompositeId, so a single order can span multiple venues and RMS platforms.PATCH /v1/orders/{orderId}: partial update of one or more bookings within an order, same per-item isolation model. Supports moving a booking to a different bookable product viacompositeId(same venue/RMS/event only — cross-venue move rejected with400 ORDER-N-007), updating guest details, and replacing (preorders) or incrementally changing (preorderChanges) pre-orders (mutually exclusive —400 ORDER-N-008).DELETE /v1/orders/{orderId}: cancel specific bookings viabookingIds, or every booking on the order when omitted.- Both
POST /v1/ordersandPATCH /v1/orders/{orderId}return200when every item succeeds,207whenever one or more items fail (including total failure) — a bulk success is never conflated with a partial or total failure.
Messaging API v2.0.0
- BREAKING CHANGE The Messaging API is now the operator↔partner conversation stored against a booking. Bookable relays each message between the venue operator and the integration partner over email (both parties email a per-booking conversation alias and Bookable forwards each message on). The previous operator→guest / IP→operator / administrator model is removed.
- BREAKING CHANGE
POST /bookings/{bookingId}/messagesnow returns201with the createdMessagebody (previously returned204and processed asynchronously). Sending is synchronous: the message is stored and relayed before the response returns. - BREAKING CHANGE Send request body:
messagerenamed tobody;maxLengthraised from2000to5000. - BREAKING CHANGE Removed the
recipientfield. Send direction is now derived from the caller's role — an Integration Partner sends to the venue operator (partner_to_operator); a venue group operator sends to the integration partner (operator_to_partner). - New
directionrequest field is a Sandbox-only test override: it forces the absolute direction so a partner can trigger their ownmessage.receivedwebhook (sendoperator_to_partner) without a real operator or inbound email. Ignored outside Sandbox; when set in Sandbox the email relay is skipped (webhook-only — message stored, webhook fires, no email sent). Messageschema changes:contentrenamed tobody.action(sent/received) replaced bydirection(operator_to_partner/partner_to_operator) — an absolute direction stating who sent and who received, now required.- Added
subject(nullable) — email subject line. - Added
attachments(nullable array ofMessageAttachmentwithfilenameand nullablecontentType). Attachment bytes are exchanged over email, not via this API — attachments cannot be sent throughPOSTand can only be added by replying to the relay email.
- New
MessageAttachmentschema.
Register to Webhook Events API v1.3.0
- Documented event delivery guarantees: delivery is at-least-once — the same event may arrive more than once, so consumers must be idempotent (dedupe booking events by booking
id, messages by messageid). - Documented request signing: every callback POST carries an
X-API-Keyheader holding a lowercase hex HMAC-SHA256 of the raw body, keyed with thesecretKeyfrom registration. - Documented the two
eventTypevalues —booking.updated(payload inbookings) andmessage.received(payload inmessages). - Added full callback payload schemas that were previously undocumented:
BookingNotification,Booking, andMessagePayload. MessagePayloadnow documentsid(stable, use to deduplicate),bookingId,body,subject(nullable — primary filter signal),senderName,senderEmail,direction,attachments(metadata only; bytes over email),sentAt, andreplyTo— the per-booking email alias to reply to; email it from anywhere and Bookable relays your message to the venue operator.message.receivedfires only foroperator_to_partnermessages (venue operator → partner).
POST /webhooks/testis deprecated and scheduled for removal in2.0.0. For ongoing integration testing use the sandbox self-echo flow instead — in sandbox every booking you create, amend, or cancel fires the corresponding webhook to your registered callback with no separate trigger.
Operator Site FAQs API
- The FAQ write verbs are now public (previously
x-internal). Operators can now manage a venue's FAQ list directly:PUT /venues/{venueCompositeId}/site-faqs— replace the whole array (also the bulk-import mechanism for a single venue's full list). Requiresvenue-group:update.PATCH /venues/{venueCompositeId}/site-faqs— apply an RFC 6902 JSON Patch (item-index pointers, e.g./0/answer, or/-to append). Requiresvenue-group:update.DELETE /venues/{venueCompositeId}/site-faqs— wipe the stored array (idempotent). Requiresvenue-group:delete.POST /venues/site-faqs/bulk— apply changes across many venues in one all-or-nothing transaction. Requiresvenue-group:update.
GETis now readable by operators and mapped partners (previously mapped partners only). Access is enforced by the caller's venue-group ownership of, or partner mapping to, the venue.
SiteFaq.questionandSiteFaq.answerare now nullable and no longer required.
OperatorTmsCredentials.message: new nullable string on the TMS credentials/connection response — free-text notes about the connection (e.g. a TMS-specific sync-schedule caveat).nullwhen none.
VenueSpacesschema:MinimumSpendRuleResponserenamed toMinimumSpendRuleBaseandMinimumSpendOverrideResponserenamed toMinimumSpendOverrideBase. The JSON shape is unchanged; only the schema component names differ (regenerate clients that reference these names).
- New endpoint
PUT /venues/bookings/{bookingId}/status— confirm or reject an in-progress booking. SetstatustoConfirmedto accept orRejectedto decline; only bookings still awaiting a decision (PendingorInProgress) can be actioned, otherwise422. Optional free-textreasonrecorded when rejecting. Requires the newvenue-booking:update:statusscope, granted separately and not available to all partners by default (403if unauthorised). NewUpdateBookingStatusRequestschema. venue-booking:update:status: new OAuth scope (Live and Sandbox) — grants permission to confirm/reject an in-progress booking.Booking.rejectionReason: new nullable field — the reason a booking was rejected, when one was provided. Null otherwise.Booking.tmsCreatedDate: new nullable date-time on booking responses — creation timestamp reported by the originating TMS; null when unavailable. Also usable as a sort field onGET /venues/bookings.Booking.createdDateclarified as the timestamp the record was created in Bookable.Product.categories: new nullable array of all main category slugs assigned to a product (a product may have more than one).Product.categoryretained as the primary (first) slug for backwards compatibility.MinimumSpendOverride.timeRange: new optional Europe/London time window a minimum-spend override applies to, returned in venue space data. Absent means the override covers the whole date; outside the window normal rules apply.
- Availability feed regeneration changed from every 4 hours to once daily.
Product.feedUrlis now alsonullwhen the product is not currently reachable by any partner (previously only null when no feed had been generated yet).
Register to Webhook Events API v1.2.0
- Webhooks can now be tested in the sandbox environment. Register your callback URL against
https://api-sandbox.bookabletech.comand any booking you create, amend, or cancel via the sandbox API delivers a signed notification to your endpoint — the same payload andX-API-KeyHMAC-SHA256 signature as production, with no external reservation system required. The sandbox server was added to the Register to Webhook Events API. See the Webhook Guide.
BookingApi v7.3.0
- Action required Availability feed format: the single 90-day gzip file per product is replaced by a plain-JSON
index.jsonplus one gzip-compressed daily shard file ({date}.json.gz) per day with availability. The previous{productId}.json.gzfiles are no longer generated, so feed consumers need to update their download logic to the new format.Product.feedUrlnow points to the index (.../{productId}/index.json). It is plain JSON — do not decompress it.- The index lists
shards[], one entry per non-empty day, each withdateand a directurlto that day's gzip-compressed shard. Days with no availability are omitted. - Each shard contains
product_id,date, and theslotsarray. The slot object shape is unchanged.product_nameandvenue_namenow appear only in the index. - Partners can download only the dates they need instead of the full 90-day payload. See the Availability Feed guide for the new format and migration notes.
Handling Webhook Events API v1.5.0
- BREAKING CHANGE
ReservationStatusenum updated to mirror the Bookings API booking statuses (Pending,InProgress,Confirmed,Cancelled,Deleted,Lost):- Added:
in_progress(enquiry received and assigned but not yet confirmed),deleted(booking deleted from the system),lost(booking not completed before its scheduled date). - Removed:
completed,no_show. Update any handling logic that depends on these values.
- Added:
BookingApi v7.2.3
Product.sub_category: new nullable string field — admin-defined sub-category slug (e.g."outdoor","easter","christmas").nullwhen no sub-category applies.noAvailabilityCode: two new known values:NO_AVAILABLE_TIMES— RMS confirmed the request was valid but returned no bookable time slots.FILTERED_BY_CAPACITY_MIN— party size is below the minimum capacity of every available space.
RecurringRuleDataandRecurringWithTimeRuleData:daysOfWeekandmonthsare no longer individually required; either may be provided alone (when both are present the match is AND). Both fields are now nullable with nominItemsconstraint.
Messaging API v1.0.0
- New API spec at
apis/production/MessagingApi.ymlfor sending and retrieving messages associated with a booking. POST /bookings/{bookingId}/messages— send a plain-text message (async, returns204). Direction determined by caller role:- Integration Partner → message delivered to venue operator.
recipientfield ignored. - Operator → message delivered to booking guest.
recipientfield ignored. - Administrator →
recipientfield required (guestorvenue).
- Integration Partner → message delivered to venue operator.
GET /bookings/{bookingId}/messages— list all processed messages for a booking, ordered bysentAtascending. Page-based pagination viapageNumberandpageSize(default 20, max 100).- Required scopes:
venue-booking:messaging:write(send),venue-booking:messaging:read(list).
Handling Webhook Events API v1.4.0
- New
message.receivedevent type: fires when a venue operator sends a message via their TMS. - New
messagesarray field onBookingNotification: populated formessage.receivedevents,nullforbooking.updated. - New
MessagePayloadschema:bookingId,content,senderName(nullable),sentAt.
Product.feedUrl: new nullable URI field onGET /venuesandGET /venues/{venueId}responses. When non-null, provides a direct URL to the pre-generated availability feed file for that product — a gzip-compressed JSON document covering a 90-day rolling window, regenerated every 4 hours. No authentication is required to download it.
X-Is-Cross-Saleheader onPOST /venues/{compositeId}/booking: optional boolean. Whentrue, any cross-sale booking label rules configured for the operator are applied automatically to the new booking.
- BREAKING CHANGE
BookingRequest.areaIdrenamed toBookingRequest.spaceId. Type changed fromstringtointeger. Obtain valid space IDs from thespacesarray in the availability response time slots.
AvailabilityTimeSlot.areas: removed. Usespacesfrom the product data to obtain valid space IDs for booking.
AvailabilityResponse.noAvailabilityCode: new nullable string field, populated only whentimesis empty. Machine-readable code indicating why no availability was found. Known values:NO_AVAILABILITY— no available slots for the requested parameters.NO_ELIGIBLE_PRODUCTS— no products match the request.FILTERED_BY_OPERATOR_RULES— all slots were filtered out by operator availability rules.FILTERED_BY_CAPACITY— no slots satisfy the requested party size.- Clients should treat unknown values as a generic no-availability condition, as new values may be introduced without prior notice.
AvailabilityResponse.noAvailabilityAction: removed. UsenoAvailabilityReason(human-readable) and the newnoAvailabilityCode(machine-readable) instead.
AvailabilityTimeSlot.requestReason: new nullable string field, present only whentypeisrequest. Indicates why the time slot requires manual operator approval rather than instant confirmation. Possible values:fully_booked— no real-time availability for this slot, but the operator is open to receiving enquiries.exceeds_auto_confirm— availability exists but the requested party size exceeds the venue's auto-confirm threshold and requires explicit operator approval.- Clients should handle unknown values gracefully as new values may be introduced in future versions.
AvailabilityResponse.noAvailabilityReason: new nullable string field, populated only whentimesis empty. Human-readable message explaining why no availability was found for the requested parameters.Product.slug: new nullable string field — aggregation slug identifier for the product.PreorderPackage.slug: new nullable string field — aggregation slug identifier for the package.Menu.slug: new nullable string field — aggregation slug identifier for the menu.
Product.spaces: new field onGET /venuesandGET /venues/{venueId}responses. Each product now returns the list of spaces available within it, including physical data (spaceName,description,floorLocation,facilities, capacity layout fields) and space policies (minimumSpend,occasionTypes,under18s,promotedEvents,accessibility,servesFood).Product.preOrderRequiredType: enum specifying which type of preorder is required —none,package,menu, orpackageAndMenu.Product.depositRequired: boolean indicating whether a deposit is required when booking a product.AvailabilityRequest.children: optional field for the number of children in the party. Note: not all TMS providers distinguish between adults and children — when unsupported, children may be added to the total party size or ignored.AvailabilityRequestspace policy filters — new optional query parameters to filter time slots by space policy:minimumSpend: maximum minimum spend (in pence); excludes slots above this threshold.under18s: soft filter on the under-18s policy.occasionTypes: filter by supported occasion type.promotedEvents: soft filter on the promoted-events policy.accessibility: filter by wheelchair accessibility.servesFood: soft filter on the serves-food policy.includeUnavailable: whentrue, filtered-out slots are included in the response withunavailableReasonspopulated instead of being excluded.
AvailabilityTimeSlot.product: new object returned in each time slot containing the product'sid,name, andspacesarray. Space policies within this object (includingminimumSpend) are pre-filtered to the requested date and time slot.AvailabilityTimeSlot.areas: list of available areas/zones for this time slot. Populated only for TMS providers that support area-based booking (e.g. Zonal). Pass the desiredidasareaIdwhen creating a booking.AvailabilityTimeSlot.unavailableReasons: present only whenincludeUnavailable=true; contains human-readable explanations for each failing policy filter.BookingRequest.children: optional field for the number of children included in the booking.BookingRequest.areaId: optional area/zone ID to target when creating a booking. Obtain valid IDs fromAvailabilityTimeSlot.areas.Booking.depositAmount: deposit amount (float, in pence) captured from the TMS at reservation time.Booking.area: area or zone assigned to the booking, withidandnameas reported by the TMS.- New schemas:
SpaceCapacityRange,Area,BookingArea. - New shared component files:
common/VenueSpaces.yaml(space schemas and policy types) andcommon/Headers.yaml(shared header parameter definitions).
AvailabilityRequest.partySizeandBookingRequest.partySize: description clarified from "number of guests/people" to "number of adults".CorrelationIDandPartnerReferenceheader parameters refactored to referencecommon/Headers.yamlinstead of being defined inline.
AvailabilityTimeSlot.productId: useAvailabilityTimeSlot.product.idinstead.
- Sparse fieldsets support via the
fieldsquery parameter on all GET endpoints. Request only the fields you need to reduce payload size and improve response times. See Sparse Fieldsets for details. text/toonresponse format support across all Bookings API endpoints that return a body. SetAccept: text/toonto receive responses in TOON (Terse Object-Oriented Notation) — a compact format that reduces token count by 30–60% compared to JSON. Fully opt-in; omitting the header continues to return standard JSON. See TOON Format for details.VenuePreorders: addedpreordersfield toGET /venuesandGET /venues/{venueId}responses.
VenuePreordersschema: new wrapper object containingpackagesandmenusarraysProductAvailabilityRulesschema: availability rules for a product grouped by source (weekly,exceptions,rules)WeeklyRuleschema: weekly booking schedule, one entry per day of the weekRuleExceptionschema: date-specific availability exceptions imposed by the TMSAvailabilityRuleschema: operator-defined availability rules per partnerAvailabilityRuleTypeenum:date_range,recurring,time_based,specific_dates,specific_dates_with_time,date_range_with_time,recurring_with_timeRuleDataBaseand all discriminated subtypes:DateRangeRuleData,RecurringRuleData,TimeBasedRuleData,SpecificDatesRuleData,SpecificDatesWithTimeRuleData,DateRangeWithTimeRuleData,RecurringWithTimeRuleDataPreorderContainerschema: container for all preorder items (packages→PreorderPackageRequest,menus→PreorderMenuRequestV2)MenuItemOptionschema: configurable option for a menu item (fieldvalue)MenuItem: added fieldsname,price,description,diet_types,allergens,configurable_options,type,subType,displayOrderMenuItemSelection: added fieldoptions(array ofMenuItemOption)Booking.preorders.menus: added fieldsubmitted(enum:pre/post)PATCH /venues/bookings/{bookingId}: new endpoint for partial booking updates via JSON Patch (RFC 6902)JsonPatchOperationschema supportingadd,remove,replaceoperationsProduct: added fieldpreOrderRequired(boolean)
MenuItem.subGroupNamerenamed tosubTypePOST /venues/{compositeId}/bookingresponse201: changed fromBookingResponseto fullBookingschema- Terminology updated throughout: "RMS (Restaurant Management System)" → "TMS (Table Management System)"
- Security schemes consolidated: staging environments (
Staging,SandboxStaging,SandboxProduction) removed; onlyProductionandSandboxremain - Servers list reduced to
Production(https://api.bookabletech.com) andSandbox(https://api-sandbox.bookabletech.com)
Venue.packages(top-level array) — replaced byVenue.preorders.packagesVenue.menus(top-level array) — replaced byVenue.preorders.menusBookingRequest.preorderPackages— replaced byBookingRequest.preorders.packagesBookingRequest.preorderMenus— replaced byBookingRequest.preorders.menus- Sandbox Staging server
https://api-sandbox-staging.bookabletech.com
compositeIdquery filter to theGET /venues/bookingsendpoint.
BREAKING CHANGE in the following endpoints:
GET /venues/bookingsGET /venues/bookings/{bookingId}PUT /venues/bookings/{bookingId}Changed:
companyfield is nowvenueGroupNameproductTypefield is nowproductName
Removed:
cursorquery parameter fromGET /venues/bookingscursorfield from response fromGET /venues/bookings
Added: Standard pagination parameters in
GET /venues/bookings:pageNumber(integer, default: 1, min: 1) - The page index to returnpageSize(integer, default: 20, min: 1, max: 100) - Items per pageNumbermetaobject with pagination metadata:
"meta": { "currentPage": 1, "pageSize": 20, "totalItems": 26, "totalPages": 2 }Migration Guide:
- GET /venues/bookings?cursor=abc123 + GET /venues/bookings?pageNumber=1&pageSize=20GET /venues/{compositeId}/availabilityAdded: preOrderItems
venueGroupNamefield on venue object inGET /venuesandGET /venues/{venueId}endpoints.
- Remove constraints on bookingRules.
X-Booking-Sourceheader inPOST venues/bookingsis now an enumeration.
Added sorting capabilities to
GET /venuesendpoint:New Query Parameters
sortBy(optional): Field to sort results bydefault- Sort by composite ID (venue_group_id, rms_id, venue_id)name- Sort alphabetically by venue namecity- Sort by city name, then venue namearea- Sort by area, then venue namevenueGroup- Sort by venue group name (requires venueGroupName filter)relevance- Sort by semantic similarity using vector embeddings (requires embedding filters)
sortDirection(optional): Sort directionASC- Ascending (A-Z, 0-9, most to least similar)DESC- Descending (Z-A, 9-0, least to most similar)
- Operator Booking Id and Partner Booking Id support to
GET venues/bookingsbyoperatorBookingIdandpartnerBookingIdfields - Partner Booking Id support to
POST venues/bookingsbypartnerBookingIdfield
Referencefield is deprecated inGET venues/bookings; useoperatorBookingIdinstead.
- Booking Overrides support to
GET venuesandGET venues\{venueId}bybookingOverridesfield - Operator availability rule support to
GET venuesandGET venues\{venueId}byoperatorAvailabilityRulesfield
- Preorders support to
GET venues/bookingsbypreordersfield - Preorder menus support to
GET venues/bookingsbypreorderMenusfield
- Possibility to filter by
dateandtimewithin theGET /venuesendpoint.
X-Booking-Sourceheader which identifies the source or channel through which the booking was created.
X-Partner-Referenceheader is now mandatory on all the endpoints for Bookable Agent clients.
- noAvailabilityAction support to
GET venues/:venueId/availability - autoConfirmRule support to
GET venues/:venueId/availability
- Preorder menu support to
GET venuesandGET venues/:venueIdbymenusfield - Preorder menu support to
POST venues/:venueId/bookingbypreorderMenusfield - Preorder menu email triggering on submit booking
- Preorder menu support to
GET venues/bookings/:bookingIdbypreorderMenusfield
packageIdfield onPOST venues/:venueId/bookingrequest
- BREAKING CHANGE: Booking PUT request now requires
compositeId
GET /venues/products/{compositeId}endpoint
- Venue packages detail by
packages - Booking POST request now accepts
packageId - Booking POST request now accepts
preorders
- Endpoint to get a venue product detail by
compositeId
- Venue Schema Fields: Deprecated
is_activeandcreated_atfields in venue responses - Booking POST request now accepts
nullvalue fordurationfield
- Booking POST request includes admin_notes, comments & labels field
- Standardized error handling across all endpoints
- BREAKING CHANGE: Modified venue composition - products are now contained within the venue structure
- X-Partner-Reference header for Bookable Agents. The header specifies the partner reference for whom the booking is being made.
- Endpoint to update an existing booking by its unique ID
- Endpoint to cancel a booking by its unique ID
- Endpoint to retrieve a paginated list of bookings
- Endpoint to retrieve a specific booking by its unique ID
- Support for paginated venue listings
- Rename shut into bookingCutoff
- bookingRules: Insert booking rules on Venue to show information about the opening/ close time, max min number of people, and other
- Validation on require field (#TS-948)
- Add the unified api
- VenueId: Introduced the concept of composite Id to manage id into the system
- type into avalability response: Specifies how an operators time slot can be handled.
- type into revervation request
- product_name: the name of product offer from venue