Browse documentation
Rate limits and quotas
429 and 402 mean opposite things, and one 429 means two different things.
Two independent limits
A per-minute rate limit, set by your plan, applied per key. Exceed it and you get
429. Wait a second and retry; the window is one minute.
A monthly request quota, also set by your plan. What happens when you reach it depends on the plan:
- On Free, the key hard-caps: further requests get
429until the period rolls over. There is no card on file, so free means free. - On paid plans, requests continue past the quota. The pricing page promises that rather than failing closed — an agent in production should not stop working because a counter rolled over.
The headers
Every authenticated response carries these, on success and on 429 alike:
x-ratelimit-limit: 600
x-ratelimit-remaining: 587
On a rate-limit 429, one more:
retry-after: 1
There is no x-ratelimit-reset. The window is one minute, so retry-after: 1 is the
whole story — do not look for a reset timestamp that does not exist.
Telling the two 429s apart
This is the part worth reading carefully. Both a rate-limit refusal and a hard-capped
quota return 429, and they call for opposite responses:
| Rate limit | Quota hard cap | |
|---|---|---|
| Body | rate limit exceeded | monthly quota exceeded and this key stops at its quota rather than billing overage |
retry-after | 1 | absent |
| Retry? | Yes, in about a second | No. It will not change until the period rolls over. |
So: retry a 429 only when retry-after is present. A retry loop that ignores the
body and hammers a hard-capped key produces thousands of identical failures and never
succeeds.
And 402 is different again
402 means the account is suspended — a subscription was cancelled, or a payment
failed. Retrying changes nothing; somebody has to settle billing in the
console.
Summary:
| Status | Meaning | Retry? |
|---|---|---|
429 with retry-after | Too fast | Yes, ~1s |
429 without retry-after | Out of monthly quota, hard-capped | No |
402 | Account suspended | No |
401 | Bad key — or a key too new to have propagated | Once, after a minute |
Rate limits are per replica
Published rates are enforced per serving replica. A fleet of N replicas therefore tolerates more than the published number in aggregate, and the limit you observe can be higher than the one you are quoted.
Do not build on that. It moves with the fleet size, and the published figure is the one the plan promises. Treat any headroom as luck.
Over MCP
Identical. The same key, the same limits, the same headers on the HTTP response.
One difference in how a refusal reaches you: over MCP, a suspended account or an
exhausted quota arrives as a tool error inside the JSON-RPC frame, not as a 402 or
429 status. That is deliberate — a client reads a transport error on an established
session as the server having gone away and tears the session down, which turns a billing
problem into an apparent outage.
Rate limiting still answers 429 at the transport, because that is what a client’s own
backoff logic understands.
Connecting is free: initialize, notifications/initialized, tools/list and ping are
not billed. Only a tool that runs counts, and it counts as one request — the same as the
equivalent REST call.
Staying inside them
- Read
x-ratelimit-remainingand pace yourself, rather than discovering the limit. - Use
limit=0withfacets=trueto size a topic in one request instead of five exploratory searches. - Use
collapse=storyso you are not spending requests — and context — on the same article repeatedly. assemble_contextis one billed call in place of a retrieval loop that would be several.