Docs
Webhooks: Events
Webhooks

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

#The request

A POST with a JSON body and these headers:

HeaderMeaning
X-Laayo-EventEvent name, for example order.created
X-Laayo-Event-IdUnique per event
X-Laayo-Idempotency-KeyUse it to drop duplicates. A retry carries the same key.
X-Laayo-KeyYour key ID
X-Laayo-TimestampUnix seconds when this attempt was signed
X-Laayo-SignatureLowercase hex HMAC-SHA256 of timestamp + '.' + raw body, with your secret
X-Laayo-Attempt1 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 }
}
Was this page clear?Updated 1 Nov 2026