ZeoAPIZeoAPI API 文档与接入指南
deep-dive

订阅平台对接

概述

这份文档面向需要把订阅服务和 zeoapi 打通的后端工程师。如果你的产品按月或按年向用户出售模型调用额度,zeoapi 提供一组接口,让你在用户开通套餐时自动发放 API key,每个账单周期到期时自动重置额度并延长有效期。

整套对接由四个接口完成:创建 key、续期、查询、删除。zeoapi 不持有你的订阅状态,也不参与计费决策;何时发放、何时续期、何时停发,完全由你这边的订阅系统决定。

业务流程图

你的订阅平台                zeoapi 服务
─────────────              ───────────────
用户开通 Pro 套餐  ───►    1. 创建 API key
                          2. 写入月度额度
                          3. 返回 sk-... 给你
                                    │
                                    ▼
                          你将 sk-... 安全交付给最终用户

每月续期日       ───►     重置该 key 额度,延长有效期
                          (同一把 key 跨月持续可用)

用户取消订阅     ───►     停止续期任务
                          key 在当前 expired_time 后自动失效

准备工作

选择凭证模式

调用 zeoapi 管理接口需要一组凭证,本文统称为「凭证 A」(access_token,作为 Authorization 头)和「凭证 B」(用户 ID 整数,作为 New-Api-User 头)。两者必须配套使用。

凭证有两种来源:

A. 个人模式

适合自营服务、个人开发者、小型团队。

  • 登录 zeoapi 控制台,进入「个人设置」,切换到「安全设置」选项卡,点击生成「系统访问令牌」(即本文的凭证 A)。「个人信息」选项卡可以看到你的用户 ID(即凭证 B)
  • 创建出来的所有 API key 归你的账号名下
  • 调用频次:当前对个人模式和服务账号模式的管理类接口调用都保持宽松策略,正常的开通、续期、批量补单场景不会遇到限流。请合理使用,避免短时间内单出口 IP 的极端峰值流量(例如每秒数百次的持续请求)

B. 服务账号模式

适合与 zeoapi 有 B2B 合作的合作伙伴。

  • 由 zeoapi 团队配发一组专用 access_token 和用户 ID
  • 更宽松的调用容量与优先技术支持,适合成批处理大量租户
  • 通过现有合作渠道申请

两种模式的接口调用方式完全一致,本文示例可以直接套用,只需替换为你拿到的实际凭证即可。

如怀疑凭证泄露:个人模式可在控制台「个人设置 → 安全设置」中立即重置系统访问令牌,旧值会同步失效;服务账号模式请通过原合作渠道申请重置。

接入端点

所有请求都发往 https://www.zeoapi.com。建议在你的项目中以环境变量集中配置 base URL,并通过域名访问,不要直接连 IP。

Key 命名约定

zeoapi 不强制 key 的命名格式。推荐使用以下结构,便于后续调试与对账:

ext:<tenant_id>:<tier>:<YYYY-MM>
字段说明示例
tenant_id你系统中的租户/客户 ID,限 25 字符以内,建议只用字母、数字、.-_acme-7
tier订阅档位,限 10 字符以内pro
YYYY-MM该 key 首次创建的年月,续期时不变2026-07

完整示例:ext:acme-7:pro:2026-07。这样命名后,tenant_id + YYYY-MM 在你的数据库中刚好可作为该 key 的天然主键。

TIP

对接多个产品线(多个 tier)或多套环境时,建议在 tenant_id 中加上区域或环境前缀,例如 cn-acme-7global-acme-7,方便后期做数据隔离。

流程一:开通时发放 API key

在用户首次支付成功后,按以下四步发放 key。

确定 key 的名字和初始额度

按上一节推荐格式生成 name。额度单位是 quota,1 USD ≈ 500,000 quota。例如月套餐售价 300 美元时,remain_quota150,000,000

创建 key

POST /api/token/。响应不包含新 key 的 ID,需要在下一步用搜索接口取回。

curl -fsS -X POST "https://www.zeoapi.com/api/token/" \
  -H "Authorization: 凭证 A" \
  -H "New-Api-User: 凭证 B" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "ext:<tenant_id>:<tier>:<YYYY-MM>",
    "remain_quota": 150000000,
    "expired_time": 1893456000,
    "unlimited_quota": false,
    "group": "default",
    "model_limits_enabled": false
  }'

成功响应:

{ "success": true, "message": "" }

取回 key 的 ID

GET /api/token/search 按名字反查。keyword 走模糊匹配,把名字 URL 编码后两侧各加一个 %

