Webhooks
Os webhooks entregam pedidos POST de saída assinados para eventos selecionados do tenant, para que possa reagir a alterações sem sondagem. Faça a gestão dos endpoints a partir de Settings -> Integrations -> Webhooks ou da API pública.
Eventos
| Evento | Estado | Entrega |
|---|---|---|
inventory.item.created | Emitido | Entrega assinada por outbox |
inventory.item.updated | Emitido | Entrega assinada por outbox |
order.created | Emitido | Entrega assinada por outbox |
order.updated | Emitido | Entrega assinada por outbox |
contact.created | Emitido | Entrega assinada por outbox |
contact.updated | Emitido | Entrega assinada por outbox |
stock_document.created | Emitido | Entrega assinada por outbox |
stock_document.updated | Emitido | Entrega assinada por outbox |
user.invited | Emitido | Entrega assinada por outbox |
organization.updated | Emitido | Entrega assinada por outbox |
integration.connected | Emitido | Entrega assinada por outbox |
bom.created | Planeado | Reservado no contrato, ainda não emitido |
bom.updated | Planeado | Reservado no contrato, ainda não emitido |
webhook.test | Apenas teste | Verificação de conectividade não assinada |
Subscrever
Crie um endpoint com POST /v1/webhooks (scope webhooks:write, Enterprise). O segredo de assinatura é devolvido uma única vez na resposta - guarde-o imediatamente.
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 de entrega
Cada entrega é um POST com o corpo do evento em JSON e estes cabeçalhos:
X-FabHub-Event- o tipo de evento, por exemploorder.createdX-FabHub-Timestamp- segundos unix de quando o payload foi assinadoX-FabHub-Signature- HMACv1=<hex>; durante a rotação de segredo surgem várias partesv1=separadas por vírgulas
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" } }
Verificar a assinatura
A assinatura é HMAC-SHA256(secret, "<timestamp>.<rawBody>"), codificada em hex, onde secret é o seu segredo de assinatura descodificado de hex. Verifique sempre contra o corpo bruto exato do pedido, antes do parsing JSON. O SDK fornece um verificador:
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
Rotação de segredo
Rode com PATCH /v1/webhooks/{webhook_id} e {"rotateSecret": true}. O novo segredo é devolvido uma única vez e, durante a janela de sobreposição, as entregas são assinadas com o novo e o anterior segredos (passe ambos ao verificador através de signingSecrets).
Registos de entrega
Inspecione as tentativas com 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 }
}
Os pings de teste sintéticos (webhook.test) são verificações de conectividade não assinadas e não aparecem no registo do outbox.
Boas práticas
- Devolva
2xxrapidamente; faça o trabalho pesado de forma assíncrona. - Trate a entrega como pelo-menos-uma-vez e faça desduplicação pela identidade do evento.
- Filtre por
X-FabHub-Evente ignore os tipos de evento que não trata.