Webhook

最終更新: 2026年7月3日

服屋のショッピングモールを運営していると考えてみてください。新しい商品を登録するたびに、毎回自分で対応しなければならない裏方の作業があります。商品説明を別の国の言葉に翻訳しておいたり、登録したことを社内メッセンジャーに知らせたりするような作業です。こうした裏方の作業を人が毎回手作業でやるのではなく、商品が登録された瞬間に外部にあるプログラムへ自動で知らせて、代わりに処理させることができます。この「何かが起きたら、あらかじめ決めておいた場所へ自動で知らせてくれる仕組み」が Webhook です。

店のドアに取り付けた呼び鈴にたとえることができます。お客さんがドアを開けて入ってくると(商品が登録されると)、呼び鈴がひとりでに鳴って、奥にいる従業員(外部プログラム)が「お客さんが来たな」とすぐに動き出します。誰かがずっとドアの前を見張っている必要はありません。Webhook はその呼び鈴のように、決めておいた出来事が起きた瞬間に、決めておいた場所へリクエストを送ります。

このページでは、Webhook が何であり、どんなときに使うのかをまず見てから、服屋の SpaceWebhook を実際に作ってみます。外部プログラムが返してきた結果を再び商品に書き戻す WriteBack もあわせて扱います。

Webhook がすること

Webhook は、三つのことをあらかじめ決めておくことで成り立ちます。

  • いつ送るか: どんな出来事が起きたときにリクエストを送るかを決めます。たとえば「商品(Content)が新しく登録されたとき」と決めることができます。
  • どこへ送るか: リクエストを受け取る外部プログラムのアドレスを決めます。インターネットのアドレス(URL)を一つ書いておきます。
  • オンにするかオフにするか: この Webhook を今オンにしておくか(ACTIVE)、しばらくオフにしておくか(INACTIVE)を決めます。オフにしておくと、決めておいた出来事が起きてもリクエストを送りません。

決めておいた出来事が実際に起きると、Webhook は書いておいたアドレスへ、その事実を知らせるリクエストを送ります。リクエストには、何が起きたのか、どの商品で起きたのかといった情報が含まれて送られます。リクエストを受け取った外部プログラムは、その情報を見て自分の仕事をします。

どんな変化でリクエストを送るか

リクエストを呼び起こす「出来事」は、Space の中のリソースに起こる変化です。商品のような Content、アップロードしたファイルである Media、書式のひな型である Content Type に何かが起きたときを選べます。

リソースごとに選べる変化は次のとおりです。

変化いつ起きるか服屋の例
Create新しく作られたとき新しい商品を登録する
Save内容を直して保存したとき商品説明を直して保存する
Delete削除されたとき廃番になった商品を消す
Publish発行して外部に公開したとき商品をサイトに公開する
Unpublish発行を取り消したとき品切れ商品をサイトから下げる
Archive保管処理したとき前シーズンの商品を保管する
Unarchive保管を解除したとき保管していた商品を戻す

たとえば「商品が新しく登録されるたびにリクエストを送れ」というのは、「商品(Content)の Create」を選ぶことです。

一つの Webhook に複数の変化をまとめて選ぶこともできます。「商品が登録されたとき」と「商品が修正されたとき」の両方を選ぶと、どちらが起きてもリクエストが送られます。

条件をつけて絞り込む

選んだ変化が起きたからといって、必ずリクエストを送りたいわけではないときがあります。たとえば「すべての Content ではなく『商品』という書式で作った Content が登録されたときだけ」受け取りたいことがあります。こういうときは フィルター をかけて、リクエストを送る場合を絞り込みます。

フィルター一つは、「何を基準に、どう比較するか」を一行で表したものです。何を基準に絞り込むかは、次の四つから選びます。

  • どの書式で作った項目か: たとえば「商品」Content Type で作った Content にだけリクエストを送ります。最もよく使う条件です。
  • 特定の項目一つか: 決めておいたその項目一つで起きた変化にだけリクエストを送ります。
  • 誰が作った項目か: 特定の人が作った項目にだけリクエストを送ります。
  • 誰が最後に直した項目か: 特定の人が最後に修正した項目にだけリクエストを送ります。

比較する方法もあわせて選びます。決めた値と等しいときだけ、異なるときだけ、決めておいた複数の値のいずれかに当てはまるときだけ、そのどれにも当てはまらないときだけ、または決めた形式(パターン)に合うとき・合わないときだけ、というように絞り込めます。

コンテンツスタジオのトリガー設定で フィルターを追加 から条件を一行ずつ追加します。フィルターを複数かけると、その条件を すべて満たす 場合にだけリクエストが送られ、一つもかけないと、選んだ変化が起きるたびにリクエストが送られます。

