# 速率限制

URL: https://docs.router.ezat.io/zh/reference/rate-limits

> 每个 key 的每分钟请求数限制、每个 key 的消费上限、组织余额、容量限制、会返回的响应头，以及如何退避和重试。

## 何时阅读本页

你收到了 429、402、529 或 503，或者正在编写一个需要妥善重试的客户端。所有错误类型见[错误](https://docs.router.ezat.io/zh/reference/errors.md)。

## 各项限制

| 限制 | 作用对象 | 默认值 | 达到限制时 |
| --- | --- | --- | --- |
| 每分钟请求数 | 每个 API key | 1,000 | 429 `rate_limit_error`，`retry-after: 30` |
| 消费上限 | 每个 API key（如果设置了） | 无 | 402 `billing_error` |
| 余额 | 组织 | | 余额为零或负数时返回 402 `billing_error` |
| 容量 | 每个模型 | | 529 `overloaded_error`（兼容 OpenAI 的 API 上为 503），`retry-after: 5`；或 429 `rate_limit_error`，`retry-after: 10` |

在兼容 OpenAI 的 API 上，同样的限制以 OpenAI 格式返回：429 `rate_limit_exceeded`、402 `insufficient_quota` 和 503 `overloaded`。

## 每分钟请求数

- 每个 key 每分钟可以发送 1,000 个请求，除非 EZAT Router 为它设置了其他限制。各个 key 不共享这个限制。
- `POST /v1/messages`、`POST /v1/messages/count_tokens` 和 `POST /openai/v1/chat/completions` 计入限制，模型列表不计入。
- 计数在每分钟开始时重置。被拒绝的请求也会计入，所以在紧密循环中重试会让 key 一直超限，直到这一分钟结束。
- 超出限制时，网关返回 429，带 `retry-after: 30` 和消息“This API key exceeded its requests-per-minute limit”。这个请求不计费。

控制台无法修改 key 的这项限制。如需调整，请发邮件至 support@ezat.io，附上 key 的名称，以及控制台中显示的 key 开头部分（`ezat_sk_…`）。

## 消费上限

消费上限限制一个 key 在一个周期内能花多少钱。在创建 key 时设置：**API Key** → **创建 key** → **消费上限**，填写 **金额（美元）** 并选择 **周期**。

| 周期 | 重置时间 |
| --- | --- |
| 天 | 每天 00:00 UTC |
| 月 | 每月 1 日 00:00 UTC |
| 总计 | 从不重置：涵盖这个 key 的全部消费 |

- 网关在每个请求之前检查上限。key 在当前周期内的消费一旦达到上限，请求就会收到 402，消息类似“This API key reached its monthly spend limit of …”。
- 在上限以内开始的请求会执行完，所以消费可能略微超过上限。
- key 创建后，无法在控制台修改它的上限。请用想要的上限创建一个新 key，把应用切换过去，然后吊销旧 key。

key 的其他设置见 [API key](https://docs.router.ezat.io/zh/api-keys.md)。

## 组织余额

组织内的所有 key 共用一个预付余额。余额为零或负数时，所有 key 都会收到 402，直到有人充值。见[计费方式](https://docs.router.ezat.io/zh/billing.md)。

## 容量

每个模型由一个或多个提供方部署提供服务。网关为每个请求选择一个部署；如果它在响应开始前失败，网关最多再尝试另外两个。

- 没有任何部署能接下请求时，网关返回 529 `overloaded_error`，带 `retry-after: 5`（兼容 OpenAI 的 API 上为 503 `overloaded`）。
- 提供方在限流时，网关返回 429“Rate limited upstream. Please retry shortly.”，带 `retry-after: 10`。
- 两者都不计费。等待 `retry-after` 之后重试。

完全没有容量的模型在 `GET https://api.router.ezat.io/api/models` 中显示为 `"available": false`。见[模型](https://docs.router.ezat.io/zh/models.md)。

## 响应头

| 响应头 | 出现在 | 值 |
| --- | --- | --- |
| `retry-after` | 429、529 和 503 | 重试前需要等待的秒数 |
| `request-id` | 到达模型的请求 | 这个请求在用量中的 id |
| `x-request-id` | 每个响应 | 本次 HTTP 调用的 id |

没有表示剩余配额的响应头（没有 `x-ratelimit-*` 或 `anthropic-ratelimit-*`）。

## 重试

官方 Anthropic 和 OpenAI SDK（Python 和 Node.js）已经会对连接错误、408、409、429 和所有 5xx（包括 529 和 503）进行重试，默认两次，采用指数退避，并在有 `retry-after` 响应头时等待它给出的时间。可以在客户端或单个请求上用 `max_retries`（Python）或 `maxRetries`（Node.js）修改。

如果你自己编写客户端：

1. 只重试 429、500、529、503 和连接错误。不要重试 400、401、402、403、404 或 413。
2. 有 `retry-after` 响应头时，等待它给出的秒数。
3. 否则每次等待的时间按指数增长，并加入随机抖动：例如 0.5 秒、1 秒、2 秒、4 秒，最多约 8 秒，每次再乘以 0.75 到 1 之间的随机系数。
4. 尝试几次后停止，报告错误并附上 `request-id` 和 `x-request-id`。
5. 重试时按原样发送请求；如果使用了 `x-ezat-session` 请求头（或兼容 OpenAI 的 API 上的 `prompt_cache_key`），保持相同的值。网关会让同一个对话留在持有其提示缓存的提供方上，所以原样重试可以保住缓存，费用更低。

不要原样重试 504 `timeout_error`：它表示一个非流式请求运行了 590 秒，而 SDK 会把它完整地再发送一次。长请求请改用 `"stream": true`。

```python title="Backoff without an SDK"
import random
import time


def with_retries(send, attempts=5):
    """send() returns (status, headers, body). Retries 429, 500, 503 and 529."""
    for attempt in range(attempts):
        status, headers, body = send()
        if status not in (429, 500, 503, 529) or attempt == attempts - 1:
            return status, headers, body
        retry_after = headers.get("retry-after")
        if retry_after:
            delay = float(retry_after)
        else:
            delay = min(0.5 * 2**attempt, 8) * random.uniform(0.75, 1.0)
        time.sleep(delay)
```

## 给 AI agent 的说明

1. 每个 key 的限制：默认每分钟 1,000 个请求；超出时返回 429，带 `retry-after: 30`。
2. 收到 429、529 或 503 时，等待 `retry-after` 秒，然后用指数退避加抖动重试。官方 SDK 已经这样做了（默认重试 2 次；批处理任务可以调高 `max_retries` / `maxRetries`）。
3. 收到 402 时停止：余额已用完，或 key 已达到消费上限。告诉用户在 https://router.ezat.io/zh/billing 充值，或创建一个上限更高的 key。
4. 没有表示剩余配额的响应头。如果需要保持在每分钟限制以内，请自行控制请求速度。
5. 重试时保持相同的 `x-ezat-session` 值（或 `prompt_cache_key`），让提示缓存继续生效。
6. 长请求使用 `"stream": true`：非流式请求在 590 秒后以 504 结束。