APIリファレンス:Webhook
Webhookは、イベントが起きた瞬間に自分のサーバーへ知らせを送ります。 アプリのWebhook URLをその他 → Merchant APIで設定すると、受け取る設定にしたイベントごとに、署名付きのJSONボディがPOSTされます。
ボディの形
{
"update_id": 123,
"update_type": "invoice_paid",
"request_date": "2026-08-11T12:00:00Z",
"payload": { … }
}
update_idは、同じイベントを送り直しても変わりません。
重複の排除はこの値を基準にしてください。
request_dateは、配信を試みるたびに記録されます。
payloadは、そのイベント種別の完全なオブジェクトです。
請求書のイベントなら請求書オブジェクト、ほかに送金リンクオブジェクトとサブスクリプションオブジェクトがあります(それぞれの形は各リファレンスのページにあります)。
イベントの種別
update_type | 発火する場面 | ペイロード |
|---|---|---|
invoice_paid | 請求書が支払われたとき。必ず配信されます | 請求書オブジェクト |
invoice_expired | 請求書が未払いのまま期限を過ぎたとき | 請求書オブジェクト |
check_activated | 発行した送金リンクが受け取られたとき | 送金リンクオブジェクト |
refund_completed | 返金が実行されたとき | refunded_*のフィールドが入った請求書オブジェクト |
subscription_activated | ユーザーがプランを承認したとき | サブスクリプションオブジェクト |
subscription_charged | 期間分が課金されたとき。どれかはcharge.kindが示します(initial・renewal・resubscribe) | サブスクリプションオブジェクトとcharge({period_no, kind, asset, amount, fee, paid_at}) |
subscription_cancelled | どちらかの側がサブスクリプションをキャンセルしたとき | サブスクリプションオブジェクト |
subscription_expired | 猶予期間が未払いのまま終わったとき | サブスクリプションオブジェクト |
invoice_paid以外はすべて、選んで受け取る方式です(Crypto Botに対する拡張です。Crypto Botの形に厳密に合わせた実装は、自分で選ばないかぎり知らないupdate_typeに出会いません)。
アプリごとに、Merchant API画面の追加のWebhookイベントから選びます。
トグルはWebhook URLを設定すると表示され、上の表の識別子がそのままラベルになっています。
署名を検証する
配信には必ず**TgCryptoPay-API-Signatureヘッダーが付きます(Crypto-Pay-API-Signatureは同じ値の互換の別名です)。
値は、生のリクエストボディのHMAC-SHA256を16進数にしたもので、鍵はアプリのメインAPIトークン**のSHA-256ダイジェストです。Crypto Botと同じ方式なので、既存の検証コードはそのまま動きます。
import hashlib, hmac
secret = hashlib.sha256(API_TOKEN.encode()).digest()
expected = hmac.new(secret, raw_body, hashlib.sha256).hexdigest()
ok = hmac.compare_digest(expected, headers["TgCryptoPay-API-Signature"])
検証は受け取った生のバイト列に対して行ってください。 一度読み込んで書き出し直したものはバイト単位で変わることがあり、検証に失敗します。 署名するのはメイントークンだけで、制限付きトークンが署名することはありません。 メイントークンを再発行すると、Webhookの署名の鍵もその場で切り替わるので、サーバー側の値も同じタイミングで更新してください。
配信と再送
- 10秒以内に2xxのレスポンスが返れば、配信は成功です。
- それ以外、エラーのステータス、タイムアウト、接続の失敗は、指数バックオフで送り直されます。 最初の再送はおよそ10秒後で、間隔は最大8時間まで倍になり、最大17回、およそ3日間にわたって続きます。
- 最後の試行が終わると、その配信は捨てられます。Webhook URL自体が自動で無効になることはありません。 応答の不安定なエンドポイントでも、アプリの設定が黙って外れることはありません。
- 送り直しがある以上、ハンドラーはべき等でなければなりません。
処理に入る前に、
update_idで重複を排除してください。
⚠️ 注文を処理する前に検証する
Webhook URLには誰でもPOSTできます。
署名の検証が通るまで、ボディは信用できない入力として扱ってください。
注文を出荷せず、ユーザーへの入金もせず、支払い済みとして記録もしないでください。
安全な順序は、署名を検証する、update_idで重複を排除する、そのうえで処理する、です。
この記事は役に立ちましたか?
ご意見ありがとうございます。