Webhook

Webhook は、Space で何かが起きたとき(例: Content の作成・公開)にあらかじめ定めた動作を自動で実行する設定です。動作は 2 つのうちいずれかです。外部 URL へ HTTP リクエストを送るか(url)、Space 内の Script を実行します(script)。外部システム連携や自動化に使います。たとえば商品 Content が公開されるたびに社内の通知サーバーを呼び出したり、定めておいた Script で後続の作業を実行するように構成できます。

url と script は ちょうど 1 つだけ 指定します。両方を指定したり、両方を空にすると拒否されます。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 }
  ],
  "basicAuth": { "username": "dailywear" },
  "topics": ["Content.Create", "Content.Publish"],
  "transformation": { "method": "POST", "contentType": "application/json", "includeBody": true },
  "url": "https://api.dailywear.example/webhooks/products",
  "activate": true,
  "runAs": "HookOwner"
}

主なキー:

  • sys.id: Webhook の一意な識別子です。単一取得・修正・削除パスの {webhookId} に入ります。
  • url: イベントが発生したときに呼び出す外部の対象 URL です。script とちょうど 1 つだけ指定します。
  • script: 外部呼び出しの代わりに実行する Script の参照です。url とちょうど 1 つだけ指定します。上の例にはありません。下の url と script(択一) で説明します。
  • runAs: script がどのユーザーとして実行されるかです。下の runAs で説明します。
  • topics: どのイベントを購読するかを定めた配列です。下の topics で形式を説明します。
  • filters: 購読したイベントのうち、実際にトリガーする条件です。下の filters で説明します。
  • transformation: url へ送るリクエストの形(メソッド・本文など)を変える設定です。下の transformation で説明します。

システム属性(sys)

すべての Webhook は共通のシステム属性を sys オブジェクトに格納します。space・createdBy・updatedBy は Refer の形({ "sys": { "id", "type": "Refer", "targetType" } })で入ります。

属性タイプ説明
idstringリソースの一意な識別子。
typestringリソースの種類。Webhook は常に "Webhook"。
spaceRefer<Space>この Webhook が属する Space。
createdByRefer<User>作成したユーザー。
createdAtstring (date-time)作成時刻。
updatedByRefer<User>最後に修正したユーザー。
updatedAtstring (date-time)最後の修正時刻。
versioninteger (≥1)リソースのバージョン。修正のたびに 1 ずつ上がります。

Webhook は設定リソースなので、公開という概念がありません。Content や Content Type と違い、publish・archive・status のような公開状態の属性を持たず、変更追跡用の version だけを持ちます。オン・オフは公開ではなく、本文フィールド activate で制御します。

本文属性

Webhook の本文(作成・修正時に送り、レスポンスで返ってくる設定値)は次のフィールドで構成されます。

フィールドタイプ必須説明
namestring (1~64)✅Webhook の名前。
urlstring (url)△イベント発生時に呼び出す外部の対象 URL。script と択一。下の url と script(択一) を参照。
scriptRefer<Script>△外部呼び出しの代わりに実行する Script の参照。url と択一。下の url と script(択一) を参照。
runAsWebhookRunAsscript を実行するユーザー。HookOwner(既定)または EventUser。下の runAs を参照。
activateboolean✅オンかどうか。false の場合はイベントが発生しても実行しません。
topicsstring[]✅購読するイベントの配列。下の topics を参照。
filtersFilter[]✅トリガー条件の配列。空にすると購読したすべてのイベントがトリガーします。下の filters を参照。
headersWebhookHeader[] (0~30)✅url 呼び出しに載せて送る HTTP ヘッダーの配列。
basicAuthBasicAuthurl 呼び出しの HTTP Basic 認証。下の basicAuth を参照。
transformationTransformation✅url へ送るリクエストのカスタマイズ。下の transformation を参照。

△ を付けた url・script は ちょうど 1 つだけ 指定します。両方を指定したり、両方を空にすると拒否されます。

headers の各項目は key(必須)・value(必須)・secret(任意、boolean)で構成されます。secret を true にすると、その値は送信記録でマスクされた状態で残ります(下の WebhookLog を参照)。ただし、この Webhook を取得すると値は原文で表示されます。 応答から外れるのは basicAuth.password だけなので、secret ヘッダーに置いた値はこの Webhook を読めるロールには見えるものとみなし、そのロールを狭く保ってください。

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 は url へ送る HTTP リクエストの形を変えます(script を使う Webhook には適用されません)。指定しない場合は、リソースのペイロード全体が既定の POST でそのまま送られます。

