You are viewing a non-production environment — the API surface may differ from production.

Receiving webhooks

How Karma delivers events to your endpoint — the envelope, signing, retries and ordering.

Karma pushes events to an HTTPS endpoint you control. Subscribe once, then handle events as they happen instead of polling for changes.

The envelope

Every event arrives as a POST with the same outer shape. Only data differs between event types — its schema is documented on each event's page.

{
  "id": "9f1c…",
  "event": "order.created",
  "resource": "order",
  "resourceId": "3b7e…",
  "timestamp": "2026-08-02T09:41:17.000Z",
  "apiVersion": "v1",
  "data": { }
}
FieldDescription
idUnique id for this delivery group. Stable across retries — use it to deduplicate.
eventEvent name, e.g. order.created.
resource / resourceIdThe entity the event is about.
timestampWhen the event occurred, ISO 8601 UTC.
apiVersionEnvelope version. Currently always v1.
dataEvent-specific payload.

Custom fields and metadata

HTTP webhooks include the object's API-readable custom fields in two forms:

  • customFields: values with their field ID, stable key, label, group, type, display value, version and status.
  • metadata.customFields: the same values keyed by the field's stable key. Other existing metadata is preserved.

For inventory, booking and order events these properties live directly under data. Tab events that already contain a tab reference put them under data.tab; other tab events put them under data. Existing location, tab, item, purchase, table and guest reference blocks are enriched too, including items[].item. A booking with a purchaseId also gets a purchase reference. A staff user reference is not a guest profile.

Only fields enabled for API reading are included, respecting inherited restrictions and the subscription's API-key permissions and location access. Company-owned subscriptions without an API key receive API-readable fields for their matched location. Unset fields are omitted; explicitly cleared values remain null. Deleted or inaccessible records have empty field projections. Decimal and money values retain the API's exact representation.

Values are captured when outbound dispatch is prepared, which can be later than the event timestamp. They are not sale-time snapshots. Once saved for a delivery, the values stay unchanged across retries, even if the fields are edited afterwards. The signature covers the entire payload, including fields. These subscriber-specific values are not added to browser realtime broadcasts.

This enrichment does not introduce new event types or emit an event merely because a custom field was edited. In particular, there is currently no standalone public purchase webhook; purchase references are enriched within existing events.

Verifying deliveries

Each request carries an X-Webhook-Signature header: an HMAC-SHA256 of the raw request body, keyed with your subscription's signing secret.

Verify before you trust

Compute the HMAC over the raw body bytes, before any JSON parsing, and compare using a constant-time comparison. Reject any request whose signature does not match.

Responding

Respond 2xx within 30 seconds to acknowledge delivery. Anything else — including a timeout — is treated as a failure and retried.

Acknowledge first, process afterwards: do the minimum work needed to persist the event, return 2xx, and handle the rest asynchronously. Slow handlers are the most common cause of duplicate deliveries.

Retries, ordering and duplicates

  • Retries — failed deliveries are retried with backoff. Your endpoint must be idempotent.
  • Duplicates — at-least-once delivery. The same id may arrive more than once; deduplicate on it.
  • Ordering — not guaranteed. Use timestamp to order events, and don't assume order.updated arrives after order.created.

Subscribing

Create and manage subscriptions through the Webhooks endpoints in the API reference. A subscription is a URL, the set of events it should receive, and the location scope it applies to.

On this page