外部プログラムが求める形で送る

特に決めなければ、リクエストには変化が起きた項目の情報がまるごと含まれて送られます。たとえば商品「ステンレスタンブラー 500ml」が登録されると、リクエストに含まれて送られる内容はおおよそこのような形です。

{
  "sys": { "id": "3trmXRM3RqbgSnifyg7OGhwhlqvAvq", "type": "Content" },
  "fields": {
    "productName": { "ko-KR": "스테인리스 텀블러 500ml" }
  }
}

(実際にはもっと多くの情報が含まれており、上はその一部だけを抜き出した形です。)外部プログラムはこの中から必要な値を選んで使えばよいのです。しかし「この形でしか受け取らない」と形式が決まっているプログラムもあります。そういうときは、コンテンツスタジオの PayloadWebhook payload をカスタマイズ を選び、送る形を自分で書いておきます。

送る形を書きますが、上のデータから値を引いて入れる場所には プレースホルダー を使います。プレースホルダーは { /payload/… } という形です。ここで payload は上に示したその項目全体を指し、その後ろのパスで望みの値をピンポイントに指し示します。

  • { /payload/sys/id } → 上のデータの sys の中の id(商品の固有番号)
  • { /payload/fields/productName/ko-KR }fields の中の productNameko-KR(韓国語の商品名)。fields/ の後ろには Field の ID(商品名なら productName)と言語コード(韓国語なら ko-KR)を順に付けます。

たとえば翻訳プログラムが「翻訳する文と商品番号をこの形でくれ」と言うなら、ペイロードはこのように書きます。

{
  "id": "{ /payload/sys/id }",
  "text": "{ /payload/fields/productName/ko-KR }"
}

すると、タンブラー商品が登録される瞬間に、プレースホルダーが実際の値に置き換わって、このように送られます。

{
  "id": "3trmXRM3RqbgSnifyg7OGhwhlqvAvq",
  "text": "스테인리스 텀블러 500ml"
}

同じプレースホルダーは、送るアドレス(URL)やヘッダーの値にも入れることができ、送る方法(method)や形式(JSON またはフォーム形式)もあわせて選べます。指し示したパスに値がなければ、その場所は空の値になります。

外部 API キーのように他人に見えてはいけない値は、ヘッダーを追加するときにタイプを Secret に指定しておきます。すると、その値は隠されて保存され、最終ユーザーには露出されません。

受け取った応答で書き戻す: WriteBack

送るリクエストの形を決めるのが前の節だとすれば、WriteBack は返ってきた 応答 を扱います。Webhook が外部プログラムを呼び出して 正常(2xx)応答を受け取ると、その応答を加工して、Space の中の ContentMedia を作ったり、直したり、発行・削除したりできます。人が結果をコピーして貼り付ける手間がなくなります。

服屋の翻訳の例を最後まで追っていきます。先ほど、新しい商品の韓国語の商品名を翻訳プログラムに送りました。翻訳プログラムがこのように応答するとします。

{ "translated": "Stainless Tumbler 500ml" }

この翻訳文を同じ商品の英語の商品名の欄に書き込む WriteBack を構成します。コンテンツスタジオの WriteBack操作を追加 から ContentUpdate(修正)の動作を一つ追加し、このように決めます。

  • 対象: 特に決めなければ、変化が起きたその商品(タンブラー)が対象になります。
  • 書き込む欄と言語: 英語の商品名なので、欄は商品名(productName)、言語は英語(en-US)。
  • 入れる値: 応答の翻訳文を指し示す { /response/translated }

すると、タンブラー商品の英語の商品名の欄が Stainless Tumbler 500ml で埋まります。

このような WriteBack は、外部の LLM とつなぐのに特に役立ちます。たとえば、商品説明を送って作った宣伝画像を Media として保存したり、生成された紹介文で新しい Content を作ったりする流れを、Webhook 一つで構成できます。

動作の順序

  1. 変化が起きると、Webhook が決めた形で外部プログラムにリクエストを送ります。
  2. 応答が 2xx なら、追加しておいた WriteBack の動作(オペレーション)を 上から順番に 実行します。
  3. 各動作は互いに独立しているので、一つが失敗しても残りは実行され続けます。
  4. WriteBack で生じた生成・修正・削除・発行も、再び変化として捉えられ、その変化を購読する別の Webhook を続けて呼ぶことがあります。終わりなく回り続ける循環は、Webhook を作ったり直したりするときに自動で検査され、止められます。

WriteBack で作られたり変わったりしたリソースの作成者(createdBy)は、その変化を引き起こしたユーザーになります。

値の表現式

