Skip to content

第三方接入认证指南

读者画像:第三方公司的工程师,初次接触外脑(WaiNao.AI)API。本指南帮你回答四个问题——"我的场景该用哪种 Token?怎么申请?怎么写第一行代码?Token 泄漏怎么办?"

与其他文档的关系

  • 本文档:接入引导视角——第三方"该选哪种 Token、怎么走完接入流程"。
  • /dev/token-types实现视角——仓内开发者写新端点时挑认证中间件、看 401/403/429 区分。
  • /api/authentication端点参考视角——每个端点接受哪种 Authorization
  • /guide/oauth + /api/oauth:OAuth 教程与字段参考。

三者互补,不重复。OAuth 字段细节、端点列表请直接看上面三篇,本指南只负责"决策树 + 申请流程 + 第一行代码"。


1. 接入决策树

外脑对外暴露 4 种凭证(Token),第三方接入只会用到其中 3 种(API Key / OAuth / Agent Token);第 4 种 Supabase JWT 仅用于浏览器登录态,不在本指南范围。

你的接入场景是?
├── 我有一个第三方系统,用我自己的账户调外脑 API
│   → API Key(前缀 wn-)。流程见 §2
├── 我有一个第三方应用,让我的用户授权后由我代用户调
│   → OAuth 2.0(前缀 wno-)。流程见 §3
├── 我在写长寿命服务 / 桌面 Agent / 设备程序
│   → Agent Token(前缀 wna-)。流程见 §4
└── 我只是在浏览器里测试
    → Supabase JWT,浏览器登录后自动持有,不在本指南范围
选型维度API KeyOAuth 2.0Agent Token
代谁调代调用方自己代用户(用户授权过)代 Agent 所属团队
前缀wn-wno-wna-
谁创建Team Owner(团队设置页)站点管理员审核(无自助注册)Team Owner(Agent 管理页)
过期机制中间件支持过期检查,但创建路由当前不开放 expires_at 配置Access Token 短期 + Refresh Token 续期永久有效(除非主动吊销)
撤销团队设置中删除/oauth/revoke 或管理员禁用/删除 OAuth AppAgent 管理页吊销
典型场景第三方系统接 API、CI/CD、爬虫SaaS 集成、用户登录"使用 WaiNao 账号"长跑 Worker、桌面 Agent、IoT 设备
额度模型usage_credits / limit_credits(按 Key 计)按用户额度按 Agent 所属团队额度

不确定?把"我代谁调"想清楚就够了:代你自己 → API Key;代你的用户 → OAuth;代 Agent 自治 → Agent Token。


2. API Key 申请与使用

申请流程

API Key 由 Team Owner 在团队设置中创建,不是站点管理员后台。

  1. 登录编辑器 → 进入团队 → 团队设置 → API Keys 页面(编辑器路径:/o/:teamSlug/settings/api-keys,是编辑器内部产品路径,不是 docs-site 链接)
  2. 点击"创建 API Key",填写名称、描述、限额(limitCredits,单位为毫积分;不填则不限额)
  3. 后端返回明文 token(前缀 wn-),只在创建时返回一次——立即保存到密钥管理器或环境变量

创建路由当前不开放 expires_at

认证中间件支持 expires_at 过期检查(参考 apps/backend/src/middleware/authenticate-api-key.ts:130-143),但 当前创建路由(POST /teams/:teamId/api-keys,参考 apps/backend/src/routes/teams.ts:246-346)只暴露 name / description / limitCredits 三个字段,不开放 expires_at 配置。如需"短期 Token"语义,请改用 OAuth Access Token,或手动定期轮换 API Key。

可调用端点范围

