Webhook
独自のシステムを Flash イベントにサブスクライブします。関心のあるイベントの HTTPS エンドポイントを登録すると、Flash は各イベントが起動した瞬間に署名付きの薄いペイロードを配信します (ポーリングや夜間のエクスポートはありません)。署名は 標準 Webhook 仕様に従い、配信はバックオフで再試行され、すべての試行がログに記録されます。
エンドポイントを登録する
webhooks:manage スコープを保持する Bearer fl_live_ キーを使用して Webhook エンドポイントを作成します。そこに配信したい HTTPS url と eventTypes のリストを投稿します。 。それは安全に保管されます。すべての配送を確認するために必要です。
curl -X POST https://flash.socialhub.ai/api/v2/webhooks \
-H "Authorization: Bearer fl_live_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://hooks.your-app.com/flash",
"description": "prod ingest",
"eventTypes": ["member.created", "loyalty.tier_upgraded"]
}'
# 201 Created
# {
# "data": {
# "id": "whe_...",
# "url": "https://hooks.your-app.com/flash",
# "eventTypes": ["member.created", "loyalty.tier_upgraded"],
# "status": "active",
# "secret": "whsec_..." <-- shown ONCE, store it now
# }
# }後で GET /api/v2/webhooks (リスト、シークレットなし)、PATCH /api/v2/webhooks/{id} (URL / イベント / ステータスを変更するか、{ "action": "rotate_secret" } を送信してシークレットをロールする)、および DELETE /api/v2/webhooks/{id} を使用してエンドポイントを管理します。 [設定] → [Webhook] から配信の登録、テスト ping、および再生を行うこともできます。
イベントカタログ
どのイベントに参加できるかを API に問い合わせてください。このカタログは、ライブ オートメーション トリガーの信頼できる情報源から派生しているため、今日実際に発生したイベントのみをライフサイクル ステージ (獲得、エンゲージメント、ロイヤリティ、保持、コマース、擁護) ごとにグループ化し、それぞれにイベント キー、説明、サンプル ペイロードとともにリストします。応答には、共有ペイロード エンベロープと署名ヘッダーも文書化されています。
curl https://flash.socialhub.ai/api/v2/events/catalog \
-H "Authorization: Bearer fl_live_..."
# { "data": { "events": [
# { "event": "member.created", "label": "Member created",
# "stage": "acquisition", "examplePayload": { ... } },
# { "event": "loyalty.tier_upgraded", "label": "Tier upgraded",
# "stage": "loyalty", "examplePayload": { ... } },
# ...
# ],
# "payload": { "schema": { ... }, "headers": { ... } }
# } }サブスクライブするときに、イベントの event キーを eventTypes 配列に直接入れます。 webhooks:manage スコープが必要です。
薄い、非 PII ペイロード
どの配達にも同じ小さな封筒が入っています。 idイベント type、 created_at timestampコンパクト data ブロック。ペイロード 個人データは一切含まれません — メールアドレス、名前、電話番号、住所は不要です。会員の詳細が必要な場合は、認証済みの方法で取得してください。 API 使用 member_refこれにより、個人情報は会員記録にのみ保持され、Webhookログには含まれません。
POST https://hooks.your-app.com/flash
webhook-id: evt_a1b2c3... # stable across retries — dedupe on this
webhook-timestamp: 1767225600 # unix seconds
webhook-signature: v1,K5x0mF...== # base64 HMAC-SHA256 (may be space-separated during rotation)
Content-Type: application/json
{
"id": "evt_a1b2c3...",
"type": "loyalty.tier_upgraded",
"created_at": "2026-01-01T00:00:00.000Z",
"data": {
"resource_id": "mbr_...",
"member_ref": "mbr_...", // opaque member id — fetch PII via the API
"tier": "Gold", // present on loyalty / tier events
"amount_band": "100-500" // coarse band on commerce events — never the exact amount
}
}すべての署名を検証する
Flash は、標準 Webhook (HMAC-SHA256) を使用して、エンドポイントの whsec_ シークレットで各配信に署名します。 {webhook-id}.{webhook-timestamp}.{body} で署名を再計算し、定数時間で webhook-signature ヘッダーと比較します。一致しないものはすべて拒否し、リプレイに対して防御するには古すぎる webhook-timestamp を拒否します。署名キーは、仕様に従って、whsec_ プレフィックスの後のシークレットの Base64 デコードされたバイトです。シークレットのローテーション中、ヘッダーにはスペースで区切られた複数の v1,… 値が含まれます。いずれか が一致する場合に配信を受け入れます。
import crypto from "node:crypto";
// req.body must be the RAW, unparsed request body string.
function verifyFlashWebhook(headers, rawBody, whsec) {
const id = headers["webhook-id"];
const ts = headers["webhook-timestamp"];
const sigHeader = headers["webhook-signature"]; // "v1,<b64> v1,<b64> ..."
// reject stale deliveries (5 min tolerance)
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
const key = Buffer.from(whsec.replace(/^whsec_/, ""), "base64");
const expected = crypto
.createHmac("sha256", key)
.update(`${id}.${ts}.${rawBody}`)
.digest("base64");
return sigHeader
.split(" ")
.map((p) => p.split(",")[1])
.some((sig) =>
sig &&
sig.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected)),
);
}再試行、冪等性、配信ログ
2xxを早く返してください
任意の 2xx で確認応答し、非同期で作業を実行します。 429、5xx、タイムアウト、または接続エラーは再試行可能として扱われます。
バックオフによる自動再試行
再試行可能な失敗は、指数関数的なフル ジッター バックオフを使用して再試行されます。 3xx または 429 以外の 4xx は永続的な失敗として扱われ、再試行されません。
webhook-idによる重複排除
id は再試行しても同一であるため、少なくとも 1 回の配信は安全です。繰り返される webhook-id はすでに処理されたものとして扱います。
配信ログ&リプレイ
すべての試行は記録されます。再試行がすべて終了すると、配信は無効とマークされます。 [設定] → [Webhook] から配信を検査して再生できます。