書き込む値は、前に見たものと同じプレースホルダー({ /… })で取得します。ただし、WriteBack では指し示せる根が 二つ あります。

指し示す対象
{ /response/… }外部プログラムが返した 応答本文
{ /payload/… }変化が起きた 元の項目(Content/Media)
  • 一つのプレースホルダーだけを単独で使うと({ /response/url })、値の 元の形(文字・数値・まとまり)をそのまま取得します。
  • 文字と混ぜて使うと("生成済み: { /payload/sys/id }")、一つの文字としてつなぎ合わさります。
  • 応答が JSON ではなく文字そのものとして来るときは、{ /response } で応答全体を文字として受け取ります(その中の下位パスは指し示せません)。

Content を扱う ($content)

応答で Content を作ったり変えたりする動作です。決める項目は次のとおりです。

項目説明
actionCreateUpdateDeletePublishUnpublishArchiveUnarchive のいずれか(大文字小文字は区別しない)
contentType作る ContentContent TypeCreate に必須で、sys.id だけあればよいです。
target変える対象 Content の ID(プレースホルダーで指定)。省略すると 変化が起きたその項目 が対象です。(UpdateDeletePublishUnpublishArchiveUnarchive)
localefields の値を記録する言語。コード(例: ko-KR)か、そのコードに解決されるプレースホルダー。省略時は Space の既定の言語。(CreateUpdate)
fields欄の名前 → 入れる値(プレースホルダー)。(CreateUpdate)
publishCreateUpdate の後すぐに発行するか(既定はオン)。オフにすると発行せず Draft のままにします。
unpublishDelete のときに発行を先に自動で下げてから削除するか(既定はオン)。オフにすると、対象がすでに削除できる状態でなければ削除に失敗します。

Media を扱う ($media)

応答で受け取ったファイルを Media として取り込んだり、Media の状態を変えたりする動作です。

項目説明
actionCreateDeletePublishUnpublishArchiveUnarchive(修正 Update はなし)
source取り込むファイルを指し示すプレースホルダー。(Create)
encodingファイルを受け取る方法: Url(アドレスからダウンロード)または Base64(応答に含まれたファイルデータを展開して保存)
locale取り込んだファイルとタイトル・説明を記録する言語。Content と同じ規則。(Create)
titledescriptionその言語のメディアのタイトル・説明(プレースホルダー、任意)。(Create)
target変える対象 Media の ID。省略すると変化が起きたその項目。(DeletePublishUnpublishArchiveUnarchive)
publishCreate 後、処理が終わったらすぐに発行するか(既定はオン)。
unpublishDelete のときに発行を先に下げてから削除するか(既定はオン)。

$mediaContent の欄の値としても使えます。応答で受け取ったファイルを Media として取り込んだ後、その Media を欄にそのまま結びつけて、「画像が入っている Content」を一度に作ることができます。

MediaDeleteArchiveUnarchive は、一覧上の情報だけでなく、保管庫にある実際のファイルまでもあわせて処理します。

設定の仕方と例

コンテンツスタジオの WriteBack操作を追加 から動作を一つずつ追加します。画面で項目を埋める Visual 方式と、下のような writeBacks のまとまりを直接書く JSON 方式を行き来できます。どちらでやっても結果は同じです。

外部 LLM が作った画像を添えて新しい商品を作る。 応答に含まれた画像のアドレスを Media として取り込み、その画像を持つ Content を新しく作ります。

{
  "writeBacks": [
    {
      "$content": {
        "action": "Create",
        "contentType": { "sys": { "id": "<商品 Content Type の sys.id>" } },
        "fields": {
          "productName": "{ /payload/fields/productName/ko-KR }",
          "photo": { "$media": { "source": "{ /response/data/0/url }", "encoding": "Url" } }
        }
      }
    }
  ]
}

変化が起きたその商品を補強する。 target を省略すると、変化が起きた Content が対象です。応答の値をその商品の欄に書き込みます。

{
  "writeBacks": [
    {
      "$content": {
        "action": "Update",
        "locale": "en-US",
        "fields": { "productName": "{ /response/translated }" }
      }
    }
  ]
}

確認してから発行するために Draft だけ作る。 publish をオフにしておくと、発行せず下書きとして残し、人が確認してから発行できます。

{
  "writeBacks": [
    {
      "$content": {
        "action": "Create",
        "contentType": { "sys": { "id": "<Content Type の sys.id>" } },
        "fields": { "text": "{ /response/choices/0/message/content }" },
        "publish": false
      }
    }
  ]
}

応答の画像を独立した Media として取り込む。 アドレスで受け取るなら encodingUrl に、応答に含まれたファイルデータで受け取るなら Base64 にします。

