Zur Startseite
API

Webhooks

Subscribe to reservation and voucher events with HMAC-signed deliveries and exponential retries.

Webhooks let you react to events in DineOS without polling. Subscribe to one or more event types, and we will POST a signed JSON payload to your endpoint every time the event occurs.

Events

NameTypeRequiredDefaultDescription
reservation.createdeventFired when a new reservation is recorded, regardless of channel.
reservation.updatedeventFired on any change to an existing reservation (time, party size, table, status).
reservation.cancelledeventFired when status transitions to cancelled.
voucher.redeemedeventFired on every full or partial voucher redemption.

Payload shape

example payloadjson
{
  "id": "evt_01HQXZ5J4M3K7P9Q1B",
  "type": "reservation.created",
  "created_at": "2026-04-16T08:42:11Z",
  "data": {
    "id": "rsv_01HQXZ5J4M3K7P9Q1C",
    "starts_at": "2026-04-20T19:30:00Z",
    "party_size": 2,
    "status": "confirmed"
  }
}

Signature verification

Every delivery includes an X-DineOS-Signature header with an HMAC-SHA256 of the raw body using your endpoint's signing secret. Verify it in constant time before processing the payload:

verify.jsjavascript
import crypto from 'node:crypto';

export function verifyDineosWebhook(rawBody, signatureHeader, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');

  const provided = Buffer.from(signatureHeader, 'hex');
  const expectedBuf = Buffer.from(expected, 'hex');

  if (provided.length !== expectedBuf.length) return false;
  return crypto.timingSafeEqual(provided, expectedBuf);
}

Retries

Non-2xx responses are retried with exponential backoff for up to 24 hours: 30 seconds, then 1 minute, 5 minutes, 30 minutes, 2 hours, and 6 hours. After 24 hours the delivery is marked as failed and surfaces in the dashboard. Use the replay button to retry manually after fixing the issue.

Respond fast
Webhook handlers should respond within 10 seconds. Heavy work belongs on a queue — ack the webhook with 200, then process asynchronously.