Webhooks
If the restaurant owner registers your endpoint (in Sitora Biz, alongside your credential), Sitora POSTs signed events as they happen. Webhooks are optional; a controller that only polls is fully conformant.
Endpoints must be HTTPS and must resolve to a public address. Sitora refuses to register — and refuses to deliver to — plain HTTP, URLs with embedded credentials, and hosts that resolve to loopback, private, or link-local ranges. Redirects are not followed: publish the final URL.
Events
Section titled “Events”| Event | Fired when |
|---|---|
serving_task.offered |
A new task is offered to your fleet. |
serving_task.cancelled |
A task you may be running was cancelled by Sitora. |
serving_task.expired |
An offer lapsed unclaimed. |
robotics.paused |
The filial’s robotics were paused. |
robotics.resumed |
The filial’s robotics were resumed. |
Payload
Section titled “Payload”A webhook body identifies the task and its new state — nothing more:
{ "delivery_id": 4412, "event_type": "serving_task.offered", "created_at": "2026-08-06T18:20:05.412Z", "payload": { "task_id": 8871, "display_number": 42, "leg": "dine_in_tray", "status": "offered", "expires_at": "2026-08-06T18:22:05.412Z" }}The manifest is deliberately absent. Webhooks travel to a URL a
restaurant owner typed in and are retained as delivery records, so the
destination — a customer’s address on courier legs — is not put on that
channel. Hydrate the task with GET /serving-tasks/, where your credential
is checked on every read. robotics.paused / robotics.resumed carry only
filial_id.
Signature
Section titled “Signature”Every delivery carries:
X-Sitora-Robotics-Signature: t=<unix_timestamp>,v1=<hex>where v1 is HMAC_SHA256(secret, "{t}.{body}") and secret is the
webhook secret shown once at registration. Verify with a constant-time
comparison and reject stale timestamps (a few minutes of tolerance is
enough) to defeat replay.
Delivery semantics — read this twice
Section titled “Delivery semantics — read this twice”Delivery is at-least-once and best-effort. Events can arrive duplicated, late, or not at all. Therefore:
- Webhooks are a latency optimization, never truth. On any event, reconcile by polling — the task list is the contract.
- Missed or doubted events can be read back from
GET /webhook-deliveries/?since_id=<last seen id>, and an individual delivery can be re-sent viaPOST /webhook-deliveries/{id}/redeliver/. - Respond
2xxquickly and do the work asynchronously; a slow endpoint is a failed delivery.