Rate limits
Per Core API key:
| Limit | Over it |
|---|---|
| 60 calls per minute | 429 with {"error": "rate_limited_minute", "retry_after": <seconds>} |
| 1 call per second | 429 with {"error": "rate_limited", "retry_after": 1} |
The wait is in the response body (retry_after, in seconds); there is no
Retry-After header. Wait at least that long before the next call.
Errors from the key check
| Status | Body | Meaning |
|---|---|---|
401 |
the standard unauthorized response, no error key |
No key was sent, or a Storefront key (upg_sf_...) was used: those never work here. |
401 |
{"error": "Malformed API key"} |
The key has no secret part (no dot). |
401 |
{"error": "Invalid API key"} |
Unknown key, wrong secret, or a key of another location. |
403 |
{"error": "API key disabled"} |
The restaurant switched the key off. |
429 |
see above | Too many calls. |
Errors from an endpoint itself are Laravel’s standard JSON: a 422 with
{"message": "...", "errors": {"field": ["..."]}} for invalid input, a 404
for an unknown id.
Behaving well
Your client runs unattended, often on a schedule. A few rules keep it (and the restaurant’s till, which uses the same API) healthy:
- Never retry a 4xx in a tight loop. A 401, 403, 404 or 422 will answer the same on the next try. Log it, alert a human, and stop.
- Back off on 429 for
retry_afterseconds, and spread your calls: one call per second is the hard ceiling. - Sync incrementally. Use the cursors the endpoints offer
(
synced_untilon sales,updated_afteron customers and products) instead of downloading everything again. - Prefer webhooks for new sales. A
pos.salewebhook pushes every new receipt the moment the till syncs it, so you only poll to catch up. - Ignore fields you do not know. Responses gain new keys over time; existing keys are never renamed or removed.
Ids and times
- Ids in responses are short hash ids (
x94d3), not database numbers. Use them as opaque strings. created_atandupdated_atstyle fields are Unix timestamps in seconds, unless the endpoint says otherwise. Ticket dates are date-time strings as the till recorded them.