Skip to main content
This format is frozen. It only applies to webhooks created before V1 (their card shows Legacy format in Settings → Integrations → Webhooks). Every new webhook, and every endpoint created through the API, uses V1. Legacy webhooks receive reservation events only: customer events have no legacy body.
Delivery, retries, the delivery journal and the list of publishing flows are the same for both formats: see the webhook reference.

Move to V1

  1. Update the receiver to verify EatNow-Signature (see Verify the signature) and to read the V1 body: type instead of event, data.object (the partner API reservation: party_size, start_at…) instead of data.reservation, data.previous_attributes (changed fields only) instead of previous_data. The secret does not change.
  2. In Settings → Integrations → Webhooks, click Upgrade to V1 on the webhook. This cannot be undone.
  3. Deliveries already in the journal keep their legacy body and signature, resends included; everything published afterwards is V1.

Headers

Custom headers from the configuration are applied first; the headers above are applied after them and always win (names compared case-insensitively), so a custom header can never replace them. Any custom header whose name starts with X-EatNow- is dropped. 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”.
Amounts are in minor units: total_amount_paid and payments[].amount are integers in cents (5000 = 50.00 in the payment’s currency). Divide by 100 to display them. previous_data accompanies most updates. When the change comes from a staff action, a partner call or an automation, it is the full reservation before the change. When it comes from a register (NowOS), it carries the reservation’s own fields before the change (status, date, time, covers…) with the current relations (customer, tables, room).
  • 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.