All API reference pages

Webhooks

Webhooks push organization events to your HTTPS endpoint as they happen. Available on Pro and Enterprise plans; managed by owners (in-app under Billing & plan → Developer, or via the API).

Managing subscriptions

GET    /orgs/{orgId}/webhooks
POST   /orgs/{orgId}/webhooks
DELETE /orgs/{orgId}/webhooks/{id}

Creating:

POST /orgs/{orgId}/webhooks
{ "url": "https://example.com/hooks/miseline", "events": ["catering.quote_accepted", "tray.delivered"] }
{
  "id": "2b83fc70-9340-4694-b176-bcf8bfd314c1",
  "url": "https://example.com/hooks/miseline",
  "events": ["catering.quote_accepted", "tray.delivered"],
  "secret": "whsec_1MkzDArsg8jZkU4EF-io8KoYFNGlXmxA",
  "active": true,
  "lastDeliveryAt": null,
  "lastStatus": null,
  "failureCount": 0
}

The secret is returned once, on creation — store it; listing never includes it. Subscribe to specific events or to everything with "events": ["*"].

Events

EventFires when
catering.quote_acceptedA client accepts a catering quote (it becomes the contract)
catering.invoice_paidA catering invoice is marked paid
policy.publishedA policy version is published
work_order.resolvedAn equipment work order is resolved
tray.deliveredA tray-line ticket is marked delivered
alert.createdAny operational alert opens (temperature excursion, offline sensor, expiring lot, certification lapse, nutrition risk)
report.publishedA site or account report is generated
signoff.decidedA dietitian approves or rejects a submitted review
walkthrough.submittedA guided walkthrough's responses are submitted
engagement.finalizedAn audit engagement's report is finalized

The delivery

Deliveries are POSTs to your URL:

POST /hooks/miseline
content-type: application/json
x-miseline-event: catering.quote_accepted
x-miseline-signature: 7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069
{
  "event": "catering.quote_accepted",
  "orgId": "05b955b6-c196-4e31-a383-4251dee16f8a",
  "at": "2026-08-08T20:40:01.598Z",
  "data": { "eventId": "…", "quoteId": "…", "totalCents": 184500 }
}

data varies per event and carries ids you can dereference through the regular API.

Verifying the signature

x-miseline-signature is the hex HMAC-SHA256 of the raw request body, keyed with your subscription's secret. Verify before trusting a delivery:

import { createHmac, timingSafeEqual } from "node:crypto";

function verify(rawBody, signatureHeader, secret) {
  const expected = createHmac("sha256", secret).update(rawBody).digest("hex");
  const a = Buffer.from(expected, "hex");
  const b = Buffer.from(signatureHeader, "hex");
  return a.length === b.length && timingSafeEqual(a, b);
}

Compute over the raw bytes — parsing and re-serializing the JSON can change the byte sequence and break the comparison.

Delivery semantics

  • Deliveries are best-effort, at-most-once: there is no automatic retry queue. Design your handler to reconcile via the API rather than depend on every event arriving.
  • Your endpoint has 8 seconds to respond; any 2xx counts as delivered. Respond fast and process async.
  • Every attempt updates lastDeliveryAt, lastStatus (0 means unreachable/timeout), and failureCount (reset on success) — poll GET /orgs/{orgId}/webhooks to monitor health.
  • Deliveries can arrive out of order; use at and the ids in data when sequence matters.