Rate limits
Limits are enforced per organization (optionally tighter per key), and every response tells you where you stand. This page also lists the OpenAI request fields the gateway accepts but deliberately ignores.
The four limits
| Limit | Window | When exceeded |
|---|---|---|
| Requests per minute (rpm) | Sliding 60s | 429 rpm_exceeded with retry-after = seconds left in the window |
| Tokens per minute (tpm) | Sliding 60s, checked against an estimate of prompt + expected output | 429 tpm_exceeded with retry-after |
| Concurrent requests | In-flight at any instant | 429 rpm_exceeded with a distinct message ("Concurrency limit: ...") and retry-after: 1 |
| Daily budget (USD) | Calendar day, resets at 00:00 UTC | 429 daily_budget_exceeded — retrying is useless until reset |
Your organization's numbers are visible in the dashboard; per-key rpm/tpm and daily budget can be set lower than the organization's (see Authentication). A rejected request does not consume quota — a 429 never digs you deeper.
Reading your position from headers
Every response carries the rpm window state of your organization:
x-ratelimit-limit: 60 x-ratelimit-remaining: 57 x-ratelimit-reset: 1774694460
x-ratelimit-limit— your rpm.x-ratelimit-remaining— requests left in the current window.x-ratelimit-reset— epoch seconds of the next minute window's start.retry-after— attached to every 429 and 503: seconds to wait before the next attempt has a chance.
Which 429s are worth retrying
rpm_exceeded and tpm_exceeded mean "wait for the window": retrying after retry-after succeeds, and the OpenAI SDKs do it automatically. daily_budget_exceeded means "waiting within the day is useless": the budget stays spent until 00:00 UTC. Branch on error.code and stop retrying — raise the budget in the dashboard if the cap is the problem, details in Idempotency — SDK auto-retries.
Separate from your limits: 503 no_capacity means service capacity is momentarily exhausted. It carries retry-after: 10 and the failed request is not billed.
Output length caps
- Omit
max_tokensand the gateway applies a default of 4096 output tokens — a spending cap, not a suggestion to the model. - Requests above your organization's output cap (default 16384) are rejected with
400 max_tokens_exceeds_cap; the message states the current cap. - If both
max_tokensandmax_completion_tokensare sent,max_completion_tokenswins (newer OpenAI semantics).
Accepted, ignored
These OpenAI request fields are valid schema that SDKs and frameworks attach on their own. The gateway accepts them and deliberately ignores them — they are stripped before the request is forwarded, with no error, because rejecting them would break "change the base URL and it runs":
logit_bias · logprobs · top_logprobs · store · service_tier · modalities · audio · prediction · web_search_options · stream_options.* (except include_usage)
Two gateway extension fields are reserved: transforms (accepted, not yet active) and models (fallback list — reserved, no-op for now). Sending them today is safe and does nothing.
Unknown fields are rejected on purpose
Any other top-level field returns 400 unknown_parameter with the field name in param. Silently swallowing a typo like max_token would make the mistake invisible — failing fast is cheaper than a support ticket. Legacy completions-API fields (functions, function_call, prompt, input) get a 400 with a hint for the modern equivalent.