Rate limits
The API is rate limited to keep it fast and fair for everyone. Limits are applied using a leaky bucket algorithm and are aggregated per restaurant (across all of that restaurant’s API keys).
The limits
Section titled “The limits”| Limit | Value |
|---|---|
| Sustained rate | ~2 requests per second |
| Burst | up to 60 requests |
| Daily cap | ~25,000 requests per day |
The leaky bucket lets you briefly burst up to 60 requests, then drains at the sustained rate — so steady traffic around 2 req/s flows smoothly, while spikes are smoothed out rather than hard-blocked at the first extra request.
Rate limit headers
Section titled “Rate limit headers”Successful responses carry the current limit state so you can pace yourself:
RateLimit-Limit: 60RateLimit-Remaining: 42RateLimit-Reset: 9| Header | Meaning |
|---|---|
RateLimit-Limit | The bucket capacity (burst size). |
RateLimit-Remaining | Requests you can still make right now. |
RateLimit-Reset | Seconds until capacity is fully replenished. |
When you are throttled
Section titled “When you are throttled”Exceeding the limit returns 429 Too Many Requests with a Retry-After
header (seconds to wait) and a rate_limit_error envelope:
HTTP/1.1 429 Too Many RequestsRetry-After: 1RateLimit-Limit: 60RateLimit-Remaining: 0RateLimit-Reset: 1{ "error": { "type": "rate_limit_error", "code": "rate_limited", "message": "Too many requests. Retry after 1 second.", "doc_url": "https://docs.useservice.app/api/errors#rate_limited" }}Staying within the limits
Section titled “Staying within the limits”- Honour
Retry-After. On a429, wait the indicated number of seconds before retrying. - Back off exponentially on repeated
429s, with a little jitter. - Watch
RateLimit-Remainingand slow down before you hit zero. - Sync incrementally. Use
updated_sinceinstead of repeatedly re-reading full collections, and prefer webhooks over tight polling loops.