Errors
Every refused call answers with an HTTP status and a short code. The code tells your POS what happened; the message is a plain sentence you can show staff.
#The error body
{ "error": {
"code": "validation_failed",
"message": "Some fields are invalid.",
"fields": { "items": "1 to 500 items." }
} }Branch on code, never on message, which can change. fields appears with validation_failed and names each bad field. Success bodies are always { "data": ... }.
A store or order that is not linked to your key answers 404 not_found, the same as one that does not exist, on purpose.
#All codes
| Status | Code | Meaning |
|---|---|---|
| 400 | bad_body | Body could not be read |
| 400 | invalid_code | Link code not valid |
| 401 | unauthorized | Signature missing or wrong |
| 401 | stale_timestamp | Timestamp too far off |
| 401 | replayed | Signature already used |
| 403 | ip_not_allowed | IP not on the allowlist |
| 403 | partner_suspended | Account suspended |
| 403 | sandbox_live_store | Sandbox key on a real store |
| 404 | not_found | Not found or not linked |
| 404 | no_route | No such endpoint |
| 409 | owner_takeover | Owner is using the Laayo app |
| 409 | store_linked_elsewhere | Linked to another POS |
| 409 | order_closed | Order is closed |
| 409 | accept_first | Accept the order first |
| 409 | rider_confirms_first | Rider confirms first |
| 409 | order_changed | Order changed meanwhile |
| 409 | needs_laayo_app | Needs the Laayo app |
| 409 | scheduled_not_active | Scheduled order not active yet |
| 409 | prep_time_unknown | Store prep time not in minutes |
| 409 | diff_closed | Menu upload no longer pending |
| 413 | body_too_large | Body too large |
| 415 | unsupported_media_type | Not JSON |
| 422 | validation_failed | Some fields are invalid |
| 429 | rate_limited | Slow down |
| 429 | too_many_codes | Too many wrong codes |
| 500 | server_error | Our side failed |
| 501 | not_implemented | Not available yet |
| 503 | api_paused | Partner API paused |
| 503 | unavailable | Try again shortly |
#Each code
400 bad_body
The body is not valid JSON, or the connection dropped while sending it.
Message: Could not read the request body.
What to do: Send valid JSON and the Content-Length of the bytes you send.
400 invalid_code
The 6 digit code is wrong, already used, or older than 15 minutes.
Message: This link code is wrong, used or expired. Ask the restaurant for a new one.
What to do: Ask the owner to tap Connect POS again for a new code.
401 unauthorized
A signing header is missing, the key ID is unknown, or the signature does not match. The console request log shows which one.
Message: Missing or invalid signature.
What to do: Sign timestamp + '.' + METHOD + '.' + path with query + '.' + raw body with your secret, lowercase hex.
401 stale_timestamp
X-Laayo-Timestamp is more than 5 minutes from our clock, or not unix seconds.
Message: X-Laayo-Timestamp must be unix seconds within 5 minutes of now.
What to do: Sync the machine clock and sign right before sending.
401 replayed
We already accepted a request with this exact signature. Two identical requests in the same second sign the same.
Message: This signature was already used. Identical requests in the same second are refused: retry after 1 s with a new timestamp.
What to do: Retry after 1 second with a new timestamp.
403 ip_not_allowed
The key has an IP allowlist and the call came from another address.
Message: Requests from this IP address are not allowed for this key.
What to do: Add the address in the console, under API keys.
403 partner_suspended
Laayo paused this partner account.
Message: This partner account is suspended. Contact Laayo.
What to do: Talk to the Laayo partner team.
403 sandbox_live_store
A sandbox key tried to link a store that is not a Laayo test store.
Message: Sandbox accounts can only link Laayo test stores.
What to do: Use Laayo Test Kitchen in the sandbox. Real stores come after go-live.
404 not_found
The store or order does not exist, or it is not linked to your key. Both answer the same, on purpose.
Message: Not found, or not linked to your account.
What to do: Check the ID. A store must be linked to you before you can see it.
404 no_route
The method and path match no endpoint.
Message: No such endpoint.
What to do: Check the path in the API reference, including the /v1 prefix.
409 owner_takeover
The owner switched to Laayo’s own controls, for up to 1 hour. Store, item and order writes from the POS are paused.
Message: The restaurant is managing this store in the Laayo app until <time>. Your changes are paused until then.
What to do: Show the owner a note in your POS and try again after the time in the message.
409 store_linked_elsewhere
The store already has an active link to another POS.
Message: This store is linked to another POS. The restaurant must unlink it first.
What to do: The owner unlinks the other POS in the Laayo vendor app, then reads you a new code.
409 order_closed
The order is delivered, cancelled or refunded.
Message: This order is <status>.
What to do: Nothing to do. Stop cooking if it was cancelled.
409 accept_first
For example ready before the order was accepted.
Message: This order can't move to <status> yet.
What to do: Call accept, then preparing or ready.
409 rider_confirms_first
In 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.
Message: A Laayo rider confirms this delivery order first. rider_assigned / rider_accepted only mean a rider took the offer; wait for order.updated type accepted (status confirmed), then go on with preparing and ready.
What to do: Wait for order.updated with type accepted (order status confirmed): the rider has confirmed and the order is accepted. Then call preparing and ready.
409 order_changed
Someone moved the order at the same moment as your call.
Message: The order changed meanwhile. Read it again and retry.
What to do: GET the order and retry if the move still makes sense.
409 needs_laayo_app
This 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.
Message: This order needs a step only the Laayo app can do. Ask the restaurant to update it in the Laayo app.
What to do: Read error.reason and the message. For store_notification_settings_missing, the restaurant moves one order in the Laayo vendor app (or asks Laayo support) and the API works for that store from then on. Otherwise ask the restaurant to move this order in the Laayo vendor app.
409 scheduled_not_active
A scheduled order cannot be accepted before its time window.
Message: This is a scheduled order that is not active yet.
What to do: Accept it when it becomes active (order.updated tells you).
409 prep_time_unknown
Busy needs the store’s normal prep time in minutes, and this store’s is set another way.
Message: This store's prep time is not in minutes.
What to do: Ask Laayo to fix the store’s delivery time, or use open and closed.
409 diff_closed
The menu upload was already reviewed or replaced by a newer one.
Message: This menu update is no longer pending.
What to do: Read GET /v1/stores/{id}/menu/sync for the latest state.
413 body_too_large
The body is over 512 KB.
Message: Request body is too large.
What to do: Split the call. Availability takes up to 500 items, menu upload up to 2000.
415 unsupported_media_type
A body was sent without Content-Type: application/json.
Message: Send Content-Type: application/json.
What to do: Set the header on every call with a body.
422 validation_failed
A field is missing, has the wrong type or is out of range, for example more than 500 items. fields names each one.
Message: Some fields are invalid.
What to do: Fix the fields listed in error.fields.
429 rate_limited
More than 600 requests in a minute on one key. The answer carries Retry-After in seconds.
Message: Too many requests. Slow down and retry after a minute.
What to do: Wait Retry-After seconds. Batch item changes into one call.
429 too_many_codes
More than 10 wrong link codes in an hour on one key. Retry-After says how long.
Message: Too many wrong link codes. Try again in an hour.
What to do: Wait Retry-After seconds, then use a fresh code from the owner.
500 server_error
Something broke at Laayo.
Message: Something went wrong. Try again.
What to do: Retry with backoff. Accept, preparing and ready are safe to repeat.
501 not_implemented
Rejecting orders from the POS is coming. In v1 this endpoint always answers 501.
Message: Rejecting from the POS is not available yet. The restaurant can deny the order in the Laayo app.
What to do: The restaurant denies the order in the Laayo vendor app.
503 api_paused
Laayo 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.
Message: The partner API is paused. Retry after the Retry-After seconds.
What to do: Keep the change in your POS and send it again after Retry-After seconds. Restaurants can use the Laayo vendor app meanwhile.
503 unavailable
A dependency at Laayo is briefly unavailable.
Message: This action is not available right now. Try again shortly.
What to do: Retry after a few seconds.
#What to retry
- Retry with backoff: 500, 503 and network errors. On 429 and on 503
api_paused, wait theRetry-Afterseconds the answer carries. Sign each retry fresh, at least a second later. - Accept, preparing and ready are forward only, so repeating them is safe. Availability answers unchanged for a repeat.
- Retry later: 409 owner_takeover, after the time in the message.
- Do not retry as is: 400, 401, 403, 404, 413, 415, 422 and the other 409 codes. Fix the cause first, and show staff a plain sentence, not the code.
The request log in the console shows the reason for every refused call, including the signature check. Start there. See also Signing requests.