SocialHub.AI
开发者中心 · 开放扩展性

Webhook

订阅您自己的系统 Flash 事件。为您关注的事件注册一个 HTTPS 端点,并且 Flash 每枚导弹发射瞬间都会送出一个带有签名的薄型有效载荷—— 不进行轮询,不进行夜间导出签名在后面 标准 Webhooks 规范、交付重试(采用退避策略),并且每次尝试都会被记录。

步骤 1 — 订阅

注册端点

创建一个包含 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} 管理端点。您还可以通过 设置 → Webhooks 注册、测试 ping 和重放发送。

第 2 步 — 发现事件

活动目录

询问 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 array 中。需要 webhooks:manage 权限范围。

交货

轻量级、非个人身份信息 (PII) 有效载荷

每次投递都包含相同的小信封:一个稳定的 id、事件 type、一个 created_at timestamp 和一个紧凑的 data 数据块。有效载荷 绝不包含个人数据——不包含电子邮件、姓名、电话号码或地址。当您需要成员的详细信息时,请使用 member_ref 通过已认证的 API 获取这些信息。这样可以将个人身份信息 (PII) 保留在成员记录中,而不会记录在您的 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 在重试中始终相同,因此至少一次交付是安全的:将重复的 webhook-id 视为已处理。

发送日志和回放

每次尝试都会被记录。如果重试次数用尽,则该次投递将被标记为失败;您可以在“设置”→“Webhooks”中查看和重放投递记录。