Registrar, probar y monitorear entregas de webhooks

Objetivo

Confirma que tus endpoints de webhook están en buen estado, diagnostica entregas fallidas y exporta logs de entrega para auditoría. Cubre el ciclo completo desde la API: registrar un endpoint, cambiarlo, rotar su secreto y retirarlo, además de las operaciones de monitoreo y prueba.

Requisitos previos

  • Una API key activa (veriko_…). Leer exige webhooks:read y probar, webhooks:create; registrar, cambiar y retirar exigen webhooks:create, webhooks:update y webhooks:delete.
  • Un receptor HTTPS alcanzable. Si aún no tienes ningún endpoint registrado, el paso 2 lo crea.
  • Tu receptor debe responder con HTTP 2xx y opcionalmente validar el encabezado HMAC-SHA256 X-Webhook-Signature.

Pasos

1. Listar tus endpoints

GET /v1/webhooks devuelve todos los endpoints registrados con su estado y eventos suscritos. El secret de firma no se incluye — solo se muestra una vez en el momento de la creación.

curl 'https://api.veriko.mx/v1/webhooks' \
  -H 'Authorization: Bearer veriko_••••'
{
  "data": [
    {
      "type": "webhook_endpoint",
      "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
      "attributes": {
        "url": "https://miapp.veriko.mx/hooks/pagos",
        "status": "active",
        "events": ["validation.completed", "validation.failed"],
        "created_at": "2025-02-01T12:00:00Z"
      }
    }
  ]
}

2. Registrar, actualizar o retirar un endpoint

Estas cuatro operaciones sí se pueden llamar con tu API key — necesitan el permiso correspondiente (webhooks:create, webhooks:update, webhooks:delete).

# Registrar
curl -X POST 'https://api.veriko.mx/v1/webhooks'   -H 'Authorization: Bearer veriko_••••'   -H 'Content-Type: application/json'   -d '{ "url": "https://miapp.veriko.mx/hooks/pagos", "events": ["validation.completed"] }'

# Cambiar la URL o los eventos suscritos
curl -X PUT 'https://api.veriko.mx/v1/webhooks/f47ac10b-58cc-4372-a567-0e02b2c3d479'   -H 'Authorization: Bearer veriko_••••'   -H 'Content-Type: application/json'   -d '{ "events": ["validation.completed", "validation.failed"] }'

# Retirar
curl -X DELETE 'https://api.veriko.mx/v1/webhooks/f47ac10b-58cc-4372-a567-0e02b2c3d479'   -H 'Authorization: Bearer veriko_••••'

El secret de firma se devuelve una sola vez, al registrar. Si lo pierdes o sospechas que se filtró, rótalo:

curl -X POST 'https://api.veriko.mx/v1/webhooks/f47ac10b-.../regenerate-secret'   -H 'Authorization: Bearer veriko_••••'

3. Enviar un evento de prueba

Después de registrar o actualizar un endpoint, envía un evento de prueba sintético para confirmar que tu receptor es alcanzable y procesa la firma correctamente. Las entregas de prueba no cuentan hacia el contador de fallos consecutivos que deshabilita endpoints automáticamente.

curl -X POST \
  'https://api.veriko.mx/v1/webhooks/f47ac10b-58cc-4372-a567-0e02b2c3d479/test' \
  -H 'Authorization: Bearer veriko_••••'

Respuesta exitosa:

{
  "data": {
    "type": "webhook_test_result",
    "attributes": {
      "delivered": true,
      "http_status": 200,
      "response_time_ms": 143
    }
  }
}

Si delivered es false, el campo error explica el problema (bloqueo SSRF, respuesta no 2xx, etc.).

La entrega que recibe tu endpoint incluye estas cabeceras:

cabeceracontenido
X-Webhook-Signaturesha256= seguido del HMAC en hexadecimal
X-Webhook-Signature-Timestampedt=<segundos>,v1=<hex>: firma de <t>.<cuerpo> con la hora del intento
X-Veriko-EventTipo de evento que originó la entrega
X-Veriko-Delivery-IdIdentificador estable para deduplicar reintentos
X-Veriko-TimestampMomento del envío, en ISO 8601 con sufijo Z

La cabecera de firma es genérica y se configura independientemente del nombre del servicio. La de firma con marca de tiempo añade el sufijo -Timestamped a ese mismo nombre. Las otras tres se forman con el identificador del servicio. La diferencia de prefijos es deliberada.

