Files
new-api-key-usage/docs/upstream/NewAPI-sk-key接口文档.md
T
skycurtain 45b312b357 docs: 设计文档体系落定(七篇定稿)
- docs/design:四张表字段设计 · 交互设计(方向层 + 细节层)· API 契约 · 同步引擎设计
- docs/upstream:sk-key 接口实证(430 行)· 接口范围(9 个接口)
- README(全景入口)· AGENTS.md(AI 协作者指引)
- 废弃旧稿已删除(不随仓库留存)
2026-09-14 23:54:52 +08:00

20 KiB
Raw Blame History

NewAPI sk-key 查询接口文档

基于源码实证调研(QuantumNous/new-api),整理所有可通过 sk- API key 直接访问的查询接口。

调研日期:2025-07 月 · 源码版本:main 分支


0. 通用说明

认证方式

所有接口均使用 API key 鉴权,在请求头中携带:

Authorization: Bearer sk-xxxxxxxxxxxx

不需要账号登录态(access token / session)。这是仅凭 sk-key 即可查询的关键前提。

BaseURL

即 NewAPI 站点地址,例如 https://your-newapi-instance.com。所有路径前不带多余前缀,直接拼接。

两种鉴权中间件

中间件 说明
TokenAuth() 标准版:校验 key 有效、未过期、有剩余额度。过期或耗尽的 key 会被拒绝。
TokenAuthReadOnly() 宽松版:只校验 key 存在、token 未被显式禁用、用户未封禁。key 已过期、额度耗尽仍可查询;显式禁用(Disabled)的 key 会被 401 拒绝(2026-09-13 源码复核,middleware/auth.go 注释原文:only explicitly disabled tokens are denied)。

/api/usage/token 和 /api/log/token 用的是 TokenAuthReadOnly(),所以 key 额度耗尽、甚至过期后,仍能查到自己的用量记录;但 key 被管理员显式禁用后会收到 401(见上表)。

已确认的换算参数

参数 值 来源
QuotaPerUnit 500000 实测验证:接口① total_used ÷ 500000 = 接口④ total_usage ÷ 100

关键开关:DisplayTokenStatEnabled

接口 受开关影响?
billing 接口(③④⑤⑥) ✅ 受影响。开启 -> 返回 token 级额度;关闭 -> 回退到账号级额度(暴露整个账号余额)
/api/usage/token、/api/log/token ❌ 不受影响,恒返回 token 级数据

实测已确认当前平台开关为开启状态(billing 接口返回的 hard_limit_usd 是 token 级占位值,非账号总额)。

开关位于后台:设置 -> 计费设置(Billing)-> "货币与显示"(Currency & Display)-> Display Token Statistics。仅管理员可改。


1. 接口清单总览

序号 方法 路径 鉴权 用途
① GET /api/usage/token TokenAuthReadOnly 查 token 的累计已用/剩余/总额(原始 quota)
② GET /api/log/token TokenAuthReadOnly 查该 key 最近 1000 条调用日志
③ GET /v1/dashboard/billing/subscription TokenAuth 查总额度上限(OpenAI 兼容,美元)
④ GET /v1/dashboard/billing/usage TokenAuth 查累计已用(OpenAI 兼容,美分)
⑤ GET /dashboard/billing/subscription TokenAuth 同 ③,不带 /v1 前缀
⑥ GET /dashboard/billing/usage TokenAuth 同 ④,不带 /v1 前缀
⑦ GET /v1/models TokenAuth 列出可用模型(OpenAI 格式)
⑧ GET /v1/models/:model TokenAuth 查单个模型详情
⑨ GET /v1beta/models TokenAuth 列出可用模型(Gemini 格式)
⑩ GET /v1beta/openai/models TokenAuth 列出可用模型(OpenAI 格式)

③和⑤是同一个接口,④和⑥是同一个接口,只是路径前缀不同(为兼容不同客户端写法)。测一组即可。

