ブログ · · 約 8 分で読めます

Stripe の Webhook の仕様:再送・順番・重複・タイムアウト・IP

Stripe の Webhook の再送の期間(本番とサンドボックス)、手動の再送、順番、重複、タイムアウト、送信元 IP、失敗の知らせを、公式のドキュメントの該当箇所へのリンク付きで 1 つの表にまとめ、受け側の実装の要点を示します。

要点

  • Stripe は本番で最長 3 日間、指数バックオフで Webhook を再送します。サンドボックスでは数時間のうちに 3 回です。
  • 順番は保証されず、同じイベントが複数回届くことがあります。受け側はイベントの ID で重複を弾き、必要なら API で最新の状態を取り直します。
  • 再送の間隔の分数と、タイムアウトの秒数は、公式のドキュメントに記載がありません(2026-09-27 時点)。

Stripe は、本番の環境では Webhook の配信を最長 3 日間、指数バックオフで再送します。サンドボックスでは数時間のうちに 3 回です。イベントが届く順番は保証されず、同じイベントが複数回届くこともあります。受け側は、処理したイベントの ID を記録して 2 回目以降を処理しないこと、順番に頼らず必要なら API で最新の状態を取り直すことが求められます。

Stripe の公式のドキュメントでは、これらの項目が複数のページに分かれています。この記事では、2026-09-27 に公式で確かめた内容を 1 つの表にまとめ、受け側の実装の要点を書きます。公式に書かれていない値は「記載なし」としています。

仕様の一覧

項目 仕様 出典
自動の再送(本番) 指数バックオフで最長 3 日間 Webhook
自動の再送(サンドボックス) 数時間のうちに 3 回 同上
各回の間隔 記載なし(次の予定はダッシュボードで見られる) 同上
再送中に送信先を無効化・削除 そのイベントの以降の再送は行わない。再送の前に無効化して再び有効にした場合は続く 同上
手動の再送 ダッシュボードはイベントの作成から 15 日まで、CLI(stripe events resend)は 30 日まで 同上
手動の再送の後の自動の再送 手動の再送が 2xx でも、自動の再送は止まらない 同上
未配信のイベントの一覧 List Events に delivery_success=false。過去 30 日に作成されたイベントだけ 未配信のイベントの処理
順番 生成された順の配信は保証しない Webhook
重複 同じイベントを複数回受け取ることがある 同上
タイムアウト 秒数の記載なし。タイムアウトは失敗として扱われる 同上
成功の判定 2xx。3xx(リダイレクト)は失敗とみなす 同上
TLS TLS 1.2 と 1.3 同上
署名 Stripe-Signature(t= と v1=)。HMAC-SHA256。再送のたびに署名と時刻を作り直す 同上
送信元 IP 公開の一覧あり(ips_webhooks.json・.txt)。変更はメーリングリストで 7 日前に告知 IP アドレス
失敗の知らせ 本番で Webhook の失敗が続くと、失敗を知らせるメールを送る サブスクリプションと Webhook
送信先の数 最大 16 個 Webhook

第三者の記事には再送の回数やタイムアウトの秒数を具体的に書いたものがありますが、2026-09-27 時点の公式のドキュメントにはどちらも見当たりませんでした。設計の前提にするなら、ダッシュボードの配信の記録で実際の値を確かめます。

再送の仕組みで気をつけること

手動の処理の後も続く自動の再送

受け側の障害の後、未配信のイベントを List Events で取り直して処理しても、Stripe はそれらをまだ未配信とみなして自動の再送を続けます。Stripe のガイドは、処理済みのイベントが届いたら処理をせずに成功の応答を返し、以降の再送を止めるよう書いています。取り直しの処理と自動の再送が同時に動くこともあるので、「処理中」と「処理済み」の 2 つの状態を記録しておきます。

// Express。本文は express.raw で受け取り、署名を検証してから使う
app.post('/webhooks/stripe', express.raw({ type: 'application/json' }), async (req, res) => {
  let event: Stripe.Event;
  try {
    event = stripe.webhooks.constructEvent(req.body, req.header('stripe-signature')!, endpointSecret);
  } catch {
    return res.status(400).end();
  }

  // 同じイベント ID を 2 回目以降は処理しない(一意制約で弾く)
  const inserted = await db.query(
    'INSERT INTO stripe_events (id, status) VALUES ($1, $2) ON CONFLICT (id) DO NOTHING',
    [event.id, 'processing'],
  );
  if (inserted.rowCount === 0) return res.status(200).end(); // 処理中か処理済み

  await queue.add('stripe-event', { id: event.id }); // 重い処理はキューの先で
  res.status(200).end();
});

再送の途中の送信先の停止と取りこぼし