キータイプ説明
methodstringHTTP メソッド。GET・POST・PUT・DELETE・PATCH のいずれか。
contentTypestringリクエスト本文の Content-Type。本文はこの形式でシリアライズされます(下記)。
bodyobject送る本文を JSON Pointer テンプレートで構成するオブジェクト。
includeBodybooleanトリガーとなったリソースの本文を一緒に送るかどうか。

本文がどの形式で送られるか

contentType が本文のシリアライズ形式を決めます。比較では大文字・小文字と ;charset=… のようなパラメーターを無視し、先頭の部分だけを見ます。指定しない場合や値が空の場合は application/json で送ります。includeBody が false の場合、または method が GET の場合は本文を送らず、そのときは Content-Type も付きません。

Webhook が送る本文は常にオブジェクトです。body テンプレートがオブジェクトであり、テンプレートを置かない場合はトリガーされたリソース全体がそのまま送られるためです。

宣言した contentType実際に送られる Content-Type送られる本文
(なし)application/jsonJSON
application/json宣言値のままJSON
application/x-www-form-urlencoded宣言値のままproduct[sku]=TUMBLER-500&product[price]=24000
text/plainapplication/jsonJSON
その他(text/xml など)宣言値のままJSON

text/plain はオブジェクトを格納できないため、格納できる形式に訂正して送ります。ヘッダーの宣言と実際の本文が食い違うことはありません。本文をテキストで受け取る必要がある対象なら contentType では解決しないため、受け取る側の契約を確認してください。

form-urlencoded はオブジェクトをブラケットキーに、配列をインデックスに展開します。

本文展開されるキーと値
{ "product": { "sku": "TUMBLER-500", "price": 24000 } }product[sku]=TUMBLER-500&product[price]=24000
{ "tags": ["kitchen", "insulated"] }tags[0]=kitchen&tags[1]=insulated
{ "items": [{ "sku": "TUMBLER-500" }] }items[0][sku]=TUMBLER-500
{ "memo": null }memo=

キーと値は UTF-8 でパーセントエンコードされて送られます。上の表はキーの構造を示すためにデコードした形です。値に & や + が入っていても、ペアの区切り文字や空白と誤解されることはなく、そのまま伝えられます。

ネストをブラケットキーに展開する表記は広く使われている慣例であり、形式そのものの規格ではありません。 受け取る側が product[sku] をネストしたオブジェクトに復元するかどうかを確認し、復元しない場合はフラットなキーで body テンプレートを構成してください。

フォームで送る transformation の例です。

"transformation": {
  "method": "POST",
  "contentType": "application/x-www-form-urlencoded",
  "includeBody": true,
  "body": {
    "sku": "{ /payload/fields/sku/ko-KR }",
    "price": "{ /payload/fields/price/ko-KR }"
  }
}

sku が TUMBLER-500、price が 24000 の Content がトリガーすると、本文は sku=TUMBLER-500&price=24000 として送られます。

basicAuth

basicAuth は、url へ送るリクエストに HTTP Basic 認証(Authorization: Basic … ヘッダー)を載せます。script を使う Webhook には適用されません。

"basicAuth": { "username": "dailywear", "password": "<パスワード>" }
キータイプ説明
usernamestring (0~32)ユーザー名。
passwordstring (0~32)パスワード。書き込み専用です。応答には表示されません。

作成時に basicAuth を指定する場合は、username と password を両方送る必要があります。

取得応答には password がないため、全体修正(PUT)は basicAuth を次の 3 通りに解釈します。

送る basicAuth結果
省略または null保存された Basic 認証を削除します。
username のみ保存された password を維持し、username は送った値で保存します。
username と password両方を送った値に置き換えます。

取得応答をそのまま修正して送り直すと username だけが入るため、パスワードは維持されます。username なしで password だけを送ると拒否されます。

部分修正(PATCH)も同じ規則に従います。basicAuth に触れない演算は、保存された password を維持します。password を変えるには、replace ではなく add 演算を使ってください({ "op": "add", "path": "/basicAuth/password", "value": "<新しいパスワード>" })。対象ドキュメントに password がないため、replace は拒否されます。

