Rate limits and quota
Two separate limits apply, and they fail differently.
The rate limit is per minute and protects the service from a burst. The quota is per calendar month, UTC, and is what you are paying for. Hitting the first means slow down; hitting the second means the month is spent.
| Plan | Rate | Monthly quota |
|---|---|---|
| Starter | 60 per minute | 10,000 |
| Team | 300 per minute | 100,000 |
| Enterprise | 1,000 per minute | 1,000,000 |
Headers
Every authenticated response carries the current state, so you never have to guess.
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Requests allowed this minute on this plan. |
X-RateLimit-Remaining | Requests left in the current minute. |
Retry-After | Seconds to wait. Present on both kinds of 429. |
X-Request-Id | Unique id for this request. Quote it in support. |
The two 429s
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
Retry-After: 60
{"error":{"code":"rate_limited","message":"Rate limit exceeded. Slow down and retry."}}HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
Retry-After: 1209600
{"error":{"code":"quota_exceeded","message":"Monthly quota exceeded."}}Read the code, not the status. rate_limited clears within the minute. quota_exceeded clears when the UTC month rolls over or when you change plan, and its Retry-After can be a fortnight, so a client that blindly sleeps on it will hang.
Backoff
Sleep for Retry-After seconds and retry once. If you are running many workers, add jitter so they do not all wake at the same instant.
A 503 unavailable is retryable with exponential backoff. A 400, 401, 403 or 404 is not: retrying an unchanged request produces the same answer.
Spending less
- Send
If-None-Matchwith the previousETag. A304costs a request but no payload, and the brief and story detail change rarely. - Poll the change feed rather than re-listing everything.
GET /api/v1/changes?since=…returns only what moved. - Raise
limitto 100 rather than paging in 40s.