API reference
All endpoints
API reference

Laayo Partner API v1

One signed REST API for every POS. JSON in, JSON out. Every success body is wrapped as { "data": ... }, and every error as { "error": { "code", "message", "fields" } }.

Base URL https://posconnect.laayo.com.np. Every path starts with /v1. Sandbox keys use the same URL and only see Laayo test stores.

Bodies are at most 512 KB. Each key can make 600 requests a minute. Times are RFC 3339 in Nepal time, for example 2026-11-01T12:41:08+05:45.

429 and 503 answers carry Retry-After in seconds. Wait that long, then sign the request again with a new timestamp. While Laayo pauses the partner API, every call answers 503 api_paused with Retry-After: 300; webhooks keep coming.

Success
{ "data": { "store_id": 9001, "state": "open" } }

Signing

Every request carries X-Laayo-Key, X-Laayo-Timestamp (unix seconds, within 5 minutes of our clock) and X-Laayo-Signature: lowercase hex HMAC-SHA256 with your secret of

timestamp + '.' + METHOD + '.' + path with query + '.' + raw body

METHOD is upper case. The path includes the query exactly as sent. The body is empty for GET. Each signature is accepted once, so identical requests in the same second are refused as 401 replayed: retry after 1 second with a new timestamp.

Webhooks we send you are signed with the same secret over timestamp + '.' + raw body.

Signing guide with code in five languages

What you sign
1762019400.GET./v1/orders/123.

1762019400.PUT./v1/stores/5/status.{"state":"open"}

Errors

A store or order that is not linked to your key is always 404 not_found, so nobody can probe which stores exist.

StatusCodeMeaning
400bad_bodyThe body is not valid JSON, or the connection dropped while sending it.
400invalid_codeThe 6 digit code is wrong, already used, or older than 15 minutes.
401unauthorizedA signing header is missing, the key ID is unknown, or the signature does not match. The console request log shows which one.
401stale_timestampX-Laayo-Timestamp is more than 5 minutes from our clock, or not unix seconds.
401replayedWe already accepted a request with this exact signature. Two identical requests in the same second sign the same.
403ip_not_allowedThe key has an IP allowlist and the call came from another address.
403partner_suspendedLaayo paused this partner account.
403sandbox_live_storeA sandbox key tried to link a store that is not a Laayo test store.
404not_foundThe store or order does not exist, or it is not linked to your key. Both answer the same, on purpose.
404no_routeThe method and path match no endpoint.
409owner_takeoverThe owner switched to Laayo’s own controls, for up to 1 hour. Store, item and order writes from the POS are paused.
409store_linked_elsewhereThe store already has an active link to another POS.
409order_closedThe order is delivered, cancelled or refunded.
409accept_firstFor example ready before the order was accepted.
409rider_confirms_firstIn this town a Laayo rider confirms delivery orders before the restaurant. rider_assigned and rider_accepted arrive when a rider takes the delivery offer; that is not the confirmation yet, so accept, preparing and ready still answer this.
409order_changedSomeone moved the order at the same moment as your call.
409needs_laayo_appThis order needs a step the Partner API does not do in v1. error.reason says which one, for example store_notification_settings_missing: the store has never had its Laayo notification settings set up.
409scheduled_not_activeA scheduled order cannot be accepted before its time window.
409prep_time_unknownBusy needs the store’s normal prep time in minutes, and this store’s is set another way.
409diff_closedThe menu upload was already reviewed or replaced by a newer one.
413body_too_largeThe body is over 512 KB.
415unsupported_media_typeA body was sent without Content-Type: application/json.
422validation_failedA field is missing, has the wrong type or is out of range, for example more than 500 items. fields names each one.
429rate_limitedMore than 600 requests in a minute on one key. The answer carries Retry-After in seconds.
429too_many_codesMore than 10 wrong link codes in an hour on one key. Retry-After says how long.
500server_errorSomething broke at Laayo.
501not_implementedRejecting orders from the POS is coming. In v1 this endpoint always answers 501.
503api_pausedLaayo switched the partner API off for a short time, for example during an incident. Every /v1 call answers this with Retry-After: 300. Webhooks keep coming.
503unavailableA dependency at Laayo is briefly unavailable.