curl -fsS "https://www.zeoapi.com/api/token/search?keyword=%25ext%3Aacme-7%3Apro%3A2026-07%25" \
  -H "Authorization: 凭证 A" \
  -H "New-Api-User: 凭证 B"

响应中 data.items[0].id 即是 key 的 ID。把它和你自己的 tenant_id 一起持久化到数据库,后续续期和查询都靠它定位。

取出原始 key 并拼出 sk- 前缀

POST /api/token/<token_id>/key 取出 48 位十六进制原始 key。zeoapi 不会重复返回这个值,错过后只能重建。建议在开通时一次取好,不要反复调用。

curl -fsS -X POST "https://www.zeoapi.com/api/token/<token_id>/key" \
  -H "Authorization: 凭证 A" \
  -H "New-Api-User: 凭证 B"

响应:

{ "success": true, "data": { "key": "ab12cd34ef56..." } }

在前面拼上 sk- 前缀,得到最终交给最终用户的 Bearer key:

sk-ab12cd34ef56...

把它通过安全通道交付给用户。当前策略下该接口对合理使用无严格频次限制,但仍建议在开通流程中一次性取出并妥善保存,避免重复调用。

WARNING

zeoapi 对单次写入的 remain_quota 设有上限(远高于常见月度套餐金额)。如果你的业务场景需要更高额度(例如企业版套餐),请通过支持渠道协商。

流程二:每月自动续期

在你的账单周期任务中触发续期(按月底或按用户开通日 + 30 天均可)。

生成幂等键并发起续期

幂等键是你为本次续期生成的唯一标识。推荐格式:

ext:<tenant_id>:<tier>:cycle-<N>

N 是该用户的续期次数(首次开通 N=1,第二次开通 N=2,依此类推)。zeoapi 用这个键去重:同一个 idempotency_key 反复调用,返回的始终是首次成功时记录的额度和有效期,请求体中后改的值不会被采纳。这让你可以在网络抖动时安全重试。

curl -fsS -X POST "https://www.zeoapi.com/api/token/external/renew" \
  -H "Authorization: 凭证 A" \
  -H "New-Api-User: 凭证 B" \
  -H "Content-Type: application/json" \
  -d '{
    "token_id": 12345,
    "set_remain_quota": 150000000,
    "set_expired_time": 1893456000,
    "idempotency_key": "ext:acme-7:pro:cycle-2"
  }'

首次调用的成功响应:

{
  "success": true,
  "data": {
    "token_id": 12345,
    "name": "ext:acme-7:pro:2026-07",
    "remain_quota": 150000000,
    "expired_time": 1893456000,
    "status": 1,
    "idempotent_replay": false
  }
}

校验响应字段

每次调用后请关注三个字段:

  • success:必须为 true,否则本次额度未生效。
  • idempotent_replay:若为 true,表示 zeoapi 已处理过相同的 idempotency_key,本次返回的是首次结果,本次请求体中的额度与有效期不会覆盖原值。这是预期行为,常见于网络重试或任务重复触发。
  • remain_quota / expired_time:与你目标值是否一致。同一幂等键反复调用,这两个字段始终保持首次结果。

处理异常与重试

续期是单次原子操作:额度、有效期、审计记录要么一起写入,要么全部回滚,不存在中间状态。重试是安全的。