⑦~⑩是模型列表接口,与用量统计无关,列出仅为完整覆盖。


2. 用量/额度查询接口详解

① GET /api/usage/token - token 级用量汇总

鉴权:TokenAuthReadOnly()(宽松版:key 过期/额度耗尽也能查;被显式禁用则 401)

请求参数:无

请求示例:

GET /api/usage/token
Authorization: Bearer sk-xxxx

返回结构(源码:controller/token.go -> GetTokenUsage):

{
    "code": true,
    "message": "ok",
    "data": {
        "object": "token_usage",
        "name": "令牌名称",
        "total_granted": 6012,
        "total_used": 673419457,
        "total_available": -673413445,
        "unlimited_quota": true,
        "model_limits": {},
        "model_limits_enabled": false,
        "expires_at": 0
    }
}

字段说明:

字段 类型 说明
name string 令牌名称
total_granted int 总额度 = RemainQuota + UsedQuota(原始 quota 单位)
total_used int 累计已用(原始 quota 单位)。从 key 创建以来累计,非当月。换算美元:total_used ÷ 500000
total_available int 剩余 = total_granted − total_used。无限额度时为负数,无实际意义
unlimited_quota bool 是否无限额度。true 时 total_granted/total_available 无实际意义
model_limits object 模型限制(map)
model_limits_enabled bool 是否启用模型限制
expires_at int 过期时间(Unix 秒),0 = 永不过期

注意事项:

  • total_used 是累计值,从 key 创建以来累计,不是当月用量。
  • 额度单位是原始 quota 整数,需自行除以 QuotaPerUnit(默认 500000)换算美元。
  • 禁用再解禁不会重置 total_used(源码验证:Update() 的 .Select(...) 列表不含 used_quota)。

② GET /api/log/token - token 级调用日志

鉴权:TokenAuthReadOnly()

请求参数:无(不支持任何 query 参数)

请求示例:

GET /api/log/token
Authorization: Bearer sk-xxxx

返回结构(源码:controller/log.go:62 -> GetLogByKey):

{
    "success": true,
    "message": "",
    "data": [
        {
            "id": 123456,
            "user_id": 12,
            "created_at": 1751328000,
            "type": 2,
            "content": "模型倍率 1.0,分组倍率 1.0",
            "username": "用户名",
            "token_name": "令牌名",
            "model_name": "gpt-4o",
            "quota": 2500,
            "prompt_tokens": 1500,
            "completion_tokens": 500,
            "use_time": 2,
            "is_stream": true,
            "channel": 0,
            "channel_name": "",
            "token_id": 100,
            "group": "default",
            "ip": "",
            "request_id": "20260911113652…",
            "other": "{\"billing_source\":\"subscription\",\"cache_tokens\":29056,\"frt\":3931,\"model_ratio\":0.075,\"request_path\":\"/v1/messages\",\"stream_status\":{\"status\":\"ok\"},…}"
        }
    ]
}

字段说明(共 21 个字段;已按实测响应 + 上游源码校正,2026-09-11):

字段 类型 说明
id int 展示序号,每次从 1 重编——跨请求无意义,绝不能用于去重
user_id int 账号 ID(同一实例内恒定)
created_at int 调用时间(UTC Unix 秒)
type int 日志类型(完整取值见下);token 日志实见 2=消费、5=错误
content string 消费记录为空串;错误记录为错误详情文本
username string 账号用户名
token_name string 令牌名
model_name string 调用的模型名
quota int 本次消耗的 quota(换算美元:quota ÷ 500000);错误记录为 0
prompt_tokens int 输入 token 数;错误记录为 0
completion_tokens int 输出 token 数;错误记录为 0
use_time int 耗时(秒);错误记录为 0
is_stream bool 是否流式
channel int 渠道 ID
channel_name string 渠道名(普通用户视角为空串)
token_id int 上游 token ID(对账用)
group string 分组名(默认 default)
ip string 请求 IP(普通用户视角为空串)
request_id string 请求 ID(格式:yyyyMMddHHmmss 前缀 + 随机串);JSON tag 为 omitempty,但源码写入时有兜底保证非空——去重唯一依据
upstream_request_id string 上游请求 ID;JSON tag 为 omitempty——空值时不出现、有值时才出现(实测样本中缺席);消费方需按「可选字段」处理
other string JSON 字符串,扩展信息(结构见下)

