Webhook
I webhook consegnano richieste POST in uscita firmate per gli eventi selezionati del tenant, così puoi reagire ai cambiamenti senza fare polling. Gestisci gli endpoint da Impostazioni -> Integrazioni -> Webhook o dall'API pubblica.
Eventi
| Evento | Stato | Consegna |
|---|---|---|
inventory.item.created | Emesso | Consegna firmata tramite outbox |
inventory.item.updated | Emesso | Consegna firmata tramite outbox |
order.created | Emesso | Consegna firmata tramite outbox |
order.updated | Emesso | Consegna firmata tramite outbox |
contact.created | Emesso | Consegna firmata tramite outbox |
contact.updated | Emesso | Consegna firmata tramite outbox |
stock_document.created | Emesso | Consegna firmata tramite outbox |
stock_document.updated | Emesso | Consegna firmata tramite outbox |
user.invited | Emesso | Consegna firmata tramite outbox |
organization.updated | Emesso | Consegna firmata tramite outbox |
integration.connected | Emesso | Consegna firmata tramite outbox |
bom.created | Pianificato | Contratto riservato, non ancora emesso |
bom.updated | Pianificato | Contratto riservato, non ancora emesso |
webhook.test | Solo test | Controllo di connettività non firmato |
Iscrizione
Crea un endpoint con POST /v1/webhooks (scope webhooks:write, Enterprise). Il segreto di firma viene restituito una sola volta nella risposta - conservalo immediatamente.
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"
}
Formato di consegna
Ogni consegna è un POST con il corpo JSON dell'evento e questi header:
X-FabHub-Event- il tipo di evento, ad esempioorder.createdX-FabHub-Timestamp- i secondi unix in cui il payload è stato firmatoX-FabHub-Signature- HMACv1=<hex>; durante la rotazione del segreto compaiono più partiv1=separate da virgola
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" } }
Verifica della firma
La firma è HMAC-SHA256(secret, "<timestamp>.<rawBody>"), codificata in esadecimale, dove secret è il tuo segreto di firma decodificato da esadecimale. Verifica sempre rispetto al corpo grezzo esatto della richiesta, prima dell'analisi JSON. L'SDK fornisce un verificatore:
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
Rotazione del segreto
Ruota con PATCH /v1/webhooks/{webhook_id} e {"rotateSecret": true}. Il nuovo segreto viene restituito una sola volta e, durante la finestra di sovrapposizione, le consegne vengono firmate sia con il nuovo sia con il precedente segreto (passa entrambi al verificatore tramite signingSecrets).
Log di consegna
Ispeziona i tentativi con 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 }
}
I ping di test sintetici (webhook.test) sono controlli di connettività non firmati e non compaiono nel log dell'outbox.
Buone pratiche
- Restituisci
2xxrapidamente; svolgi il lavoro pesante in modo asincrono. - Tratta la consegna come almeno-una-volta e deduplica sull'identità dell'evento.
- Filtra su
X-FabHub-Evente ignora i tipi di evento che non gestisci.