第三方 API Key 集成文档
2026-09-13 修正:所有路径统一 /api/v1/*。上一版本文档写的 /api/third-party/keys、/api/third-party/orders/:id、/api/third-party/packages 在 baozi-server 里 不存在(404),已被替换为下面这套 v1 真端点。
baozi 第三方接入:你(第三方)通过 OAuth 2.0 client_credentials 拿 access token → 用 token 调 baozi /api/v1/* 接口 → 创 key、下单、对账。
1. 准备工作
baozi 用 baozi 自己的 M2M 表(m2m_clients + m2m_tokens),不需要走 Logto。直接联系 baozi 运营(dev@ohoooho.com)拿:
| 字段 | 来源 |
|---|---|
client_id | baozi 运营手工创建 |
client_secret | baozi 运营手工创建(仅创建时返回一次) |
scopes | 默认全开:packages:read / tokens:read / tokens:write / orders:read / orders:write |
| 绑定 baozi 用户 | M2M client 创建时绑一个 baozi 普通用户(OIDC 登录过的),所有调用都归这个用户管 |
2. 拿 access token
POST /api/v1/m2m/auth
注意路径:OAuth 标准是 /oauth/token 或 /oidc/token,baozi v1 放在 /api/v1/m2m/auth(带 v1 + baozi 自己的命名空间)。
请求 body(application/x-www-form-urlencoded):
grant_type=client_credentials&client_id=<YOUR_CLIENT_ID>&client_secret=<YOUR_CLIENT_SECRET>
响应 200:
{
"access_token": "108b257775f415ef7c1e54a39fb49b07...",
"token_type": "Bearer",
"expires_in": 7200,
"scope": "packages:read tokens:read tokens:write orders:read orders:write"
}
实测:2026-09-13 跑通,token 有效期 2 小时,建议在过期前 5 分钟刷新。
错误码:
| HTTP | code | 含义 |
|---|---|---|
| 400 | invalid_grant | grant_type 错 |
| 401 | invalid_client | client_id / client_secret 错 |
3. 查可购买套餐
GET /api/v1/packages
返回 baozi 当前所有在售套餐 + 每个套餐的 tier 数组。
调用:
curl https://baozi.ohoooho.com/api/v1/packages \
-H "Authorization: Bearer <access_token>"
响应 200(实测):
{
"success": true,
"api_version": "v1",
"data": [
{
"id": "bz-chat",
"name": "日常套餐",
"scene": "chat",
"tiers": [
{ "id": "lite", "name": "Lite", "price_yuan": 18, "quota": 2000, "period": "月" },
{ "id": "standard", "name": "Standard", "price_yuan": 28, "quota": 5000, "period": "月" },
{ "id": "pro", "name": "Pro", "price_yuan": 99, "quota": 20000, "period": "月" }
]
}
],
"total": 1
}
需要 scope:packages:read(默认包含)
4. 下单
POST /api/v1/orders
注意:上一版本文档把这个动作写成「创建 API Key」(POST /api/third-party/keys),那是 错的。正确流程是「先下单 → baozi 内部 fulfillment → 创 key」(拆成 2 步,跟 SaaS 标准对账/履约一致)。
请求 body(application/json):
{
"package_id": "bz-chat",
"tier_id": "lite",
"period": "月",
"external_order_id": "my-order-2026-09-13-001"
}
响应 201:
{
"success": true,
"api_version": "v1",
"data": {
"id": "m2m-bz-2-1757771234567-97ti6t",
"package_id": "bz-chat",
"tier_id": "lite",
"period": "月",
"amount_cents": 1800,
"amount_yuan": 18,
"status": "pending",
"external_order_id": "my-order-2026-09-13-001",
"created_at": 1757771234567
}
}
需要 scope:orders:write
5. 创建 API Key
POST /api/v1/tokens
订单创建后,第三方立刻调这个端点创 baozi API Key(一个订单对应一个 key)。
请求 body:
{
"order_id": "m2m-bz-2-1757771234567-97ti6t",
"name": "prod-key-001"
}
响应 201(实测 2026-09-13):
{
"success": true,
"api_version": "v1",
"data": {
"user_token_id": 2,
"new_api_token_id": 284,
"name": "prod-key-001",
"masked_key": "w3SE***...6MC9",
"package_id": "bz-chat",
"tier_id": "lite",
"quota": 500000,
"expires_at": 1791857235000
}
}
需要 scope:tokens:write
重要:完整 key(明文)只在 POST /api/v1/tokens 响应里返回一次。baozi 只存 masked 版本,请立即保存。
6. 查 API Key
GET /api/v1/tokens?end_user_email=<email>
查 baozi 用户的所有 key(默认查 M2M 绑定的 baozi 用户)。
响应 200:
{
"success": true,
"api_version": "v1",
"data": [
{ "id": 2, "name": "prod-key-001", "status": "active", "masked_key": "w3SE***...6MC9", "quota": 500000, "expires_at": 1791857235000 }
],
"total": 1
}
GET /api/v1/tokens/:id
查单个 key 详情。
DELETE /api/v1/tokens/:id
禁用 key(baozi 内部禁用 + new-api 双写)。
响应 200:
{ "success": true, "api_version": "v1", "data": { "id": 2, "status": "disabled" } }
7. 对账
GET /api/v1/orders/:id
查单个订单详情(订单 + 该订单下的 API Key)。
响应 200:
{
"success": true,
"api_version": "v1",
"data": {
"id": "m2m-bz-2-1757771234567-97ti6t",
"package_id": "bz-chat",
"tier_id": "lite",
"period": "月",
"amount_cents": 1800,
"status": "paid",
"external_order_id": "my-order-2026-09-13-001",
"created_at": 1757771234567,
"tokens": [
{ "user_token_id": 2, "name": "prod-key-001", "status": "active", "masked_key": "w3SE***...6MC9", "quota": 500000, "expires_at": 1791857235000 }
]
}
}
GET /api/v1/orders?end_user_email=<email>
查某 baozi 用户的所有订单(按时间倒序)。
8. 用 API Key 调 baozi 模型
baozi 把 third-party 创建的 key 转发到 new-api(baozi 自己的 new-api 实例 = https://llm.ohoooho.com)。调模型走 new-api 标准 OpenAI 兼容路径:
curl -X POST https://llm.ohoooho.com/v1/chat/completions \
-H "Authorization: Bearer <baozi_api_key>" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o-mini",
"messages": [{ "role": "user", "content": "Hello" }]
}'
9. 错误码(v1 端点)
| HTTP | code | 含义 | 触发场景 |
|---|---|---|---|
| 400 | invalid_grant | grant_type 错 | 拿 token 时 |
| 401 | invalid_client | client_id / client_secret 错 | 拿 token 时 |
| 401 | unauthorized | 缺 Bearer 或 token 过期 | 调 v1 业务接口 |
| 403 | scope_missing | token 缺 scope | scope 不够 |
| 404 | package_not_found | 套餐 ID 不存在 | GET /packages 时 ID 错 |
| 404 | order_not_found | 订单 ID 不存在 | GET /orders/:id |
| 409 | package_exists | 套餐 ID 已存在 | 创套餐时 |
10. 完整流程示例(一气呵成)
# 1. 拿 token
TOKEN=$(curl -s -X POST https://baozi.ohoooho.com/api/v1/m2m/auth \
-d "grant_type=client_credentials&client_id=$CID&client_secret=$SECRET" \
| jq -r .access_token)
# 2. 查套餐
PKG=$(curl -s https://baozi.ohoooho.com/api/v1/packages \
-H "Authorization: Bearer $TOKEN" | jq -r '.data[0].id')
# 3. 下单
ORDER=$(curl -s -X POST https://baozi.ohoooho.com/api/v1/orders \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"package_id\":\"$PKG\",\"tier_id\":\"lite\",\"period\":\"月\",\"external_order_id\":\"demo-001\"}" \
| jq -r .data.id)
# 4. 创 key
curl -X POST https://baozi.ohoooho.com/api/v1/tokens \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"order_id\":\"$ORDER\",\"name\":\"prod-001\"}"
# 5. 对账
curl https://baozi.ohoooho.com/api/v1/orders/$ORDER \
-H "Authorization: Bearer $TOKEN"
11. URL 自检清单
| URL | 状态 | 说明 |
|---|---|---|
POST /api/v1/m2m/auth | ✅ 200 | 已实现(实测) |
GET /api/v1/packages | ✅ 200 | 已实现(实测) |
GET /api/v1/packages/:id | ✅ 200/404 | 已实现 |
POST /api/v1/orders | ✅ 201 | 已实现(实测) |
GET /api/v1/orders | ✅ 200 | 已实现 |
GET /api/v1/orders/:id | ✅ 200/404 | 已实现(实测) |
POST /api/v1/tokens | ✅ 201 | 已实现(实测) |
GET /api/v1/tokens | ✅ 200 | 已实现(实测) |
GET /api/v1/tokens/:id | ✅ 200/404 | 已实现 |
DELETE /api/v1/tokens/:id | ✅ 200 | 已实现(实测) |
/api/third-party/keys | ❌ 已下架 | 从未注册(老文档凭空写) |
/api/third-party/orders/:id | ❌ 已下架 | 从未注册(老文档凭空写) |
/api/third-party/packages | ❌ 已下架 | 从未注册(老文档凭空写) |
12. 联系 baozi
- 邮箱:dev@ohoooho.com
- M2M client 创建 / 配额调整:发邮件附
client_id+ 你 baozi 账号 email - client_secret 泄露 / 撤销:发邮件,baozi 重置 + 旧 secret 立刻作废