API Key 可调用的端点列表请见 /api/authentication 中的『API Key 认证』章节(不写死 anchor,VitePress 自动生成的锚点含数字前缀,链接锚点容易失效)。常用端点包括 /my/api/released-app/*、ROMP 会话/消息等。

注意 JWT-only 端点

部分端点(例如 /runs 列表与详情)仅接受 Supabase JWT,不接受 API Key——API Key 调用会返回 403。具体哪个端点接受哪种 Token,永远以 /api/authentication 为准,不要按"看起来该可以"猜测。

第一行代码

GET /my 验证 Token 有效(API Key 可访问该端点):

bash
curl -H "Authorization: Bearer wn-xxxxxxxx" \
  https://block2-api.wainao.chat/my
ts
const res = await fetch('https://block2-api.wainao.chat/my', {
  headers: { Authorization: 'Bearer wn-xxxxxxxx' },
})
const me = await res.json()
console.log(me)
python
import requests

res = requests.get(
    'https://block2-api.wainao.chat/my',
    headers={'Authorization': 'Bearer wn-xxxxxxxx'},
)
print(res.json())

3. OAuth 2.0 接入

一句话决策

如果你需要 代用户调用 而不是 代你自己调用,用 OAuth。

例如你做了一个 SaaS 工具,希望用户在你的产品中"用 WaiNao 账号登录",并由你的服务端代用户访问其在 WaiNao 上的资源,就该走 OAuth。

时序图

第三方应用                    用户浏览器                    外脑 (WaiNao)
   │                              │                            │
   │ 1. 跳转 /oauth/authorize     │                            │
   │ ───────────────────────────> │                            │
   │                              │ 2. 显示授权页              │
   │                              │ <───────────────────────── │
   │                              │ 3. 用户点同意              │
   │                              │ ─────────────────────────> │
   │                              │ 4. 重定向到 redirect_uri   │
   │                              │ <───────────────────────── │
   │ 5. 收到 ?code=xxx            │                            │
   │ <─────────────────────────── │                            │
   │                                                           │
   │ 6. POST /oauth/token (code → access_token + refresh_token)│
   │ ──────────────────────────────────────────────────────────>│
   │ <──────────────────────────────────────────────────────────│
   │                                                           │
   │ 7. 用 wno- token 调 API                                   │
   │ ──────────────────────────────────────────────────────────>│
   │                                                           │
   │ 8. (Token 过期) POST /oauth/token (refresh_token)         │
   │ ──────────────────────────────────────────────────────────>│
   │ <──────────────────────────────────────────────────────────│

接入文档导航

完整接入流程与 API 字段细节请直接查阅以下文档(不在本指南重复):

  • 完整接入教程/guide/oauth
  • API 端点字段参考/api/oauth
  • 外脑自身 OAuth Callback 页面/oauth/callback(仅当你做"反向 OAuth"——让外脑作为客户端去回调外部 OAuth 提供方时才需要,普通接入不涉及)

OAuth App 创建

目前没有自助注册 API

当前站点管理员在管理后台创建/审核 OAuth App,暂无对外自助注册接口。申请方需联系站点管理员获取 client_id

外脑 OAuth App 是 Public Client + PKCE不会发放 client_secret,授权流程必须使用 PKCE(code_verifier / code_challenge)。如果你看到任何"开发者后台/自助申请页"或"获取 client_secret"的说法,那是计划中而未上线 / 不适用本平台的功能,请以本文为准。

第一行代码

获取 access_token 后调 GET /oauth/userinfo 验证(需要 token 持有 profile:read scope,否则返回 insufficient_scope;外脑当前仅支持 profile:readchat:completions 两个 scope,不使用 OpenID 标准 scope):

bash
curl -H "Authorization: Bearer wno-xxxxxxxx" \
  https://block2-api.wainao.chat/oauth/userinfo
ts
const res = await fetch('https://block2-api.wainao.chat/oauth/userinfo', {
  headers: { Authorization: 'Bearer wno-xxxxxxxx' },
})
const userinfo = await res.json()
console.log(userinfo)
python
import requests

res = requests.get(
    'https://block2-api.wainao.chat/oauth/userinfo',
    headers={'Authorization': 'Bearer wno-xxxxxxxx'},
)
print(res.json())

4. Agent Token 接入

申请流程

Agent Token 适合"长寿命服务 / 桌面 Agent / 设备程序"——需要永久有效、不需要 refresh、可以放在配置文件中的场景。

  1. 登录编辑器 → 进入团队 → Agent 管理页(编辑器路径:/o/:teamSlug/agents,是编辑器内部产品路径,不是 docs-site 链接)
  2. Team Owner 创建 Agent:填写名称、描述、绑定项目权限
  3. 签发 Token:后端返回明文 Token(前缀 wna-),只在签发时返回一次

行为特点

  • 永久有效:除非主动吊销,否则不过期,没有 refresh 概念
  • 撤销机制:在团队 Agent 管理页面"吊销 Token"——保留 Agent 配置,仅将后端的 token_hash 置为 null,被吊销后该 Token 立即失效
  • 额度归属:调用消耗 Agent 所属团队的积分,不消耗个人额度
  • 使用建议:写在配置文件 / 环境变量中,明确告知运维"明文只能拿一次,丢了只能吊销重发"

第一行代码

Agent Token 的典型使用场景是调"已发布应用的运行时端点"。前提:你的团队对该已发布应用有访问权限,且你有应用的 aliasversion

bash
curl -X POST \
  -H "Authorization: Bearer wna-xxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"input": "hello"}' \
  https://block2-api.wainao.chat/api/released-app/r/<alias>/<version>/<endpoint>
ts
const res = await fetch(
  'https://block2-api.wainao.chat/api/released-app/r/<alias>/<version>/<endpoint>',
  {
    method: 'POST',
    headers: {
      Authorization: 'Bearer wna-xxxxxxxx',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ input: 'hello' }),
  },
)
console.log(await res.json())
python
import requests

res = requests.post(
    'https://block2-api.wainao.chat/api/released-app/r/<alias>/<version>/<endpoint>',
    headers={
        'Authorization': 'Bearer wna-xxxxxxxx',
        'Content-Type': 'application/json',
    },
    json={'input': 'hello'},
)
print(res.json())

注意:/my 端点不接受 Agent Token,因为 Agent 不是"个人用户",没有个人 profile。要拿 Agent 自身信息请调 Agent 管理 API。


5. 代码示例(实战对比)

如果你想让三类 Token 调同一个端点对比行为,请用 /api/released-app/* 系列运行时端点——它们同时支持 API Key、OAuth、Agent Token(前提是有发布应用 + 对应的权限/scope)。当前同时挂在该认证链上的运行时端点包括:

  • POST /api/released-app/:deploymentId/run
  • POST /api/released-app/d/:documentId/run
  • ALL /api/released-app/r/:alias/:version/:path(本文以下示例统一用此别名版本路径形式)

/my 端点只接受 API Key 与 Supabase JWT(不接受 OAuth/Agent);/oauth/userinfo 只接受 OAuth Token。下面 9 段示例按"端点合法性"挑选。

5.1 API Key 调 /my

bash
curl -H "Authorization: Bearer wn-xxxxxxxx" \
  https://block2-api.wainao.chat/my
ts
const res = await fetch('https://block2-api.wainao.chat/my', {
  headers: { Authorization: 'Bearer wn-xxxxxxxx' },
})
console.log(await res.json())
python
import requests

res = requests.get(
    'https://block2-api.wainao.chat/my',
    headers={'Authorization': 'Bearer wn-xxxxxxxx'},
)
print(res.json())

5.2 Agent Token 调已发布应用

bash
curl -X POST \
  -H "Authorization: Bearer wna-xxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"input": "hello"}' \
  https://block2-api.wainao.chat/api/released-app/r/<alias>/<version>/<endpoint>
ts
const res = await fetch(
  'https://block2-api.wainao.chat/api/released-app/r/<alias>/<version>/<endpoint>',
  {
    method: 'POST',
    headers: {
      Authorization: 'Bearer wna-xxxxxxxx',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ input: 'hello' }),
  },
)
console.log(await res.json())
python
import requests

res = requests.post(
    'https://block2-api.wainao.chat/api/released-app/r/<alias>/<version>/<endpoint>',
    headers={
        'Authorization': 'Bearer wna-xxxxxxxx',
        'Content-Type': 'application/json',
    },
    json={'input': 'hello'},
)
print(res.json())

5.3 OAuth Token 调 /oauth/userinfo

bash
curl -H "Authorization: Bearer wno-xxxxxxxx" \
  https://block2-api.wainao.chat/oauth/userinfo
ts
const res = await fetch('https://block2-api.wainao.chat/oauth/userinfo', {
  headers: { Authorization: 'Bearer wno-xxxxxxxx' },
})
console.log(await res.json())
python
import requests

res = requests.get(
    'https://block2-api.wainao.chat/oauth/userinfo',
    headers={'Authorization': 'Bearer wno-xxxxxxxx'},
)
print(res.json())

6. 常见问题(FAQ)

Q1: Token 泄漏怎么办?

立即撤销 + 检查日志两步走。

撤销入口(这些是编辑器内部产品路径,不是 docs-site 链接,复制到编辑器域名访问即可):

  • 当前可用:
    • API Key → 编辑器内 /o/:teamSlug/settings/api-keys
    • Agent Token → 编辑器内 /o/:teamSlug/agents("吊销 Token")
  • F3(凭证管理 UI)上线后:
    • 三类凭证聚合页 → 编辑器内 /o/:teamSlug/settings/credentials

撤销后立即检查后端日志,确认是否有未授权调用,必要时联系运维拉取 IP / UA 维度的访问统计。

Q2: 如何撤销?

按 Token 类型选择对应入口(路径不一致,不要套用同一个端点):

Token 类型撤销方式入口
API Key编辑器 UI(当前由前端调 Supabase RPC delete_api_key,没有公开 REST 端点)编辑器内 /o/:teamSlug/settings/api-keys
Agent Token编辑器 UI 或后端 REST 端点编辑器内 /o/:teamSlug/agents("吊销 Token");后端 POST /teams/:teamId/agents/:bindingId/revoke-token(实现见 apps/backend/src/routes/team-agents.ts:730+
OAuth Access / Refresh TokenRFC 7009 撤销端点POST /oauth/revoke(详见 /api/oauth
OAuth App 整体站点管理员后台禁用 / 删除 OAuth App,所有发给该 client 的 Token 立即失效站点管理员操作

Q3: 我收到 4xx 错误,是额度耗尽还是限流?

403429 含义完全不同,不要混淆

状态码含义触发条件自愈方式
403 API key credit limit exceeded额度耗尽(按月/总量)usage_credits >= limit_credits提高 limit_credits 或等下个计费周期
429 Too Many Requests频率限流(短时间内 QPS 过高)触发 X-RateLimit-* headers 中的窗口阈值客户端做指数退避重试,降低 QPS

判别要点:

  • 403:响应体里能看到 credit limit exceeded 关键字,说明你这个月(或这个 Key 的限额)用光了——这是用量问题,不是网络问题,重试也没用。
  • 429:响应头里能看到 X-RateLimit-Limit / X-RateLimit-Remaining / X-RateLimit-Reset,说明你刚才发得太快,按 Retry-AfterX-RateLimit-Reset 等待后重试即可。

Q4: API Key vs OAuth,到底选哪个?

回到 §1 的决策树:

代调用方自己 ────→ API Key
代第三方用户 ────→ OAuth
代自治 Agent ────→ Agent Token

如果你的产品里"用户必须先登录 WaiNao",那一定是 OAuth;如果"用户不知道你在背后调 WaiNao",那一定是 API Key。两者不可互换——OAuth Token 不能调 /my(属主是 OAuth User,不是 API Key 持有者),API Key 也不能代替你的用户的额度。

Q5: 一个 Team 可以同时持有多种 Token 吗?

可以。同一个 Team 可以有:

  • 多个 API Key(按用途区分,比如 croncidev
  • 多个 Agent(每个 Agent 一个 Token)
  • 任意数量的 OAuth Client(如果该 Team 是 OAuth 应用的所有者)

每种 Token 独立计费、独立撤销,互不影响。

Q6: 测试环境怎么办?

外脑当前没有公开的"沙箱环境"。建议你在自己的 Team 下创建一个 dev API Key 设置较低的 limitCredits(比如 1000 毫积分 = 1 积分),用完后自然报 403,不会越权消耗主额度。


下一步

最后更新于:

AI Workflow Editor