Webhookとは?アプリ同士が通知し合う仕組み
Webhook とは、何かが起きたときに、あるサービスがあなたのアプリへ自動的に送るメッセージです。顧客の支払いが成功すると、Stripeはアプリ内のアドレスに「支払いが成功しました。詳細はこちらです」というWebhookを送ります。するとアプリは反応し、注文を支払い済みにしたり、領収書を送ったり、アカウントを有効にしたりします。要するに、APIはアプリが他のサービスに質問することであり、Webhookは他のサービスがアプリに何かを知らせるためにアプリを呼び出すことです。
AIで作る場合になぜ重要なのか
アプリで決済を受け付けたり、別のツールからフォームの送信を受け取ったり、GitHubやShopify、カレンダーなどのサービスに接続したりすると、すぐにWebhookに出会います。Webhookは、何かが起きたことを知るための 正しい 方法であることが多いのですが、AIで作ったアプリが微妙に間違えやすい場所でもあります。
- エンドポイントがどんなリクエストも受け付けるため、誰でも偽の「支払い成功」イベントを作れてしまう。
- Webhookではなく決済完了後のリダイレクトページでアクセス権を付与しているため、途中でタブを閉じた人は購入したものを受け取れず、成功URLを見つけた人は無料で手に入れてしまう。
- 同じイベントが2回届き、顧客に注文やメールが2回届いてしまう。
Webhookの仕組みを知っておくと、これらの保護をあらかじめ依頼できます。
身近なたとえ:荷物の配達通知
荷物が届いたかどうかは、2つの方法で知ることができます。10分おきに玄関まで確認しに行くこともできます(これが ポーリング で、アプリが繰り返しAPIを呼んで「何か新しいものはある?」と尋ねることです)。あるいは、配達員が配達完了時にメッセージを送ってくれることもあります(これが Webhook です)。
メッセージのほうが明らかに楽ですが、信用できることが前提です。誰でも「荷物が届きました」というメッセージを送れるなら、本当に配達員から来たのかを確認する方法が必要です。さらに、通知が届いたときに電話の電源が切れていたら、配達員が後でもう一度送ってくれることも必要です。この2つ、つまり 検証 と 再送 が、Webhookを難しくしている大部分です。
Webhookの仕組み、ステップごとに
- アプリのバックエンドにエンドポイントを作る。
POSTリクエストを受け付けるhttps://yourapp.com/webhooks/stripeのようなURLです。 - そのURLを提供元に登録し、受け取りたいイベントを選ぶ。 たとえば「チェックアウト完了」や「サブスクリプションのキャンセル」です。
- 提供元が署名用のシークレットを発行する。 それをサーバーのシークレットとして保存します。詳しくは 環境変数とシークレット をご覧ください。
- イベントが発生する。 提供元は、あなたのURLに、イベントを説明するJSONの本文と、署名のヘッダーを付けてHTTPリクエストを送ります。
- アプリは署名を検証し、イベントIDを記録し、すぐに成功を示す応答(
200)を返してから、実際の処理を行います。 - アプリが成功の応答を返さなかった場合、多くの提供元は後で再試行します。
署名
署名は、リクエストが提供元から来たものであり、改ざんされていないことを証明します。たとえばStripeは、リクエストの本文とタイムスタンプに対して、署名用シークレットを使ってSHA-256のHMAC(鍵付きのフィンガープリントのようなもの)を計算し、Stripe-Signature ヘッダーで送ります。アプリは、自分が持つシークレットのコピーで同じ計算をし、結果が一致すれば、そのリクエストは本物です。タイムスタンプにも署名がかかっているため、誰かが記録して後から再送した古いリクエストを拒否できます。Stripeのライブラリは、2026年9月時点のドキュメントによれば、デフォルトで5分の許容時間を使います。
実務上の細かい点として、署名は 生の リクエスト本文に対して計算されます。フレームワークが検証の前にJSONを解析して整形し直すと、検証は失敗します。これは非常によくあるバグです。
再送、重複、順序
提供元によって異なるので、各提供元のドキュメントを確認してください。2026年9月時点では次のとおりです。
| 動作 | Stripe | GitHub |
|---|---|---|
| 自動の再送 | あり。本番モードでは、間隔を空けながら最大3日間 | なし。失敗した配信は手動、またはスクリプトで再送する |
| 応答時間 | 遅い処理を始める前に、すばやく2xxを返す | 応答に10秒以上かかった配信は失敗とみなされる |
Stripeのドキュメントはまた、イベントが発生した順番どおりに届く保証はないこと、同じイベントがまれに2回届くことがあることも説明しており、イベントIDを追跡することを推奨しています。
この一般的な教訓は、どの提供元にも当てはまります。イベントは 遅れて 、2回 、そして 順不同で 届くことがあります。ハンドラーは 冪等 であるべきです。つまり、同じイベントを2回処理しても、1回処理したときと同じ結果になる必要があります。
具体例:有料コースのロックを解除する
オンラインコースを販売しているとします。受講生が 購入 をクリックし、Stripeのホスト型決済ページで支払い、サイトに戻されます。
脆い方法: 「ありがとうございます」ページでコースのロックを解除する。受講生がリダイレクトの途中でブラウザを閉じると、支払ったのにアクセスできません。感謝ページのURLを推測した人は、支払わずにアクセスできてしまいます。
Webhookを使う方法:
- Stripeが支払いを確認すると、
checkout.session.completedイベントを/webhooks/stripeに送ります。 - バックエンドは、署名用シークレットで署名を検証します。失敗した場合は
400を返し、何もしません。 - そのイベントIDがすでに処理済みかを確認します。処理済みなら
200を返して終わります。 - イベントIDを保存し、
200を返してから、受講生にアクセス権を付与し、ようこそメールを送ります。 - 「ありがとうございます」ページには「お支払いを確認しました。コースはまもなく表示されます」とだけ表示し、受講生のアクセス状況を確認します。
その後、サブスクリプションがキャンセルされたり、カードが失敗したりすると、別のWebhookイベントが、アプリにアクセス権の削除や一時停止を指示します。これにより、サブスクリプション型の商品は請求とずれないように保たれます。SaaSとは と アプリに決済を追加する方法 もご覧ください。
主な用語
- エンドポイント: アプリ内で、Webhookを受け取るURLです。
- イベント / ペイロード: 何が起きたかと、それを説明するデータ(通常はJSON)です。
- 署名用シークレット: 署名を検証するために共有される秘密の値です。
- 冪等(idempotent): 同じ結果になる形で、何度実行しても安全なことです。
- ポーリング: Webhookを待つ代わりに、変更があるかを API に繰り返し問い合わせることです。
- トンネル: 開発中にWebhookが届くよう、ノートPCに一時的な公開URLを与えるツールです。
よくある間違いと誤解
- 署名を検証しない。 エンドポイントのURLは秘密ではありません。検証があることで、初めてリクエストを信頼できます。
- 返信の前に重い処理をする。 応答の前にメールを送ったりPDFを生成したりすると、タイムアウトが起き、それが再送を引き起こし、さらに重複を生みます。
- 1回だけ、順番どおりに届くと思い込む。 イベントIDを記録し、到着順序に頼らないようにしましょう。
- プレビューのURLを使う。 Webhookには安定した公開アドレスが必要です。非公開のプレビューや
localhostはインターネットからは届きません。公開したURLを使うか、テスト中はトンネルを使いましょう。 - テスト用と本番用のシークレットを混ぜる。 提供元は、テストモードと本番モードで異なる署名用シークレットを発行することがよくあります。両方を保存し、正しい方を使いましょう。
- 重要な判断を、ペイロードだけで鵜呑みにする。 影響の大きい操作では、イベントを受け取ったあとに提供元のAPIから最新の状態を取得するのが妥当です。
AIビルダーへの頼み方
サーバーに
POST /webhooks/stripeエンドポイントを追加してください。生のリクエスト本文と、シークレットSTRIPE_WEBHOOK_SECRETを使ってStripeの署名を検証してください。無効な署名は400で拒否してください。各イベントIDを保存し、処理済みのイベントはスキップしてください。すぐに200を返し、そのあとcheckout.session.completedを処理して、注文を支払い済みにし、領収書を送ってください。イベントの種類はログに残してください。決済の成功ページからアクセス権を付与しないでください。
そのあとテストします。提供元のダッシュボードからテストイベントを送り、同じものをもう一度送り、さらに不正な署名のリクエストも送ります。変更が起きるのは最初の1回だけであるべきです。
MythexでのWebhook
Mythexは、Webhook専用のサービスは別に持っていません。エージェントに頼むと、アプリ自身のバックエンドにWebhookのエンドポイントを追加してくれます。Webhookには公開されたアドレスが必要なので、提供元には 公開された URLを登録します。署名用シークレットはプロジェクトのシークレットに保存し、公開中のアプリでそれを変更したら、もう一度公開してください。Webhookの扱い方 のドキュメントのレシピにはスターターのプロンプトがあり、決済を受け付けるアプリの出発点としては、ストアのテンプレート も役立ちます。
よくある質問
Webhookとは簡単に言うと何ですか?
Webhookは、支払いの成功やフォームの送信などが起きたときに、あるサービスがアプリ内のWebアドレスへ自動的に送るメッセージです。アプリが何か変わったかどうかを何度も問い合わせる代わりに、相手側が知らせてくれます。
Webhookと APIの違いは何ですか?
API呼び出しでは、アプリが他のサービスに何かを尋ね、回答を受け取ります。Webhookでは、出来事が起きたときに相手のサービスがアプリを呼び出します。多くの連携では両方を使います。Webhookで出来事を知り、APIで詳細を取得したり操作を実行したりします。
Webhookは安全ですか?
検証すれば安全にできます。信頼できる提供元は、あなただけが知っている秘密の値で各Webhookに署名します。アプリは、署名が一致しないリクエストを拒否すべきです。この確認がないと、URLを見つけた誰もが偽のイベントを送れてしまいます。
Webhookが送られたとき、アプリがダウンしていたらどうなりますか?
提供元によって異なります。たとえばStripeは、本番モードで最大3日間、失敗した配信を再試行します。一方GitHubは自動では再試行せず、失敗した配信を手動で再送することを前提にしています。各提供元のドキュメントを確認し、遅れて届いたイベントや重複したイベントにも対応できるように、ハンドラーを設計しましょう。