Events
We POST each event to your webhook URL as it happens, signed with your secret. The same events come back from GET /v1/events for a POS without a public address.
#Set it up
- Set your https URL in the console under Webhooks, or with PUT /v1/partner/webhook. Send
nullto stop webhooks and poll instead. - Press Send test event, or call POST /v1/partner/webhook/test, and watch it arrive in GET /v1/partner/webhooks/deliveries.
#The request
A POST with a JSON body and these headers:
| Header | Meaning |
|---|---|
X-Laayo-Event | Event name, for example order.created |
X-Laayo-Event-Id | Unique per event |
X-Laayo-Idempotency-Key | Use it to drop duplicates. A retry carries the same key. |
X-Laayo-Key | Your key ID |
X-Laayo-Timestamp | Unix seconds when this attempt was signed |
X-Laayo-Signature | Lowercase hex HMAC-SHA256 of timestamp + '.' + raw body, with your secret |
X-Laayo-Attempt | 1 on the first try, then 2, 3 and so on |
Check the signature before you trust the body. See Verify a signature.
#Your answer
- Answer with any 2xx within 10 seconds. Anything else, or no answer in time, is a failure and we retry. See Retries.
- A retry carries the same
X-Laayo-Idempotency-Key. Drop one you have already handled, but still answer 2xx.
#Read the status, do not count
Laayo checks linked stores' orders every few seconds. Two quick changes between two checks can arrive as one event with the latest status. Always read data.status and act on it; never count events to work out where an order is. Read the order with GET /v1/orders/{id} if you need to be sure.
#Event types
v1 sends four events. order.updated carries a type: accepted, preparing, ready, rider_accepted, rider_assigned, rider_arrived, picked_up, delivered, cancelled, refunded, refund_requested.
order.created
A customer placed an order at a linked store. data is the full order, as in GET /v1/orders/{id}. Sandbox test orders carry "test": true and ids from 9000000001 up.
{
"event": "order.created",
"idempotency_key": "order.created:104812",
"occurred_at": "2026-11-01T12:41:11+05:45",
"data": { "laayo_order_id": "104812", "external_store_id": "TK-01", "status": "pending",
"items": [ { "external_item_id": "MOMO-C-10", "quantity": 2, "...": "..." } ], "...": "..." }
}order.updated
The order moved. type says how: accepted, preparing, ready, rider_accepted, rider_assigned, rider_arrived, picked_up, delivered, cancelled, refunded or refund_requested. Includes changes made in the Laayo vendor app. Two quick changes can arrive as one event with the latest status, so read data.status and do not count events.
{
"event": "order.updated",
"type": "rider_arrived",
"idempotency_key": "order.updated:104812:rider_arrived",
"occurred_at": "2026-11-01T12:58:40+05:45",
"data": { "laayo_order_id": "104812", "status": "handover", "rider": { "name": "Ram" }, "...": "..." }
}payout.paid
A payout reached the restaurant. data lists every order in it with Laayo’s commission on each, and your_order_ref when you sent one. You can turn this event off in the console under Webhooks; order events cannot be turned off.
{
"event": "payout.paid",
"idempotency_key": "payout.paid:2210",
"occurred_at": "2026-10-31T16:00:04+05:45",
"data": {
"laayo_store_id": 27, "external_store_id": "DBZ-01", "disbursement_id": 2210,
"payout_channel": "bank", "paid_at": "2026-10-31T16:00:00+05:45",
"gross_amount": 1000, "total_commission": 100, "total_store_amount": 900,
"fee": 0, "tds": 13, "net_payable": 887,
"orders": [ { "laayo_order_id": "104755", "your_order_ref": "KOT 41", "order_amount": 1000,
"admin_commission": 100, "store_amount": 900, "delivery_charge": 0 } ]
}
}test
Sent by Send test event in the console, or POST /v1/partner/webhook/test.
{
"event": "test",
"idempotency_key": "test:7:1762003860",
"occurred_at": "2026-11-01T12:51:00+05:45",
"data": { "message": "Test event from Laayo. Answer 2xx to acknowledge.", "partner_id": 7 }
}