Get store status

GET/v1/stores/{id}/status

What customers see right now: open or not and why, the delivery time, busy minutes and owner takeover.

Parameters

idintegerpathRequired
Laayo store ID, from the link response.

Errors

More in the guide: /docs/store-status

Request
GET /v1/stores/9001/status
X-Laayo-Key: lpk_8f2c41a9e07b5d13c6a2f904
X-Laayo-Timestamp: 1762003860
X-Laayo-Signature: 5f0c2a8e9d41…
Response 200
{
  "data": {
    "store_id": 9001,
    "state": "busy",
    "customers_see": "35-50 min",
    "customer_view": {
      "open_now": true,
      "reason": "open",
      "delivery_time": "35-50 min",
      "closed_until": null,
      "closed_until_type": null,
      "busy_extra_minutes": 15
    },
    "owner_takeover": { "active": false, "until": null }
  }
}

Set store status

PUT/v1/stores/{id}/status

Open, close or mark the store busy. open and closed are exactly the restaurant’s own toggle in the Laayo app.

Parameters

idintegerpathRequired
Laayo store ID, from the link response.
state"open" | "closed" | "busy"bodyRequired
busy keeps the store open and adds prep time.
extra_prep_minutesinteger, 5 to 120body
Required for busy. Not added up: each busy call replaces the last. Ends with open, closed or unlink.
reopen_after_minutesinteger, 1 to 1440body
Optional for closed. The store reopens by itself after this many minutes.
With 15 extra minutes, a store showing 20-35 min shows 35-50 min.

Errors

More in the guide: /docs/store-status

Request
PUT /v1/stores/9001/status
Content-Type: application/json
X-Laayo-Key: lpk_8f2c41a9e07b5d13c6a2f904
X-Laayo-Timestamp: 1762003860
X-Laayo-Signature: 5f0c2a8e9d41…

{ "state": "busy", "extra_prep_minutes": 15 }
Response 200
{
  "data": {
    "store_id": 9001,
    "state": "busy",
    "customers_see": "35-50 min",
    "customer_view": {
      "open_now": true,
      "reason": "open",
      "delivery_time": "35-50 min",
      "closed_until": null,
      "closed_until_type": null,
      "busy_extra_minutes": 15
    },
    "owner_takeover": { "active": false, "until": null }
  }
}

Send a heartbeat

POST/v1/heartbeat

Tell Laayo the POS is running. Send one every 60 seconds. After 10 minutes without one, the link shows offline.

Parameters

store_idsinteger[], up to 1000body
Stores this POS is running for. Default: all your linked stores.
pos_versionstringbody
Your app version, up to 60 characters.
An offline POS never closes the store. Laayo records it and alerts the owner and its ops team.

Errors

More in the guide: /docs/pos-offline

Request
POST /v1/heartbeat
Content-Type: application/json
X-Laayo-Key: lpk_8f2c41a9e07b5d13c6a2f904
X-Laayo-Timestamp: 1762003860
X-Laayo-Signature: 5f0c2a8e9d41…

{ "store_ids": [9001], "pos_version": "nRestro 4.12" }
Response 200
{
  "data": {
    "server_time": "2026-11-01T12:31:00+05:45",
    "stores": [ { "store_id": 9001, "online": true } ],
    "next_heartbeat_seconds": 60
  }
}

Set items sold out or back

PUT/v1/stores/{id}/items/availability

Mark up to 500 items sold out or available in one call, by your ID or by Laayo item ID. back_at brings an item back by itself.

Parameters

idintegerpathRequired
Laayo store ID, from the link response.
itemsarray, 1 to 500bodyRequired
Each entry names the item by external_item_id (after mapping) or laayo_item_id.
items[].availablebooleanbodyRequired
false = sold out, true = back.
items[].back_atRFC 3339 timebody
Sold out only. 1 minute to 7 days ahead. The item comes back by itself at that time.
Each item gets its own result: updated, unchanged, not_found (map the ID first) or refused (with a reason, for example item management is off for this store). One bad ID does not stop the others.

Errors

More in the guide: /docs/sold-out

