API 运行接口
已发布应用的外部 API 调用入口。支持通过 Deployment ID、Document ID 或 Release 别名三种方式调用。
源码: apps/backend/src/routes/api-run.ts
POST /api/released-app/:deploymentId/run
通过 Deployment ID 运行已发布的应用。
认证方式
API Key / Schedule Token / OAuth Access Token
- API Key:
Authorization: Bearer wn-... - Schedule Token:JWT 格式
- OAuth Token:
Authorization: Bearer wno-...(需要chat:completionsscope)
请求参数
Path 参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
deploymentId | string | 是 | 部署 UUID |
Body 参数
{
"inputs": { "text": "hello world" },
"version": "^1.0",
"stream": true,
"format": "ndjson",
"timeout": 60
}| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
inputs | object | {} | Input Block 的输入值 |
version | string | - | 版本号。"1.0":精确匹配;"^1.0":major=1 的最新 minor;省略:最新版本 |
stream | boolean | true | 是否流式响应 |
format | "sse" | "ndjson" | "ndjson" | 流式响应格式(注意:API 调用默认 NDJSON,与编辑器默认 SSE 不同) |
timeout | number | - | 超时时间(秒),不超过管理后台配置的最大值 |
允许空 body(使用默认值)。
触发上下文
_trigger(issue #691):服务端会按调用来源构造_trigger对象并注入inputs._trigger(API 调用为{ source: 'api', triggered_at };定时任务/Webhook 触发分别为source: 'schedule'/'webhook'并附schedule_id/webhook_id等)。该字段为保留字: 调用方在inputs或 body 顶层传入的_trigger会被服务端覆写,无法伪造。 工作流绑定触发器模板后可通过_trigger输入读取,详见/api/webhook-triggers。
Query 参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
trace | string | - | 设为 full 时返回完整执行轨迹 globalCtx(调试用)。默认不返回,详见下文「响应体大小上限与 trace 开关」。 |
响应体大小上限与 trace 开关
行为变更(Breaking Change)
为防止内联大文件(如大 base64 图片)经子流程放大撑爆响应体打垮平台,自本次起:
- 裸部署 run 端点(
/:deploymentId/run、/d/:documentId/run)默认不再返回globalCtx(完整执行轨迹)。只返回最终输出sessions(通常几 KB)。 - 需要完整轨迹用于调试时,显式加查询参数
?trace=full。globalCtx中的超大字符串(如大 base64)会被替换为占位{ "__truncated": true, "originalBytes": N, "preview": "..." },避免多份内联副本。 - 整个响应体受大小上限保护(默认约 8 MiB,可由管理后台
run.response_limit配置)。超限时:- JSON 一次性模式(
stream:false)→ 返回 HTTP 413 +{ "error": "response_too_large", ... },不会尝试序列化超大对象到 OOM。 - 流式模式(NDJSON / SSE)→ HTTP 状态码已发出无法更改,故返回 200,并以终态事件
run_error(error: "response_too_large",含executionStatus)结束,不发送超大的run_complete/globalCtx。
- JSON 一次性模式(
- Release 网关端点(
/r/:alias/:version/*)行为不变(本就通过输出映射只返回精简输出,不含globalCtx)。
迁移建议:依赖 globalCtx 的调用方请改加 ?trace=full;更稳妥的做法是改用 /r/ 网关端点 + 输出映射,或用 wnfile 句柄传入大文件而非内联 base64。
请求体 / 输入大小上限(issue #664)
行为变更(Breaking Change)
为根治输入侧 OOM(超大 prompt / 内联大 base64 图纸撑爆平台内存),所有 run 入口(/:deploymentId/run、/d/:documentId/run、Release /r/:alias/:version/*)在解析输入后、执行前加分层硬上限,超限明确报错(4xx),不静默放行。
| 维度 | 默认上限 | 超限错误码 | HTTP |
|---|---|---|---|
| 请求体总大小 | 4 MiB | request_body_too_large | 413 |
| 单个输入字段 | 1 MiB | input_field_too_large | 400 |
| 内联 data URI base64 负载 | 1 MiB | inline_base64_too_large | 400 |
| 全部文本输入聚合字节 | 1 MiB | prompt_too_large_bytes | 400 |
| 全部文本输入聚合 token | 200,000 | prompt_too_large_tokens | 400 |
| 输入结构嵌套深度 | 32 | input_structure_too_deep | 400 |
| 输入结构节点数 | 100,000 | input_structure_too_large | 400 |
- 所有阈值热可调:管理后台
site_settings的run.input_limit配置(缺失/非法走上表安全默认,5 分钟缓存)。回归较大时可临时调大对应项。 - 请求体总大小上限远小于网关
client_max_body_size(512m)——run 输入应走文件句柄而非内联文件。 - 错误响应体形如
{ "error": "<code>", "message": "...", "field": "inputs.xxx", "actual": <字节/token>, "limit": <上限> }。 wnfile:/storage://文件句柄不计入上述字段/聚合限制(仅当引用串短于 256 字符、形如「协议 + ID」时豁免;超长的伪句柄不豁免,照常计入文本限制)。- 只精确拦截 data URI(
data:...;base64,...)形态的内联 base64;裸 base64(无data:前缀)不做启发式识别(避免误伤普通长文本),由单字段 / 聚合字节限兜底。
内联 base64 → wnfile 句柄迁移示例
不要把图片 base64 内联进 inputs:
// ❌ 会被 inline_base64_too_large 拒绝(超过 base64 上限时)
{ "inputs": { "image": "data:image/png;base64,iVBORw0KGgoAAAANS...(很长)" } }改为先上传文件拿到 wnfile: 句柄,再把句柄作为输入传入:
// ✅ 先调上传接口得到 file id,再传句柄(不受 base64/字段大小限制)
{ "inputs": { "image": "wnfile:550e8400-e29b-41d4-a716-446655440000" } }PDF 输入处理(base64 / data URL,issue #677 / #678)
PDF 类型输入({"_type":"pdf","value":...})支持三种 value 形态,行为统一:
| value 形态 | 处理 |
|---|---|
wnfile:<id> / storage://<id> 句柄 | 服务端下载并走 PDF→文字预处理(转 Markdown 注入 prompt),任意模型可读,不要求模型有 pdf 能力 |
data:application/pdf;base64,<...> | 服务端直接解码并走同一套 PDF→文字预处理,无需先上传(API Key 无法走 /storage 上传,故由服务端代解码) |
裸 base64(无 data: 前缀) | 自动按 %PDF- 文件头识别为 PDF,走同样的预处理;非 PDF 内容(无 %PDF- 头)则按原样文本处理 |
要点:
- 任意模型可读:经预处理转文字后,识别块即使配置的模型没有
pdf原生能力也能正常跑通(这正是「编辑器手动上传 PDF 能跑通、而早期 base64 直传报错」的根因修复)。 - 裸 base64 自动补前缀:未走预处理而直达模型原生通道的内联 PDF/图片,服务端按文件魔数自动补
data:application/pdf;base64,/data:image/<png|jpeg|webp|gif>;base64,前缀,调用方无需自己拼 data URL。 - 降级不再爆上下文:若模型既无
pdf能力又未走预处理,PDF 输入会被替换为简短提示文本(而非把整串 base64 当文本注入 prompt),避免撑爆上下文。 - 体积上限:内联 PDF base64 仍受输入层
inline_base64_too_large(默认 1 MiB)限制;大文件请改用wnfile:句柄。
// ✅ 直接内联 base64 PDF(自动预处理,任意模型可读)
{ "inputs": { "doc": { "_type": "pdf", "value": "data:application/pdf;base64,JVBERi0xLjQK..." } } }
// ✅ 裸 base64 也可(自动识别 %PDF- 并补前缀)
{ "inputs": { "doc": { "_type": "pdf", "value": "JVBERi0xLjQK..." } } }响应格式
NDJSON 流式响应(默认)
Content-Type: application/x-ndjson
API 模式下仅输出数据类 Block 的事件,过滤掉 prompt 等内部 Block 信息:
{"type":"run_start","runId":"uuid","documentId":"uuid"}
{"type":"block_start","blockId":"uuid","blockType":"code"}
{"type":"block_chunk","blockId":"uuid","delta":"部分输出"}
{"type":"block_complete","blockId":"uuid","output":"完整输出"}
{"type":"block_end","blockId":"uuid"}
{"type":"run_complete","runId":"uuid","sessions":[...],"completedBlocks":1,"duration":1234}
run_complete默认不含globalCtx;加?trace=full后才追加(大 blob 已截断)。 若响应体超限,最后一行改为{"type":"run_error","runId":"uuid","error":"response_too_large","executionStatus":"completed",...}。
SSE 流式响应(format: "sse")
Content-Type: text/event-stream
事件类型与 NDJSON 一致,但使用 SSE 格式:
event: run_start
data: {"runId":"uuid","documentId":"uuid"}
event: block_complete
data: {"blockId":"uuid","output":"完整输出"}
event: run_complete
data: {"runId":"uuid","sessions":[...],"completedBlocks":1,"duration":1234}同 NDJSON:默认不含
globalCtx,?trace=full才追加;超限时以event: run_error(error: "response_too_large")终止。
JSON 一次性响应(stream: false)
状态码: 200
{
"runId": "uuid",
"documentId": "uuid",
"sessions": [
{
"blockId": "uuid",
"blockType": "code",
"blockName": "处理数据",
"status": "completed",
"output": "处理结果"
}
],
"duration": 1234,
"status": "success",
"timedOut": false
}默认不含
globalCtx。加?trace=full后,响应额外包含globalCtx数组(完整执行轨迹,大 blob 已截断为占位)。
块级错误透出(
?trace=full,issue #678):当某个 blockstatus为error时,仅在带?trace=full的请求下,该 session 会额外携带一个脱敏后的error字段(简短可定位的错误信息,已剥离凭证 / data URI / 长 base64 等敏感大负载,并截断到 500 字符)。不带?trace=full时维持原行为(仅status: "error",无error字段,保持向后兼容)。流式(NDJSON/SSE)的block_error事件本就实时携带error,不受此开关影响。json// ?trace=full 下出错 block 的 session 形态 { "blockId": "uuid", "blockType": "structure", "blockName": "识别", "status": "error", "output": null, "error": "内联数据不是合法 PDF(缺少 %PDF- 文件头)" }
响应体超限(stream: false)
状态码: 413
{
"runId": "uuid",
"error": "response_too_large",
"message": "响应体超过大小上限,已拒绝返回完整结果",
"actualBytes": 8389000,
"limitBytes": 8388608,
"executionStatus": "completed",
"hint": "请改用 wnfile 句柄输入以避免内联大 base64;或通过 /r/ 网关端点 + 输出映射获取精简输出;或减小工作流输出体积。"
}
hint默认建议改用 wnfile 句柄 //r/网关 / 减小输出;仅当本次请求确实带了?trace=full时,才额外提示「去掉?trace=full重试」(避免误导未带该参数的调用方)。
actualBytes是 fail-fast 在「首次累计超过上限」那一刻的字节数,是真实响应大小的下界(不会继续序列化以求精确值),语义为「至少这么大、已超限」。
权限规则
| 部署可见性 | API Key 认证 | Schedule 认证 | OAuth 认证 |
|---|---|---|---|
public | 任意有效 API Key | 已通过 Token 验证 | 任意有效 OAuth Token |
private | API Key 所属团队必须与部署所属团队一致 | 已通过 Token 验证(跳过权限检查) | 部署 owner 必须是当前用户,或用户属于部署所属团队 |
请求示例
# JSON 一次性响应
curl -X POST \
-H "Authorization: Bearer wn-your-api-key" \
-H "Content-Type: application/json" \
-d '{"inputs": {"text": "hello"}, "stream": false}' \
https://block2-api.wainao.chat/api/released-app/DEPLOYMENT_UUID/run
# NDJSON 流式响应
curl -X POST \
-H "Authorization: Bearer wn-your-api-key" \
-d '{"inputs": {"text": "hello"}}' \
https://block2-api.wainao.chat/api/released-app/DEPLOYMENT_UUID/run
# 指定版本
curl -X POST \
-H "Authorization: Bearer wn-your-api-key" \
-d '{"inputs": {"text": "hello"}, "version": "^1.0"}' \
https://block2-api.wainao.chat/api/released-app/DEPLOYMENT_UUID/run错误码
| 状态码 | 错误 | 说明 |
|---|---|---|
| 400 | Input validation failed | 输入参数验证失败 |
| 400 | input_field_too_large | 单个输入字段超大小上限(见「请求体 / 输入大小上限」) |
| 400 | inline_base64_too_large | 内联 data URI base64 超上限,请改用 wnfile: 句柄 |
| 400 | prompt_too_large_bytes / prompt_too_large_tokens | 全部文本输入聚合字节 / token 超上限 |
| 400 | input_structure_too_deep / input_structure_too_large | 输入结构嵌套过深 / 节点过多 |
| 401 | Unauthorized | 认证失败或认证方式不支持 |
| 402 | insufficient_credits | 积分余额不足 |
| 403 | Permission denied: This is a private app... | 无权访问私有应用 |
| 403 | Deployment ID mismatch | Schedule Token 中的 deploymentId 不匹配 |
| 404 | Deployment not found | 部署不存在或版本未找到 |
| 413 | request_body_too_large | 请求体总大小超上限(见「请求体 / 输入大小上限」) |
| 413 | response_too_large | 响应体超过大小上限(仅 stream:false;流式模式以终态 run_error 表达,状态码仍 200) |
| 500 | Invalid deployment snapshot: missing content | 部署快照数据损坏 |
POST /api/released-app/d/:documentId/run
通过 Document ID 运行已发布的应用。Document ID 是稳定的标识符,不会因重新发布而改变。
认证方式
API Key(仅 API Key,apiKeyAuth)
请求参数
Path 参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
documentId | string | 是 | 文档 UUID(稳定标识) |
Body 参数
与 /:deploymentId/run 一致。
响应格式
与 /:deploymentId/run 一致。
请求示例
curl -X POST \
-H "Authorization: Bearer wn-your-api-key" \
-d '{"inputs": {"text": "hello"}, "stream": false}' \
https://block2-api.wainao.chat/api/released-app/d/DOCUMENT_UUID/run错误码
与 /:deploymentId/run 一致,额外包含:
| 状态码 | 错误 | 说明 |
|---|---|---|
| 401 | Unauthorized: Document ID route only supports API key authentication | 仅支持 API Key 认证 |
ALL /api/released-app/r/:alias/:version/*
Release 网关路由。通过应用别名 + 版本号 + 路径匹配已发布的端点并执行。
认证方式
接受 API Key、OAuth Access Token 或 Agent 绑定授权(路由链 releaseGatewayResolve → oauthAuth → oauthScopeGuard → apiKeyAuth)。是否强制鉴权由 Release 配置决定(REL-001,fail-closed):
- 默认要鉴权:
releaseConfig.requireAuth !== false时,调用必须携带有效凭据(API Key / OAuth Access Token / Agent 绑定授权),否则401。配置缺失或解析失败一律按「要鉴权」。 - 端点级豁免:端点配置
skipAuth: true可让单个端点公开(覆盖全局requireAuth),此时无需凭据即可调用。 - 防 401 绕过:只要请求带了任一凭据 header(
Authorization/X-API-Key/X-Internal-Secret/X-Internal-Api-Key-Id,即便值非法或为空),都会强制走鉴权,不会被当匿名放行。 - 私有部署:匿名访问私有部署返回
403,即使该端点免鉴权。
限流(REL-002)
Release 可配置 rateLimit(windowSeconds 正整数 ≤ 3600、maxRequests 正整数 ≤ 100000);配置非法时回落全局限流。按调用方分桶(API Key 按 apiKeyId、Agent 按 bindingId,OAuth 与匿名公开端点按 release + 客户端 IP)。超过限流返回 429(附 Retry-After 头),响应体 { "error": "Too many requests, please try again later" }。
请求参数
Path 参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
alias | string | 是 | Release 别名 |
version | string | 是 | 版本号字符串 |
* | string | 是 | 路由路径(匹配 routerTree 中的端点) |
Body / Query 参数
- 非 GET 请求: 从请求体解析 inputs
- GET 请求: 从 query 参数构建 inputs
匹配规则
- 通过
alias在release_aliases表中查找release_document_id - 根据版本号解析匹配的已发布版本
- 在版本的
routerTree中按 path + HTTP method 匹配端点 - 找到端点关联的
deploymentId并执行
响应格式
固定使用 JSON 一次性响应(runWithJSON),格式与上述 JSON 响应一致。
请求示例
# GET 请求(参数通过 query 传递)
curl -H "Authorization: Bearer wn-your-api-key" \
"https://block2-api.wainao.chat/api/released-app/r/my-app/v1/users?name=test"
# POST 请求(参数通过 body 传递)
curl -X POST \
-H "Authorization: Bearer wn-your-api-key" \
-d '{"name": "test"}' \
"https://block2-api.wainao.chat/api/released-app/r/my-app/v1/users"错误码
| 状态码 | 错误 | 说明 |
|---|---|---|
| 401 | Unauthorized | 认证失败;或要求鉴权(requireAuth)时未携带有效凭据 |
| 403 | Permission denied | 无权访问私有应用(含匿名访问私有部署) |
| 429 | Too many requests, please try again later | 触发 Release 限流(rateLimit),见 Retry-After 头 |
| 404 | Release alias 'xxx' not found | 别名不存在 |
| 404 | No published version matching 'xxx' found | 版本不存在 |
| 404 | No endpoint matching METHOD /path | 端点未匹配 |
| 400 | Endpoint 'xxx' has no deployment configured | 端点未配置部署 |
| 404 | Deployment not found | 关联的部署不存在 |
| 413 | request_body_too_large | 请求体总大小超上限(见「请求体 / 输入大小上限」,与裸部署端点同一套阈值) |
| 400 | input_field_too_large / inline_base64_too_large / prompt_too_large_bytes / prompt_too_large_tokens / input_structure_too_deep / input_structure_too_large | 输入分层硬上限(见「请求体 / 输入大小上限」);内联 base64 超限请改用 wnfile: 句柄 |
补充端点
本节补充 plans/need-update-api.md 中尚未覆盖到 docs-site 的接口。端点标题保持严格的 METHOD /path 格式,便于后台文档覆盖率服务识别。
GET /api/released-app/cross-team/bindings
列出当前调用方可用的跨团队 released app 绑定。
认证:API Key、Schedule Token、OAuth Access Token 或跨团队绑定授权。 请求:无请求体。Query 参数用于分页、过滤、搜索或状态筛选;未传时按后端默认排序与分页返回。
响应:成功时返回目标资源详情、状态或配置对象。
常见错误:400 参数非法,401 未认证,403 权限不足,404 资源不存在;服务端或上游异常返回 500。
POST /api/released-app/cross-team/proxy
通过跨团队绑定代理调用目标 released app。
认证:API Key、Schedule Token、OAuth Access Token 或跨团队绑定授权。 请求:请求体为 JSON,包含创建、提交、安装、发布或业务动作所需字段。
响应:成功时返回创建或更新后的资源对象,或 { "success": true }。
常见错误:400 参数非法,401 未认证,403 权限不足,404 资源不存在;服务端或上游异常返回 500。