type 完整取值(上游源码 model/log.go;常量注释明确「刻意不用 iota,以保证枚举值永不改变」):

值 常量 含义 可能出现在 token 日志?
0 LogTypeUnknown 未知 兜底值
1 LogTypeTopup 充值 否(账号级,无 token_id)
2 LogTypeConsume 消费 是(实测)
3 LogTypeManage 管理操作 否(审计类)
4 LogTypeSystem 系统 否
5 LogTypeError 错误 是(实测)
6 LogTypeRefund 退款 可能(任务计费链路带 token_id)
7 LogTypeLogin 登录 否(账号级)

本接口按 token_id 过滤、不按 type 过滤——凡是「带 token_id 写入」的类型都可能返回。

other 字段(JSON 字符串,内容随 type 变化,实测 2026-09-11):

  • 消费记录(type=2):billing_source、cache_ratio、cache_tokens、completion_ratio、frt、group_ratio、model_price、model_ratio、reasoning_effort、request_conversion、request_path、stream_status(对象)、subscription_*(订阅维度,共 8 个)、user_group_ratio、wallet_quota_deducted
  • 错误记录(type=5):error_code、error_type、request_path、status_code
  • 注:普通用户视角下,服务端会先对 other 做一层「可见性过滤」再返回——上表为过滤后实际可见的键

关键限制:

  • 硬上限 1000 条:固定返回最近 1000 条日志(Limit(common.MaxRecentItems),MaxRecentItems = 1000,定义于 common/constants.go)。
  • 不支持任何请求参数:GetLogByKey 不读任何 c.Query(),没有分页(page/limit/offset),没有时间过滤(start_timestamp/end_timestamp)。
  • 固定按 id desc 排序:即最新 1000 条。
  • 超过 1000 条的旧记录无法获取:无法翻页,无法扩大 limit。
  • 当月调用超 1000 次时,此接口无法覆盖完整当月数据。

③ GET /v1/dashboard/billing/subscription - 总额度上限

鉴权:TokenAuth()

请求参数:无

请求示例:

GET /v1/dashboard/billing/subscription
Authorization: Bearer sk-xxxx

返回结构(源码:controller/billing.go:13 -> GetSubscription):

{
    "object": "billing_subscription",
    "has_payment_method": true,
    "soft_limit_usd": 100000000,
    "hard_limit_usd": 100000000,
    "system_hard_limit_usd": 100000000,
    "access_until": 0
}

字段说明:

字段 类型 说明
hard_limit_usd float 总额度上限(美元)。无限额度 key 返回 100000000(占位值,无实际意义)
soft_limit_usd float 软上限(同 hard_limit_usd)
system_hard_limit_usd float 系统上限(同 hard_limit_usd)
access_until int token 过期时间(Unix 秒),0 = 永不过期

注意事项:

  • 受 DisplayTokenStatEnabled 开关影响。开启时返回 token 级额度;关闭时返回账号级额度(会暴露整个账号余额)。
  • 无限额度 key 返回 100000000(一亿)作为占位值,无参考意义。
  • 受 quota_display_type 影响:USD 模式直接是美元;CNY 模式会做货币转换;Tokens 模式是原始 token 数。

④ GET /v1/dashboard/billing/usage - 累计已用

鉴权:TokenAuth()

请求参数:无

请求示例:

GET /v1/dashboard/billing/usage
Authorization: Bearer sk-xxxx