Request
PUT /v1/stores/9001/items/availability
Content-Type: application/json
X-Laayo-Key: lpk_8f2c41a9e07b5d13c6a2f904
X-Laayo-Timestamp: 1762003860
X-Laayo-Signature: 5f0c2a8e9d41…

{ "items": [
  { "external_item_id": "MOMO-C-10", "available": false,
    "back_at": "2026-11-02T10:00:00+05:45" }
] }
Response 200
{
  "data": {
    "updated": 1,
    "items": [
      { "ref": "MOMO-C-10", "laayo_item_id": 55102, "result": "updated",
        "back_at": "2026-11-02T10:00:00+05:45" }
    ]
  }
}

Get the Laayo menu

GET/v1/stores/{id}/menu

Items, variations and add-ons on Laayo for this store, with your mapped IDs, for building the item map.

Parameters

idintegerpathRequired
Laayo store ID, from the link response.

Errors

More in the guide: /docs/item-mapping

Request
GET /v1/stores/9001/menu
X-Laayo-Key: lpk_8f2c41a9e07b5d13c6a2f904
X-Laayo-Timestamp: 1762003860
X-Laayo-Signature: 5f0c2a8e9d41…
Response 200
{
  "data": {
    "store_id": 9001,
    "items": [
      { "laayo_item_id": 55102, "name": "Chicken momo", "price": 180,
        "available": true, "back_at": null, "category_id": 12, "category": "Momo",
        "veg": false, "variations": [], "addon_ids": [ 701 ],
        "external_item_ids": [ "MOMO-C-10" ] }
    ],
    "addons": [
      { "laayo_addon_id": 701, "name": "Extra achar", "price": 20, "available": true }
    ]
  }
}

Get the item map

GET/v1/stores/{id}/item-map

Your item IDs and the Laayo items they point to, for this store.

Parameters

idintegerpathRequired
Laayo store ID, from the link response.

Errors

More in the guide: /docs/item-mapping

Request
GET /v1/stores/9001/item-map
X-Laayo-Key: lpk_8f2c41a9e07b5d13c6a2f904
X-Laayo-Timestamp: 1762003860
X-Laayo-Signature: 5f0c2a8e9d41…
Response 200
{
  "data": {
    "store_id": 9001,
    "mappings": [
      { "external_item_id": "MOMO-C-10", "laayo_item_id": 55102 },
      { "external_item_id": "MOMO-V-10", "laayo_item_id": 55101 }
    ]
  }
}

Map items

PUT/v1/stores/{id}/item-map

Add or change pairs of your item ID and a Laayo item ID, and remove pairs. Send only what changes.

Parameters

idintegerpathRequired
Laayo store ID, from the link response.
mappingsarray, up to 1000body
Each entry: external_item_id (string, up to 100) and laayo_item_id (integer). Upserts.
removestring[], up to 1000body
Your item IDs to unmap.

Errors

More in the guide: /docs/item-mapping

Request
PUT /v1/stores/9001/item-map
Content-Type: application/json
X-Laayo-Key: lpk_8f2c41a9e07b5d13c6a2f904
X-Laayo-Timestamp: 1762003860
X-Laayo-Signature: 5f0c2a8e9d41…

{
  "mappings": [
    { "external_item_id": "MOMO-C-10", "laayo_item_id": 55102 },
    { "external_item_id": "MOMO-V-10", "laayo_item_id": 55101 }
  ],
  "remove": [ "OLD-SKU-7" ]
}
Response 200
{ "data": { "saved": 2, "removed": 1 } }

Get an order

GET/v1/orders/{id}

One order of a linked store, with items, your item IDs, the masked customer and its timeline.

Parameters

idintegerpathRequired
Laayo order ID (laayo_order_id in events).
Phone numbers are masked, in the customer object and in notes.

Errors

More in the guide: /docs/receiving-orders

