功能定价关于文章文档
开发者

API、SDK、MCP 和 webhook。

开发者平台快速开始身份验证API 参考SDKMCPWebhook错误分页速率限制幂等性更新日志迁移与版本控制策略
原始 API 文档OpenAPI YAMLAsyncAPI YAML
  1. 首页
  2. /
  3. 开发者
  4. /
  5. Webhook

Webhook

Webhook 会针对选定的租户事件投递带签名的出站 POST 请求,因此你无需轮询即可对变更做出响应。可从 Settings -> Integrations -> Webhooks 或公共 API 管理端点。

  • AsyncAPI JSON - AsyncAPI YAML

事件

事件状态投递
inventory.item.created已发出带签名的发件箱投递
inventory.item.updated已发出带签名的发件箱投递
order.created已发出带签名的发件箱投递
order.updated已发出带签名的发件箱投递
contact.created已发出带签名的发件箱投递
contact.updated已发出带签名的发件箱投递
stock_document.created已发出带签名的发件箱投递
stock_document.updated已发出带签名的发件箱投递
user.invited已发出带签名的发件箱投递
organization.updated已发出带签名的发件箱投递
integration.connected已发出带签名的发件箱投递
bom.created计划中契约已预留,尚未发出
bom.updated计划中契约已预留,尚未发出
webhook.test仅测试无签名的连通性检查

订阅

使用 POST /v1/webhooks(作用域 webhooks:write,企业版)创建端点。签名密钥在响应中仅返回一次,请立即存储。

curl -X POST https://api.fabhub.app/v1/webhooks \
  -H "X-API-Key: $FABHUB_API_KEY" \
  -H "Idempotency-Key: 7c1f...-..." \
  -H "Content-Type: application/json" \
  -d '{"name":"Orders sync","targetUrl":"https://example.com/hooks/fabhub","subscribedEvents":["order.created","order.updated"]}'
{
  "data": {
    "id": "wh_1",
    "name": "Orders sync",
    "targetUrl": "https://example.com/hooks/fabhub",
    "status": "active",
    "environment": "production",
    "description": null,
    "subscribedEvents": ["order.created", "order.updated"],
    "createdAt": "2026-06-20T09:00:00Z",
    "updatedAt": "2026-06-20T09:00:00Z"
  },
  "signingSecret": "whsec_9f3a...stored-once"
}

投递格式

每次投递都是一个带有 JSON 事件主体及以下标头的 POST:

  • X-FabHub-Event - 事件类型,例如 order.created
  • X-FabHub-Timestamp - 对负载签名时的 unix 秒数
  • X-FabHub-Signature - v1=<hex> HMAC;在密钥轮换期间会出现多个以逗号分隔的 v1= 部分
POST /hooks/fabhub HTTP/1.1
X-FabHub-Event: order.created
X-FabHub-Timestamp: 1718873400
X-FabHub-Signature: v1=4f2c...e1

{ "event": "order.created", "data": { "id": "ord_1", "module": "sell", "status": "open" } }

验证签名

签名为 HMAC-SHA256(secret, "<timestamp>.<rawBody>"),以十六进制编码,其中 secret 是你从十六进制解码的签名密钥。务必对照确切的原始请求主体进行验证,并在 JSON 解析之前进行。 SDK 自带一个验证器:

import { verifyFabHubWebhookSignature } from '@fabhub/sdk';

const result = verifyFabHubWebhookSignature({
  signingSecret: process.env.FABHUB_WEBHOOK_SECRET,
  rawBody,
  timestamp: req.headers['x-fabhub-timestamp'],
  signature: req.headers['x-fabhub-signature'],
  // toleranceSeconds: 300 (default) - rejects stale/replayed timestamps
});

if (!result.ok) return res.status(400).end();
// safe to JSON.parse(rawBody) now

密钥轮换

使用 PATCH /v1/webhooks/{webhook_id} 并传入 {"rotateSecret": true} 进行轮换。新密钥仅返回一次,在重叠窗口期间投递会同时使用新密钥和旧密钥签名(通过 signingSecrets 将两者都传给验证器)。


投递日志

使用 GET /v1/webhooks/{webhook_id}/deliveries(作用域 webhooks:deliveries:read)检查投递尝试:

{
  "data": [
    {
      "id": "del_1",
      "eventType": "order.created",
      "status": "delivered",
      "attempts": 1,
      "lastError": null,
      "lastHttpStatus": 200,
      "createdAt": "2026-06-20T09:01:00Z",
      "updatedAt": "2026-06-20T09:01:01Z"
    }
  ],
  "pagination": { "page": 1, "pageSize": 20, "total": 1, "totalPages": 1 }
}

合成测试探测(webhook.test)是无签名的连通性检查,不会出现在发件箱日志中。


最佳实践

  • 快速返回 2xx;繁重工作异步执行。
  • 将投递视为至少一次(at-least-once),并基于事件标识进行去重。
  • 在 X-FabHub-Event 上进行过滤,忽略你不处理的事件类型。
首页功能定价关于文章文档开发者
© FabHub隐私与 Cookie条款无障碍