Rate limits
Each workspace has a number of requests and changes it can make a minute, shared by all its tokens, with a short per-token limit on top. The Sandbox's limits are lower than Production's.
The limits#
| Limit | Sandbox | Production |
|---|---|---|
| Requests a minute, per workspace | 30 | 300 |
| Requests a day, per workspace | 1,000 | No daily limit |
| Changes a minute, per workspace | 10 | 60 |
| Requests per token | 10 every 10 seconds | 10 every 10 seconds |
- Per workspace means all of the workspace's tokens share one allowance. Two integrations on the same workspace draw from the same minute.
- Changes are requests that create, update or delete something: every
POST,PATCHandDELETE. They count towards the requests limits too. - Per token is a short burst limit, so one busy token can't use a whole workspace's minute in a few seconds.
- A location import counts as one change, however many features it has (up to 1,000). Importing in batches is much cheaper than creating locations one by one.
Rate limit headers#
Responses carry two headers:
| Header | What it tells you |
|---|---|
X-RateLimit-Limit | The size of the limit that's closest to running out. |
X-RateLimit-Remaining | How many requests are left in that limit. |
Several limits apply to each request, so the headers describe whichever one has the fewest requests left. On a quiet Production workspace that's usually the per-token limit of 10.
When you hit a limit#
A request over a limit gets 429 Too Many Requests with the code rate_limited, and does nothing:
{
"error": {
"code": "rate_limited",
"message": "Too many requests. Slow down and try again shortly."
}
}When a request is over the changes limit, the message is "Too many changes. Slow down and try again shortly."
The response carries a Retry-After header: wait that many seconds before you retry. It also has X-RateLimit-Reset, the Unix time when you can retry, and X-RateLimit-Remaining is 0. The per-token limit frees up within 10 seconds and the per-minute limits within a minute. The Sandbox's daily limit resets 24 hours after the first request that counted towards it.
Failed authentication#
Requests with an unknown token are limited separately, by IP address: after 30 within a minute, that address gets 429 with the code too_many_failed_attempts and a Retry-After header. Check that your token is right before retrying.
Staying under the limits#
- Poll for changes, not everything. Pass
updated_sinceso each poll only returns what changed. See Pagination and syncing. - Use the biggest page you need.
limitgoes up to 100, so fewer requests fetch the same list. - Import in batches. Send up to 1,000 locations in one import rather than one request each.
- Spread scheduled jobs out so several integrations on the same workspace don't all run at the top of the minute.
- Retry with backoff, and give up after a few tries, rather than retrying in a tight loop, which uses up the limit that's blocking you.