Request
GET /v1/orders/104812
X-Laayo-Key: lpk_8f2c41a9e07b5d13c6a2f904
X-Laayo-Timestamp: 1762003860
X-Laayo-Signature: 5f0c2a8e9d41…
Response 200
{
  "data": {
    "laayo_order_id": "104812",
    "laayo_store_id": 9001,
    "external_store_id": "TK-01",
    "status": "confirmed",
    "order_type": "delivery",
    "payment_method": "cash_on_delivery",
    "payment_status": "unpaid",
    "order_amount": 545,
    "delivery_charge": 60,
    "total_tax": 0,
    "created_at": "2026-11-01T12:41:08+05:45",
    "scheduled": false,
    "schedule_at": null,
    "prep_minutes": "15",
    "your_order_ref": "KOT 48",
    "note": "Less spicy",
    "customer": { "name": "Sita", "phone": "+977*******521", "address": "Near Birtamod chowk" },
    "rider": { "name": "Ram" },
    "items": [
      { "id": 88213, "external_item_id": "MOMO-C-10", "name": "Chicken momo",
        "quantity": 2, "price": 180, "variation": null,
        "addons": [ { "name": "Extra achar", "quantity": 1, "price": 20 } ], "note": null }
    ],
    "timeline": { "confirmed": "2026-11-01T12:42:30+05:45", "processing": null,
      "handover": null, "picked_up": null, "delivered": null, "canceled": null }
  }
}

Accept an order

POST/v1/orders/{id}/accept

The kitchen took the order. Forward only: repeating it, or calling it on an order that is already further, answers 200 with changed false.

Parameters

idintegerpathRequired
Laayo order ID (laayo_order_id in events).
prep_minutesinteger, 1 to 600body
How long the kitchen needs. Without it, the store’s usual prep time.
your_order_refstring, 1 to 64body
Your bill or KOT number. Echoed in GET /v1/orders/{id}, in order events and in payout.paid orders[], so your books match.

Errors

More in the guide: /docs/order-status

Request
POST /v1/orders/104812/accept
Content-Type: application/json
X-Laayo-Key: lpk_8f2c41a9e07b5d13c6a2f904
X-Laayo-Timestamp: 1762003860
X-Laayo-Signature: 5f0c2a8e9d41…

{ "prep_minutes": 15, "your_order_ref": "KOT 48" }
Response 200
{
  "data": { "order_id": 104812, "action": "accept", "status": "confirmed",
    "changed": true, "prep_minutes": 15 }
}

Mark preparing

POST/v1/orders/{id}/preparing

Cooking started. Moves the customer’s live tracking forward.

Parameters

idintegerpathRequired
Laayo order ID (laayo_order_id in events).
prep_minutesinteger, 1 to 600body
Updated prep time, if it changed.

Errors

More in the guide: /docs/order-status

Request
POST /v1/orders/104812/preparing
X-Laayo-Key: lpk_8f2c41a9e07b5d13c6a2f904
X-Laayo-Timestamp: 1762003860
X-Laayo-Signature: 5f0c2a8e9d41…
Response 200
{
  "data": { "order_id": 104812, "action": "preparing", "status": "processing", "changed": true }
}

Mark ready

POST/v1/orders/{id}/ready

The food is packed. The customer sees it at once, and the answer includes the rider when one is assigned.

Parameters

idintegerpathRequired
Laayo order ID (laayo_order_id in events).

Errors

More in the guide: /docs/order-status

Request
POST /v1/orders/104812/ready
X-Laayo-Key: lpk_8f2c41a9e07b5d13c6a2f904
X-Laayo-Timestamp: 1762003860
X-Laayo-Signature: 5f0c2a8e9d41…
Response 200
{
  "data": { "order_id": 104812, "action": "ready", "status": "handover", "changed": true,
    "rider": { "name": "Ram", "arrived_at_store": false, "eta_minutes": 4 } }
}

Reject an order

POST/v1/orders/{id}/reject
Coming. Answers 501 in v1.

Rejecting orders from the POS is coming. In v1 this answers 501, and the restaurant denies orders in the Laayo vendor app.

Parameters

idintegerpathRequired
Laayo order ID (laayo_order_id in events).

Errors

More in the guide: /docs/order-status

Request
POST /v1/orders/104812/reject
X-Laayo-Key: lpk_8f2c41a9e07b5d13c6a2f904
X-Laayo-Timestamp: 1762003860
X-Laayo-Signature: 5f0c2a8e9d41…
Response 501
{
  "error": { "code": "not_implemented",
    "message": "Rejecting from the POS is not available yet. The restaurant can deny the order in the Laayo app." }
}

