# Rate limits

> Requests per minute, requests in flight, credit and the limits that apply to images.

## Limits

| Limit                                            | Value                                                                                                                                                                                                                                                                      | When exceeded                                                                                                                                                                         |
| ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Requests per minute                              | 300 per key                                                                                                                                                                                                                                                                | `429 rate_limited` with `retry-after`. On Messages: `rate_limit_error`                                                                                                                |
| Requests in flight                               | 8 per key                                                                                                                                                                                                                                                                  | `429 too_many_concurrent_requests` with `retry-after: 1`. On Messages: `rate_limit_error`                                                                                             |
| Requests per minute before credit is first added | 20 per account, across all its keys                                                                                                                                                                                                                                        | `429 rate_limited` with `retry-after`. On Messages: `rate_limit_error`                                                                                                                |
| Credit                                           | The account's available credit must cover the request's hold                                                                                                                                                                                                               | `402 insufficient_credit` — or `402 free_credit_not_eligible` when the account has free credit left, no backed credit, and the request does not qualify. On Messages: `billing_error` |
| Key credit limit                                 | The limit you set on the key, less what its running requests hold                                                                                                                                                                                                          | `402 key_limit_reached`. On Messages: `billing_error`                                                                                                                                 |
| Request body                                     | 32 MB, or 64 MB on Images                                                                                                                                                                                                                                                  | `413 request_too_large`. On Messages: `request_too_large`                                                                                                                             |
| Time to answer                                   | 120 seconds for image generation including streams. A non-streamed text call ends at 5 minutes when response headers have not arrived or the body stalls, and otherwise at 15 minutes. A text stream has no deadline of its own, but the same 5-minute stalls still end it | Before response headers, `504` with OpenAI `error.code: upstream_timeout` or Messages `error.type: timeout_error`. After headers, the open stream stops                               |

Limits are counted per key, except the limit that applies until credit is first added, which is counted per account. The limits apply to every endpoint that reaches a model. The codes above are OpenAI `error.code` values; the Messages body carries `error.type` only, with no machine code.

A non-streamed timeout charges nothing yet and keeps its hold reserved. A streamed timeout before response headers returns `504` and costs zero. The OpenAI `error.code` is `upstream_timeout`. Messages uses `error.type: timeout_error`. After headers, a timeout interrupts the HTTP `200` stream. A reported cost is charged plus OpenRouter's 5% platform fee. Deference adds no markup. Token counts with a generation id are a provisional estimate. Anything else does not charge the hold.

## The 20 per minute limit

An account that has never had credit added is limited to 20 requests per minute in total, whichever key sends them, and the error message says so. Adding credit with USDC or INFERENCE, or claiming rewards as credit, lifts it; buying INFERENCE without activating it does not. The 300 per minute key limit remains. See [Free credit](https://deference.si/docs/concepts/free-credit).

## Retry

A `429` carries `retry-after`, a whole number of seconds. Wait that long, then retry. If you get `too_many_concurrent_requests`, this key already has 8 requests in flight: retry when one finishes, or keep fewer than 8 running.

```python
import random
import time

import requests


def post_with_retry(url, headers, body, attempts=5):
    for attempt in range(attempts):
        response = requests.post(url, headers=headers, json=body, timeout=120)
        retryable = response.status_code in (429, 502, 503, 504)
        if not retryable or attempt == attempts - 1:
            return response
        wait = float(response.headers.get("retry-after", 2**attempt))
        time.sleep(wait + random.random())
```

Do not retry `400`, `401`, `404` or `413`: the same request fails again. Do not retry a `402` while the account or key has no credit left — but a `402` returned while other requests are holding credit can succeed once one of them finishes and releases its hold. See [Errors](https://deference.si/docs/api-reference/errors).

## Stay under the limits

* Reuse connections and cap your own concurrency at 8 per key.
* Create a key for each tool or job, so one busy job does not use another's budget.
* Set `max_tokens` on Chat Completions, Messages and legacy Completions, or `max_output_tokens` on Responses. On Chat Completions and legacy Completions that are not using free credit, omitting the cap reserves the model's maximum output, or 8,192 tokens when that maximum is unknown, and never more than 32,768. That default is sent upstream as `max_tokens`. A cap you set above 32,768 is priced in full up to the model's maximum. On Messages and Responses, omitting the cap prices the model's full maximum output, which can exceed 32,768, and returns `400 output_cap_required` when the model publishes no maximum.

Credit that a running request holds is released when it ends. See [Pricing](https://deference.si/docs/concepts/pricing-and-metering).
