Webhooks
Los webhooks entregan peticiones POST salientes firmadas para eventos seleccionados del tenant, de modo que puedes reaccionar a los cambios sin sondear. Gestiona los endpoints desde Settings -> Integrations -> Webhooks o desde la API pública.
Eventos
| Evento | Estado | Entrega |
|---|---|---|
inventory.item.created | Emitido | Entrega firmada por bandeja de salida |
inventory.item.updated | Emitido | Entrega firmada por bandeja de salida |
order.created | Emitido | Entrega firmada por bandeja de salida |
order.updated | Emitido | Entrega firmada por bandeja de salida |
contact.created | Emitido | Entrega firmada por bandeja de salida |
contact.updated | Emitido | Entrega firmada por bandeja de salida |
stock_document.created | Emitido | Entrega firmada por bandeja de salida |
stock_document.updated | Emitido | Entrega firmada por bandeja de salida |
user.invited | Emitido | Entrega firmada por bandeja de salida |
organization.updated | Emitido | Entrega firmada por bandeja de salida |
integration.connected | Emitido | Entrega firmada por bandeja de salida |
bom.created | Planificado | Reservado en el contrato, aún no emitido |
bom.updated | Planificado | Reservado en el contrato, aún no emitido |
webhook.test | Solo prueba | Comprobación de conectividad sin firmar |
Suscribirse
Crea un endpoint con POST /v1/webhooks (scope webhooks:write, Enterprise). El secreto de firma se devuelve una sola vez en la respuesta - guárdalo de inmediato.
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 es un POST con el cuerpo del evento en JSON y estas cabeceras:
X-FabHub-Event- el tipo de evento, por ejemploorder.createdX-FabHub-Timestamp- segundos unix en que se firmó el cuerpoX-FabHub-Signature- HMACv1=<hex>; durante la rotación del secreto aparecen varias partesv1=separadas por comas
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 la firma
La firma es HMAC-SHA256(secret, "<timestamp>.<rawBody>"), codificada en hexadecimal, donde secret es tu secreto de firma decodificado desde hexadecimal. Verifica siempre contra el cuerpo de petición sin procesar exacto, antes de hacer el parseo JSON. El SDK incluye un 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
Rotación del secreto
Rota con PATCH /v1/webhooks/{webhook_id} y {"rotateSecret": true}. El nuevo secreto se devuelve una sola vez, y durante la ventana de solapamiento las entregas se firman tanto con el secreto nuevo como con el anterior (pasa ambos al verificador mediante signingSecrets).
Registros de entrega
Inspecciona los intentos 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 }
}
Los pings de prueba sintéticos (webhook.test) son comprobaciones de conectividad sin firmar y no aparecen en el registro de la bandeja de salida.
Buenas prácticas
- Devuelve
2xxrápidamente; realiza el trabajo pesado de forma asíncrona. - Trata la entrega como al-menos-una-vez y deduplica según la identidad del evento.
- Filtra por
X-FabHub-Evente ignora los tipos de evento que no manejes.