Limits
Four kinds of limit apply to API traffic. They are checked in this order on every request, and each fails with its own status code:
| Order | Limit | Protects | Status when hit |
|---|---|---|---|
| 1 | Request rate | The service, from bursts | 429 |
| 2 | Request size | The service, from oversized payloads | 413 |
| 3 | Plan windows | Your plan’s token allowance | 402 quota_exhausted (unless credits take over) |
| 4 | Spend limits and credit balance | Your budget | 402 quota_exhausted |
Rate and size limits are the same on every plan. Plan windows and spend limits depend on your plan and on settings your administrators control.
Request rate
| Credential | Limit | Counted per |
|---|---|---|
API key (sk_live_… or sk_syntic_…) | 600 requests per minute | Key |
| Syntic Code sign-in token | 600 requests per minute | User |
The window slides: at any moment it counts the requests made in the previous 60 seconds, so there is no fixed point in the minute when the counter resets.
When you go over, the API answers 429 with this body and headers:
{ "error": "Rate limit exceeded", "scope": "api-proxy:apikey", "retry_after_seconds": 7 }| Header | Meaning |
|---|---|
Retry-After | Seconds to wait before the next attempt. |
X-RateLimit-Limit | The limit that applied (600). |
X-RateLimit-Remaining | Always 0 on a 429. |
X-RateLimit-Reset-Seconds | Seconds until the window has room again (same value as Retry-After). |
These headers appear only on this 429; successful responses carry none. Browser JavaScript cannot read the X-RateLimit-* headers.
If the shared rate counter is briefly unavailable, each server keeps its own count instead, so the limit stays in force but may be enforced slightly less evenly for a short time. Either way, treat every 429 as retryable.
Staying under the rate
For which errors to retry and a ready-made helper, see Rate limits & retries.
- Put outgoing requests through a queue with a fixed number of workers instead of firing them all at once.
- On
429, wait forRetry-Afterand then retry the same request; do not retry immediately. - Add a little random delay (jitter) to retries so many workers do not wake up together.
- One key per application is easier to monitor than spreading traffic across several keys; extra keys are not a way around the limit.
Request size
| Limit | Value | Error when exceeded |
|---|---|---|
| Request body | 2,000,000 bytes (about 2 MB) | 413 payload_too_large, with max_bytes |
| Messages per request | 500 | 413 too_many_messages, with max_messages |
| Context window | 262,144 tokens | 400 context_length_exceeded (see below) |
The body limit is checked against both the Content-Length header and the bytes actually received. The message count includes every entry in messages: system, user, assistant and tool messages.
A request within the byte limit can still exceed the context window, because tokens and bytes are not the same thing. When the prompt plus max_tokens will not fit, the request fails with 400 context_length_exceeded. As a rough guide, English text averages around four characters per token; source code and non-Latin scripts use more tokens per character.
The highest max_tokens each model accepts is listed in the catalog and returned as max_output_tokens by GET /v1/models. A larger value is lowered to that ceiling rather than refused.
Staying within size limits
- Trim old turns from long conversations, or replace them with a short summary.
- Shorten tool results before sending them back; return only the fields the model needs.
- Split very long documents and process them in parts; see Summarize long documents.
Plan windows
Your plan’s token allowance is enforced over three windows at once:
| Window | Size | When it reopens |
|---|---|---|
| Monthly | The plan’s full monthly allowance | Start of the next billing month |
| Weekly | 60% of the monthly allowance | Once a week, at a fixed time |
| Session | 25% of the monthly allowance | Rolling: five hours after usage in the window began |
A request is covered by the plan only while all three have room. When one is full, the request moves to usage credits if they are turned on; otherwise it gets 402 quota_exhausted with limit set to monthly, weekly or session and resets_at set to when that window reopens. If more than one window is full, the one that reopens last is reported.
Token figures per plan are on Pricing.
The check happens before a request runs, based on usage already recorded. If a window still has a little room when a request begins, that request may finish even if it takes the window over its size.
Spend limits and credit balance
When requests are paid from usage credits, three more checks apply:
| Check | Set by | limit value when hit | Reopens |
|---|---|---|---|
| Organization monthly spend limit | Administrator, in Billing | spend_limit | Start of next calendar month (UTC) |
| Member or group spend limit | Administrator, per member or group | spend_limit | Start of next calendar month (UTC) |
| Credit balance covers the request’s worst-case cost | Your top-ups and auto-reload | no_credits | When credits are added |
A member’s own spend limit counts only usage paid from credits, never usage covered by the plan. The message in the error says whether the organization’s or the member’s limit was reached.
See Billing & credits for how to change these, and Pricing for how the worst-case cost is estimated.
When usage cannot be checked
If the platform cannot read your usage, it refuses the request rather than serve it unmetered. You receive 402 quota_exhausted with limit: "unavailable" and no resets_at. This is temporary: retry with backoff.
Long-running requests
There is no separate time limit you can configure. For long replies, use streaming (the default) so that text arrives as it is produced, and set max_tokens to bound how long a reply can run.
Related pages
- Rate limits & retries: what to retry, backoff timing and a retry helper.
- Handle usage limits: code that reacts to each of these limits.
- Errors: the full list of error codes.
- Usage & cost: where to see current usage in the Console.