送信記録(WebhookLog)には、basicAuth が作った Authorization ヘッダーの値がマスクされた状態で残ります。

url と script(択一)

Webhook がトリガーされると、2 つのうちいずれかを実行します。url を指定すると、その外部 URL へ HTTP リクエストを送ります(リクエストの形は transformation・headers・basicAuth で決めます)。script を指定すると、外部へ送らず Space 内の Script を 1 つ実行します。

  • url: 外部の対象 URL(http/https)。プライベートネットワーク・ループバックなどブロックされた対象は拒否されます。
  • script: 実行する Script の Refer。

2 つは ちょうど 1 つだけ 指定する必要があります。両方を指定したり、両方を空にすると拒否され、返ってくるコードはパスごとに異なります(エラー を参照)。

"script": { "sys": { "id": "3trmXRMZcTAjDnphewjj1AaxYcaxlK", "type": "Refer", "targetType": "Script" } }

トリガーされると Script は委任された権限で実行され、statement ごとのリソース権限は実行時に再検査されません。何が許可されるかは Script を作成する時点ですでに検査されます。詳しい実行・権限モデルは Script の実行セマンティクス、制約、セキュリティ を参照してください。

runAs

runAs は script が どのユーザーとして実行されるか を定めます。この ID は、実行中に作成または修正されるリソースの createdBy/updatedBy になり、Script 内の createdBy: ":self" フィルターもこの ID を基準に解決されます。帰属(attribution)であって、権限の境界ではありません。何ができるかは Script を作成する時点の権限検査で決まります。

値実行するユーザー
HookOwnerWebhook を作成したユーザー(sys.createdBy)。既定値。
EventUserそのイベント(変化)を起こしたユーザー、すなわちトリガーとなったリソースの sys.updatedBy。

url だけを使う Webhook では runAs は無視されます。指定しない場合は HookOwner です。

WebhookLog

Webhook が 1 回送信を試みるたびに、記録が 1 つ残ります。取得専用で、作成・修正・削除エンドポイントはありません。パスは /spaces/{spaceId}/webhooks/{webhookId}/logs です。

{
  "sys": {
    "id": "3trmXRM3RqbgSnifyg7PWhc01Exam",
    "type": "WebhookLog",
    "space": { "sys": { "id": "HnQ32YiH", "type": "Refer", "targetType": "Space" } },
    "requestId": "3trmXRM3qWnLb7Vd1yPcYs04kKrjq",
    "statusCode": 200,
    "errors": [],
    "eventType": "Create",
    "url": "https://api.dailywear.example/webhooks/products",
    "requestAt": "2026-06-18T11:35:00.100Z",
    "responseAt": "2026-06-18T11:35:00.350Z",
    "request": {
      "url": "https://api.dailywear.example/webhooks/products",
      "method": "POST",
      "headers": { "Content-Type": "application/json", "X-Source": "weegloo" },
      "body": "{\"sys\":{\"type\":\"Content\"}}"
    },
    "response": {
      "url": "https://api.dailywear.example/webhooks/products",
      "headers": { "Content-Type": "application/json" },
      "body": "{\"ok\":true}",
      "statusCode": 200
    },
    "createdBy": { "sys": { "id": "3trmXRM3RqbgSnifyg7PWhk01Examp", "type": "Refer", "targetType": "Webhook" } },
    "createdAt": "2026-06-18T11:35:00.350Z",
    "updatedBy": { "sys": { "id": "3trmXRM3RqbgSnifyg7PWhk01Examp", "type": "Refer", "targetType": "Webhook" } },
    "updatedAt": "2026-06-18T11:35:00.350Z"
  }
}

すべての値が sys の中にあり、本文属性はありません。値のないキーはレスポンスから外れます。

どの Webhook が残した記録かは sys.createdBy が指します。ユーザーではなくその Webhook の Refer であり、sys.updatedBy も同じ Webhook です。

