第三方 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_idbaozi 运营手工创建
client_secretbaozi 运营手工创建(仅创建时返回一次)
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 含义
400invalid_grantgrant_type 错
401invalid_clientclient_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
}

需要 scopepackages: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
  }
}

需要 scopeorders: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
  }
}

需要 scopetokens: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 含义 触发场景
400invalid_grantgrant_type 错拿 token 时
401invalid_clientclient_id / client_secret 错拿 token 时
401unauthorized缺 Bearer 或 token 过期调 v1 业务接口
403scope_missingtoken 缺 scopescope 不够
404package_not_found套餐 ID 不存在GET /packages 时 ID 错
404order_not_found订单 ID 不存在GET /orders/:id
409package_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