Skip to main content
Webhooks send HTTP POST requests to the URL configured in Settings → Integrations → Webhooks. They use a signing secret separate from API keys. No Bearer token or WEBHOOKS_WRITE scope is needed to receive them; v1 exposes no public endpoint for managing webhook configurations.

Events and coverage

An active configuration receives only its selected events. Cancellation is a status change, not deletion: inspect CANCELED_BY_USER or CANCELED_BY_RESTAURANT on an update when that flow publishes one. There is no separate cancellation event.
These events are not an exhaustive change feed. Publishing exists in selected staff reservation/table operations and automatic status or table assignment flows. Partner API writes and booking portal flows do not directly publish these generic webhooks. A later automatic change can produce an update without a preceding creation event. Do not rely on them as the sole source for complete synchronization.

Headers

Do not override these headers in custom configuration. The signature covers the raw body only, not a concatenation of the timestamp header and body.

Payload

Illustrative creation event; IDs and timestamps are examples:
The reservation always includes id, restaurantId, status, group_size, reservation_date, reservation_time, created_at, updated_at, source, tags and metadata (which can be null). This is not the Partner API reservation format: it uses group_size and separate date/time fields, not party_size and start_at. reservation_date carries the restaurant’s service-day label, normally serialized as an ISO midnight string. Preserve its YYYY-MM-DD part; do not convert that UTC midnight to another timezone to determine the day. reservation_time is a local HH:mm value. Do not treat the pair as a UTC instant. created_at, updated_at and the event timestamp are UTC instants. Optional content depends on the reservation:
  • customer: ID, nullable external_id, name and available email, phone and language.
  • tables: objects with id and name; no nested room.
  • room: id and multilingual name object, not a string.
  • waiter: id and name.
  • payments: id, amount, currency, status, provider, optional provider_id and created_at.
  • custom_message, allergies and total_amount_paid: omitted when empty or zero by the current transformer. Omission does not mean “unchanged”.
  • shift: may appear in the test sample; ordinary reservation events currently omit it. Do not require it.
Webhooks may contain personal and payment-related data regardless of API key scopes. Restrict access to bodies and secrets; avoid logging complete payloads.

Verify the signature

Compute HMAC-SHA256 over the exact bytes received, using the webhook secret. Reject missing or malformed signatures, then compare digests in constant time. Only parse the JSON after verification. Parsing and reserializing JSON changes whitespace or field order and can invalidate a legitimate signature.

Express receiver example

Save the Node.js verifier as verify-signature.js. Register the raw-body webhook route before any express.json() middleware. This example only validates and logs event identifiers; replace that demonstration handling with your processing before acknowledging a production event. Load the real secret from secure server-side storage rather than committing it.

Delivery and retries

  • The receiver should return 2xx within the configured timeout, after successful processing or durable acceptance. Default timeout is 5,000 ms, configurable from 1,000 to 30,000 ms.
  • Thrown network or timeout errors use the delivery task’s retry policy: at most 5 attempts total, exponential backoff with factor 2 and delay bounds of 1–10 seconds. These are configuration bounds, not a guaranteed schedule.
  • HTTP 4xx and 5xx responses do not currently trigger those retries. They are recorded as an unsuccessful result without throwing a task error.
  • Delivery order and exactly-once delivery are not guaranteed. A retry keeps the same body and id; multiple destinations can receive that same ID. Use (restaurant_id, id) to identify a repeated event in your consumer, scoped to the integration when it handles multiple destinations independently.
  • The settings interface has no delivery journal or replay control. There is no public replay API.
A lost response can cause a retry after your receiver already processed the event. Avoid repeating a business action for an already handled ID. The signature establishes body authenticity; it does not itself prevent replay.

Test and troubleshoot

The Test action sends a real, synchronous RESERVATION_CREATED request with fictional data; it does not create a reservation. The sample uses a fixed service date (2025-12-25, date-only) and includes a shift, unlike ordinary events. It does not exercise the background delivery task or its retry behavior. For a signature failure, check the secret, raw bytes, middleware order and custom headers. After regenerating a secret, update the receiver. Already queued attempts may still carry signatures made with the previous secret. For a missing event, check activation, selected events, publishing coverage, URL, response status and timeout. Provide support with the restaurant, webhook name, event ID if available, time and HTTP status; never send the secret.