属性タイプ説明
idstring記録の一意な識別子。
typestring常に "WebhookLog"。
spaceRefer<Space>この記録が属する Space。
requestIdstringこの送信試行の追跡識別子。
statusCodeinteger受け取ったレスポンスの HTTP ステータスコード。
errorsstring[]失敗理由のリスト。URL へ送る Webhook の記録では 常に空です(ステータスコードが失敗を示します)。script で Script を実行する Webhook の記録にのみ、その Script の失敗メッセージが入ります。
eventTypestringこの送信を引き起こした アクション名 です(例: Create・Publish)。topics に書く Content.Create の形ではなく、後ろのアクションだけが入ります。
urlstring送信先の URL。
requestAtstring (date-time)リクエストを送った時刻。
responseAtstring (date-time)レスポンスを受け取った時刻。
requestobject送ったリクエスト。下位構造は下にあります。一覧取得では外れます。
responseobject受け取ったレスポンス。下位構造は下にあります。一覧取得では外れます。
createdByRefer<Webhook>この記録を残した Webhook。
createdAtstring (date-time)記録の作成時刻。
updatedByRefer<Webhook>createdBy と同じです。
updatedAtstring (date-time)createdAt と同じです。

request と response はそれぞれ次のキーを持ちます。

  • request: url(リクエストを送った対象 URL)・method(HTTP メソッド)・headers(送ったヘッダーのマップ)・body(送った本文の文字列)。
  • response: url(レスポンスを受け取った URL)・headers(受け取ったヘッダーのマップ)・body(受け取った本文の文字列)・statusCode(受け取ったステータスコード)。

script で Script を実行する Webhook の記録は形が違います。送る宛先がないため url がなく、request の method は "SCRIPT" に固定されます。request の body にはその送信を引き起こした payload が、response の body にはその Script が返した値(または失敗メッセージ)が入ります。

secret をオンにしたヘッダーの値と、basicAuth が作った Authorization ヘッダーの値はマスクされて保存されます。実際の値は記録に残りません。

長い本文は縮めて保存されます。 request の body は 65,536 文字、response の body は 8,192 文字が基準です。それより長い場合は 前後を残して中間を省略 し、省略された文字数をその場所に書き込みます。本文が JSON の場合は構造を壊さないよう、長い文字列の値だけを同じ方式で縮めるため、キーと短い値はそのまま残ります。

成功と失敗を分ける基準は連携方式ごとに異なります。 URL へ送る Webhook は、レスポンスが 2xx または 3xx なら成功です。script で Script を実行する Webhook は、statusCode が 400 より小さく errors が空のときに成功です。この判定 1 つが、下の保存期間と 送信状態 の成功率を合わせて決めます。

一覧取得は request と response を外して返します。 一覧エンドポイントの select の既定値が -sys.response,-sys.request だからです。送ったリクエストと受け取ったレスポンスの本文まで見るには、単一取得を使うか、select を直接指定してその既定値を上書きする必要があります。

成功した送信の記録は 1 時間後、失敗した送信の記録は 3 日後に消えます。有効期限を収めたフィールドはレスポンスになく、時が来ると記録は自然に消えます。それより長く保管する必要がある値は、受け取る側のサーバーに別途保存するか、script で実行する Script から Content として残してください。

エラー

Webhook を扱うときに出会うコードです。すべてのリソースに共通するコードは 共通エラー を参照してください。

コード条件
WGL400042作成(POST)・全体修正(PUT)で url と script を両方指定したか、両方空にしました。
WGL422061部分修正(PATCH)で url と script を両方指定したか、両方空にしました。
WGL422050url がプライベートネットワーク・ループバックのようにブロックされた対象を指しています。
WGL400104basicAuth に username がありません。
WGL400105basicAuth に password がなく、維持する保存済みの password もありません(作成、または Basic 認証がなかった Webhook の修正)。

API

以下のすべてのエンドポイントの基準 URL は https://cma.weegloo.com/v1 で、Authorization ヘッダーに CMA を認証する Bearer トークンが必要です。修正(PUT)と部分修正(PATCH)は、楽観的同時実行制御のために X-Weegloo-Version ヘッダー(現在のリソースの sys.version)を一緒に送る必要があります。

  • Content: Webhook をトリガーする本文データ。
  • Media: Webhook をトリガーできるファイルリソース。
  • Script: script で実行する宣言型のバックエンドエンドポイント。実行・権限モデルを含む。
  • SpaceRole: Script の実行(Execute)権限などを持つロール設定。