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 reintento, y los eventos disponibles.
Eventos emitidos
Sección titulada «Eventos emitidos»Los eventos actualmente disponibles:
| Evento | 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 |
Formato de transmisión
Sección titulada «Formato de transmisión»Cada entrega 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 entrega |
X-Webhook-Event | el evento (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 cuerpo sin procesar usando el secreto de la suscripción (devuelto solo al crear).
El header es sha256=<hex> (formato simple, no estilo Stripe 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 reintento
Sección titulada «Semántica de reintento»- Tracium dispara entregas a través de una cola interna de procesamiento.
- Si la respuesta no es 2xx, se hacen 3 reintentos con backoff exponencial (delay inicial: 30s).
- Después de 3 fallos la entrega se marca como failed y queda visible
en
GET /api/v1/webhooks/:id/deliveriescon el error capturado.
Hacé tu endpoint idempotente. Usá el X-Webhook-Id como clave de
deduplicación ya que los reintentos 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 del lado del servidor básica
estándar; HTTPS recomendado.
Gestión de suscripciones
Sección titulada «Gestión de suscripciones»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 }# El secret se muestra UNA SOLA VEZ; guardalo ahora.
# 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 la plataforma expone (alerts, documents, supplier performance, etc.)
- Reference: schemas completos de payload por evento
- Autenticación: API keys para gestionar webhooks desde tu backend