Subscribe to Flipdish Events (v3)

Use Flipdish Flipdish Webhooks to receive HTTP POSTs when things happen in your account (e.g., menu.published.v1). You configure which event types to receive and the callback URL in the Portal.

These docs describe the delivery contract and how to verify requests. See the Event schemas in API Reference v3.0Flipdish Webhooks for exact payloads.


Prerequisites

  • Only users with the Owner or Managed Owner role in the Flipdish portal can create webhooks, as these roles include the Edit Webhooks permission.
  • Access to the Flipdish Portal with permission to manage the Org’s settings
  • An HTTPS endpoint you control (staging recommended for first tests)
  • Your subscription’s shared secret for request verification

1. How it works

  1. In the Portal, go to Settings → Webhooks and create a Webhook Subscription.
  2. Select one or more event types (e.g., menu.published.v1).
  3. Provide your HTTPS callback URL
  4. When an event occurs, Flipdish sends an HTTP POST to your URL with the event payload.

Org-scoped ownership

Webhook subscriptions now belong to the OrgId, not a user or OAuth app.


2. Request format

  • Method: POST
  • Content-Type: application/json
  • Body: Event payload (see schemas in API Reference), e.g. menu published v1.

Headers

X-Flipdish-Event-Type: <event-type>            # e.g., menu.published.v1
X-Flipdish-Event-Version: v1
X-Flipdish-Timestamp: 2025-08-14T12:34:56.789Z
X-Flipdish-Signature: t=2025-08-14T12:34:56.789Z,sha256=<hex>

See the Delivery contract section below for details on each header.

Response contract

  • Return any 2xx to acknowledge receipt.
  • Non-2xx or timeouts are treated as failures and will be retried.

Delivery contract

  • Method: POST, Content-Type: application/json
  • Acknowledge with any 2xx once you persist the event
  • Retries are automatic (at-least-once semantics). Handlers must be idempotent
HeaderDescription
X-Flipdish-Event-TypeEvent type identifier (e.g., menu.published.v1)
X-Flipdish-Event-VersionEvent version (e.g., v1, v2)
X-Flipdish-TimestampISO-8601 timestamp when the event was sent
(planned) X-Flipdish-SignatureHMAC-SHA256 signature for payload verification
(planned) X-Flipdish-Idempotency-KeyKey to support idempotent processing

Verifying requests

Below is a minimal Node.js/TypeScript example. It uses the raw request body, concatenates ${timestamp}.${rawBody}, computes an HMAC-SHA256 with your subscription secret, and compares using a timing-safe comparison.

import crypto from 'node:crypto';

function timingSafeEqual(a: string, b: string): boolean {
  const ab = Buffer.from(a, 'utf8');
  const bb = Buffer.from(b, 'utf8');
  if (ab.length !== bb.length) return false;
  return crypto.timingSafeEqual(ab, bb);
}

export function verifySignature(
  rawBody: string,
  timestamp: string,
  signature: string,
  secret: string,
): boolean {
  const payload = `${timestamp}.${rawBody}`;
  const expected = crypto.createHmac('sha256', secret).update(payload, 'utf8').digest('hex');
  return timingSafeEqual(expected, signature);
}

Usage sketch (framework-agnostic):

// Pseudocode – ensure you read the RAW body bytes (do not JSON.parse before signing!)
const rawBody = getRawBodyFromHttpFramework(req); // string or Buffer → string
const timestamp = req.headers['x-flipdish-timestamp'] as string;
const signatureHeader = req.headers['x-flipdish-signature'] as string; // "sha256=<hex>" or similar
const signature = signatureHeader.split('sha256=')[1] ?? signatureHeader; // normalize to hex only

if (!verifySignature(rawBody, timestamp, signature, process.env.FLIPDISH_WEBHOOK_SECRET!)) {
  return res.status(401).send('Invalid signature');
}

// Persist event, then acknowledge with 2xx
res.status(200).send('OK');

3. Testing your endpoint

  • Create a subscription to a non-critical URL (staging).
  • Trigger a known event (e.g., publish a test menu).
  • Confirm you receive a POST and that verification passes.
  • Return 2xx when you persist the event; retry logic will handle transient outages.

4. Operational guidance

  • Time budget: Keep handlers fast; offload work to a queue.

5. Where to find event schemas

Go to API Reference → Webhook Events and open the event type page (e.g., menu.published.v1) for the exact JSON schema and example payloads.


6. Troubleshooting

  • We don’t see any requests: Check that the subscription is enabled, the URL is public and HTTPS, and that your firewall allows Flipdish IPs (if applicable).

7. Legacy vs New

AspectLegacy WebhooksFlipdish Webhooks
OwnershipWebhooks tied to a user/OAuth appOrg-scoped subscriptions (belong to orgId)
Location in PortalUser → Developer tools → OAuth apps → WebhooksSettings → Webhooks
VerificationLegacy app secret, varied patternsHMAC-SHA256 over ${timestamp}.${rawBody} with timing-safe compare
Supported eventsLegacy set, limited growthNew v3.0 events (e.g., menu.published.v1, menu.published.v2)