Poll for events

GET/v1/events

The same events the webhooks carry, for a POS with no public address. Holds the call open up to wait seconds when nothing is new.

Parameters

afterstringquery
next_cursor from your last call. Without it you get the events of the last 24 hours.
waitinteger, 0 to 25query
Seconds to hold the call open. Default 25.
limitinteger, 1 to 500query
Default 100.
The path you sign includes the query exactly as sent, for example /v1/events?after=5521&wait=25.
Save next_cursor after you have handled the events, then call again. Do not run two polls at once.

Errors

More in the guide: /docs/polling

Request
GET /v1/events?after=5521&wait=25
X-Laayo-Key: lpk_8f2c41a9e07b5d13c6a2f904
X-Laayo-Timestamp: 1762003860
X-Laayo-Signature: 5f0c2a8e9d41…
Response 200
{
  "data": {
    "events": [
      { "event": "order.created",
        "event_id": "5521",
        "idempotency_key": "order.created:104812",
        "occurred_at": "2026-11-01T12:41:11+05:45",
        "data": { "laayo_order_id": "104812", "status": "pending", "...": "..." } }
    ],
    "next_cursor": "5521"
  }
}

Your account

GET/v1/partner/me

Your key, profile, webhook URL, IP allowlist and whether an old secret is still valid after a rotation.

Parameters

None. Only the three signing headers.

Errors

Request
GET /v1/partner/me
X-Laayo-Key: lpk_8f2c41a9e07b5d13c6a2f904
X-Laayo-Timestamp: 1762003860
X-Laayo-Signature: 5f0c2a8e9d41…
Response 200
{
  "data": {
    "partner_id": 7, "name": "nRestro", "key_id": "lpk_8f2c41a9e07b5d13c6a2f904",
    "status": "active", "sandbox": true,
    "webhook_url": "https://pos.example.com/laayo/webhook",
    "rate_limit_per_minute": 600, "linked_stores": 1,
    "profile": { "company_name": "nRestro Pvt. Ltd.", "support_phone": "9801234567",
      "website": "https://nrestro.example", "logo_url": null, "contact_email": "support@nrestro.example" },
    "ip_allowlist": [ "203.0.113.24" ],
    "last_used_at": "2026-11-01T12:30:58+05:45",
    "previous_secret_valid_until": null,
    "created_at": "2026-10-20T10:02:00+05:45"
  }
}

Update your profile

PUT/v1/partner/profile

Company name, the support phone restaurants see, website, logo URL and contact email.

Parameters

company_namestringbody
Up to 190 characters.
support_phonestringbody
Shown to restaurants in the Laayo vendor app.
websiteURLbody
logo_urlURLbody
contact_emailemailbody

Errors

Request
PUT /v1/partner/profile
Content-Type: application/json
X-Laayo-Key: lpk_8f2c41a9e07b5d13c6a2f904
X-Laayo-Timestamp: 1762003860
X-Laayo-Signature: 5f0c2a8e9d41…

{ "support_phone": "9801234567", "website": "https://nrestro.example" }
Response 200
{ "data": { "partner_id": 7, "...": "same as GET /v1/partner/me" } }

List linked stores

GET/v1/partner/stores

Every store linked to your key, with online or offline, busy and owner takeover state.

Parameters

None. Only the three signing headers.

Errors

Request
GET /v1/partner/stores
X-Laayo-Key: lpk_8f2c41a9e07b5d13c6a2f904
X-Laayo-Timestamp: 1762003860
X-Laayo-Signature: 5f0c2a8e9d41…
Response 200
{
  "data": [
    { "store_id": 9001, "name": "Laayo Test Kitchen", "external_store_id": "TK-01",
      "online": true, "last_heartbeat_at": "2026-11-01T12:31:00+05:45", "offline_since": null,
      "pos_version": "nRestro 4.12", "linked_at": "2026-10-31T17:30:04+05:45",
      "owner_takeover_until": null, "busy_extra_minutes": null }
  ]
}

Set the webhook URL

