Appearance
开放 API
Base URL:https://<你的机灵兔部署域名>/api/open
除 POST /auth/token 外,其余接口都需要:
Authorization: Bearer <app access token>端点速查
| 端点 | 能力 | 一句话 |
|---|---|---|
POST /auth/token | — | app_key/secret 换 2h token |
POST /auth/user | 免登 | authCode 换用户身份 |
GET /org/members | contacts | 成员列表(分页) |
GET /org/teams、GET /org/teams/{id}/members | contacts | 团队树/团队成员 |
POST /im/send | im | 给成员发工作通知(≤100 人/次) |
GET /ai/models | ai | 可用对话模型清单(不必硬编码模型 id) |
POST /ai/completions | ai | 对话补全(支持 stream SSE) |
POST /kb/search | kb | 绑定知识库内检索 |
GET /db/databases、GET /db/{id}/tables… | db | 绑定库清单/表结构 |
POST /db/query | db | 只读 SELECT(强校验) |
GET/POST/PUT/DELETE /tools[/{id}] | ai_tools 前提 | 工具自管理(免管理员 UI) |
POST /tools/result | 同上 | 异步工具结果回填 |
GET /jsapi/jlt.js | — | JSAPI SDK(公开) |
token 的获取与缓存见免登与鉴权。可直接复制运行的完整调用示例 (curl / Node.js / Python)见完整示例;平台主动推送的事件 回调见事件订阅。
POST /auth/token
app_key + app_secret 换 app access token。
| 参数 | 类型 | 约束 |
|---|---|---|
app_key | string | ≤ 64 字符 |
app_secret | string | ≤ 128 字符 |
json
// 请求
{ "app_key": "oak_xxx", "app_secret": "xxx" }
// 响应
{ "access_token": "xxx", "token_type": "Bearer", "expires_in": 7200 }POST /auth/user
免登:一次性 authCode 换当前用户身份。请求/响应详见免登与鉴权。
| 参数 | 类型 | 约束 |
|---|---|---|
auth_code | string | ≤ 128 字符,5 分钟有效、一次性 |
GET /org/members
需要 contacts 能力。分页读取组织成员,按加入时间排序。
| 参数 | 类型 | 约束 |
|---|---|---|
org_id | string | 可选,缺省 = 应用所属组织;传安装方组织需对方已授 contacts,否则 403 |
offset | int | ≥ 0,默认 0 |
limit | int | 1–100,默认 50 |
json
{
"org_id": "org_abc",
"members": [
{ "user_id": "u_1", "role": "owner", "nickname": "张三", "avatar_url": "", "title": "" }
],
"offset": 0,
"limit": 50
}GET /org/teams
需要 contacts 能力。组织架构(团队拉平 + 各自成员数);parent_team_id 为空表示顶层团队,用它可以自行组装出层级树。
GET /org/teams?org_id=json
{
"org_id": "org_abc",
"teams": [
{ "id": "team_1", "name": "研发组", "description": "", "parent_team_id": null, "member_count": 12, "created_at": "…" },
{ "id": "team_2", "name": "前端小组", "description": "", "parent_team_id": "team_1", "member_count": 5, "created_at": "…" }
]
}GET /org/teams/{team_id}/members
需要 contacts 能力。某个团队的成员(含团队角色 admin/member);团队 必须属于目标组织(org_id 缺省 = 应用所属组织),否则 404。
json
{
"team_id": "team_1",
"members": [
{ "user_id": "u_1", "role": "admin", "nickname": "张三", "avatar_url": "", "title": "前端负责人" }
]
}POST /im/send
需要 im 能力。给组织成员发工作通知,由系统通知账号代发,消息会自动带上 【你的应用名】 前缀——你的应用不能冒充某个用户说话。
| 参数 | 类型 | 约束 |
|---|---|---|
user_ids | string[] | 1–100 个,目标必须是该组织成员,否则该项返回失败 |
content | string | 1–2000 字符 |
org_id | string | 可选,缺省 = 应用所属组织;传安装方组织需对方已授 im |
json
// 请求
{ "user_ids": ["u_1", "u_2"], "content": "你有一条新的审批待处理", "org_id": "" }
// 响应(逐目标返回,单个失败不影响其他目标)
{ "results": [{ "user_id": "u_1", "ok": true }, { "user_id": "u_2", "ok": false, "error": "不是该组织成员" }] }GET /ai/models
需要 ai 能力。可用对话模型清单——模型集由平台统一管理,会随时增删, 三方应用不应在自己代码里硬编码模型 id,改为启动时/定期拉一次这个接口渲染选择器。 default 是 /ai/completions 不传(或传 "auto")时实际生效的模型。
json
{
"default": "qwen3.7-plus",
"models": [
{ "id": "qwen3.7-plus", "name": "qwen3.7-plus", "context_length": null },
{ "id": "glm-5", "name": "glm-5", "context_length": null }
]
}POST /ai/completions
需要 ai 能力。非流式对话补全(OpenAI 兼容的消息格式),计费走应用所属组织 的积分钱包(不是调用方所在组织);组织未开通钱包时返回 402。
| 参数 | 类型 | 约束 |
|---|---|---|
messages | array | 1–50 条,每条 role ≤ 16 字符(user/assistant/system…)、content ≤ 32000 字符 |
model | string | 可选;留空或传 "auto" 都用平台默认模型(见 GET /ai/models 的 default),也可传该接口返回的任意模型 id |
max_tokens | int | 1–8192,默认 2048 |
temperature | number | 可选,0–2 |
stream | boolean | 可选,默认 false;true 时返回 OpenAI 兼容的 SSE 流(text/event-stream) |
json
// 请求
{
"messages": [{ "role": "user", "content": "帮我总结一下这段文字…" }],
"max_tokens": 2048
}
// 响应
{
"model": "qwen3.7-plus",
"content": "……",
"finish_reason": "stop",
"usage": { "prompt_tokens": 12, "completion_tokens": 88, "total_tokens": 100 }
}POST /kb/search
需要 kb 能力,且应用必须已绑定至少一个知识库(在应用设置里配置,只能绑定 配置人自己能访问的知识库)。检索永远限制在绑定白名单内。
| 参数 | 类型 | 约束 |
|---|---|---|
query | string | 1–200 字符 |
kb_id | string | 可选;传则必须已绑定到此应用,否则 403;缺省检索全部绑定的库 |
max_hits | int | 1–50,默认 20 |
json
// 请求
{ "query": "报销流程", "max_hits": 20 }
// 响应
{ "hits": [{ "kb_id": "kb_1", "path": "报销制度.md", "line": 12, "snippet": "……" }] }GET /db/databases / GET /db/{db_id}/tables[/{table}]
需要 db 能力。绑定的数据库清单(只含 id/名称/类型,不含连接信息与凭证); 表清单与表结构用于拼查询。
POST /db/query
需要 db 能力,且 db_id 必须已绑定到此应用。在绑定库上执行只读查询, 安全边界与用户侧完全一致:单条 SELECT/WITH、禁写关键字、行数上限、语句 超时——写语句直接被拒,不会到达数据库。
| 参数 | 类型 | 约束 |
|---|---|---|
db_id | string | 必须在绑定白名单内,否则 403 |
sql | string | 1–8000 字符,单条只读 SELECT |
limit | int | 1–1000,默认 100 |
json
// 请求
{ "db_id": "…", "sql": "SELECT status, COUNT(*) FROM orders GROUP BY status", "limit": 100 }
// 响应
{ "ok": true, "columns": ["status", "count"], "rows": [{ "status": "paid", "count": 12 }] }
// 写语句被拒
{ "ok": false, "error": "仅允许 SELECT 查询" }GET/POST/PUT/DELETE /tools[/{tool_id}]
应用自管理自己的 AI 工具(注册/列出/修改/删除,无需管理员 UI)。POST/PUT 的 callback_url 会先做 challenge 验证;字段与给 AI 注册工具 一致(name/description/parameters/callback_url/timeout_sec(5–120)/ wants_context)。前提:应用已勾选 ai_tools 能力。变更限流 30 次/分钟。
POST /tools/result
异步工具模式的结果回填: {call_id, result}——call_id 来自工具回调体,绑定本应用。
GET /jsapi/jlt.js
公开接口,返回 JSAPI SDK 源码,供页面 <script> 引入。可缓存(1 小时)。
限流
进程内限流,超限返回 429,稍后重试即可:
| 接口 | 限额 |
|---|---|
POST /auth/token | 20 次/分钟(按 app_key) |
POST /im/send | 60 次/分钟(按应用) |
GET /ai/models | 30 次/分钟(按应用) |
POST /ai/completions | 30 次/分钟(按应用) |
POST /kb/search | 60 次/分钟(按应用) |
POST /db/query | 30 次/分钟(按应用) |
/tools 变更(POST/PUT/DELETE) | 30 次/分钟(按应用) |
服务器 IP 白名单
应用设置里可配置服务器 IP 白名单(精确 IP 或 CIDR,如 203.0.113.5、 10.0.0.0/8,最多 20 条)。非空时,所有 /api/open/* 调用(含换 token) 只接受这些来源 IP,其余返回 403——即使 app_secret 泄露,别的机器也换不出 token。留空 = 不限制。
填什么地址
填你应用后端服务器的出口 IP(即它访问机灵兔 API 时对外呈现的地址), 不是你办公室/用户的 IP。服务器有多台或出口不固定时用 CIDR 段。
来源 IP 以反向代理记录的真实客户端地址为准(X-Real-IP / 转发链尾跳), 伪造 X-Forwarded-For 首部无法通过白名单。
错误响应
统一形状:
json
{ "detail": "人类可读的错误说明" }| HTTP 状态 | 含义 |
|---|---|
| 400 | 参数校验失败;authCode 无效/已使用/已过期 |
| 401 | app token 缺失/无效/过期;app_key/app_secret 不正确;密钥已轮换;应用已停用或组织已解散 |
| 402 | 组织钱包未开通(AI 能力) |
| 403 | 能力未被授予;目标组织未安装此应用;知识库未绑定到此应用;来源 IP 不在白名单内 |
| 429 | 触发限流 |
| 502 | 上游模型调用失败(AI 能力) |
| 503 | 系统通知账号暂不可用(im/send) |