Webhooks
PreviewReal-time events delivered to your server
Outbound webhook delivery is rolling out. The events, payload shapes, and signing scheme below are the stable contract — subscribe a URL once and new event types will start flowing as they ship.
A customer places an order, a seating session opens, a reservation is confirmed — any state change on your restaurant emits an event.
Tastify serializes the event as JSON and delivers it to your configured URL over HTTPS, with an X-Tastify-Signature header you can verify.
Return any 2xx status within 10 seconds to acknowledge. Anything else, or a timeout, triggers an automatic retry with exponential backoff.
Delivery platforms and payment gateways push order and payment updates to Tastify at tenant-specific URLs. Copy these from your integrations dashboard when configuring the partner.
POST https://your-domain.com/api/v1/webhook/delivery/{tenant_slug}/{platform}POST https://your-domain.com/api/v1/webhook/payment/{tenant_slug}/{gateway}Every outbound event uses the same envelope — a stable id, the event name, a timestamp, the tenant id, and a data object whose shape is specific to the event.
{
"id": "evt_01HKX9J8Q2MBZ7R3T5V6W4P1Y2",
"event": "order.created",
"created_at": "2026-04-21T10: 30: 05Z",
"tenant_id": "550e8400-e29b-41d4-a716-000000000001",
"data": {
"order": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"order_number": "ORD-001",
"status": "pending",
"order_type": "dine-in",
"total_amount": 45.5,
"table_name": "Table 3"
}
}
}Orders
Fires as orders move through their lifecycle.
order.createdA new order was created.order.updatedAn order was updated (items, notes, or status transition other than creation/completion).order.completedAn order was fully paid and closed.order.cancelledAn order was cancelled before completion.Sessions
Seating session lifecycle events.
session.createdA seating session was opened at a table.session.closedA seating session was closed; linked queue ticket marked completed and seats released.Reservations
Reservation lifecycle events.
reservation.createdA new reservation was submitted by a customer.reservation.confirmedA reservation was confirmed (auto or manual).reservation.cancelledA reservation was cancelled by the customer or staff.reservation.checked_inThe party arrived and was either queued or directly seated.reservation.completedA reservation was marked completed after the visit.reservation.no_showThe party did not arrive within the grace window.Every request carries an X-Tastify-Signature header. Combine the timestamp and the raw request body with your endpoint's signing secret using HMAC-SHA256, then compare against v1 using a constant-time comparison.
X-Tastify-Signature: t=1713696000,v1=5d41402abc…Rotate the secret at any time from your integrations dashboard. Old signatures stop validating immediately after rotation.
// Node.js — verify an X-Tastify-Signature header
import crypto from 'node:crypto';
export function isValidTastifySignature(
rawBody: string,
header: string, // e.g. "t=1713696000,v1=5d41402abc..."
secret: string,
) {
const parts = Object.fromEntries(
header.split(',').map((p) => p.split('=') as [string, string]),
);
const timestamp = parts.t;
const signature = parts.v1;
if (!timestamp || !signature) return false;
const signedPayload = `${timestamp}.${rawBody}`;
const expected = crypto
.createHmac('sha256', secret)
.update(signedPayload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected, 'hex'),
Buffer.from(signature, 'hex'),
);
}Non-2xx responses and timeouts are retried with exponential backoff for up to 24 hours, then marked failed and surfaced in the dashboard.
The event id is stable across retries. Store processed ids on your side to safely ignore duplicate deliveries.
Events are delivered in best-effort order per resource, but retries can overtake fresh events — use the created_at timestamp when ordering matters.