送信先を無効にしている間に予定の再送の時刻が来ると、そのイベントの再送は打ち切られます。受け側の保守のために送信先を止める場合は、再開した後に List Events(delivery_success=false)で取りこぼしを拾います。照合と取り直しの手順は届かなかった Webhook の取り戻しの記事で扱います。

サンドボックスと本番の再送の違い

サンドボックスの再送は数時間で 3 回なので、本番で数日後に古いイベントがまとめて届く状況は試せません。受け側の重複の除去と順番の扱いは、手元でイベントを送り直して試験します。

順番と重複への備え

Stripe は、サブスクリプションの作成で customer.subscription.created・invoice.created・invoice.paid・charge.created のようにいくつものイベントが生まれる例を挙げ、これらが生成された順に届くことを保証しないと書いています。スナップショットのイベントの created は秒単位なので、別のイベントが同じ時刻を持つこともあります。Stripe は、created を順番や処理済みの判定に使わず、イベント ID で重複を見分けるよう求めています。

受け側の組み方は次の 3 つです。

  1. イベント ID で重複を弾く。処理したイベントの ID を一意制約つきの表に記録し、入らなければ処理しません。
  2. 状態は API で取り直す。invoice.paid を最初に受け取った場合でも、その中の ID で invoice・charge・subscription を API から取得すれば、先に来るはずだったイベントに頼らずに済みます。
  3. 2 つの別のイベントが同じ出来事を表す場合がある。Stripe は、2 つの Event オブジェクトが別々に生成される場合があり、その重複は data.object のオブジェクト ID と event.type で見分けるよう書いています。

重複の除去の組み方は重複と冪等性の記事で、順番の扱いは順番の入れ替わりの記事で詳しく扱います。

重い処理の前の 2xx の応答

Stripe は、タイムアウトを引き起こしうる複雑な処理の前に、2xx を素早く返すよう求めています。例として、会計システムで請求書を支払い済みに更新する前に 200 を返すよう書いています。タイムアウトの秒数が公式に書かれていない以上、受け側は「受け取って記録し、キューに入れて 200」を短い時間で終える形にしておくのが安全です。月初のように配信が急に増える時期のために、非同期のキューで処理することも勧めています。

送信元 IP で絞る場合

Stripe は Webhook の送信元の IP の一覧を公開していて、https://stripe.com/files/ips/ips_webhooks.json と .txt でも取得できます。変更は API の告知のメーリングリストで、実施の 7 日前に知らされます。Stripe は、IP の許可リストと署名の検証の両方を使うよう書いています。IP で絞る場合も署名の検証は外さず、一覧は定期的に取得して更新します。送信元 IP の扱い全般は固定の送信元 IP の記事にまとめました。

自社が送る側になるとき

Stripe の Webhook の性質は、送る側の設計の手本として参考になります。再送の期間を決めて指数バックオフで送り直す、配信の記録と次の予定を見せる、手動で送り直せる、失敗が続けばメールで知らせる、署名は送るたびに作り直す、の 5 点です。再送の間隔の決め方は再送の設計の記事で扱いました。

Webhook Admin は、これと同じ性質を持つ送信の仕組みを API から使えます。再送は既定ではすぐ・5 秒・5 分・30 分・2 時間・5 時間・10 時間・10 時間の 8 回(約 28 時間。送信先ごとに回数と間隔を選べます)、配信の記録には応答のコードと応答の先頭 1,024 バイトを残し、管理画面と API から送り直せます。失敗が 1 時間続いたとき、再送を使い切ったとき、失敗が 5 日続いて送信先を自動で止めたときに、Slack・Teams・Chatwork・メール・Webhook で知らせます。

自社のサービスから顧客へ Webhook を送る仕組みが必要な場合は、Webhook Admin を無料で試せます(月 5 万通まで)。https://app.webhookadmin.com/signup

よくある質問

Stripe の Webhook の再送を止めるにはどうすればよいですか。

送信先が 2xx を返せば、そのイベントの再送は止まります。手動で処理を済ませても、手動の再送が 2xx になっても、Stripe の自動の再送は止まらないので、処理済みのイベントが届いたら処理をせずに 2xx を返します。再送の途中で送信先を無効にするか削除すると、そのイベントの以降の再送は行われません。

再送の間隔は何分ですか。

公式のドキュメントには、本番で最長 3 日間、指数バックオフで再送するとだけ書かれていて、各回の間隔は書かれていません。次の再送の予定時刻は、ダッシュボードの送信先の「イベントの配信」タブで確かめられます。

サンドボックスの再送は本番と同じですか。

違います。サンドボックスで作成されたイベントは、数時間のうちに 3 回再送されます。本番の最長 3 日間の再送の挙動はサンドボックスでは確かめられないので、受け側の重複の除去や順番の扱いは、手元でイベントを送り直して試します。

関連記事