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.
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, nullableexternal_id, name and available email, phone and language.tables: objects withidandname; no nested room.room:idand multilingualnameobject, not a string.waiter:idandname.payments:id,amount,currency,status,provider, optionalprovider_idandcreated_at.custom_message,allergiesandtotal_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.
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.- Node.js
- Python
- PHP
Express receiver example
Save the Node.js verifier asverify-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
2xxwithin 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
4xxand5xxresponses 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.
Test and troubleshoot
The Test action sends a real, synchronousRESERVATION_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.