Verificar la firma con marca de tiempo

La cabecera X-Webhook-Signature-Timestamped firma la hora del intento junto con el cuerpo, de modo que el receptor puede descartar una entrega vieja que alguien vuelva a enviar. La cabecera X-Webhook-Signature no cambia.

import { createHmac, timingSafeEqual } from 'node:crypto';

const VENTANA_SEGUNDOS = 300; // 5 minutos

function verificar(cabecera, cuerpoCrudo, secreto) {
  const partes = Object.fromEntries(cabecera.split(',').map((p) => p.split('=')));
  const esperada = createHmac('sha256', secreto).update(`${partes.t}.${cuerpoCrudo}`).digest('hex');
  const iguales =
    esperada.length === partes.v1.length &&
    timingSafeEqual(Buffer.from(esperada), Buffer.from(partes.v1));
  const reciente = Math.abs(Date.now() / 1000 - Number(partes.t)) <= VENTANA_SEGUNDOS;
  return iguales && reciente;
}

La ventana de 5 minutos se mide contra t, que es la hora de ese intento, y no contra el campo timestamp del cuerpo. Un reintento llega hasta unas 8,6 horas después del evento, pero con una t nueva; medir contra el timestamp del cuerpo rechazaría reintentos legítimos. Para descartar duplicados sigue sirviendo el X-Veriko-Delivery-Id, que se mantiene entre reintentos: guárdalo al menos 24 horas.

El monto y la cuenta que confirma Banxico

Cuando el evento es validation.completed y Banxico confirmó el CEP, el cuerpo de la entrega trae un bloque attributes.banxico_confirmed con el monto, la fecha y hora de la operación, la clave de rastreo, los bancos emisor y receptor, y la cuenta beneficiaria enmascarada a los últimos 4 dígitos. Es la forma completa del cuerpo, campo por campo — ver Arquitectura de webhooks.

Enterarse de una devolución posterior

Un valid es el veredicto del momento de la consulta: Banxico puede reportar la devolución del pago horas o días después. Cuando eso pasa, la validación cambia a returned y se emite validation.returned, con el mismo cuerpo que validation.completed más attributes.payment_status. El endpoint sólo recibe los eventos a los que se suscribió, así que hay que añadir ese evento a los que ya tiene:

curl -X PUT 'https://api.veriko.mx/v1/webhooks/f47ac10b-58cc-4372-a567-0e02b2c3d479'   -H 'Authorization: Bearer veriko_••••'   -H 'Content-Type: application/json'   -d '{ "events": ["validation.completed", "validation.returned"] }'

La devolución se detecta en una revisión posterior: el servicio revisa solo las validaciones valid de las últimas 72 horas, y POST /v1/validations/{id}/recheck la pide en el momento. El cuerpo completo del evento está en Arquitectura de webhooks.

3. Inspeccionar logs de entrega de un endpoint

Ver los 50 intentos de entrega más recientes de un endpoint específico:

curl 'https://api.veriko.mx/v1/webhooks/f47ac10b-.../deliveries?per_page=50' \
  -H 'Authorization: Bearer veriko_••••'

Cada entrada muestra el código de estado HTTP, el tiempo de respuesta y un cuerpo de respuesta truncado — suficiente para diagnosticar la mayoría de los fallos de entrega sin exponer los cuerpos completos.

4. Ver entregas de todos los endpoints

Para una vista consolidada de todos los intentos de entrega independientemente del endpoint:

curl 'https://api.veriko.mx/v1/webhooks/deliveries' \
  -H 'Authorization: Bearer veriko_••••'

5. Exportar logs de entrega

Exporta logs de un endpoint específico o de todos los endpoints:

# Un endpoint — CSV
curl 'https://api.veriko.mx/v1/webhooks/f47ac10b-.../deliveries/export?format=csv' \
  -H 'Authorization: Bearer veriko_••••' \
  --output webhook-entregas-f47ac10b.csv

# Todos los endpoints — XLSX
curl 'https://api.veriko.mx/v1/webhooks/deliveries/export?format=xlsx' \
  -H 'Authorization: Bearer veriko_••••' \
  --output todas-las-entregas.xlsx

Siguientes pasos

  • Monitorear el consumo de cuota API y ciclo de facturación: ver Monitorear uso.
  • Analizar tendencias de validaciones y patrones por contraparte: ver Analizar insights.