Indicia Code.

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.

Limitlimit valueHow it countsResets
Requests per minuterequests_per_minuteRequests in the last 60 seconds, slidingWhen the oldest request in the window is 60 seconds old
Tokens per daytokens_per_dayInput plus output tokens of the token's requests todayAt 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.

HeaderValue
x-ratelimit-limit-requestsRequests per minute
x-ratelimit-remaining-requestsRequests left in the current minute window, after this one
x-ratelimit-reset-requestsTime until the window is empty again, such as 42s
x-ratelimit-limit-tokensTokens per day
x-ratelimit-remaining-tokensTokens left today, before this request
x-ratelimit-reset-tokensTime 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.

headers.py
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:

429 response
{
  "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:

429 response on /v1/messages
{"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.

On this page