# 认证

URL: https://docs.router.ezat.io/zh/authentication

> 在 x-api-key 或 Authorization Bearer 中发送 ezat_sk_ key，妥善保管 key，并解决 401 和 403 错误。

## 何时阅读本页

本页介绍如何发送 API key、key 是什么格式、如何保管 key，以及 `401` 或 `403` 是什么意思。

## 在请求头中发送 key

两种 API 的每个端点都可以从以下任一请求头中读取 key：

| 请求头 | 示例 | 发送方 |
| --- | --- | --- |
| `x-api-key` | `x-api-key: ezat_sk_…` | Anthropic SDK，以及使用 `ANTHROPIC_API_KEY` 的 Claude Code |
| `Authorization` | `Authorization: Bearer ezat_sk_…` | OpenAI SDK，以及使用 `ANTHROPIC_AUTH_TOKEN` 的 Claude Code |

两者在 `https://api.router.ezat.io/v1/…`（Anthropic 格式）和 `https://api.router.ezat.io/openai/v1/…`（OpenAI 格式）上都有效，你的工具发送哪个都可以。

```bash tab="x-api-key" test
curl --fail-with-body -sS https://api.router.ezat.io/v1/models \
  -H "x-api-key: $EZAT_API_KEY"
```

```bash tab="Authorization: Bearer" test
curl --fail-with-body -sS https://api.router.ezat.io/v1/models \
  -H "Authorization: Bearer $EZAT_API_KEY"
```

```bash tab="OpenAI format" test
curl --fail-with-body -sS https://api.router.ezat.io/openai/v1/models \
  -H "Authorization: Bearer $EZAT_API_KEY"
```

细节：

- 如果请求同时带有这两个请求头，会使用 `x-api-key`，忽略 `Authorization`。因此，残留在一个变量里的旧 key 可能会盖过另一个变量里的正确 key（见[故障排查](https://docs.router.ezat.io/zh/troubleshooting.md)）。
- key 前后的空格会被忽略。`Bearer` 不区分大小写。
- 不要把 key 放在 URL 或查询字符串里。key 只从这两个请求头中读取。

## Key 的格式

key 由 `ezat_sk_` 加上 40 个字母和数字组成，共 48 个字符。控制台只显示 key 的开头和结尾，例如 `ezat_sk_a1b2…wxyz`，方便你区分不同的 key。

EZAT Router 只保存每个 key 的哈希值，所以完整的 key 只在创建时显示一次。丢失的 key 无法再次显示：请创建一个新的（[API key](https://docs.router.ezat.io/zh/api-keys.md)）。

## Key 属于组织

每个 key 属于一个组织。用它发出的请求从该组织的余额中扣费，并显示在该组织的用量中，无论是谁发出的。创建 key 的人离开组织后，key 仍然有效，直到有人吊销它。见[组织和成员](https://docs.router.ezat.io/zh/organizations.md)。

登录控制台（邮箱验证码、GitHub 或 Google）是另一回事：API key 只能用于 API，你的控制台登录也永远不能当作 API key 使用。

## 保管好你的 key

- **从环境变量读取 key**，或者从你的密钥管理工具读取，不要在代码里写成字符串。本文档使用 `EZAT_API_KEY`。
- **只在服务器端使用**。不要把 key 放进前端、浏览器或移动应用的代码里：任何打开应用的人都能读到它，并花掉你的余额。请改为从你的后端调用 EZAT Router。
- **不要提交到 git**。本地的密钥放在被 `.gitignore` 排除的 `.env` 文件里，CI 中使用 CI 自带的密钥存储。不要把 key 写进会提交的工具配置，例如项目的 `.claude/settings.json`。
- **不要在聊天、工单、日志或截图中分享 key**。支持团队从不需要你的 key；请改为提供 `request-id`。
- **每个应用、机器或人各用一个 key**，这样吊销其中一个不会影响其他的，还能在**用量**中看到每个 key 的花费。[消费上限](https://docs.router.ezat.io/zh/api-keys.md)可以限制泄露的 key 最多能花掉多少。
- **通过替换来轮换**。先创建新 key 并部署，确认请求成功后，再吊销旧 key。吊销立即生效。
- **key 一旦泄露，立即吊销**：在 **API Key** 页面吊销它，然后创建一个新的。

## 认证错误

错误使用各个 API 自己的格式。Anthropic 格式如下：

```json title="401 response"
{
  "type": "error",
  "error": { "type": "authentication_error", "message": "Invalid API key" },
  "request_id": "…"
}
```

| 状态码 | 消息 | 含义 | 解决方法 |
| --- | --- | --- | --- |
| `401` | `Missing API key. Send it in the x-api-key or Authorization: Bearer header.` | 没有收到 key：请求头缺失或拼写错误，或者发出请求的进程中环境变量为空 | 设置请求头；检查工具运行的环境中是否设置了该变量 |
| `401` | `Invalid API key` | 这个值不是有效的 EZAT Router key：输错了、复制不完整、key 中间有引号或换行，或者是其他服务商的 key | 重新复制 key，或者创建一个新的 |
| `401` | `This API key has been revoked` | 有人吊销了这个 key | 创建新 key |
| `401` | `This API key has expired` | key 已超过创建时设置的有效期 | 创建新 key |
| `403` | `This organization is suspended. Contact support@ezat.io.` | 该组织的所有 key 都会被拒绝 | 发邮件到 support@ezat.io |
| `403` | `This API key is not allowed to use …` | 这个 key 只能使用其他模型 | 使用允许的模型，或者使用没有模型限制的 key（[API key](https://docs.router.ezat.io/zh/api-keys.md)） |

在 OpenAI 格式中，同样的错误返回相同的状态码。`401` 带有 `"type": "invalid_request_error"` 和 `"code": "invalid_api_key"`，`403` 带有 `"type": "permission_error"`。这些错误重试都没有用。其他所有错误见[错误](https://docs.router.ezat.io/zh/reference/errors.md)。

## 给 AI agent 的说明

1. 从用户指定的环境变量（按惯例是 `EZAT_API_KEY`）读取 key。不要让用户把 key 粘贴到对话里，也不要打印、记录或提交它。
2. 要在不打印 key 的情况下检查它，比较它的长度（48）和前 8 个字符（`ezat_sk_`），然后调用 `GET https://api.router.ezat.io/v1/models`，看是否返回 `200`。
3. 以 `x-api-key` 或 `Authorization: Bearer` 发送 key；两者在 `https://api.router.ezat.io/v1/…` 和 `https://api.router.ezat.io/openai/v1/…` 上都有效。如果两个都设置了，它们必须是同一个 key，因为 `x-api-key` 优先。
4. 遇到 `401` 或 `403` 时，停下来把消息告诉用户。不要重试，也不要尝试你在机器上找到的其他 key。
5. 不要把 key 放进客户端代码、URL 或会被提交的文件。