# Token API 参考文档 > 本文档以仓库当前实现为准。`controller.GetTokenStatus` 存在,但未在路由中注册;当前可公开调用的 token 相关端点见下文。 ## 通用约定 ### 基础信息 | 项目 | 说明 | |------|------| | Base URL | `{host}/api` | | 认证方式 | 除 `/api/usage/token/` 外,均使用登录态鉴权 | | 响应格式 | JSON | | 字符编码 | UTF-8 | ### 鉴权说明 | 场景 | 说明 | |------|------| | `/api/token/*` | 需要登录态。优先使用 session cookie;若无 session,也可用系统 `access_token` 放在 `Authorization` 头里,但仍必须携带 `New-Api-User` | | `/api/usage/token/` | 只需要 `Authorization: Bearer sk-...`,不需要 session 和 `New-Api-User` | > session cookie 名由服务端 `SESSION_NAME` 决定,默认是 `session`。 > > `New-Api-User` 必须与当前登录身份的用户 ID 一致,否则返回: > ```json > {"success": false, "message": "无权进行此操作,未提供 New-Api-User"} > ``` > ```json > {"success": false, "message": "无权进行此操作,New-Api-User 与登录用户不匹配"} > ``` ### 统一响应 大多数接口成功时返回: ```json {"success": true, "message": "", "data": {}} ``` 业务失败通常返回: ```json {"success": false, "message": "错误描述"} ``` > 注意:鉴权失败、限流等中间件可能直接返回 `401/403/429`,不一定是 `200`。 ### 分页参数 | 参数 | 别名 | 说明 | 默认 | 上限 | |------|------|------|------|------| | `p` | - | 页码,从 1 开始 | 1 | - | | `page_size` | `ps` / `size` | 每页条数 | 10 | 100 | ### Token 数据模型 > `key` 为原始密钥,不含 `sk-` 前缀;创建接口不回传密钥,列表/详情/搜索会返回该原始值。 ```json { "id": 123, "user_id": 44, "key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "status": 1, "name": "my-token", "created_time": 1716163200, "accessed_time": 1716249600, "expired_time": -1, "remain_quota": 500000, "unlimited_quota": false, "model_limits_enabled": true, "model_limits": "gpt-4o,claude-3-5-sonnet", "allow_ips": "192.168.1.0/24\n10.0.0.1", "used_quota": 120000, "group": "default", "cross_group_retry": false } ``` | 字段 | 说明 | |------|------| | `status` | `1` 启用,`2` 禁用,`3` 过期,`4` 耗尽 | | `expired_time` | Unix 秒级时间戳,`-1` 表示永不过期 | | `remain_quota` | 剩余额度,单位为内部 quota | | `model_limits` | 逗号分隔的模型列表 | | `allow_ips` | 换行分隔的 IP 白名单,空则不限制 | | `group` | 空字符串表示使用用户默认分组 | | `cross_group_retry` | 仅 `auto` 分组有意义 | ## API 端点 ### 1. 获取令牌列表 ``` GET /api/token/ ``` #### 请求 | 参数 | 说明 | |------|------| | `p` | 页码 | | `page_size` / `ps` / `size` | 每页条数 | #### 响应 `data` 为分页结构;其中每个 token 的 `key` 是原始密钥,不带 `sk-` 前缀。 ### 2. 搜索令牌 ``` GET /api/token/search ``` #### 请求 | 参数 | 说明 | |------|------| | `keyword` | 按名称搜索 | | `token` | 按密钥搜索,`sk-` 前缀可选 | | `p` | 页码 | | `page_size` / `ps` / `size` | 每页条数 | #### 搜索规则 - 不含 `%` 时为精确匹配 - 含 `%` 时为模糊匹配 - 最多允许 2 个 `%` - 不允许连续 `%%` - 含 `%` 时,去掉 `%` 后长度必须至少 2 - 令牌数量超过上限时,只允许精确搜索 ### 3. 获取单个令牌 ``` GET /api/token/:id ``` 返回单个 token 对象,`key` 同样是原始密钥。 ### 4. 创建令牌 ``` POST /api/token/ ``` #### 请求体 | 字段 | 说明 | |------|------| | `name` | 必填,最长 50 字符 | | `remain_quota` | 可选,默认 0 | | `unlimited_quota` | 可选,默认 false | | `expired_time` | 可选,默认 -1 | | `model_limits_enabled` | 可选,默认 false | | `model_limits` | 可选,逗号分隔字符串 | | `allow_ips` | 可选,换行分隔字符串 | | `group` | 可选,空字符串表示用户默认分组 | | `cross_group_retry` | 可选,默认 false | #### 说明 - 后端自动生成 `key` - 创建成功不返回 `key` - 创建成功后通常去列表页复制原始 `key` ### 5. 更新令牌 ``` PUT /api/token/ ``` #### 请求 | 参数 | 说明 | |------|------| | `status_only=true` | 只更新状态 | | 字段 | 说明 | |------|------| | `id` | 必填 | | `name` | 可选 | | `status` | 仅 `status_only=true` 时生效 | | `remain_quota` | 可选 | | `unlimited_quota` | 可选 | | `expired_time` | 可选 | | `model_limits_enabled` | 可选 | | `model_limits` | 可选 | | `allow_ips` | 可选 | | `group` | 可选 | | `cross_group_retry` | 可选 | #### 业务规则 - 已过期且过期时间已到的 token 不能重新启用 - 已耗尽且非无限额度的 token 不能重新启用 - 非无限额度时,`remain_quota` 不能为负,也不能超过 `10^9 × QuotaPerUnit` - 不带 `status_only=true` 时,`status` 字段会被忽略 #### 响应 返回更新后的 token 对象。 ### 6. 删除令牌 ``` DELETE /api/token/:id ``` 软删除,只能删除自己的 token。 ### 7. 批量删除令牌 ``` POST /api/token/batch ``` #### 请求体 ```json {"ids":[1,2,3]} ``` #### 响应 `data` 为实际删除数量。 ### 8. 查询令牌用量 ``` GET /api/usage/token/ ``` #### 请求头 ```bash Authorization: Bearer sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ``` #### 响应 ```json { "code": true, "message": "ok", "data": { "object": "token_usage", "name": "my-api-key", "total_granted": 620000, "total_used": 120000, "total_available": 500000, "unlimited_quota": false, "model_limits": { "gpt-4o": true }, "model_limits_enabled": true, "expires_at": 0 } } ``` `expires_at` 单位是秒,`0` 表示永不过期。 ## 错误消息速查 | 场景 | message | |------|---------| | 未提供 `New-Api-User` | `无权进行此操作,未提供 New-Api-User` | | `New-Api-User` 格式错误 | `无权进行此操作,New-Api-User 格式错误` | | `New-Api-User` 不匹配 | `无权进行此操作,New-Api-User 与登录用户不匹配` | | 名称过长 | `令牌名称过长` | | 额度为负 | `额度值不能为负数` | | 额度超限 | `额度值超出有效范围,最大值为 {{.Max}}` | | 数量达上限 | `已达到最大令牌数量限制 (N)` | | 生成失败 | `生成令牌失败` | | 过期不能启用 | `令牌已过期,无法启用,请先修改令牌过期时间,或者设置为永不过期` | | 耗尽不能启用 | `令牌可用额度已用尽,无法启用,请先修改令牌剩余额度,或者设置为无限额度` | | 搜索通配符过多 | `搜索模式中最多允许包含 2 个 % 通配符` | | 连续 `%` | `搜索模式中不允许包含连续的 % 通配符` | | 模糊搜索太短 | `使用模糊搜索时,关键词长度至少为 2 个字符` | | 超量用户模糊搜索 | `令牌数量超过上限,仅允许精确搜索,请勿使用 % 通配符` | | 无效令牌 | `无效的令牌` | | 令牌过期 | `该令牌已过期` | | 令牌耗尽 | `该令牌额度已用尽 ...` | ## 状态枚举 | 值 | 常量名 | 含义 | |----|--------|------| | 1 | `TokenStatusEnabled` | 已启用 | | 2 | `TokenStatusDisabled` | 已禁用 | | 3 | `TokenStatusExpired` | 已过期 | | 4 | `TokenStatusExhausted` | 已耗尽 |