返回结构(源码:controller/billing.go:75 -> GetUsage):

{
    "object": "list",
    "total_usage": 134683.8914
}

字段说明:

字段 类型 说明
total_usage float 累计已用(单位:美分)。换算美元:total_usage ÷ 100

实测验证:

total_usage = 134683.8914 美分 ÷ 100 = 1346.84 美元
与接口① total_used(673419457) ÷ 500000 = 1346.84 美元 完全吻合

注意事项:

  • total_usage 是累计值(从 key 创建至今),不是当月用量。
  • 受 DisplayTokenStatEnabled 开关影响(开启时为 token 级)。
  • 受 quota_display_type 影响(USD 模式才是美元,否则需另行换算)。
  • hard_limit_usd(接口③)− total_usage ÷ 100(接口④)= 剩余额度(仅有限额 key 有意义)。

3. 模型列表接口(与用量无关)

以下接口 sk-key 可访问,但返回的是模型列表,与用量统计无关。列出仅为完整覆盖。

⑦ GET /v1/models

返回当前 key 可用的模型列表,OpenAI 兼容格式。

{
    "object": "list",
    "data": [
        {
            "id": "gpt-4o",
            "object": "model",
            "created": 1686935000,
            "owned_by": "openai"
        }
    ]
}

⑧ GET /v1/models/:model

返回单个模型详情。将 :model 替换为模型名,如 /v1/models/gpt-4o。

已知限制:此接口与 /v1/models 数据源不同。/v1/models 查数据库 abilities 表(反映渠道实际配置的模型),而此接口查代码内硬编码的静态模型列表(openAIModelsMap)。当渠道配了新模型或自定义模型名但代码未收录时,会出现"列表里有但单查返回 model_not_found"的现象。不影响实际模型调用。

⑨ GET /v1beta/models

返回模型列表(Gemini 兼容格式)。

⑩ GET /v1beta/openai/models

返回模型列表(OpenAI 格式,Gemini 路由下)。


4. 确认不存在的接口(排除清单)

以下接口在源码中不存在或不可用 sk-key 访问,测试时应返回 404 或 401:

4.1 不存在的接口(返回 404)

路径 状态
/v1/usage 不存在
/v1/quota 不存在
/api/token/self 不存在

4.2 存在但需要登录态的接口(sk-key 访问返回 401)

这些接口支持时间范围查询和 token_name 过滤,但必须用账号登录态(access token + New-Api-User header),sk-key 无法访问:

路径 鉴权 能力
/api/log/self UserAuth() 支持 start_timestamp、end_timestamp、token_name 过滤,返回日志明细
/api/log/self/stat UserAuth() 支持时间范围 + token_name,返回 quota 汇总(调 SumUsedQuota)
/api/data/self UserAuth() 按日聚合的看板数据
/api/token/ (GET/POST/PUT/DELETE) UserAuth() token 的增删改查
/api/user/self UserAuth() 用户自身信息

特别说明:/api/log/self/stat 是 NewAPI 中最适合算"当月用量"的接口--传当月起止时间 + token_name 即可返回该 key 当月消耗的 quota 总和。但它需要登录态,是"按时间段统计用量"难以纯客户端实现的核心障碍。

4.3 参数被忽略的情况

请求 实际行为
/api/log/token?p=2 参数被忽略,仍返回最近 1000 条
/api/log/token?limit=5000 参数被忽略,仍返回最近 1000 条
/api/log/token?start_timestamp=1751328000 参数被忽略,仍返回最近 1000 条
/v1/dashboard/billing/usage?start_date=2025-07-01 参数被忽略

5. 用量换算速查

核心换算公式

原始 quota ÷ 500000 = 美元

消费记录的 quota 是怎么算出来的(实测反推,2026-09-13)

按 tokens 计费的模型,quota 在请求时由「倍率 × 用量」算出并固化进日志(此后不再变化):

