Documentation / Guides
Rate limits and quotas
Per minute, per month, and the headers that tell you.
Two limits, both per key, both visible on every response. Neither is a surprise if you read the headers.
The limits
| Plan | Per minute | Per month |
|---|---|---|
| Free key | 60 | 15,000 |
| Live | 180 | 250,000 |
| Archive | 90 | 150,000 |
| Complete | 180 | 400,000 |
| Analyst | 240 | 1,000,000 |
Archive's rate is lower than Live's on purpose. It is research at research pace: nine years of history and no live window, priced for somebody walking the archive rather than serving a page.
The headers
X-RateLimit-Limit: 180
X-RateLimit-Remaining: 174
X-RateLimit-Reset: 1757423460
Retry-After: 12 # only on a 429
Read X-RateLimit-Remaining on successful responses and slow down before
you hit zero, rather than sprinting into a 429 and reacting. It is on every response and
costs nothing to check.
The two 429s are different
| Code | Means | Do |
|---|---|---|
rate_limited | Too fast this minute. | Sleep for Retry-After and continue. Genuinely transient. |
quota_exceeded | Monthly allowance gone. | Stop. It resets on the first. Retrying achieves nothing. |
Branch on the code rather than the status. A client that retries both on a backoff spends the rest of the month asking a question it already has the answer to.
Pacing, rather than backing off
A fixed gap between requests is simpler and better behaved than a retry loop.
$perMinute = 180;
$gap = (int) (60_000_000 / $perMinute * 1.1); // 10% headroom
foreach ($dates as $date) {
fetchDay($date);
usleep($gap);
}
Ten percent of headroom costs you almost nothing and means clock drift between your server and ours never trips the limit.
Watching the month
GET /v1/account/usage returns requests, errors and every refusal, by day or by
endpoint, and does not count against your own quota. Call it daily and warn
yourself at whatever threshold you are comfortable with.
by=endpoint is also the fastest way to find a wasteful loop. A single endpoint
dominating a month is usually a poller that should be a webhook.
Things that do not cost you a request
- Webhook deliveries. Zero, always. Polling is the largest source of wasted requests we see and charging for the alternative would be perverse.
- Caching. A settled race never changes. Re-fetching one is a request you chose to spend.
- 4xx responses. They count toward the rate but we would rather you fixed the cause than tuned around it.
If a limit is genuinely wrong for you
Tell us what you are building. A rate that blocks a legitimate use is a badly chosen number rather than a policy, and it is easier to change than you might expect.