Rate Limits & Quotas
RPM windows, token quotas, the response headers, and how 429s behave.
What is limited
| Limit | Scope | Window | Exceeded returns |
|---|---|---|---|
| Requests per minute (RPM) | Per API key | Rolling ~60 s | 429 rate_limit_exceeded |
| Project RPM | Per project | Rolling window | 429 project_rate_limit_exceeded |
| Token quota (daily/monthly) | Per key | Calendar window | 429 quota_exceeded |
| Project token quota | Per project | Calendar window | 429 project_quota_exceeded |
| Project monthly cost ceiling | Per project | Monthly | 402 project_quota_exceeded |
| Per-key USD spend cap | Per key | Rolling | 402 key_spend_cap_reached |
RPM is enforced with a two-bucket weighted sliding window — it bounds you to
approximately limit requests per any rolling 60 seconds, rather than a
cliff-edge minute boundary.
Response headers
Rate-limit headers are sent on both 200 and 429 responses:
| Header | Meaning |
|---|---|
x-ratelimit-limit-requests | RPM limit for the key |
x-ratelimit-remaining-requests | Requests remaining in the current rolling minute |
x-ratelimit-reset-requests | Seconds until the request window resets (integer seconds) |
x-ratelimit-limit-tokens | Token quota window limit, when configured |
x-ratelimit-remaining-tokens | Tokens remaining in the quota window |
x-ratelimit-reset-tokens | Seconds until the token window resets |
Retry-After | 429 only — seconds to wait (see below) |
Retry-After semantics
| Source | Value |
|---|---|
Gateway 429 (rate_limit_exceeded, quota_exceeded, …) | Seconds until the tracked window resets |
Provider 429 (provider_rate_limited) | The provider's own Retry-After, forwarded when present |
| 402 | Not sent — a funds denial is not congestion (why) |
OpenAI SDKs honour Retry-After automatically; if you roll your own retry
logic, always wait for it before retrying.
Example 429
{
"error": {
"type": "rate_limit_error",
"message": "Rate limit exceeded",
"code": "rate_limit_exceeded",
"param": null,
"request_id": "req_01J8EXAMPLE"
}
}HTTP/1.1 429 Too Many Requests
Retry-After: 17
x-ratelimit-limit-requests: 600
x-ratelimit-remaining-requests: 0
x-ratelimit-reset-requests: 17Handling provider 429s
A provider-side 429 is preserved as 429 provider_rate_limited with the
provider's verbatim message, e.g.:
{
"error": {
"type": "rate_limit_error",
"message": "Rate limit reached for gpt-4o in organization org-x on tokens per min (TPM): Limit 30000, Used 29000, Requested 2000.",
"code": "provider_rate_limited",
"param": null,
"request_id": "req_01J8TESTERR02"
}
}Treat it exactly like a gateway 429: honour Retry-After and back off.