Webhooks overview
Webhooks push events to your server in real time, so you do not have to poll.
When something happens in a restaurant — a reservation is created, a guest is
updated, feedback comes in — we send an HTTP POST to a URL you control with a
JSON event describing what happened.
Registering an endpoint
Section titled “Registering an endpoint”The API is in beta. Self-serve endpoint management from the back office (URL,
event selection, signing secret, and a delivery log with manual replay) is on the
roadmap but not available yet. For now, webhook endpoints are provisioned
on request: the Service team registers your endpoint URL and the events you
want, and returns a signing secret (whsec_…) used to
verify signatures.
Each endpoint is pinned to an API version at creation, so the payload shape you receive stays stable.
The event envelope
Section titled “The event envelope”Every delivery is a JSON object with this envelope:
{ "id": "evt_1K8xQ2m4Vd0pErJ7sN1aZ9bQ", "object": "event", "type": "reservation.updated", "created": "2026-06-27T17:30:00Z", "livemode": true, "api_version": "2026-06-27", "data": { "object": { "object": "reservation", "id": "resv_…" }, "previous_attributes": { "party_size": 2 } }}| Field | Description |
|---|---|
id | Unique event id (evt_…). Use this to deduplicate (see below). |
object | Always "event". |
type | The event type, e.g. reservation.updated. See the event catalog. |
created | When the event was emitted — ISO-8601 in UTC (a Z suffix). See the timezone note below. |
livemode | Always true for real events. |
api_version | The version the payload is rendered in (the endpoint’s pinned version). |
data.object | A full snapshot of the affected resource, in the same shape as the API. |
data.previous_attributes | Only on reservation.updated — a map of the changed fields to their previous values. Omitted on every other event type. |
Responding to events
Section titled “Responding to events”Return a 2xx status code quickly (ideally within a few seconds) to acknowledge
receipt. Do the real work asynchronously. Any non-2xx response, a timeout, or a
connection error is treated as a failed delivery and will be retried.
Delivery semantics
Section titled “Delivery semantics”At-least-once, deduplicate on event.id
Section titled “At-least-once, deduplicate on event.id”Delivery is at-least-once. The same event may be delivered more than once
(for example, if your server is slow to acknowledge and we retry, or after a
transient network error). Deduplicate on the event id (evt_…): record
the ids you have processed and ignore repeats. Make your handler idempotent.
No ordering guarantee
Section titled “No ordering guarantee”Events are not guaranteed to arrive in the order they occurred. For example,
you might receive reservation.seated before reservation.confirmed. Do not
assume order. When a decision depends on current state, treat the event as a
hint and fetch the latest resource from the API, or reconcile using each
resource’s updated_at.
Retries and auto-disable
Section titled “Retries and auto-disable”If a delivery fails, we retry with exponential backoff over roughly 3 days.
If every attempt fails for that whole window (the endpoint stays unreachable or
keeps returning errors), the endpoint is automatically disabled and an alert
is raised. You will need to fix the endpoint and have it re-enabled. To recover
events missed while an endpoint was down, re-fetch with
updated_since.