Skip to content

Handling Webhook Events API (1.9.0)

Webhook API specification for receiving real-time notifications from The Bookings Group system. Distributors must implement this endpoint to receive notifications about booking updates, inbound messages from operators via their Table Management System (TMS), and venue status changes.

Event Types

eventTypeDescriptionPopulated fields
booking.updatedA booking was created, updated, or cancelledbookings
message.receivedOne or more operator messages were sent for a bookingmessages
venue.updatedA venue's status changed. Today only closure is sentvenues
webhook.pingA connectivity test you asked for (POST /webhooks/test)none

Always switch on eventType and ignore values you do not recognise. New event types are added over time. A subscription created without an eventTypes list receives every event type, including new ones; rejecting an unfamiliar one causes delivery failures on your endpoint rather than preventing the event. A subscription with an eventTypes list receives only the types it names.

venue.updated is sent only to distributors that distribute the venue (an active relationship with the venue group, and the venue in their catalogue) and hold an active subscription for it.

A payment status change on a booking also fires booking.updated, but the payload carries no payment fields, so you will occasionally receive an update in which nothing visible changed. Treat it as a no-op.

POST /webhooks/test (Webhook API) sends any of these to your subscriptions on demand and reports what each endpoint answered. In Live it sends webhook.ping only; in the sandbox it also sends sample, real and simulated booking.updated, message.received and venue.updated events. Every test delivery carries an X-Webhook-Test: true header — a real event never does.

To test your message.received handling, use POST /webhooks/test with eventType: message.received: the message is built for the test only (never stored or emailed), the sender defaults to the booking's venue and can be overridden along with the subject, and a repeat is always delivered. In the sandbox, POST /bookings/{bookingId}/messages with direction: operator_to_partner (Messaging API) stores a real message and sends it too, but reports nothing about the delivery.

Authentication

Every request carries:

  • X-API-Key — lowercase hex HMAC-SHA256 of the raw request body, keyed with the secretKey of the subscription it was sent for.
  • X-Webhook-Id — that subscription's webhookId. If you hold more than one subscription, use it to pick the secret.
  • X-Webhook-Test: true — only on deliveries triggered by POST /webhooks/test.

Verify the signature before processing the payload:

expected = HMAC-SHA256(key=SUBSCRIPTION_SECRET_KEY, message=raw_request_body).hex()
assert request.headers["X-API-Key"] == expected

Response Codes

Return 204 No Content on success. Any non-2xx response, including a redirect (3xx, which is never followed), causes the delivery to be considered failed.

Respond within 10 seconds. venue.updated deliveries and test deliveries time out after 10 seconds per attempt; booking.updated and message.received deliveries allow 45 seconds in total, retries included.

Retries

A delivery that fails with 5xx, 408, 429, a timeout or a connection error is retried up to 3 times (once for venue.updated), waiting roughly 1–2, 2–4 and 4–8 seconds between attempts. On 429 we wait for your Retry-After, up to 10 seconds.

What happens after that depends on the event type:

eventTypeAfter the immediate retriesAny other 4xx
booking.updatedRedelivered, up to 5 deliveries in total, then parked for investigationTreated as a failure and redelivered
venue.updatedRedelivered, up to 5 deliveries in total, then parked for investigationFinal: recorded and not retried
message.receivedNot redelivered automatically; Bookable support can resend itNot redelivered automatically

A redelivery skips subscriptions that already answered 2xx. Delivery is at least once, so the same event can still arrive twice: deduplicate on the booking id and lastUpdate, or the message id.

Languages
Servers
Distributor webhook endpoint
https://your-distributor-domain.com

Receive booking and messaging notifications

Request

Endpoint that distributors must implement to receive notifications. The Bookings Group system sends HTTP POST requests to this endpoint when:

  • A booking is updated (booking.updated)
  • An operator sends a message via their TMS (message.received)
  • A venue closes (venue.updated)

Use eventType to determine which top-level field (bookings, messages or venues) is populated.

Security
apiKey
Headers
X-Webhook-Idstringrequired

The webhookId of the subscription this delivery was sent for. Its secretKey signed the body.

Example: whk_3f2b8c1e5a7d4e9b9c0a1d2e3f4a5b6c
X-Webhook-Teststring

true on deliveries triggered by POST /webhooks/test. Never sent on a real event.

Value"true"
Bodyapplication/jsonrequired
eventTypestringrequired

Type of event that triggered the notification

Enum"booking.updated""message.received""venue.updated""webhook.ping"
Example: "booking.updated"
timestampstring(date-time)required

ISO 8601 timestamp when the event was dispatched

Example: "2025-06-17T10:30:00Z"
bookingsArray of objects or null(Booking)

Booking data. Present when eventType is booking.updated, omitted otherwise.

messagesArray of objects or null(MessagePayload)

Message data. Present when eventType is message.received, omitted otherwise. All messages in a single notification belong to the same booking.

venuesArray of objects or null(VenuePayload)

Venue data. Present when eventType is venue.updated, omitted otherwise.

curl -i -X POST \
  https://your-distributor-domain.com/ \
  -H 'Content-Type: application/json' \
  -H 'X-API-Key: YOUR_API_KEY_HERE' \
  -H 'X-Webhook-Id: whk_3f2b8c1e5a7d4e9b9c0a1d2e3f4a5b6c' \
  -H 'X-Webhook-Test: true' \
  -d '{
    "eventType": "booking.updated",
    "timestamp": "2025-06-17T11:45:00Z",
    "bookings": [
      {
        "id": "29|X9|275cc44dd2e2496fba44857c9257443a|B",
        "compositeId": "29|X9|275cc44dd2e2496fba44857c9257443a|d99128c546b34b619c4477b712869f2b",
        "date": "2025-06-25",
        "time": "21:30:00",
        "partySize": 6,
        "status": "confirmed",
        "reference": "REF-20250617-001",
        "firstName": "John",
        "lastName": "Doe",
        "email": "john.doe@example.com",
        "phone": "+1234567890",
        "duration": 120,
        "productName": "dinner",
        "productType": "dinner",
        "notes": "Anniversary dinner — window table if possible",
        "source": "MyDistributor",
        "createdDate": "2025-06-17T09:15:00Z",
        "lastUpdate": "2025-06-17T11:45:00Z"
      }
    ]
  }'

Responses

Notification received and processed successfully

Response
No content