PUT/v1/partner/webhook

Where Laayo POSTs events. https only. Send null to stop webhooks and poll instead.

Parameters

urlhttps URL or nullbodyRequired

Errors

More in the guide: /docs/webhook-events

Request
PUT /v1/partner/webhook
Content-Type: application/json
X-Laayo-Key: lpk_8f2c41a9e07b5d13c6a2f904
X-Laayo-Timestamp: 1762003860
X-Laayo-Signature: 5f0c2a8e9d41…

{ "url": "https://pos.example.com/laayo/webhook" }
Response 200
{ "data": { "webhook_url": "https://pos.example.com/laayo/webhook" } }

Send a test event

POST/v1/partner/webhook/test

Queues a signed test event to your webhook URL. Watch it arrive in the deliveries list.

Parameters

None. Only the three signing headers.

Errors

More in the guide: /docs/webhook-events

Request
POST /v1/partner/webhook/test
X-Laayo-Key: lpk_8f2c41a9e07b5d13c6a2f904
X-Laayo-Timestamp: 1762003860
X-Laayo-Signature: 5f0c2a8e9d41…
Response 202
{ "data": { "event_id": "5530", "idempotency_key": "test:7:1762003860" } }

List webhook deliveries

GET/v1/partner/webhooks/deliveries

Recent events with their delivery status and every attempt.

Parameters

limitinteger, 1 to 200query
Default 50.

Errors

More in the guide: /docs/retries

Request
GET /v1/partner/webhooks/deliveries
X-Laayo-Key: lpk_8f2c41a9e07b5d13c6a2f904
X-Laayo-Timestamp: 1762003860
X-Laayo-Signature: 5f0c2a8e9d41…
Response 200
{
  "data": [
    { "event_id": "5521", "event": "order.created", "idempotency_key": "order.created:104812",
      "store_id": 9001, "status": "delivered", "attempts": 1, "last_status_code": 200,
      "last_error": null, "created_at": "2026-11-01T12:41:11+05:45",
      "next_attempt_at": null, "delivered_at": "2026-11-01T12:41:12+05:45" }
  ]
}

Rotate your secret

POST/v1/partner/secret/rotate

A new secret, shown once. The old one keeps working for 24 hours, so you can roll it out without downtime.

Parameters

None. Only the three signing headers.

Errors

More in the guide: /docs/signing

Request
POST /v1/partner/secret/rotate
X-Laayo-Key: lpk_8f2c41a9e07b5d13c6a2f904
X-Laayo-Timestamp: 1762003860
X-Laayo-Signature: 5f0c2a8e9d41…
Response 200
{
  "data": {
    "key_id": "lpk_8f2c41a9e07b5d13c6a2f904",
    "secret": "lps_…",
    "previous_secret_valid_until": "2026-11-02T12:35:00+05:45",
    "note": "Shown once. Store it now; the old secret keeps working for 24 hours."
  }
}

Go-live checks

GET/v1/partner/go-live

The six go-live checks, computed from your sandbox history.

Parameters

None. Only the three signing headers.

Errors

More in the guide: /docs/go-live

Request
GET /v1/partner/go-live
X-Laayo-Key: lpk_8f2c41a9e07b5d13c6a2f904
X-Laayo-Timestamp: 1762003860
X-Laayo-Signature: 5f0c2a8e9d41…
Response 200
{
  "data": {
    "ready": false,
    "passed": "5/6",
    "checks": [
      { "id": "signed_request", "label": "Signed requests work", "passed": true,
        "passed_at": "2026-10-21T11:04:52+05:45" },
      { "id": "order_flow", "label": "An order taken from accept to ready", "passed": false,
        "passed_at": null,
        "hint": "Accept, then mark ready, one test order (POST /v1/orders/{id}/accept, /ready)." }
    ]
  }
}

Webhook events

Laayo POSTs each event to your webhook URL. Answer 2xx within 10 seconds. A failed delivery waits 30 seconds, 1 minute, 2 minutes and longer, for about 24 hours, then the event is set aside. The same events are available with GET /v1/events.

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

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.

order.created
{
  "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.

order.updated
{
  "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.

payout.paid
{
  "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.

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 }
}