Rate limits
Limits exist to catch misbehaving integrations, not to cap your volume. A single integrator may serve thousands of restaurants; if your legitimate traffic approaches a ceiling, tell us and we will raise it for your account.
Limits
| Endpoint | Sustained | Burst | Scope |
|---|---|---|---|
POST /orders | 600 / min | 120 / 10 s | account |
GET /orders/{id} | 1 / 10 s | 3 000 / min | per order and account |
POST /orders/{id}/cancel | 600 / min | — | account |
PUT /stores/{id} | 60 / min | 200 / 10 s | account |
POST /token | 60 / hour | — | account |
Two of these deserve a note.
GET /orders/{id} is limited per order. Account quota does not help you poll one delivery in a loop. Status is meant to arrive by webhook.
POST /token is 60 per hour while a token lives for one hour. If you approach this limit, you are requesting a token per request instead of caching it — see Authentication.
Response headers
Every response carries the state of the bucket it consumed:
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 588
X-RateLimit-Reset: 1785312000X-RateLimit-Reset is a Unix timestamp.
When you exceed a limit
HTTP/1.1 429 Too Many Requests
Retry-After: 7{
"success": false,
"message": "Rate limit exceeded.",
"data": { "errorCode": "RATE_LIMITED", "retryAfterSeconds": 7 }
}Wait Retry-After seconds. Do not retry immediately, and do not retry in a tight loop — sustained overage is one of the conditions that leads to suspension.
Sandbox
Sandbox uses a separate bucket with the same values. Your testing never eats production quota, and you learn the real behaviour before you go live. Seeing 429 in sandbox is much better than seeing it for the first time on a Friday night.
Getting a higher limit
Ask, with numbers: how many restaurants, expected orders per hour, peak windows. Limits are configured per account and changing them does not require a release on our side.