Rate limits
Per-token limits, rate-limit headers and pool limits.
Token limits
Service tokens have two limits, set per token by an admin. Personal tokens have none.
| Limit | limit value | How it counts | Resets |
|---|---|---|---|
| Requests per minute | requests_per_minute | Requests in the last 60 seconds, sliding | When the oldest request in the window is 60 seconds old |
| Tokens per day | tokens_per_day | Input plus output tokens of the token's requests today | At midnight Europe/Amsterdam |
The gateway checks both before a request reaches a provider. A refused
request does not take a slot in the minute window. The request that crosses
the daily budget still completes; the next one is refused. count_tokens
requests count toward requests per minute only. Every request that passes
authentication takes a slot, including one the gateway then answers with
400.
Rate-limit headers
Responses to a service token carry the state of its limits, in the headers
OpenAI uses. They are on every response from /v1/chat/completions,
/v1/responses, /v1/messages and /v1/messages/count_tokens, including
errors and 429s, and are sent before a stream starts.
| Header | Value |
|---|---|
x-ratelimit-limit-requests | Requests per minute |
x-ratelimit-remaining-requests | Requests left in the current minute window, after this one |
x-ratelimit-reset-requests | Time until the window is empty again, such as 42s |
x-ratelimit-limit-tokens | Tokens per day |
x-ratelimit-remaining-tokens | Tokens left today, before this request |
x-ratelimit-reset-tokens | Time until midnight Europe/Amsterdam, such as 7h49m35s |
A token without a requests-per-minute limit sends no -requests headers, and
a token without a daily budget sends no -tokens headers. Personal tokens
send none.
remaining-tokens lags one request
remaining-tokens cannot include the current request, because its size is
known only when it finishes. To know when to retry after a 429, use
retry-after. To read the same numbers without sending a request to a
model, call GET /v1/usage.
raw = openai.chat.completions.with_raw_response.create(
model="indicia/snel",
messages=[{"role": "user", "content": "Say hello"}],
)
print(raw.headers.get("x-ratelimit-remaining-tokens"))429 responses
Over a limit, the gateway answers 429 with a retry-after header in
seconds:
{
"error": {
"code": "rate_limit_exceeded",
"message": "This token has used its tokens for today; retry after 2026-10-13T22:00:00.000Z.",
"limit": "tokens_per_day",
"retryAt": "2026-10-13T22:00:00.000Z"
}
}On /v1/messages the same error has the Anthropic shape:
{"type": "error", "error": {"type": "rate_limit_error", "message": "This token has used its tokens for today; retry after 2026-10-13T22:00:00.000Z."}}Pool limits
The pools are shared subscription accounts with their own provider limits.
When every account that could serve a request is rate limited, the answer is
429 pool_exhausted, with retryAt and retry-after set to the earliest
known reset when there is one. This applies to every token, personal or
service.
Batch jobs
The OpenAI and Anthropic SDKs retry 429 responses twice by default and
honour retry-after. For long batch jobs, wait until retryAt instead of
retrying in a loop.