Webhookとは?読み方・仕組み・APIとの違いを実際のHTTPリクエストで解説
Webhookは、あるサービスでイベントが起きた瞬間に、あらかじめ登録しておいた相手のURLへHTTPリクエストを1回投げる仕組みです。GitHubへのpush、決済の完了、LINEへのメッセージ着信といった出来事を、受け取る側が問い合わせに行かなくても知ることができます。専用のプロトコルや特別なライブラリは登場しません。実体はHTTP POSTが1往復するだけです。この記事では、読み方と定義、送られてくるリクエストの中身、ポーリング型のAPI連携との通信量の差、そして「Webhookが廃止される」という話の正体までを、公式仕様と実際のヘッダに沿って整理します。
まとめ
Webhookの読み方は「ウェブフック」です。2007年にJeff Lindsayが提唱した「ユーザー定義のHTTPコールバック」が原義で、送信側がイベント発生時に受信側のURLへHTTP POSTを送る一方向の通知を指します。
APIとの最大の違いは通信の起点にあります。ポーリング型のAPI連携を1分間隔で回すと1日1,440回の問い合わせが発生しますが、Webhookなら実際に起きたイベントの数だけしか通信しません。引き換えに受信側は公開URLを用意する義務を負い、届いたリクエストが本物かを署名で検証する責任も負います。
「Webhookプロトコル」という規格は存在しません。HTTP POSTの慣習にすぎないため実装がサービスごとにばらつき、それを揃えようとする動きがStandard Webhooks仕様とCloudEventsです。2026年に話題になった「Webhook廃止」も、Microsoft TeamsのMicrosoft 365コネクタという特定製品の終了であって、Webhookという仕組み自体は現役です。以下で、それぞれの根拠を具体的に見ていきます。
Webhookの定義と「ウェブフック」という読み方
2007年に提唱された「ユーザー定義のHTTPコールバック」という原義
Webhookの読み方は「ウェブフック」です。日本語の記事では「Webフック」と書かれることもありますが、公式ドキュメントの日本語版でも英語表記のWebhookがそのまま使われるため、技術文書ではWebhookと書くのが無難です。
語源はプログラミング用語の「フック(hook)」で、既存のコードの決められた場所に利用者側の処理を差し込むための口を指します。2007年にJeff Lindsayがこれをウェブに持ち込み、Webhookを「user-defined HTTP callbacks(ユーザーが定義するHTTPコールバック)」と定義しました。処理を差し込む口がURLになった、と考えると原義に近くなります。
定義に「HTTP」と入っている点が肝心です。Webhookは特定の企業の製品でもソフトウェアでもなく、HTTPリクエストの使い方に付いた名前にすぎません。だからGitHubにもStripeにもLINEにも「Webhook」という機能があり、しかもそれぞれ仕様が微妙に違います。
Webhook URL・イベント・ペイロードという3つの構成要素
Webhookを構成する要素は、Webhook URLとイベント、そしてペイロードだけです。
- Webhook URL:受信側が用意し、送信側の管理画面に登録するエンドポイント。インターネットから到達できる必要があります
- イベント:送信のきっかけになる出来事。GitHubなら
pushやpull_request、決済サービスなら支払い成功や返金など、送信側が定義した一覧から選びます - ペイロード:リクエストボディに載る本体データ。Standard Webhooks仕様は最大限の互換性のためJSON形式を推奨しています
登録作業はたいてい管理画面でURLを貼り付け、通知したいイベントにチェックを入れるだけです。GitHub・GitLab・Discordのように、無料プランでもWebhookを設定できるサービスは多くあります。費用が発生しやすいのは、受け取った側で動かすサーバーやワークフローの実行回数のほうです。
Webhookの仕組み:1回のHTTP POSTで完結する通信の中身
GitHubが送るリクエストのヘッダとボディの実物
抽象的な図よりも、実際に飛んでくるリクエストを見るほうが早いです。GitHubのリポジトリにpushが起きたとき、登録済みのWebhook URLには次のような形のリクエストが届きます。
POST /webhooks/github HTTP/1.1
Host: example.com
Content-Type: application/json
X-GitHub-Event: push
X-GitHub-Delivery: 72d3162e-cc78-11e3-81ab-4c9367dc0958
X-Hub-Signature-256: sha256=757107ea0eb2509fc211221cce984b8a37570b6d7586c22c46f4379c8b043e17
{
"ref": "refs/heads/main",
"repository": { "full_name": "example/app" },
"pusher": { "name": "octocat" }
}
GitHubの公式ドキュメントによれば、X-GitHub-Eventがイベント種別、X-GitHub-Deliveryが配信ごとに振られる一意のGUID、X-Hub-Signature-256がシークレットを設定した場合に付く署名です。署名はリクエストボディをシークレットを鍵としてHMAC-SHA256でハッシュ化した値で、必ずsha256=で始まります。旧来のX-Hub-SignatureはHMAC-SHA1を使っており、GitHubは「レガシー目的でのみ含まれている」としてX-Hub-Signature-256の利用を推奨しています。
受信側がやることは、このリクエストを受け取って200を返すことだけです。返事の本文は基本的に読まれません。送信側の多くは、返ってきたステータスコードが成功(2xx)かどうかしか見ていないからです。この一方向性が、Webhookを理解するうえでの出発点になります。
「Webhookプロトコル」が存在しない理由と標準化仕様の現在地
Webhookのプロトコル仕様書を探しても見つかりません。Webhookに固有のプロトコルが存在しないからです。トランスポートはHTTP、フォーマットは各社が個別に決めたJSON、認証も各社が個別に決めたヘッダになっています。共通しているのは「POSTで送る」という一点だけです。
この野放し状態が、受け取る側に実害を出します。5つのサービスからWebhookを受けるなら、署名ヘッダ名を5通り覚え、署名対象文字列の作り方を5通り実装することになります。
これを揃えようとしている仕様が2つあります。ひとつがStandard Webhooksで、必須ヘッダをwebhook-id・webhook-timestamp・webhook-signatureの3つに固定します。仕様書が示す例は次のとおりです。
webhook-id: msg_2KWPBgLlAfxdpx2AI54pPJ85f4W
webhook-timestamp: 1674087231
webhook-signature: v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4=
署名の対象はmsg_id.timestamp.payloadをピリオドで連結した文字列と決められており、対称鍵ならHMAC-SHA256で接頭辞v1,、非対称鍵ならed25519で接頭辞v1a,を付けます。ボディだけでなくIDとタイムスタンプまで署名に含めるのは、同じリクエストを後から投げ直すリプレイ攻撃を防ぐためです。仕様は受信側にwebhook-timestampが現在時刻から許容範囲内かを確かめるよう求めていますが、許容幅の具体的な分数までは定めていないため、実装側で決める必要があります。
もうひとつがCloudEventsです。こちらはイベントデータそのものの記述形式を定める仕様で、CNCFで2018年5月にsandbox、2019年10月にincubatingを経て、2024年1月25日にgraduatedプロジェクトになりました。安定版は2022年2月5日リリースのv1.0.2で、そのタグ配下にはHTTP・Kafka・AMQP・MQTT・NATS・WebSocketsの6つのバインディング定義が置かれています。Standard Webhooksが「配送と署名の作法」を、CloudEventsが「イベントの中身の書式」を担当する、と分けて捉えると混乱しません。
ただし、これらの仕様に対応しているサービスは限られます。連携先がGitHubやStripeのような独自仕様である以上、当面は相手ごとの実装が必要だと割り切ったほうが現実的です。自社がWebhookを送る側になるときだけ、Standard Webhooksに寄せる価値があります。
ポーリング型APIとの違い:通信回数とリアルタイム性の比較
1分間隔ポーリングとの1日あたり通信回数の差
WebhookとAPIは対立する技術ではありません。どちらもHTTPを使い、多くの場合は同じサービスが両方を提供しています。違うのは「誰が通信を始めるか」です。APIは受信側が欲しいときに取りに行き、Webhookは送信側が起きたときに届けに来ます。
| 観点 | Webhook | ポーリング型API |
|---|---|---|
| 通信の起点 | 送信側 | 受信側 |
| 1日の通信回数(1分間隔) | イベント発生数だけ | 1,440回 |
| 検知までの遅延 | 数秒 | 最大で間隔ぶん |
| 受信側の事前準備 | 公開URLと署名検証 | 不要 |
| 取りこぼしの回復 | 再送・再取得の設計が必要 | 次回取得で自動回復 |
| 過去データの取得 | 不可 | 可能 |
通信回数の差は単純な掛け算で出ます。1分間隔のポーリングは60×24で1日1,440回、5分間隔でも288回になります。連携先が10サービスあれば1日14,400回の問い合わせを投げ続けることになり、その大半は「変化なし」という空振りです。イベントが1日10件しか起きない業務なら、Webhookの通信は10回で済みます。API側のレート制限に頻繁に当たっている場合は、空振りのポーリングが枠を食い潰していないかを先に疑ってください。
Webhookを選ぶ条件と、ポーリングを残すべき条件
判断は好みではなく条件で決まります。イベントの発生が散発的で、かつ数秒以内に反応する必要があるならWebhookです。決済完了通知やCI/CDのトリガーが典型で、ここでポーリングを選ぶ理由はありません。
逆に、次のいずれかに当てはまるならWebhookを採用すべきではありません。第一に、受信側を外部公開できない環境。社内ネットワークからの片方向通信しか許されないなら、Webhookは物理的に届きません。第二に、過去にさかのぼった一括取得が必要な場合。Webhookは登録後に起きたイベントしか流れてこないので、初期同期は必ずAPIで行う必要があります。第三に、データの整合性を自分で保証したい場合。後述のとおりWebhookには欠損の可能性があり、最終的な突き合わせはAPI取得に頼ることになります。
実務では、初期同期と定期的な整合性チェックをAPIで、日常のリアルタイム反映をWebhookで、と両方を併用する構成が安定します。API方式そのものの選定で迷っている場合は、REST APIとGraphQLの違いと使い分けもあわせて確認してください。
Webhookでできること:通知・データ同期・処理の連鎖
用途は、通知・データ同期・処理の連鎖に分かれます。
- チャットへの通知:エラー発生やデプロイ完了をSlack・Teams・Discordへ流す使い方。受信側のコードを書かずに導入できるため、最初の一歩になりやすい用途です
- システム間のデータ同期:決済サービスの支払い確定を受けて自社DBの注文ステータスを更新する、フォーム送信をCRMへ流し込むなど
- 処理の連鎖(自動化のトリガー):GitHubへのpushでCI/CDを起動する、問い合わせ着信でワークフローを開始するといった使い方。ノーコードツール側がWebhookの受け口を用意する例もあり、LangflowのWebhook連携はその一例です
同じ「Webhook」という言葉でも、通信の向きが逆のものが混在している点には注意が必要です。LINEの公式アカウントで使うWebhookは、ユーザーの発言をLINEプラットフォームが自社サーバーへ送ってくる受信側の設定です。対してSlackやDiscordのIncoming Webhookは、発行されたURLへ自社から投稿を送る送信側の仕組みで、受信エンドポイントを用意する必要がありません。後者の具体的な設定手順は、Slack・DiscordのIncoming Webhookの使い方で扱っています。
Webhookの安全性:at-least-once配信と署名検証という前提
重複・順序入れ替わり・欠損が起きる配信保証の実態
「Webhookは危険か」という問いには、2つの層があります。ひとつは配信の信頼性、もうひとつはなりすましです。まず信頼性から見ます。
Webhookの配信は、多くのサービスでat-least-once(最低1回)です。受信側が200を返せなかった場合、送信側は間隔を空けて再送します。GitHubが配信ごとに一意のX-GitHub-Deliveryを振り、Standard Webhooks仕様がwebhook-idヘッダを冪等キーとして使うよう明記しているのは、同じイベントが複数回届く前提で設計されているからです。
ここから導かれる前提が2つ、そして見落とされがちな最悪ケースが1つあります。同じイベントが2回以上届くことがあります。届く順序が発生順と入れ替わることもあります。そして再送の上限回数を使い切れば、そのイベントは永久に失われます。
受信したデータをそのまま「1回だけ起きたこと」として処理すると、二重課金や在庫の二重引き当てを起こします。イベントIDを保存して処理済みかを判定する冪等性の設計は、Webhookを本番投入する際の必須要件です。
署名ヘッダの構成と、検証を省いた場合の失敗パターン
もうひとつの層がなりすましです。Webhook URLはインターネットに公開されているので、URLさえ知っていれば誰でもリクエストを送れます。署名を検証していない受信エンドポイントは、「決済が完了しました」という偽のJSONを外部から送り込めば商品を出荷してしまう、という状態に等しくなります。
これを防ぐのが、前述のX-Hub-Signature-256やwebhook-signatureといった署名ヘッダです。送信側と受信側で共有したシークレットを鍵にしてボディのHMACを計算し、届いた署名と一致するかを確かめます。検証の実装には落とし穴がいくつかあります。ハッシュ計算はJSONをパースする前の生のボディに対して行うこと(パースして再構築すると1文字の差で署名が変わります)。比較は文字列の単純一致ではなくタイミング攻撃に強い比較関数を使うこと。署名にタイムスタンプが含まれる方式では、その鮮度も必ず確認すること。そして署名ヘッダに複数の値が空白区切りで並ぶ仕様もあるため、1つ目だけを見て判定しないことです。
署名検証・リトライ処理・冪等性の実装コードや、受信エンドポイントを実際に組む手順は、Webhookの実装方法と作り方で扱っています。
「Webhookが廃止される」という誤解の正体:Microsoft 365コネクタの終了
終了が告知されたのがコネクタというレイヤーだけである根拠
検索結果に「Webhookが廃止される理由は何ですか?」という質問が並ぶため、技術そのものが終わるように読めてしまいます。終了が告知されたのは、Microsoft TeamsのMicrosoft 365コネクタ(旧Office 365コネクタ)という一機能です。
Microsoftの公式開発者ブログによれば、この廃止計画は2024年8月15日の新規コネクタ作成停止(Wave 1)から始まりました。当初は2024年10月に全停止する予定でしたが、利用者からの反発を受けて期限が複数回延長されています。最終的な無効化については「ロールアウト開始が2026年5月18日、完了が2026年5月22日」として告知されました。代替として案内されているのは、Teams内のWorkflowsアプリ(Power Automate)から発行するWebhookです。
ここで押さえるべきは、置き換え先もまたWebhookだという点です。終了したのはMicrosoftが独自に載せていたコネクタというレイヤーであって、HTTP POSTでイベントを届けるという仕組み自体は何も変わっていません。GitHubもStripeもLINEもWebhookを提供し続けています。
ベンダー独自機能に依存した連携が抱える寿命リスク
この件から実務的に引き出せる教訓は、Webhook URLの発行元がベンダー独自の機能である場合、その機能の寿命がそのまま連携の寿命になるということです。移行期限が複数回延期されたぶん、対応を後回しにしたまま期日を迎えた組織もあると考えられます。
備え方は2つに分かれます。事前の備えとしては、連携先ごとにURLの発行元と、そのサービスの廃止予告をどこで受け取るか(Microsoftならメッセージセンター、GitHubならChangelog)を一覧にしておくこと。これが最も確実な手立てです。事後の検知としては、一定時間Webhookが1件も届かない状態を異常として拾う監視を入れておくと、告知を見落とした場合でも停止に気づけます。
よくある質問
Webhookの受信URLを外部に公開できない場合はどうすればよいですか?
社内ネットワークからの片方向通信しか許されない環境では、Webhookをそのまま受けることはできません。現実的な選択肢は2つです。ひとつはクラウド上に受信専用の中継を置き、そこで署名を検証してから社内へ引き渡す構成。もうひとつはWebhookを諦めてAPIポーリングに寄せる判断です。開発中の動作確認だけであれば、ローカル環境を一時的に外部公開するトンネリングツールを使う手もありますが、本番運用の解決策にはなりません。
Webhookは無料で使えますか?
Webhookの送信機能自体は、GitHub・GitLab・Discordなど多くのサービスが無料プランに含めています。ただし無制限ではなく、登録数の上限や1分あたりの呼び出し回数の制限があるため、上限値は連携先のドキュメントで個別に確認してください。費用が発生しやすいのはむしろ受け取る側で、リクエストを受けるサーバーの稼働費や、iPaaS・ワークフローツールの実行回数課金がここに当たります。Microsoft TeamsのようにWorkflowsアプリ経由へ移行した場合は、Power Automateのライセンス条件も確認が必要です。
LINEやSlackのWebhookも同じ仕組みですか?
HTTP POSTでイベントを届けるという原理は同じですが、署名の検証方法はサービスごとに異なります。LINEのMessaging APIは専用のヘッダで署名を送り、GitHubはX-Hub-Signature-256、Standard Webhooks準拠のサービスはwebhook-signatureを使います。ヘッダ名だけでなく、署名の対象になる文字列の作り方も統一されていません。共通のライブラリで一括処理できると考えず、連携先ごとに公式ドキュメントの検証手順を読む前提で設計してください。
Webhookを自分で実装するには何から始めればよいですか?
受信側から作るのが順序として自然です。インターネットから到達できるURLを1本用意し、POSTを受けたら中身を保存してすぐに200を返すところまでを最初に作ります。処理を同期的に書き切ろうとすると送信側のタイムアウトに引っかかるため、受信と処理は分けるのが原則です。署名検証・重複排除・リトライを含む具体的な手順とコードは、Webhookの実装方法と作り方にまとめています。
Webhookが届かないとき、まず何を確認すればよいですか?
送信側の配信ログを最初に見ます。GitHubやStripeなど主要サービスは管理画面に配信履歴とレスポンスコードを残しており、そもそもリクエストが飛んでいないのか、飛んだが4xx・5xxで弾かれたのかがここで切り分けられます。リクエストが届いているのに失敗している場合、原因の多くは署名検証でのボディの扱い、レスポンスが遅すぎることによるタイムアウト、あるいはファイアウォールによる送信元IPの遮断です。届いていない場合は、登録したURLの綴りと、通知対象イベントにチェックが入っているかを先に疑ってください。