入站 Webhook
外部系统向 Soln 写入数据时调用入站 Webhook 接口:请求体就是流程的输入数据,流程再按画布上的映射写入本地表单。
只有 入站 + Webhook 流程会暴露这个地址。查询数据和消息推送各有自己的地址,见查询数据和消息推送。
请求方式
| 项 | 说明 |
|---|---|
| 方法 | POST |
| 地址 | <runtime-origin>/api/open-link/inbound/webhooks/<flowCode> |
| Content-Type | 必须以 application/json 开头,否则返回 OPEN_LINK_CONTENT_TYPE_INVALID |
| 请求体大小 | 最大 10 MiB,超出返回 OPEN_LINK_PAYLOAD_TOO_LARGE |
| 鉴权 | 按该 OpenLink 的入站鉴权配置携带请求头(共享令牌 / Bearer Token / 签名校验),并且先经过白名单校验 |
| 可选请求头 | X-Idempotency-Key 用于防重复提交;X-Request-Id 会记录为外部请求 ID |
<runtime-origin> 是工作区运行时地址(和浏览器打开 Soln 的地址一致),<flowCode> 是流程编码,例如 open_link_flow_0505058add3a。流程的开始节点展示完整 Webhook URL,设计画布的 请求示例 也会给出可复制的调用示例。
请求体
请求体必须是一个 JSON 对象,字段怎么传取决于画布上有没有转换节点。
有转换节点:按外部字段编码传
key 是外部字段编码,value 是该字段的值:
{
"order_no": "SO-2026-0001",
"amount": 128.5,
"customer": { "code": "C-1001" },
"ordered_at": "2026-09-18T10:00:00.000Z"
}
- 字段编码取自外部表单的字段定义
- 外键或关联字段传被引用对象的字段,例如
customer.code;嵌套对象按路径读取 - 没有出现在映射里的字段会被忽略,多余字段不影响执行
没有转换节点:按本地表单字段 API 名传
画布上只有目标节点、没有转换节点时,Soln 把请求体直接当作本地表单数据写入,key 用本地表单的字段 API 名:
{
"order_no": "SO-2026-0001",
"amount": 128.5
}
子表数据
子表数据放在 input.childTables 数组里:
{
"order_no": "SO-2026-0001",
"input": {
"childTables": [
{
"externalObjectCode": "order_lines",
"rows": [
{ "line_no": "1", "sku": "A-100", "qty": 2 },
{ "line_no": "2", "sku": "A-200", "qty": 1 }
]
}
]
}
}
每个子表按 externalObjectCode(也可以写 externalObjectId)与画布上配置的子表配对匹配,不按数组顺序;匹配不到的 rows 不会被写入。
可选包装与回调
- 请求体只包含
payload(以及可选callback)时,Soln 取payload的内容作为输入数据 callback是异步回调控制对象:{ "url": "https://...", "headers": { ... } },用于流程结束后回调外部系统- 请求体里带
callbackId时,它会被当作幂等键使用(等价于X-Idempotency-Key) - 工作流回调流程的字段约定见工作流集成
响应
| 场景 | 返回 |
|---|---|
| 接收成功 | HTTP 202,返回 accepted、duplicate、logId、traceId、status、flowCode、callbackRequested 和 statusQueryUrl |
| 重复提交 | 同一个幂等键再次提交时返回 duplicate: true 和已有执行的 logId,不会重复写入 |
| 失败 | 非 2xx,响应体为 { code, requestId, message?, detail? } |
接收成功只代表请求进入队列。查询执行结果时用 GET 请求 statusQueryUrl:
curl --request GET \
'https://runtime.example.com/api/open-link/inbound/webhooks/executions/<logId>?traceId=<traceId>'
结果包含 status、completed、localRecordId、durationMs、errorCode、errorMessage 以及回调投递状态。
常见错误
| errorCode | 说明 |
|---|---|
OPEN_LINK_CONTENT_TYPE_INVALID | Content-Type 不是 JSON |
OPEN_LINK_JSON_VALUE_INVALID | 请求体不是合法 JSON |
OPEN_LINK_PAYLOAD_TOO_LARGE | 请求体超过 10 MiB |
OPEN_LINK_EXECUTION_PAYLOAD_INVALID | 请求体不是 JSON 对象 |
OPEN_LINK_WEBHOOK_SOURCE_DENIED | 来源没有通过白名单 |
OPEN_LINK_WEBHOOK_AUTH_INVALID | 入站凭证校验失败 |
OPEN_LINK_WEBHOOK_TIMESTAMP_EXPIRED | 签名时间戳超出允许的时钟窗口 |
OPEN_LINK_WEBHOOK_CALLBACK_INVALID | callback 控制对象不合法 |
OPEN_LINK_FLOW_DEFINITION_NOT_PUBLISHED | 流程没有可运行的已发布版本 |
OPEN_LINK_IDEMPOTENCY_KEY_CONFLICT | 同一个幂等键被用于其他流程 |
OPEN_LINK_INBOUND_RATE_LIMIT_EXCEEDED | 超过每分钟请求数限制 |
OPEN_LINK_INBOUND_CONCURRENCY_LIMIT_EXCEEDED | 超过最大并发请求数限制 |
调用示例
两个示例都使用签名校验:签名原文是 METHOD\npath\ntimestamp\n原始 body,时间戳必须是当前时间,签名也要按真实请求体重新计算,示例里的写法只表示格式。
只写主表
curl --request POST \
'https://runtime.example.com/api/open-link/inbound/webhooks/open_link_flow_0505058add3a' \
--header 'Content-Type: application/json' \
--header 'X-App-Id: app_Aqg9LRZahMDuMRS9' \
--header 'X-OpenLink-Timestamp: 1789712190157' \
--header 'X-OpenLink-Signature: <按真实请求体重新计算>' \
--data '{"order_no":"SO-2026-0001","amount":128.5,"customer":{"code":"C-1001"}}'
主表加子表
curl --request POST \
'https://runtime.example.com/api/open-link/inbound/webhooks/open_link_flow_0505058add3a' \
--header 'Content-Type: application/json' \
--header 'X-App-Id: app_Aqg9LRZahMDuMRS9' \
--header 'X-OpenLink-Timestamp: 1789712190157' \
--header 'X-OpenLink-Signature: <按真实请求体重新计算>' \
--data '{
"order_no": "SO-2026-0001",
"amount": 128.5,
"customer": { "code": "C-1001" },
"input": {
"childTables": [
{
"externalObjectCode": "order_lines",
"rows": [
{ "line_no": "1", "sku": "A-100", "qty": 2 },
{ "line_no": "2", "sku": "A-200", "qty": 1 }
]
}
]
}
}'
子表的 externalObjectCode 必须与画布上子表配对选中的外部对象编码一致,主表字段和 input.childTables 放在同一个请求体里提交。如果画布上没有转换节点,主表字段改用本地表单字段 API 名。
两个示例都使用签名校验;改用共享令牌或 Bearer Token 时,把三个签名请求头换成对应请求头,规则见入站鉴权。