quota = ( (prompt_tokens − cache_tokens)             ← 提示 tokens(未命中缓存部分)
          + cache_tokens × cache_ratio               ← 缓存命中部分按折扣
          + completion_tokens × completion_ratio )   ← 补全 tokens 按倍率
        × model_ratio                                ← 模型倍率
        × group_ratio                                ← 分组倍率
  • 验证:6/6 条实测日志逐条吻合(差值仅为四舍五入)
  • 按次计费模型走 model_price 分支:quota = model_price × QuotaPerUnit × group_ratio(源码 relay/helper/price.go)
  • 公式中没有 QuotaPerUnit:倍率与美元的锚定(model_ratio = 1 ⇔ $0.002 / 1K tokens)已隐含它——倍率制下改 QuotaPerUnit 等于全站重定标;美元定价路径(model_price / 表达式 $/1M)才显式乘 QuotaPerUnit

实测数据验证

来源 原始值 换算 结果
接口① total_used 673,419,457 quota ÷ 500000 1346.84 美元
接口④ total_usage 134,683.8914 美分 ÷ 100 1346.84 美元

两者完全吻合,确认 QuotaPerUnit = 500000。


6. 关键限制总结

6.1 时间维度

  • 所有 sk-key 接口返回的用量都是累计值(从 key 创建至今),没有任何接口直接返回"当月用量"。
  • 唯一带时间戳的是 /api/log/token,但硬限 1000 条且不支持时间过滤。
  • 支持时间范围的接口(/api/log/self、/api/log/self/stat)需要登录态,sk-key 无法访问。

6.2 日志条数

  • /api/log/token 硬上限 1000 条(MaxRecentItems = 1000,定义于 common/constants.go)。
  • 不支持分页、不支持时间过滤、不支持改变 limit。
  • 月调用量超过 1000 次时,此接口无法覆盖完整当月数据。

6.3 写操作

  • sk-key 没有任何写接口(没有 POST/PUT/DELETE 能改 token 自身)。
  • token 的增删改查(/api/token/)全部需要登录态 UserAuth()。
  • 无法通过 sk-key 重置 used_quota(没有"重置用量"接口,Update() 的 Select 列表不含 used_quota)。

6.4 禁用/解禁行为

  • 禁用 token 只改 status 字段,不重置 used_quota,不清零 remain_quota,不丢历史日志。
  • 解禁后 used_quota、remain_quota、历史日志全部原封不动。
  • 唯一让 used_quota 归零的途径是删除 token 后新建(产生全新 Id/Key,旧日志按旧 token_id 关联,新 token 查不到旧日志)。
  • 解禁保护:额度耗尽(Exhausted)且 RemainQuota ≤ 0 且非无限额度的 token 不能直接解禁,需先充值;已过期的 token 也不能直接解禁,需改过期时间。

7. 源码参考

关注点 文件路径 关键函数/位置
路由注册 router/api-router.go usageRoute、logRoute 组
路由注册 router/dashboard.go:14-23 billing 路由组
路由注册 router/relay-router.go models 路由
API key 鉴权 middleware/auth.go:171 TokenAuthReadOnly()
API key 鉴权 middleware/auth.go TokenAuth() / SetupContextForToken
token 用量查询 controller/token.go GetTokenUsage
日志查询 controller/log.go:62 GetLogByKey
日志查询(model) model/log.go GetLogByTokenId(Limit 1000)
billing 查询 controller/billing.go:13 GetSubscription
billing 查询 controller/billing.go:75 GetUsage
显示开关 common/constants.go DisplayTokenStatEnabled
日志上限 common/constants.go MaxRecentItems = 1000
配额单位 common/constants.go QuotaPerUnit(默认 500000)
token 更新 model/token.go Update()(Select 不含 used_quota)
额度增减 model/token.go increaseTokenQuota / decreaseTokenQuota

仓库地址:https://github.com/QuantumNous/new-api