{
  "writeBacks": [
    { "$media": { "action": "Create", "source": "{ /response/data/0/url }", "encoding": "Url" } }
  ]
}

DeletePublishUnpublishArchiveUnarchive は形が同じです。action と変える対象 target だけ書けば、その対象の状態だけが変わります(対象を省略すると変化が起きたその項目)。たとえば応答が知らせてきた Content を発行するには、このように書きます。

{
  "writeBacks": [
    { "$content": { "action": "Publish", "target": "{ /response/contentId }" } }
  ]
}

動作を複数追加すると、書いた順に実行されます。「翻訳結果を商品に書き込み、続いて宣伝画像を Media として取り込む」というように、続けて並べる形です。

実行結果の確認

WriteBack の動作がどうなったかは、Webhook の呼び出し履歴で確認します。動作ごとに次が残ります。

項目説明
順序追加しておいた動作のうち何番目か
対象Content なのか Media なのか
動作実行した action
状態Success(成功) ・ Failed(失敗) ・ Skipped(スキップ)
結果 ID作られたり変わったりしたリソースの ID(あるとき)
エラー失敗したときのメッセージ

成功した動作は、結果 ID で、どのリソースが作られたり変わったりしたのかをたどれます。応答が 2xx でなければ WriteBack はそもそも実行されず、結果の記録も空のままです。

知っておくこと

  • リクエストを送る変化は一つだけ。 一つの Webhook が「登録(Create)」と「発行(Publish)」を同時に捉えると、外部プログラムが二回呼ばれることがあります。WriteBack を使う Webhook は変化を一つだけ選んでください。
  • 値を移すだけで計算はできません。 応答から値を取り出して入れることまでしかせず、条件分岐や繰り返しのような処理はしません。
  • 再試行はしません。 処理の途中で問題が起きると、その動作はそのまま失われることがあります。
  • むやみに作れないように。 WriteBack でのみ作られる Content Type は、一般ユーザーが直接作れないように権限を絞っておくのがよいです。

服屋の Webhook を作る

では、服屋の SpaceWebhook を一つ作ってみます。「新しい商品が登録されたら、あらかじめ用意しておいた外部の翻訳プログラムにその事実を知らせる」という Webhook です。リクエストを受け取る外部プログラムのアドレスは https://example.com/translate とします。

  1. 服屋の Space の設定で Webhook 画面を開いてください。
  2. 右上の 作成 ボタンを押してください。
  3. 名前の欄に 新商品の翻訳通知 を入力してください。この名前は、後でどの Webhook なのかを見分けるためのものです。
  4. リクエストを送る変化を決めてください。特定の変化にだけ送るなら 特定のトリガーイベントを選択 を選んでから、望みの変化(ここでは商品(Content)の Create)を指定し、すべての変化に送るなら すべてのイベントでトリガー を選びます。
  5. URL の欄に、リクエストを受け取る外部プログラムのアドレス https://example.com/translate を入力してください。
  6. 有効 をオンにしておくと、作った直後にリクエストを送ります(ACTIVE)。しばらく試すだけなら、オフにしておいてください(INACTIVE)。
  7. 作成 ボタンを押して Webhook を作ってください。

新しい Webhook 作成画面。名前・有効化・トリガー選択・URL を埋めた様子

一覧に 新商品の翻訳通知ACTIVE の状態で現れたら、Webhook が作られたということです。

Webhook 一覧に「新商品の翻訳通知」が ACTIVE の状態で見える画面

作った後は、服屋に実際に新しい商品を一つ登録してみてください。登録する瞬間に Webhook が書いておいたアドレスへリクエストを送ります。リクエストがうまく届いたか、外部プログラムがどう応答したかは、Webhook の呼び出し履歴で確認できます。

オン・オフと修正

Webhook は、作った後でもいつでもオン・オフできます。しばらくリクエストを止めたいときは、削除せずに INACTIVE にしてオフにしておいてください。オフにしている間は、新しい商品を登録してもリクエストは送られません。再び ACTIVE にしてオンにすると、そこから再びリクエストを送ります。

作った Webhook を再び開くと、有効 をオフにしたり、再びオンにしたりできます。名前、リクエストを送るアドレス、呼ぶ変化といった内容も後で修正でき、もう使わない Webhook は削除すればよいです。

次にすること

  • Content モデリング: Webhook がリクエストを呼び起こす対象である「商品」のような Content の書式のひな型を作る方法を扱います。
  • Content を作成する: 実際に商品を登録して、Webhook が動作するか確認してみることができます。
  • API リファレンス: Webhook をプログラムから直接作成・管理するときに使うリクエスト・応答の形式とフィールドの仕様を扱います。