Webhooks
Tracium dispara webhooks cuando ocurren eventos de trazabilidad. Ejemplos:
- Se grabó un nuevo evento on-chain (
event.recorded). - Se acuñó un nuevo NFT/lote (
nft.created). - Se hizo recall de un lote (
nft.recalled). - Se transfirió custodia entre custodians (
custody.transferred).
Esta página cubre estructura del payload, verificación de firma HMAC, semántica de retry, y los topics disponibles.
Topics emitidos
Sección titulada «Topics emitidos»Los topics actualmente shipped:
| Topic | Cuándo se emite |
|---|---|
event.recorded | Un trace event capturado fue grabado on-chain |
nft.created | Se acuñó un NFT (lote nuevo) |
nft.recalled | Un NFT fue recalled (fuente del recall: TENANT_ADMIN) |
custody.transferred | Se completó una transferencia de custodia |
webhook.test | Disparado manualmente vía POST /api/v1/webhooks/:id/test para testing |
Wire format
Sección titulada «Wire format»Cada delivery de webhook es POST con body application/json:
{ "event": "event.recorded", "timestamp": "2026-05-08T12:34:56.789Z", "data": { ... }}Headers:
| Header | Valor |
|---|---|
X-Webhook-Id | UUID único de delivery |
X-Webhook-Event | el topic (ej. event.recorded) |
X-Webhook-Signature | sha256=<hex-hmac> |
Content-Type | application/json |
Verificación de firma
Sección titulada «Verificación de firma»Tracium firma cada payload con HMAC-SHA256 sobre el body raw usando el secret del subscription (devuelto solo al crear).
El header es sha256=<hex> (formato simple, no Stripe-style con
timestamp). Verificá con comparación constant-time para prevenir
ataques de timing.
Node.js
Sección titulada «Node.js»import { createHmac, timingSafeEqual } from 'crypto';
function verify(req, secret) { const header = req.headers['x-webhook-signature']; // header format: 'sha256=<hex>' const [, hex] = header.match(/^sha256=([a-f0-9]+)$/) || []; if (!hex) throw new Error('invalid signature header');
const expected = createHmac('sha256', secret) .update(req.rawBody) .digest('hex');
if (!timingSafeEqual(Buffer.from(hex), Buffer.from(expected))) { throw new Error('signature mismatch'); }}import hmac, hashlib
def verify(headers, raw_body, secret): sig = headers['X-Webhook-Signature'] # 'sha256=<hex>' if not sig.startswith('sha256='): raise ValueError('invalid signature header') received = sig[len('sha256='):]
expected = hmac.new( secret.encode(), raw_body, hashlib.sha256, ).hexdigest()
if not hmac.compare_digest(received, expected): raise ValueError('signature mismatch')Semántica de retry
Sección titulada «Semántica de retry»- Tracium dispara delivery vía cola BullMQ (
webhook-delivery). - Si la respuesta no es 2xx → 3 intentos de retry con exponential backoff (delay inicial: 30s).
- Después de 3 fallos se marca como failed; queda visible en
GET /api/v1/webhooks/:id/deliveriescon el error capturado.
Hacé tu endpoint idempotente — usá el X-Webhook-Id como key de
dedup ya que retries repiten el mismo id.
Validación de URL al registrar
Sección titulada «Validación de URL al registrar»Cuando registrás un endpoint vía POST /api/v1/webhooks, la URL
tiene que ser válida + alcanzable. Validación server-side básica
estándar; HTTPS recomendado.
Gestión de subscriptions
Sección titulada «Gestión de subscriptions»Endpoints (todos requieren rol TENANT_ADMIN):
# Listar subscriptions del tenantcurl "$BASE_URL/api/v1/webhooks" \ -H "Authorization: Bearer $TOKEN"
# Crear nueva subscriptioncurl -X POST "$BASE_URL/api/v1/webhooks" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "url": "https://tu-app.example.com/webhooks/darwin", "events": ["event.recorded", "nft.created"] }'# Devuelve: { id, url, events, active, createdAt, secret } — secret SOLO una vez
# Update parcialcurl -X PATCH "$BASE_URL/api/v1/webhooks/$ID" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "active": false }'
# Borrarcurl -X DELETE "$BASE_URL/api/v1/webhooks/$ID" \ -H "Authorization: Bearer $TOKEN"
# Ver últimas 100 deliveriescurl "$BASE_URL/api/v1/webhooks/$ID/deliveries" \ -H "Authorization: Bearer $TOKEN"
# Disparar evento testcurl -X POST "$BASE_URL/api/v1/webhooks/$ID/test" \ -H "Authorization: Bearer $TOKEN"Qué sigue
Sección titulada «Qué sigue»- Reportes operacionales — endpoints de reporting que el platform expone (alerts, documents, supplier performance, etc.)
- Reference — schemas completos de payload por topic
- Autenticación — API keys para gestionar webhooks desde tu backend