Webhooks
Webhooks liefern signierte ausgehende POST-Anfragen für ausgewählte Tenant-Ereignisse, sodass Sie auf Änderungen reagieren können, ohne zu pollen. Verwalten Sie Endpunkte über Settings -> Integrations -> Webhooks oder die öffentliche API.
Ereignisse
| Ereignis | Status | Zustellung |
|---|---|---|
inventory.item.created | Emittiert | Signierte Outbox-Zustellung |
inventory.item.updated | Emittiert | Signierte Outbox-Zustellung |
order.created | Emittiert | Signierte Outbox-Zustellung |
order.updated | Emittiert | Signierte Outbox-Zustellung |
contact.created | Emittiert | Signierte Outbox-Zustellung |
contact.updated | Emittiert | Signierte Outbox-Zustellung |
stock_document.created | Emittiert | Signierte Outbox-Zustellung |
stock_document.updated | Emittiert | Signierte Outbox-Zustellung |
user.invited | Emittiert | Signierte Outbox-Zustellung |
organization.updated | Emittiert | Signierte Outbox-Zustellung |
integration.connected | Emittiert | Signierte Outbox-Zustellung |
bom.created | Geplant | Vertrag reserviert, noch nicht emittiert |
bom.updated | Geplant | Vertrag reserviert, noch nicht emittiert |
webhook.test | Nur Test | Unsignierte Konnektivitätsprüfung |
Abonnieren
Erstellen Sie einen Endpunkt mit POST /v1/webhooks (Scope webhooks:write, Enterprise). Das Signiergeheimnis wird in der Antwort einmalig zurückgegeben - speichern Sie es sofort.
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"
}
Zustellformat
Jede Zustellung ist ein POST mit dem JSON-Ereignis-Body und diesen Headern:
X-FabHub-Event- der Ereignistyp, zum Beispielorder.createdX-FabHub-Timestamp- Unix-Sekunden zum Zeitpunkt der Signierung der NutzlastX-FabHub-Signature-v1=<hex>HMAC; mehrere kommagetrenntev1=-Teile erscheinen während der Geheimnisrotation
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" } }
Die Signatur prüfen
Die Signatur ist HMAC-SHA256(secret, "<timestamp>.<rawBody>"), hexcodiert, wobei secret Ihr aus Hex decodiertes Signiergeheimnis ist. Prüfen Sie immer gegen den exakten rohen Anfrage-Body, vor dem JSON-Parsing. Das SDK liefert einen Verifizierer mit:
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
Geheimnisrotation
Rotieren Sie mit PATCH /v1/webhooks/{webhook_id} und {"rotateSecret": true}. Das neue Geheimnis wird einmalig zurückgegeben, und während des Überlappungsfensters werden Zustellungen sowohl mit dem neuen als auch mit dem vorherigen Geheimnis signiert (übergeben Sie beide an den Verifizierer über signingSecrets).
Zustellprotokolle
Prüfen Sie Versuche mit GET /v1/webhooks/{webhook_id}/deliveries (Scope 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 }
}
Synthetische Test-Pings (webhook.test) sind unsignierte Konnektivitätsprüfungen und erscheinen nicht im Outbox-Protokoll.
Best Practices
- Geben Sie schnell
2xxzurück; erledigen Sie aufwändige Arbeit asynchron. - Behandeln Sie die Zustellung als At-least-once und deduplizieren Sie anhand der Ereignisidentität.
- Filtern Sie nach
X-FabHub-Eventund ignorieren Sie Ereignistypen, die Sie nicht verarbeiten.