Webhook
最后更新:2026年6月22日
Webhook 是当 Space 中发生某件事时(例如 Content 创建、发布),向预先指定的外部 URL 发送 HTTP 请求的配置。用于外部系统集成或自动化。例如,可以配置为在每次商品 Content 发布时调用公司内部的通知服务器,或调用外部 API。
Webhook 不止于发送请求,还可以接收响应并将其回写到 Content 或 Media,即配置 WriteBack。通过这种方式构建将外部 API 结果吸收为 Space 内数据的异步作业流程。Webhook 在 CMA 中是 Space 的下级资源,路径以 /spaces/{spaceId}/webhooks 为基准。
资源结构
下面是 Webhook “商品变更通知” 的单条查询响应。它在 sys(系统属性)之外,还拥有发送目标、订阅事件、触发条件等配置字段。
{
"sys": {
"id": "3trmXRM3RqbgSnifyg7PWhk01Examp",
"type": "Webhook",
"space": { "sys": { "id": "HnQ32YiH", "type": "Refer", "targetType": "Space" } },
"createdBy": { "sys": { "id": "3p4tcFbQRwz503VXdtHXNI5dZH5TVB", "type": "Refer", "targetType": "User" } },
"createdAt": "2026-06-18T11:30:00.000Z",
"updatedBy": { "sys": { "id": "3p4tcFbQRwz503VXdtHXNI5dZH5TVB", "type": "Refer", "targetType": "User" } },
"updatedAt": "2026-06-18T11:30:00.000Z",
"version": 1
},
"name": "商品变更通知",
"filters": [
{ "doc": "sys.contentType.sys.id", "op": "EQ", "value": "3trmXRLdJF4GBlAjtcuoZ7Pnxj8dlA" }
],
"headers": [
{ "key": "X-Source", "value": "weegloo", "secret": false }
],
"httpBasicUsername": "dailywear",
"topics": ["Content.Create", "Content.Publish"],
"transformation": { "method": "POST", "contentType": "application/json", "includeBody": true },
"url": "https://api.dailywear.example/webhooks/products",
"activate": true
}主要键:
sys.id:Webhook 的唯一标识符。用于单条查询、修改、删除路径中的{webhookId}。url:事件发生时调用的外部目标 URL。topics:定义订阅哪些事件的数组。格式在下文 topics 中说明。filters:在已订阅的事件中实际触发的条件。在下文 filters 中说明。transformation:改变出站请求形态(方法、正文等)的配置。在下文 transformation 中说明。writeBacks:接收外部响应并回写到 Content 或 Media 的作业数组。上面的示例中没有。在下文 writeBacks 中说明。
系统属性 (sys)
每个 Webhook 都在 sys 对象中包含公共系统属性。space、createdBy、updatedBy 以 Refer 形态({ "sys": { "id", "type": "Refer", "targetType" } })出现。
| 属性 | 类型 | 说明 |
|---|---|---|
id | string | 资源唯一标识符。 |
type | string | 资源类型。Webhook 始终为 "Webhook"。 |
space | Refer<Space> | 此 Webhook 所属的 Space。 |
createdBy | Refer<User> | 创建该资源的用户。 |
createdAt | string (date-time) | 创建时间。 |
updatedBy | Refer<User> | 最后修改该资源的用户。 |
updatedAt | string (date-time) | 最后修改时间。 |
version | integer (≥1) | 资源版本。每次修改递增 1。 |
Webhook 是配置型资源,因此没有发布这一概念。与 Content 或 Content Type 不同,它不具备 publish、archive、status 等发布状态属性,只有用于变更追踪的 version。开启与关闭不是通过发布,而是通过正文字段 activate 控制。
正文属性
Webhook 的正文(创建、修改时发送,并作为响应返回的配置值)由以下字段构成。
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
name | string (1~64) | ✅ | Webhook 名称。 |
url | string (url) | ✅ | 事件发生时调用的外部目标 URL。 |
activate | boolean | ✅ | 是否开启。为 false 时即使事件发生也不发送请求。 |
topics | string[] | ✅ | 订阅的事件数组。参见下文 topics。 |
filters | Filter[] | ✅ | 触发条件数组。留空则所有已订阅的事件都会触发。参见下文 filters。 |
headers | WebhookHeader[] (0~30) | ✅ | 随请求一起发送的 HTTP 头数组。 |
httpBasicUsername | string (1~32) | HTTP Basic 认证用户名。 | |
httpBasicPassword | string (1~32) | HTTP Basic 认证密码。仅写入。不会出现在响应中。 | |
transformation | Transformation | ✅ | 自定义出站请求。参见下文 transformation。 |
writeBacks | WriteBack[] | 接收响应后执行的写入作业数组。参见下文 writeBacks。 |
headers 的每个项目由 key(必填)、value(必填)、secret(可选,boolean)构成。secret 为 true 的头,其值在响应中会被遮蔽。 像 API 密钥这类不应暴露的值,放在 secret: true 的头中。
topics
topics 的每个项目为 {资源}.{动作} 格式。例如:Content.Create、Content.Publish、Media.Create。
动作为以下之一,或表示资源全部动作的 *(例如 Content.*)。
| 动作 | 含义 |
|---|---|
All | 全部动作。 |
Create | 创建。 |
Read | 查询。 |
Edit | 编辑。 |
Save | 保存(修改)。修改事件是 Save,不是 Update。 |
Delete | 删除。 |
Publish | 发布。 |
Unpublish | 取消发布。 |
Archive | 归档。 |
Unarchive | 取消归档。 |
filters
filters 是在已订阅的 topics 中缩小实际触发 Webhook 条件的数组。每个过滤器为以下形态。
{ "doc": "sys.contentType.sys.id", "op": "EQ", "value": "3trmXRLdJF4GBlAjtcuoZ7Pnxj8dlA" }doc:要比较的字段路径。为sys.id、sys.contentType.sys.id、sys.createdBy.sys.id、sys.updatedBy.sys.id之一。op:比较运算符。为EQ、NE、IN、NOT_IN、REGEX、NOT_REGEX之一。value:比较值。EQ、NE、REGEX、NOT_REGEX使用字符串,IN、NOT_IN使用字符串数组。
设置多个过滤器时,必须全部满足才会触发(AND)。将 filters 留空时,已订阅 topics 的所有事件都会触发。
transformation
transformation 改变出站 HTTP 请求的形态。不指定时,资源载荷整体以默认的 POST 原样发送。
| 键 | 类型 | 说明 |
|---|---|---|
method | string | HTTP 方法。为 GET、POST、PUT、DELETE、PATCH 之一。 |
contentType | string | 请求正文的 Content-Type。 |
body | object | 用 JSON Pointer 模板构成所发送正文的对象。 |
includeBody | boolean | 是否一并发送触发资源的正文。 |
writeBacks
writeBacks 是 Webhook 用接收到的外部响应回写到 Content 或 Media 的有序作业数组。仅当外部 API 以 2xx 响应时才按顺序执行。每个项目拥有一个 $content(WriteBackContent)或 $media(WriteBackMedia)。
WriteBackContent($content)的键:
| 键 | 类型 | 说明 |
|---|---|---|
action | string | 为 Create、Update、Delete、Publish、Unpublish、Archive、Unarchive 之一。 |
contentType | Refer<ContentType> | Create 时要创建的 Content Type。只需给出 sys.id。 |
target | string | 在 Update、Delete 等中指向目标 Content 的 sys.id 的 JSON Pointer 模板(例如 { /response/id })。必须用 { } 包裹,不包裹则视为字面量。省略时以触发 Webhook 的资源为目标。 |
locale | string | Create、Update 时写入值的语言区域。为语言区域代码或指针模板。省略时为 Space 默认语言区域。 |
fields | object | Create、Update 时目标字段键 → 源表达式的映射。键为目标 Content 字段的 apiName。 |
publish | boolean | Create、Update 后是否发布。默认值 true。 |
unpublish | boolean | Delete 时删除前是否取消发布。默认值 true。 |
WriteBackMedia($media)的键:
| 键 | 类型 | 说明 |
|---|---|---|
action | string | 为 Create、Delete、Publish、Unpublish、Archive、Unarchive 之一。 |
source | string | Create 时要导入到 Media 的值的指针模板(例如 { /response/data/0/url })。必须用 { } 包裹。 |
encoding | string | Create 时解释 source 的方式。为 Url、Base64、Binary 之一。 |
locale | string | Create 时写入文件、标题、说明的语言区域。省略时为 Space 默认语言区域。 |
title | string | Create 时的 Media 标题(源表达式或字面量)。 |
description | string | Create 时的 Media 说明。 |
target | string | 在 Delete 等中指向目标 Media 的 sys.id 的指针模板。省略时以触发资源为目标。 |
publish | boolean | Create 时处理完成后是否发布。默认值 true。 |
unpublish | boolean | Delete 时删除前是否取消发布。默认值 true。 |
下面是从外部响应 JSON 中提取值创建一个 Content 的 writeBacks 示例。
"writeBacks": [
{
"$content": {
"action": "Create",
"contentType": { "sys": { "id": "3trmXRLdJF4GBlAjtcuoZ7Pnxj8dlA" } },
"locale": "ko-KR",
"fields": {
"productName": "{ /response/title }",
"price": "{ /response/price }"
},
"publish": true,
"unpublish": true
}
}
]{ /response/... } 是从 Webhook 接收到的响应 JSON 中提取值的 JSON Pointer 模板。fields 的键(productName、price)是目标 Content 字段的 apiName。上面的示例将响应中的 title 填入 Content 的 productName,将 price 填入 price,创建 Content 后发布。
API
下面所有端点的基准 URL 为 https://cma.weegloo.com/v1,并且 Authorization 头中需要认证 CMA 的 Bearer 令牌。修改(PUT)和部分修改(PATCH)为实现乐观并发控制,需一并发送 X-Weegloo-Version 头(当前资源的 sys.version)。