建议你的任务实现以下行为:

  • 网络断开 / 5xx / 超时:用相同 idempotency_key 重试,直到收到响应。idempotent_replay: true 不是错误。
  • 校验失败(success: false:通常是请求体本身的问题(额度超限、过期时间不合法等),重试同一请求不会改变结果。修正参数后用新的 idempotency_key(即 cycle-N+1)再发起一次。
  • 鉴权失败(HTTP 401):凭证 A 或 凭证 B 错误或失效。个人模式可在控制台「个人设置 → 安全设置」核对或重新生成系统访问令牌;服务账号模式请通过合作渠道核实。
  • 找不到 key(HTTP 200 + success: false:通常是 token_id 错了,或这把 key 已在 zeoapi 中删除。请用 search 接口重新定位。

流程三:用户取消订阅

推荐做法是停止续期任务,不调用任何接口。这把 key 会在当前 expired_time 自然失效,之后所有调用会被 zeoapi 直接拒绝。这种方式不会引入额外的状态同步,是大多数订阅产品默认的处理方式。

如果业务场景需要立即停发(例如已退款、用户主动停用),可以调用 DELETE /api/token/<token_id>

curl -fsS -X DELETE "https://www.zeoapi.com/api/token/12345" \
  -H "Authorization: 凭证 A" \
  -H "New-Api-User: 凭证 B"

调用成功后该 key 立即失效,之后的请求会被拒绝。该操作不可由你这边自助恢复,请在确认要永久停止访问时再使用。

流程四:查询用量(可选)

zeoapi 提供两种查询方式,覆盖不同场景。

由最终用户用 sk-key 自查

适合在你产品的用户中心或 dashboard 里展示「本月剩余」。最终用户用自己的 sk-key 即可,无需用到你的凭证 A / 凭证 B:

curl -fsS "https://www.zeoapi.com/api/usage/token/" \
  -H "Authorization: Bearer sk-abc123..."

返回:

{
  "code": true,
  "data": {
    "total_available": 150000000,
    "expires_at": 1893456000
  }
}

WARNING

URL 末尾的斜杠 /api/usage/token/ 必须保留。漏写时 zeoapi 会以 301 重定向到带斜杠的版本,curl 在没有 -L 选项时不会跟进重定向,看起来像「响应为空」。

这个查询走最终用户的 sk-key 鉴权,不计入凭证 A / 凭证 B 的速率配额,因此可以放心暴露给前端 dashboard 高频调用。

由你用凭证 A / 凭证 B 查询

适合做月度对账或跨租户报表。返回字段比上面更全,包含已用额度、剩余额度、状态、过期时间、分组、模型限制等:

curl -fsS "https://www.zeoapi.com/api/token/12345" \
  -H "Authorization: 凭证 A" \
  -H "New-Api-User: 凭证 B"

错误处理

zeoapi 的业务类失败(参数校验、资源不存在等)一律返回 HTTP 200 + 响应体中 success: false。只有鉴权失败会返回 HTTP 401。请你的代码读 success 字段判断结果,不要只依赖 HTTP 状态码。

WARNING

关于速率限制:当前对个人模式和服务账号模式的管理类接口调用保持宽松策略,常见的月度续期、开通时取 sk-key、批量初始化等场景都可以正常运行。但请合理使用——避免同一出口 IP 每秒数百次的持续洪流请求。如果你的业务需要长期大量并发调用(例如同时对上千租户执行操作),请通过合作渠道提前告知运营方,以便协调容量。若未来因异常流量导致策略收紧,运营方会通过合作渠道通知。

常见错误的处理建议:

类别触发条件处理方式
参数校验失败remain_quotaexpired_time 超限 / 格式错误,idempotency_key 为空或过长修正请求体,并使用新的幂等键再次调用
凭证失效Authorization 头错误或已被吊销个人模式:在控制台「个人设置 → 安全设置」重新生成系统访问令牌;服务账号模式:通过合作渠道申请重置
用户标识不匹配New-Api-User 头与凭证 A 不配对检查 New-Api-User 是否就是凭证 A 对应账户的用户 ID
资源不存在token_id 错误,或这把 key 不属于你的账户用 search 接口重新定位 token_id
速率限制(HTTP 429)极端峰值流量(同一出口 IP 每秒数百次的持续请求)退避重试。持续大批量需求请通过合作渠道协商

最佳实践

  • 凭证保密。凭证 A / 凭证 B 必须放在环境变量或密钥管理服务中,不要写入代码或配置文件,不要下发给最终用户。定期轮换;个人模式可在控制台自助轮换,服务账号模式通过合作渠道处理。
  • 幂等键不可修改。同一笔续期重试时,必须保持完全相同的 idempotency_key(包括 cycle-N 中的 N)。修改幂等键意味着发起一笔新的续期,会被记入新的审计行。
  • 取消订阅优先走自然过期,避免使用 DELETEDELETE 不可由你自助恢复,仅在确认永久停发时使用。
  • 命名规范有助于排障。建议所有 key 都按 ext:<tenant_id>:<tier>:<YYYY-MM> 命名,便于在控制台搜索和与你自己的数据库对账。
  • 额度换算函数化。quota = dollars × 500_000 这类换算只在一处实现,避免散落多处导致单位混淆。
  • 月度任务做错峰、重试和告警。避免所有租户在每月 1 号同时触发;失败请重试,连续失败时触发人工介入。
  • 区分凭证用途。最终用户拿到的始终是他自己的 sk-key;凭证 A / 凭证 B 只在你的服务端使用,不应出现在前端、客户端 SDK 或最终用户能接触到的任何地方。

完整示例

以下是从开通到首次续期再到用量查询的端到端 bash 脚本。替换 <...> 占位符后即可运行。

#!/usr/bin/env bash
set -euo pipefail

# ===== 配置 =====
ZEO_BASE="https://www.zeoapi.com"
ZEO_TOKEN="<凭证 A>"            # 你的 access_token
ZEO_USER="<凭证 B>"             # 你的用户 ID(整数)

TENANT_ID="<your-tenant-id>"    # 例如 acme-42
TIER="pro"
YYYY_MM=$(date +%Y-%m)
NAME="ext:${TENANT_ID}:${TIER}:${YYYY_MM}"
CYCLE=1                         # 首次开通算第 1 次

# 1 USD = 500,000 quota;以 300 美元月套餐为例
QUOTA=150000000
EXPIRY=$(( $(date +%s) + 30*86400 ))   # 30 天后

# ===== 1. 开通时创建 key =====
echo ">>> 创建 key: ${NAME}"
curl -fsS -X POST "${ZEO_BASE}/api/token/" \
  -H "Authorization: ${ZEO_TOKEN}" \
  -H "New-Api-User: ${ZEO_USER}" \
  -H "Content-Type: application/json" \
  -d "{\"name\":\"${NAME}\",\"remain_quota\":${QUOTA},\"expired_time\":${EXPIRY},\"unlimited_quota\":false,\"group\":\"default\",\"model_limits_enabled\":false,\"allow_ips\":\"\"}"

# ===== 2. 用 search 接口取回 token_id =====
echo ">>> 取回 token_id"
TOKEN_ID=$(curl -fsS "${ZEO_BASE}/api/token/search?keyword=%25$(printf %s "$NAME" | jq -sRr @uri)%25" \
  -H "Authorization: ${ZEO_TOKEN}" \
  -H "New-Api-User: ${ZEO_USER}" \
  | jq -r ".data.items[] | select(.name == \"${NAME}\") | .id" | head -n1)

echo "TOKEN_ID=${TOKEN_ID}"
# 把 TOKEN_ID 与 tenant_id 一起持久化到你的数据库

# ===== 3. 取出原始 key 并拼出 sk- 前缀 =====
SK_KEY="sk-$(curl -fsS -X POST "${ZEO_BASE}/api/token/${TOKEN_ID}/key" \
  -H "Authorization: ${ZEO_TOKEN}" \
  -H "New-Api-User: ${ZEO_USER}" \
  | jq -r .data.key)"

echo "Subscriber sk-key: ${SK_KEY}"
# 通过安全通道把 SK_KEY 交付给最终用户

# ===== 4. 一个月后:续期 =====
sleep 1   # 实际场景:放在月度任务里
CYCLE=$((CYCLE + 1))
NEW_EXPIRY=$(( $(date +%s) + 30*86400 ))
IDEM_KEY="ext:${TENANT_ID}:${TIER}:cycle-${CYCLE}"

echo ">>> 续期 cycle=${CYCLE} idempotency_key=${IDEM_KEY}"
curl -fsS -X POST "${ZEO_BASE}/api/token/external/renew" \
  -H "Authorization: ${ZEO_TOKEN}" \
  -H "New-Api-User: ${ZEO_USER}" \
  -H "Content-Type: application/json" \
  -d "{\"token_id\":${TOKEN_ID},\"set_remain_quota\":${QUOTA},\"set_expired_time\":${NEW_EXPIRY},\"idempotency_key\":\"${IDEM_KEY}\"}" \
  | jq

# ===== 5. 用户侧自查(用 sk-key,不用凭证 A/B)=====
echo ">>> 用户用 sk-key 自查"
curl -fsS "${ZEO_BASE}/api/usage/token/" \
  -H "Authorization: Bearer ${SK_KEY}" | jq

把第 1 至 3 步接入「用户开通成功」回调,把第 4 步接入月度任务,第 5 步可作为前端 dashboard 展示数据来源。订阅 + 用量两条主链路就接通了。

联系与支持

下列情况欢迎通过支持渠道联系 zeoapi 团队:

  • 个人模式凭证:登录 zeoapi 控制台「个人设置 → 安全设置」自助生成系统访问令牌,无需联系
  • 服务账号模式凭证申请,或 B2B 合作洽谈
  • 单次额度上限超出默认值的协商
  • 速率限制超出默认配额的协商
  • 出口 IP 白名单或来源限制
  • 接口返回了未在本文档列出的错误,或者最终用户报告无法调用

反馈时请提供:tenant_id、调用时间、请求 ID(如有)以及响应体原文。这些信息能显著加快排查。

本文档随 zeoapi 接口变化更新。如果实际响应与本文不一致,请以接口实际返回为准,并通过支持渠道反馈。