令牌管理
用于管理你 BUZZ 账号下的 sk- API key —— 也就是平时调用 /v1/messages、/v1/chat/completions 时携带的那串 token。BUZZ 后台界面的「创建 / 改名 / 吊销 key」走的就是这组接口。
POST /v1/messages 或 POST /v1/chat/completions。
鉴权
所有 /api/token/* 接口都过 UserAuth 中间件。它接受两种身份:浏览器 dashboard 自带的 session cookie,或者更适合脚本调用的 Access Token。Access Token 是从用户设置页生成的另一种长期凭证,不是你平时用的 sk- API key。
| Header | 说明 |
|---|---|
Authorization: <ACCESS_TOKEN> | 必填。整串 access token 裸传,不带 Bearer 前缀。这与 /v1/* 模型调用的 Bearer 鉴权刻意不同。 |
Buzz-User: <USER_ID> | 必填。当前用户 ID。必须与 access token 解析出的 user id 一致,不一致返回 401。 |
sk- key 调这组接口。 sk- 只用于 /v1/* 模型转发流量和 GET /api/usage/token/ 自查这一条路径。用 sk- 调 /api/token/* 会直接 401。
Headers
Authorization: <YOUR_ACCESS_TOKEN>
Buzz-User: 1
Content-Type: application/json
端点列表
9 个端点覆盖一个 key 的完整生命周期,加 1 条用 sk- 鉴权的自查端点。
| 方法 | 路径 | 用途 |
|---|---|---|
| GET | /api/token/ | 列出当前用户所有 token(分页) |
| GET | /api/token/search | 按 name 或 key 片段搜索 |
| GET | /api/token/:id | 取单条详情(key 已 mask) |
| POST | /api/token/:id/key | 取完整未 mask 的 key |
| POST | /api/token/ | 新建 token |
| POST | /api/token/batch | 批量删除 |
| POST | /api/token/batch/keys | 批量取完整 key(最多 100) |
| PUT | /api/token/ | 更新 token |
| DELETE | /api/token/:id | 软删除单条 |
Token 对象
所有 list / get / update 端点都返回这个结构:
| 字段 | 类型 | 说明 |
|---|---|---|
| id | integer | Token ID |
| user_id | integer | 所属用户 ID |
| name | string | 显示名,最长 50 字符 |
| key | string | sk- key。list/get 响应里已 mask(长度 > 8 时为 头 4 + ********** + 尾 4)。需要原值用 POST /api/token/:id/key。 |
| status | integer | 1 = Enabled、2 = Disabled、3 = Expired、4 = Exhausted |
| created_time | int64 | Unix 秒 |
| accessed_time | int64 | Unix 秒,每次调用模型时更新 |
| expired_time | int64 | Unix 秒。-1 = 永不过期。 |
| remain_quota | integer | 剩余额度。可能为负(透支)。 |
| unlimited_quota | boolean | true 时 remain_quota 仅作展示,不会触发额度限制。 |
| used_quota | integer | 已用额度 |
| model_limits_enabled | boolean | true 时仅允许 model_limits 中列出的模型 |
| model_limits | string | 逗号分隔的模型名白名单 |
| allow_ips | string | null | 换行分隔的 IP / CIDR 白名单。null 或空字符串 = 不限制。 |
| group | string | 默认路由 group(单 group 字段,保留向后兼容) |
| vendor_routes | string | JSON 字符串 {"<vendor>":"<group>"},按厂商指定 group。空字符串 = 回退到 group。 |
| DeletedAt | string | null | 软删除时间;未删则 null |
Status 常量
| 值 | 名称 | 含义 |
|---|---|---|
| 1 | Enabled | 启用,接受请求 |
| 2 | Disabled | 用户手动禁用 |
| 3 | Expired | expired_time 已过 |
| 4 | Exhausted | 额度耗尽(且 unlimited_quota 为 false) |
GET /api/token/
分页列出当前用户的所有 token。
查询参数
| 名称 | 类型 | 说明 |
|---|---|---|
| p | integer | 页码,默认 1 |
| page_size | integer | 每页条数。别名 ps、size。硬上限 100。 |
示例
curl 'https://buzzai.cc/api/token/?p=1&page_size=10' \
-H "Authorization: $BUZZ_ACCESS_TOKEN" \
-H "Buzz-User: 1"
响应
{
"success": true,
"message": "",
"data": {
"page": 1,
"page_size": 10,
"total": 4,
"items": [
{
"id": 21,
"user_id": 1,
"name": "cc",
"key": "OnyH**********esAm",
"status": 1,
"created_time": 1779358699,
"accessed_time": 1779778939,
"expired_time": -1,
"remain_quota": 0,
"unlimited_quota": true,
"used_quota": 18009,
"model_limits_enabled": false,
"model_limits": "",
"allow_ips": null,
"group": "default",
"vendor_routes": "",
"DeletedAt": null
}
]
}
}
GET /api/token/search
按 name 或 key 片段搜索。带 SearchRateLimit。
查询参数
| 名称 | 类型 | 说明 |
|---|---|---|
| keyword | string | 对 name 列做 LIKE 匹配 |
| token | string | 对 key 列做 LIKE 匹配,sk- 前缀会被自动剥离 |
| p | integer | 页码 |
| page_size | integer | 每页条数(上限 100) |
支持 % 通配符。限制:%% 拒绝;每个表达式 % 数量上限 2;含 % 时去除 % 后关键词至少 2 个字符;用户的 token 总数达到 MaxUserTokens 时禁用模糊匹配。
示例
curl 'https://buzzai.cc/api/token/search?keyword=AWS&p=1' \
-H "Authorization: $BUZZ_ACCESS_TOKEN" \
-H "Buzz-User: 1"
响应结构与 GET /api/token/ 一致。
GET /api/token/:id
取单条 token 详情,key 字段已 mask。
示例
curl https://buzzai.cc/api/token/21 \
-H "Authorization: $BUZZ_ACCESS_TOKEN" \
-H "Buzz-User: 1"
响应
{
"success": true,
"message": "",
"data": {
"id": 21,
"name": "cc",
"key": "OnyH**********esAm",
"status": 1,
"...": "..."
}
}
不存在跨用户读取问题 —— 查询条件锁定 (id, user_id),请求别人的 id 会以 not-found 形式返回。
POST /api/token/:id/key
返回完整未 mask 的 key。
CriticalRateLimit + DisableCache,前置 CDN 不会缓存敏感数据;第二,常用列表接口不带敏感字段,服务端开销和缓存策略都可以更激进。
示例
curl -X POST https://buzzai.cc/api/token/21/key \
-H "Authorization: $BUZZ_ACCESS_TOKEN" \
-H "Buzz-User: 1"
响应
{
"success": true,
"message": "",
"data": {
"key": "OnyHCHFmoxWEB0bIHS6Kc8RMI9ezNyBjG07kumzorg9tesAm"
}
}
POST /api/token/
新建一个 token。
请求体
提交一个部分 Token 对象。服务端只读取以下字段构造新记录,其它(id、user_id、key、时间戳)都是后端生成的:
| 字段 | 必填 | 说明 |
|---|---|---|
| name | 是 | ≤ 50 字符 |
| expired_time | 是 | Unix 秒,-1 表示永不过期 |
| remain_quota | 是 | 非无限额度时:必须 ≥ 0 且 ≤ 1_000_000_000 × QuotaPerUnit |
| unlimited_quota | 否 | 默认 false |
| model_limits_enabled | 否 | |
| model_limits | 否 | 逗号分隔 |
| allow_ips | 否 | 换行分隔 |
| group | 否 | 默认路由 group |
| vendor_routes | 否 | JSON map,经 ValidateVendorRoutes 校验 |
示例
curl -X POST https://buzzai.cc/api/token/ \
-H "Authorization: $BUZZ_ACCESS_TOKEN" \
-H "Buzz-User: 1" \
-H "Content-Type: application/json" \
-d '{
"name": "ci-runner",
"expired_time": -1,
"remain_quota": 0,
"unlimited_quota": true,
"model_limits_enabled": false,
"model_limits": "",
"group": "default",
"vendor_routes": ""
}'
响应
{
"success": true,
"message": ""
}
id 和 key。 完整流程是:再调一次 GET /api/token/(或按 name 搜索)拿到新建条目的 id,然后调 POST /api/token/:id/key 取完整 key。
校验失败的两种情况:用户 token 总数已达 MaxUserTokens;vendor_routes 不是合法 JSON 或 key/value 为空。
PUT /api/token/
更新一个已有 token。
查询参数
| 名称 | 说明 |
|---|---|
| status_only | 设为 1 时仅写入 status 字段,body 中其他字段被忽略。 |
请求体
id 必填。可写字段:name、expired_time、remain_quota、unlimited_quota、model_limits_enabled、model_limits、allow_ips、group、vendor_routes。其它字段被忽略。
状态切换规则:
- 从
3(Expired)切回1(Enabled):若expired_time仍在过去 → 拒绝 - 从
4(Exhausted)切回1(Enabled):若remain_quota ≤ 0且unlimited_quota为 false → 拒绝
示例:改名
curl -X PUT https://buzzai.cc/api/token/ \
-H "Authorization: $BUZZ_ACCESS_TOKEN" \
-H "Buzz-User: 1" \
-H "Content-Type: application/json" \
-d '{
"id": 21,
"name": "ci-runner-prod",
"expired_time": -1,
"remain_quota": 0,
"unlimited_quota": true
}'
示例:仅禁用(status_only)
curl -X PUT 'https://buzzai.cc/api/token/?status_only=1' \
-H "Authorization: $BUZZ_ACCESS_TOKEN" \
-H "Buzz-User: 1" \
-H "Content-Type: application/json" \
-d '{"id": 21, "status": 2}'
响应
{
"success": true,
"message": "",
"data": { "id": 21, "name": "ci-runner-prod", "key": "OnyH**********esAm", "status": 1, "...": "..." }
}
DELETE /api/token/:id
软删除单条(GORM DeletedAt)。
示例
curl -X DELETE https://buzzai.cc/api/token/21 \
-H "Authorization: $BUZZ_ACCESS_TOKEN" \
-H "Buzz-User: 1"
响应
{ "success": true, "message": "" }
POST /api/token/batch
事务内一次性软删多条,Redis 缓存同时清理。
请求体
{ "ids": [21, 133, 656] }
响应
{
"success": true,
"message": "",
"data": 3
}
data 是实际删除的行数。查询锁定 user_id = current_user,他人 id 会被静默跳过。
POST /api/token/batch/keys
批量取多个 token 的完整 key。带 CriticalRateLimit + DisableCache。
请求体
{ "ids": [21, 133] }
单次最多 100 个 id,超限返回 MsgBatchTooMany 错误。
响应
{
"success": true,
"message": "",
"data": {
"keys": {
"21": "OnyHCHFmoxWEB0bIHS6Kc8RMI9ezNyBjG07kumzorg9tesAm",
"133": "..."
}
}
}
GET /api/usage/token/(自查)
独立的一条 sk- key 自查端点,适合 SDK 在不接触管理 API 的情况下问「这把 key 还剩多少额度」。
鉴权
Authorization: Bearer sk-<YOUR_BUZZ_KEY>
响应
{
"code": true,
"message": "ok",
"data": {
"object": "token_usage",
"name": "cc",
"total_granted": 513586360,
"total_used": 515813135,
"total_available": -2226775,
"unlimited_quota": true,
"model_limits": {},
"model_limits_enabled": false,
"expires_at": 0
}
}
注意这条端点用 {code, message, data} 包络,与其它端点的 {success, message, data} 不同。expired_time = -1 时 expires_at 返回 0。
工作流示例
端到端创建一把新 key
# 1. 创建
curl -X POST https://buzzai.cc/api/token/ \
-H "Authorization: $BUZZ_ACCESS_TOKEN" \
-H "Buzz-User: 1" \
-H "Content-Type: application/json" \
-d '{"name":"ci-runner","expired_time":-1,"remain_quota":0,"unlimited_quota":true,"group":"default"}'
# 2. 拉列表或按 name 搜索找到新建条目的 id
curl 'https://buzzai.cc/api/token/search?keyword=ci-runner&p=1' \
-H "Authorization: $BUZZ_ACCESS_TOKEN" \
-H "Buzz-User: 1"
# 3. 取完整 key,写入你的 secret store(只取这一次)
curl -X POST https://buzzai.cc/api/token/<id>/key \
-H "Authorization: $BUZZ_ACCESS_TOKEN" \
-H "Buzz-User: 1"
轮换 key:先禁用旧的、再创建新的
# 1. 把旧 token 置为 Disabled(status=2)
curl -X PUT 'https://buzzai.cc/api/token/?status_only=1' \
-H "Authorization: $BUZZ_ACCESS_TOKEN" \
-H "Buzz-User: 1" \
-H "Content-Type: application/json" \
-d '{"id": 21, "status": 2}'
# 2. 走「端到端创建」流程拿到新 key
# 3. 新 key 部署完毕、确认无误后,硬吊销旧 token
curl -X DELETE https://buzzai.cc/api/token/21 \
-H "Authorization: $BUZZ_ACCESS_TOKEN" \
-H "Buzz-User: 1"
批量清理失效 key
# 1. 拉列表,客户端筛 status=3(Expired)或 status=4(Exhausted)
# 2. 批量删
curl -X POST https://buzzai.cc/api/token/batch \
-H "Authorization: $BUZZ_ACCESS_TOKEN" \
-H "Buzz-User: 1" \
-H "Content-Type: application/json" \
-d '{"ids":[101,102,103]}'
错误码
| HTTP | 典型场景 |
|---|---|
| 400 | 请求体格式错、name 超长、vendor_routes JSON 非法、批量超过 100、状态切换被拒 |
| 401 | Authorization 缺失或非法、Buzz-User 缺失、Buzz-User 与 token 拥有者不匹配 |
| 403 | 用户被禁用或角色不足以满足 RoleCommonUser |
| 404 | token id 不存在或属于其他用户(查询锁定 user_id) |
| 429 | SearchRateLimit 或 CriticalRateLimit 触发 |
| 500 | 服务端内部错误 |
错误响应包络:
{
"success": false,
"message": "Unauthorized, New-Api-User header not provided"
}
注:i18n 文案里仍写着 New-Api-User,但实际读取的 header 是 Buzz-User。请发 Buzz-User。
相关链接
POST /v1/messages— 用这里发出来的 key 调 ClaudeGET /api/user/self— 当前用户账号信息GET /api/user/dashboard— 额度与用量看板- 鉴权指南