审批开放 API
需购买并开通审批中心扩展模块
审批开放接口
- 生产环境基础地址:
https://open.musedam.cc/api/muse - 审批接口路径:
/approval-api - 完整调用地址:
POST https://open.musedam.cc/api/muse/approval-api - 开通要求:仅购买并开通「审批中心扩展模块」后,当前开放接口能力才可用。
调用约定
- 请求方法:
POST Content-Type:application/json- 请求体必须为合法 JSON
- 使用
service字段区分能力 - 请求头需携带:
Authorization: Bearer your_api_key
Service 能力总览
公共字段:
service(必填,string)- 可选值:
subscriptionQuery/subscriptionChange/listTemplates/createApproval/taskStatusQuery
公共请求示例:
{"service": "listTemplates"}
统一响应结构:
{"code": "0","message": "成功","result": {},"traceId": "trace_20261012_001"}
常见失败码:
400:参数错误(如invalid_payload:*)401:鉴权失败403:权限不足404:资源不存在(如team_not_found/template_not_found/task_not_found/asset_not_found)500:服务内部错误
查询模板(listTemplates)
接口路径:/approval-api
请求参数:
| 字段名 | 类型 | 必填 | 描述 |
|---|---|---|---|
| service | String | 是 | 固定为 listTemplates |
响应(result):模板数组,单项结构如下:
| 字段名 | 类型 | 描述 |
|---|---|---|
| id | String | 模板 ID |
| name | String | 模板名称 |
| description | String | 模板描述 |
| enabled | Boolean | 模板是否启用 |
| usageCount | Number | 使用次数 |
| autoImportEnabled | Boolean | 是否自动入库 |
| targetFolder | Object | null | 入库目标文件夹 |
| workflow | Array | 节点流程定义 |
请求:
{"service": "listTemplates"}
响应 result 为模板数组,核心字段:
id/name/description/enabledusageCount/autoImportEnabledtargetFolder(可能为空)workflow(节点定义,包含审批人、抄送、签审模式、超时配置等)
curl 示例:
curl --location --request POST 'https://open.musedam.cc/api/muse/approval-api' \--header 'Authorization: Bearer your_api_key' \--header 'Content-Type: application/json' \--data-raw '{"service": "listTemplates"}'
创建审批任务(createApproval)
接口路径:/approval-api
请求参数:
| 字段名 | 类型 | 必填 | 描述 |
|---|---|---|---|
| service | String | 是 | 固定为 createApproval |
| templateId | String | 是 | 审批模板 ID |
| createdBy | String | 是 | 发起人用户 ID |
| assets | Array | 是 | 素材列表,至少 1 条 |
| sourceContext | Object | 否 | 业务上下文 |
| reason | String | 否 | 发起原因 |
assets[] 字段:
| 字段名 | 类型 | 必填 | 描述 |
|---|---|---|---|
| name | String | 是 | 素材名称,建议传原始文件名 |
| url | String | 是 | 公网可访问 http/https 地址 |
| size | Number | 否 | 文件大小(字节) |
| mimeType | String | 否 | MIME 类型 |
| extension | String | 否 | 文件扩展名 |
响应参数:
| 字段名 | 类型 | 描述 |
|---|---|---|
| taskId | String | 审批任务 ID |
请求字段:
service(必填,固定createApproval)templateId(必填,string)createdBy(必填,string,发起人用户 ID)assets(必填,array,至少 1 条)name(建议传原始文件名)url(必填,公网可访问http/https)size/mimeType/extension(可选)
sourceContext(可选,业务上下文)reason(可选,发起原因)
请求示例:
{"service": "createApproval","templateId": "101","createdBy": "10086","assets": [{"name": "demo.mp4","url": "https://cdn.example.com/m/asset_1.mp4"}]}
成功响应:
{"code": "0","message": "成功","result": {"taskId": "9527"}}
调用限制:
assets不能为空assets[].url不能为空且同一请求内不能重复assets[].url必须是公网地址,不能是localhost、内网域名或私网 IP- 下载超时或超大小限制会返回
invalid_payload:*
curl 示例:
curl --location --request POST 'https://open.musedam.cc/api/muse/approval-api' \--header 'Authorization: Bearer your_api_key' \--header 'Content-Type: application/json' \--data-raw '{"service": "createApproval","templateId": "101","createdBy": "10086","assets": [{"name": "demo.mp4","url": "https://cdn.example.com/m/asset_1.mp4"}]}'
查询任务状态(taskStatusQuery)
接口路径:/approval-api
请求参数:
| 字段名 | 类型 | 必填 | 描述 |
|---|---|---|---|
| service | String | 是 | 固定为 taskStatusQuery |
| taskId | String | 是 | 审批任务 ID(正整数) |
响应参数:
| 字段名 | 类型 | 描述 |
|---|---|---|
| taskId | String | 任务 ID |
| status | String | 任务状态:PENDING / PROCESSING / APPROVED / REJECTED / CANCELED |
| statusLabel | String | 状态文案 |
| progressPercent | Number | 进度百分比 |
| currentNodeName | String | null | 当前节点名称 |
| currentNodeSignMode | String | null | 当前节点签审模式(and / or) |
| currentNodeProgress | Object | 当前节点统计 |
| currentNodeApprovers | Array | 当前节点审批人状态列表 |
| operator | String | null | 最近操作人 |
| updatedAt | String | 更新时间(ISO) |
请求:
{"service": "taskStatusQuery","taskId": "9527"}
响应 result 关键字段:
taskIdstatus:PENDING | PROCESSING | APPROVED | REJECTED | CANCELEDstatusLabelprogressPercentcurrentNodeName/currentNodeSignModecurrentNodeProgress(通过、拒绝、待审统计)currentNodeApprovers(节点内审批人状态)operator/updatedAt
curl 示例:
curl --location --request POST 'https://open.musedam.cc/api/muse/approval-api' \--header 'Authorization: Bearer your_api_key' \--header 'Content-Type: application/json' \--data-raw '{"service": "taskStatusQuery","taskId": "9527"}'
订阅与回调(subscriptionQuery / subscriptionChange)
查询订阅状态(subscriptionQuery)
接口路径:/approval-api
请求参数:
| 字段名 | 类型 | 必填 | 描述 |
|---|---|---|---|
| service | String | 是 | 固定为 subscriptionQuery |
响应参数:
| 字段名 | 类型 | 描述 |
|---|---|---|
| subscribed | Boolean | 是否已订阅 |
| callbackUrl | String | null | 当前订阅回调地址 |
| updatedAt | String | null | 最近更新时间(ISO) |
查询是否订阅:
{"service": "subscriptionQuery"}
curl 示例:
curl --location --request POST 'https://open.musedam.cc/api/muse/approval-api' \--header 'Authorization: Bearer your_api_key' \--header 'Content-Type: application/json' \--data-raw '{"service": "subscriptionQuery"}'
变更订阅(subscriptionChange)
接口路径:/approval-api
请求参数:
| 字段名 | 类型 | 必填 | 描述 |
|---|---|---|---|
| service | String | 是 | 固定为 subscriptionChange |
| operation | String | 否 | ADD / DELETE,默认 ADD |
| callbackUrl | String | 条件必填 | 当 operation = ADD 时必填,必须为 http/https |
响应参数:
| 字段名 | 类型 | 描述 |
|---|---|---|
| result | Boolean | true 表示当前为已订阅状态;false 表示当前为取消订阅状态 |
订阅回调:
{"service": "subscriptionChange","operation": "ADD","callbackUrl": "https://example.com/webhook/approval"}
取消订阅:
{"service": "subscriptionChange","operation": "DELETE"}
curl 示例(ADD):
curl --location --request POST 'https://open.musedam.cc/api/muse/approval-api' \--header 'Authorization: Bearer your_api_key' \--header 'Content-Type: application/json' \--data-raw '{"service": "subscriptionChange","operation": "ADD","callbackUrl": "https://example.com/webhook/approval"}'
curl 示例(DELETE):
curl --location --request POST 'https://open.musedam.cc/api/muse/approval-api' \--header 'Authorization: Bearer your_api_key' \--header 'Content-Type: application/json' \--data-raw '{"service": "subscriptionChange","operation": "DELETE"}'
订阅回调 payload 说明
当调用 subscriptionChange 且 operation = ADD 成功后,审批状态变化会回调到你传入的 callbackUrl。
回调请求基础约定
- 请求方法:
POST Content-Type:application/json
回调体结构:
{"eventId": "evt_xxx","eventType": "APPROVAL","eventTime": "1760258885000","payload": {"eventName": "TASK_APPROVED","orgId": "233","taskId": "9527","taskStatus": "APPROVED"}}
字段说明:
| 字段名 | 类型 | 描述 |
|---|---|---|
| eventId | String | 事件唯一 ID(接收方建议按此做幂等) |
| eventType | String | 固定为 APPROVAL |
| eventTime | String | 毫秒时间戳字符串 |
| payload | Object | 业务数据体 |
payload 公共字段
每个回调事件的 payload 至少包含:
| 字段名 | 类型 | 描述 |
|---|---|---|
| eventName | String | 事件名 |
| orgId | String | 组织 ID(由系统填充) |
| taskId | String | 审批任务 ID |
| taskStatus | String | 任务状态:PROCESSING / APPROVED / TIMEOUT |
事件全集(触发条件)
| eventName | 触发条件 |
|---|---|
| NODE_STARTED | 节点开始处理时触发(创建任务首节点、节点流转到下一节点、流转到重提节点) |
| APPROVER_SUBMITTED | 审批人在节点提交审批意见时触发(同一节点可多次触发) |
| NODE_COMPLETED | 某节点办结时触发(通过 / 拒绝) |
| NODE_TRANSFERRED | 节点办结后流转到下一处理节点时触发(正常流转、重提流转、超时转交流转) |
| SUBMITTER_RESUBMITTED | 发起人在“待重新提交”节点提交新素材时触发 |
| TASK_APPROVED | 任务终态通过时触发 |
| NODE_TIMEOUT | 节点超时时触发(超时转交或超时待重新分配) |
字段定义(完整)
payload.node(节点对象)
| 字段名 | 类型 | 描述 |
|---|---|---|
| nodeId | String | 节点 ID(必有) |
| nodeOrder | Number | 节点顺序(部分事件存在) |
| nodeRole | String | 节点角色:normal / resubmit_submitter / resubmit_approver(部分事件存在) |
| nodeStatus | String | 节点状态,常见值:pending / processing / approved / rejected / timeout_transferred / re_assigned |
| signMode | String | 签审模式:and / or(按场景出现) |
| approverCount | Number | 审批人数(按场景出现) |
| approvers | Array | 节点办结时审批人结果(NODE_COMPLETED),子项含 id / name / status |
| startedAt | String | 节点开始时间(ISO) |
| completedAt | String | 节点完成时间(ISO) |
| timeoutHours | Number | 节点超时阈值小时数(超时事件出现) |
payload.approver(审批人提交对象,APPROVER_SUBMITTED)
| 字段名 | 类型 | 描述 |
|---|---|---|
| id | String | 审批人用户 ID |
| name | String | 审批人名称 |
| decision | String | 审批决定:approved / rejected |
| comment | String | 审批意见 |
| submittedAt | String | 提交时间(ISO) |
payload.submitter(提交人对象,SUBMITTER_RESUBMITTED)
| 字段名 | 类型 | 描述 |
|---|---|---|
| id | String | 提交人用户 ID |
| name | String | 提交人名称 |
| comment | String | 重提备注 |
| submittedAt | String | 提交时间(ISO) |
payload.timeout(超时对象)
| 字段名 | 类型 | 描述 |
|---|---|---|
| transferTo | Object | null | 超时转交目标;有转交人时为 { "id": "...", "name": "..." },无转交人时为 null |
payload.latestAssets(重提素材快照,SUBMITTER_RESUBMITTED)
| 字段名 | 类型 | 描述 |
|---|---|---|
| assetId | String | 素材 ID |
| filePathId | String | 文件路径 ID |
| version | Number | 素材版本号 |
| oldStorePath | String | 旧版本存储路径 |
| newStorePath | String | 新版本存储路径 |
| updatedAt | String | 更新时间(ISO) |
payload.transferReason(NODE_TRANSFERRED)
| 枚举值 | 描述 |
|---|---|
| NEXT_NODE | 正常流转到下一审批节点 |
| RESUBMIT_SUBMITTER | 流转到待重新提交节点 |
| RESUBMIT_APPROVER | 重提后流转到重审节点 |
| TIMEOUT_TRANSFER | 超时后转交 |
回调示例(全事件)
TASK_APPROVED 示例:
{"eventId": "evt_2a93f5f5f4d64907a2f3b73cb8f0f201","eventType": "APPROVAL","eventTime": "1760258885000","payload": {"eventName": "TASK_APPROVED","orgId": "233","taskId": "9527","taskStatus": "APPROVED","operator": {"id": "10086","name": "张三"},"finishedAt": "2026-10-12T08:08:05.000Z"}}
NODE_STARTED 示例:
{"eventId": "evt_d3a39140643a4d73afedf0a47c0a601d","eventType": "APPROVAL","eventTime": "1760258700000","payload": {"eventName": "NODE_STARTED","orgId": "233","taskId": "9527","taskStatus": "PROCESSING","node": {"nodeId": "12001","nodeOrder": 1,"nodeRole": "normal","nodeStatus": "processing","signMode": "and","approverCount": 2,"startedAt": "2026-10-12T08:05:00.000Z"}}}
APPROVER_SUBMITTED 示例:
{"eventId": "evt_8bc9f92f83564f10adf8270b598f95d2","eventType": "APPROVAL","eventTime": "1760258820000","payload": {"eventName": "APPROVER_SUBMITTED","orgId": "233","taskId": "9527","taskStatus": "PROCESSING","node": {"nodeId": "12001","nodeOrder": 1,"nodeStatus": "processing","signMode": "and"},"approver": {"id": "10086","name": "张三","decision": "approved","comment": "同意","submittedAt": "2026-10-12T08:07:00.000Z"},"approverCount": 2}}
NODE_COMPLETED 示例:
{"eventId": "evt_652d4d8c09d24477af9fdb21624fd070","eventType": "APPROVAL","eventTime": "1760258855000","payload": {"eventName": "NODE_COMPLETED","orgId": "233","taskId": "9527","taskStatus": "PROCESSING","node": {"nodeId": "12001","nodeOrder": 1,"nodeStatus": "approved","signMode": "and","approvers": [{"id": "10086","name": "张三","status": "approved"},{"id": "10087","name": "李四","status": "approved"}],"completedAt": "2026-10-12T08:07:35.000Z"}}}
NODE_TRANSFERRED 示例(正常流转):
{"eventId": "evt_21881077723e4a17aa4e2e58ee78ce79","eventType": "APPROVAL","eventTime": "1760258856000","payload": {"eventName": "NODE_TRANSFERRED","orgId": "233","taskId": "9527","taskStatus": "PROCESSING","transferReason": "NEXT_NODE","fromNode": {"nodeId": "12001","nodeOrder": 1,"nodeStatus": "approved"},"node": {"nodeId": "12002","nodeOrder": 2,"nodeRole": "normal","nodeStatus": "pending"}}}
NODE_TRANSFERRED 示例(拒绝后流转到待重提):
{"eventId": "evt_e612f8b5e1de4960bb712d3df18e2617","eventType": "APPROVAL","eventTime": "1760258900000","payload": {"eventName": "NODE_TRANSFERRED","orgId": "233","taskId": "9527","taskStatus": "PROCESSING","transferReason": "RESUBMIT_SUBMITTER","fromNode": {"nodeId": "12001","nodeOrder": 1,"nodeStatus": "rejected"},"node": {"nodeId": "13001","nodeOrder": 2,"nodeRole": "resubmit_submitter","nodeStatus": "pending"}}}
NODE_TRANSFERRED 示例(重提后流转到重审):
{"eventId": "evt_f0c43dd5ca5d4fca9e4adbe536fbb8f5","eventType": "APPROVAL","eventTime": "1760259005000","payload": {"eventName": "NODE_TRANSFERRED","orgId": "233","taskId": "9527","taskStatus": "PROCESSING","transferReason": "RESUBMIT_APPROVER","fromNode": {"nodeId": "13001","nodeOrder": 2,"nodeStatus": "approved"},"node": {"nodeId": "13002","nodeOrder": 3,"nodeRole": "resubmit_approver","nodeStatus": "pending"}}}
NODE_TIMEOUT 示例(超时转交):
{"eventId": "evt_b0d67fb6f3de42e79a60b8f9df6ad20d","eventType": "APPROVAL","eventTime": "1760260000000","payload": {"eventName": "NODE_TIMEOUT","orgId": "233","taskId": "9527","taskStatus": "TIMEOUT","node": {"nodeId": "12002","nodeStatus": "timeout_transferred","timeoutHours": 24},"timeout": {"transferTo": {"id": "10100","name": "王五"}}}}
NODE_TIMEOUT 示例(超时未转交):
{"eventId": "evt_2e4372871f0c4a7eb95a9d7c638de8a0","eventType": "APPROVAL","eventTime": "1760260100000","payload": {"eventName": "NODE_TIMEOUT","orgId": "233","taskId": "9527","taskStatus": "TIMEOUT","node": {"nodeId": "12002","nodeStatus": "re_assigned","timeoutHours": 24},"timeout": {"transferTo": null}}}
SUBMITTER_RESUBMITTED 示例:
{"eventId": "evt_5d017db5b458443697f6c10d5f6370df","eventType": "APPROVAL","eventTime": "1760259000000","payload": {"eventName": "SUBMITTER_RESUBMITTED","orgId": "233","taskId": "9527","taskStatus": "PROCESSING","node": {"nodeId": "12002","nodeOrder": 3,"nodeStatus": "approved","signMode": "and"},"submitter": {"id": "10010","name": "李四","comment": "已更新素材,重新提交","submittedAt": "2026-10-12T08:10:00.000Z"},"latestAssets": [{"assetId": "asset_1","filePathId": "30001","version": 3,"oldStorePath": "assets/old/asset_1_v2.mp4","newStorePath": "assets/new/asset_1_v3.mp4","updatedAt": "2026-10-12T08:10:00.000Z"}],"latestAssetCount": 1}}
NODE_TRANSFERRED 示例(超时转交后):
{"eventId": "evt_15f4348dd4f34a4b9d51ec93313f4dff","eventType": "APPROVAL","eventTime": "1760260001000","payload": {"eventName": "NODE_TRANSFERRED","orgId": "233","taskId": "9527","taskStatus": "PROCESSING","transferReason": "TIMEOUT_TRANSFER","node": {"nodeId": "12002","nodeStatus": "timeout_transferred"},"timeout": {"transferTo": {"id": "10100","name": "王五"}}}}
事件时序(关键流程)
说明:回调为“至少一次投递”,消费方应按 eventId 做幂等去重,不要假设不会重复投递。
正常通过(多节点)
NODE_STARTED(首节点开始)APPROVER_SUBMITTED(每位审批人提交时触发,可能多次)NODE_COMPLETED(当前节点完成)- 若有下一节点:
NODE_TRANSFERRED->NODE_STARTED - 重复 2~4,直到最后一个节点完成
TASK_APPROVED(任务终态通过)
拒绝后重提
APPROVER_SUBMITTED(decision = rejected)NODE_COMPLETED(nodeStatus = rejected)NODE_TRANSFERRED(transferReason = RESUBMIT_SUBMITTER)NODE_STARTED(nodeRole = resubmit_submitter)SUBMITTER_RESUBMITTED(提交人重提)NODE_COMPLETED(重提节点完成)NODE_TRANSFERRED(transferReason = RESUBMIT_APPROVER)NODE_STARTED(重审节点开始)- 后续再次进入正常审批链路(
APPROVER_SUBMITTED...)
超时转交 / 超时未转交
- 节点超时触发
NODE_TIMEOUT(taskStatus = TIMEOUT) - 若配置了超时转交人:紧接着触发
NODE_TRANSFERRED(transferReason = TIMEOUT_TRANSFER),任务回到PROCESSING - 若无可转交人:仅有
NODE_TIMEOUT(常见nodeStatus = re_assigned),等待人工处理后再推进