This guide covers the full booking lifecycle: creating, retrieving, updating, and cancelling reservations.
POST /venues/{compositeId}/bookingCOMPOSITE_ID="29|CO|275cc44dd2e2496fba44857c9257443a|d99128c546b34b619c4477b712869f2b"
curl -X POST "https://api.bookabletech.com/venues/${COMPOSITE_ID}/booking" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-H "x-Partner-Reference: YOUR_INTERNAL_REF" \
-d '{
"firstName": "Jane",
"lastName": "Smith",
"email": "jane.smith@example.com",
"phone": "+441234567890",
"partySize": 4,
"dateTime": "2025-08-15T19:00:00+01:00",
"type": "book",
"notes": "Anniversary dinner — please add candles"
}'Example response:
{
"id": "29|CO|550e8400e29b41d4a716446655440000",
"operatorBookingId": "BKA-7X2P",
"status": "Confirmed",
"firstName": "Jane",
"lastName": "Smith",
"partySize": 4,
"date": "2025-08-15",
"time": "19:00",
"dateTime": "2025-08-15T19:00:00+01:00",
"venueGroupName": "The Grand Table Group"
}Send the slot's times[].dateTime from the availability response unchanged as dateTime. date and time are on the venue's trading day (a 00:30 slot under Saturday's date starts on Sunday); dateTime is the real start moment. date + time are still accepted instead (as in the preorder examples below) — send one form, or both only if they agree (BOOK-N-018). Neither → BOOK-N-019; dateTime without a UTC offset → BOOK-N-020.
Some venues offer packages (standalone add-ons — a bottle of wine, a tasting platter, a cocktail kit) and menus (structured multi-course offerings where the guest selects specific dishes). Both are submitted inside the preorders field of the booking request.
If products[].preOrderRequired is true for the chosen product, a preorder must be included — the booking will be rejected without one.
Packages and menus available at the venue are returned in the GET /venues response under data[].preorders.
Example venue response (truncated):
{
"data": [
{
"name": "The Grand Table",
"preorders": {
"packages": [
{
"id": "5888a5afc71620e04002d5bb",
"name": "Prosecco on arrival",
"price": 8.50,
"type": "drink"
},
{
"id": "62692e90d2cf1f163744efc4",
"name": "Sharing charcuterie board",
"price": 18.00,
"type": "food",
"sub_type": "starter"
}
],
"menus": [
{
"id": "68a5f2eee07ae30fcd653b03",
"name": "Set Menu",
"description": "2 or 3 courses from our seasonal menu",
"items": [
{ "packageId": "62c6c9f532c7cc7e4265dfdc", "name": "Pan roasted Padron peppers (V)", "price": 9.00 },
{ "packageId": "619d19eb40e1512ebb03b378", "name": "Beef fillet with truffle jus", "price": 28.00 }
]
}
]
}
}
]
}The availability response filters this catalogue per time slot. Each entry in times[] includes a preOrderItems object:
allowedPackages / allowedMenus | Meaning |
|---|---|
"all" | Every item in the venue catalogue is available |
"set" | Only the IDs listed in packageIds / menuIds are available |
"none" | No packages / menus for this slot |
Example availability response (truncated):
{
"times": [
{
"time": "19:00",
"type": "book",
"preOrderItems": {
"allowedPackages": "set",
"packageIds": ["5888a5afc71620e04002d5bb"],
"allowedMenus": "all",
"menuIds": null
}
}
]
}In this example, only the 5888a5afc71620e04002d5bb package is allowed at 19:00, but all menus are available.
Include a preorders object in the booking request body.
Packages — supply the package id and quantity:
curl -X POST "https://api.bookabletech.com/venues/${COMPOSITE_ID}/booking" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"firstName": "Jane",
"lastName": "Smith",
"email": "jane.smith@example.com",
"phone": "+441234567890",
"partySize": 4,
"date": "2025-08-15",
"time": "19:00",
"type": "book",
"preorders": {
"packages": [
{ "id": "5888a5afc71620e04002d5bb", "quantity": 4 }
]
}
}'Menus — supply the menu id, quantity, and optionally items[] to pre-select specific dishes. Each item uses the packageId from the menu's items[] catalogue:
curl -X POST "https://api.bookabletech.com/venues/${COMPOSITE_ID}/booking" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"firstName": "Jane",
"lastName": "Smith",
"email": "jane.smith@example.com",
"phone": "+441234567890",
"partySize": 4,
"date": "2025-08-15",
"time": "19:00",
"type": "book",
"preorders": {
"menus": [
{
"id": "68a5f2eee07ae30fcd653b03",
"quantity": 4,
"items": [
{ "id": "62c6c9f532c7cc7e4265dfdc", "quantity": 2 },
{ "id": "619d19eb40e1512ebb03b378", "quantity": 2 }
]
}
]
}
}'Omitting items is valid — the venue will send the guest a link after booking to complete their menu selections.
Packages and menus can be combined in the same request using both preorders.packages and preorders.menus together.
GET /venues/bookings/{bookingId}Use this to poll the current status of a Pending booking, or to sync booking details into your system.
BOOKING_ID="29|CO|550e8400e29b41d4a716446655440000"
curl "https://api.bookabletech.com/venues/bookings/${BOOKING_ID}" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"The response carries dateTime (the real start moment) alongside date and time, and payments — the payments recorded in Bookable for the booking, oldest first (id, optionType, amount in pence, status, updatedAt). payments is omitted when none is recorded in Bookable, which does not mean the booking is unpaid.
For ongoing status tracking, prefer webhooks over polling.
PATCH /venues/bookings/{bookingId}Updates use JSON Patch (RFC 6902) with Content-Type: application/json-patch+json. Only confirmed bookings can be updated.
Patchable fields: date, time, partySize, duration, firstName, lastName, email, phone, notes, preorders/packages, preorders/menus
curl -X PATCH "https://api.bookabletech.com/venues/bookings/${BOOKING_ID}" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json-patch+json" \
-d '[
{ "op": "replace", "path": "/partySize", "value": 6 },
{ "op": "replace", "path": "/notes", "value": "Now 6 guests — please arrange accordingly" }
]'If you're changing date, time, or partySize, check availability first — the update will be rejected if the new slot is unavailable.
/payments is read-only. An update can also be refused with:
| Code | Status | Meaning |
|---|---|---|
BKRUL-N-007 | 400 | An operator booking_window rule stops amending a confirmed booking this close to its start |
VENUE-N-009 | 404 | The venue has closed — the booking can no longer be amended, only cancelled |
DELETE /venues/bookings/{bookingId}Cancellation is permanent. The booking status changes to Cancelled and a booking.updated webhook fires (if configured) carrying the booking with status: cancelled.
- Cancelling still works at a closed venue (one returning
VENUE-N-009elsewhere) — use it to unwind bookings you hold. 400BKRUL-N-008: an operatorbooking_windowrule stops cancelling a confirmed booking this close to its start. Not retryable — contact the venue to cancel.
curl -X DELETE "https://api.bookabletech.com/venues/bookings/${BOOKING_ID}" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
# 204 No Content on success| HTTP Status | Meaning |
|---|---|
400 | Invalid request, or an operator booking rule refused it (e.g. BKRUL-N-007 amend / BKRUL-N-008 cancel window closed) |
401 | Token expired — refresh and retry |
403 | You don't have permission to modify this booking |
404 | Booking not found; VENUE-N-009 = venue closed (amend refused, cancel still works) |
409 | Booking cannot be modified in its current state |
422 | Business rule violation |
See the Error Catalog for detailed error codes.
- Quickstart — first booking in 5 steps
- Webhooks — real-time booking status events
- Bookings API Reference