curl -X POST 'https://api.trebol.com/v2/webhooks' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "url": "https://tu-servidor.com/webhooks/trebol",
    "events": ["verification.v2.created", "verification.v2.finished"],
    "description": "Webhook principal de producción"
  }'
{
  "id": "wh_123",
  "url": "https://tu-servidor.com/webhooks/trebol",
  "events": ["verification.v2.created", "verification.v2.finished"],
  "status": "enabled",
  "description": "Webhook principal de producción",
  "secret": "whsec_XXXXXXXXXXXXXXXXXXXXXXXX",
  "created_at": "2025-01-15T10:00:00Z",
  "updated_at": "2025-01-15T10:00:00Z"
}

Configuración y Seguridad

Los webhooks permiten que Trébol te notifique automáticamente cuando ocurren eventos importantes, como la finalización de una verificación.
  • URL de entrega: Debe aceptar solicitudes HTTPS POST.
  • Autenticación: Firma HMAC-SHA256 con un secreto por webhook.

Obtención del secreto de webhook

Cada webhook tiene un secreto único que se genera automáticamente cuando lo creas. Este secreto es esencial para verificar la autenticidad de los webhooks que recibes.

Cómo obtener tu secreto

El secreto del webhook se genera y se muestra únicamente una vez cuando creas el webhook a través de la API. Es crucial que guardes este secreto de forma segura, ya que no podrás recuperarlo posteriormente.
1

Crear webhook con API

Usa el endpoint POST /v2/webhooks para crear un nuevo webhook:
curl -X POST 'https://api.trebol.com/v2/webhooks' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "url": "https://tu-servidor.com/webhooks/trebol",
    "events": ["verification.v2.created", "verification.v2.finished"],
    "description": "Webhook principal de producción"
  }'
2

Guardar el secreto

En la respuesta, encontrarás el campo secret que contiene tu secreto único:
{
  "id": "wh_123",
  "url": "https://tu-servidor.com/webhooks/trebol",
  "events": ["verification.v2.created", "verification.v2.finished"],
  "status": "enabled",
  "description": "Webhook principal de producción",
  "secret": "whsec_XXXXXXXXXXXXXXXXXXXXXXXX",
  "created_at": "2025-01-15T10:00:00Z",
  "updated_at": "2025-01-15T10:00:00Z"
}
¡Importante! Copia y guarda el secreto inmediatamente. Una vez que cierres esta respuesta, no podrás ver el secreto nuevamente por razones de seguridad.
3

Configurar en tu aplicación

Almacena el secreto de forma segura en tu aplicación:
Environment Variables
# .env
WEBHOOK_SECRET=whsec_XXXXXXXXXXXXXXXXXXXXXXXX
Configuration
// config.js
const config = {
  webhookSecret: process.env.WEBHOOK_SECRET
};

Gestión de secretos

Si pierdes tu secreto de webhook, deberás crear un nuevo webhook para obtener un nuevo secreto. No es posible recuperar o regenerar el secreto de un webhook existente.
  1. Crea un nuevo webhook con la misma configuración
  2. Actualiza tu aplicación con el nuevo secreto
  3. Elimina el webhook anterior una vez que confirmes que el nuevo funciona correctamente
Para mayor seguridad, puedes implementar una rotación periódica de secretos:
  1. Crea un nuevo webhook con un nuevo secreto
  2. Actualiza tu aplicación para aceptar ambos secretos temporalmente
  3. Una vez confirmado que el nuevo webhook funciona, elimina el anterior
  4. Actualiza tu aplicación para usar solo el nuevo secreto
Es recomendable usar diferentes webhooks (y por tanto diferentes secretos) para cada entorno:
  • Desarrollo: whsec_dev_XXXXXXXXXXXXXXXXXXXXXXXX
  • Staging: whsec_staging_XXXXXXXXXXXXXXXXXXXXXXXX
  • Producción: whsec_prod_XXXXXXXXXXXXXXXXXXXXXXXX
Esto te permite probar webhooks sin afectar tu entorno de producción.

Verificación de firmas de webhook

Para garantizar la seguridad y autenticidad de los webhooks, Trébol incluye una firma HMAC-SHA256 en el header Trebol-Signature de cada solicitud. Esta firma te permite verificar que el webhook proviene realmente de Trébol y que el payload no ha sido modificado.

Formato del header de firma

El header Trebol-Signature contiene múltiples elementos separados por comas:
Trebol-Signature: t=1640995200,v1=abc123def456...
  • t: Timestamp Unix de cuando se generó la firma
  • v1: Firma HMAC-SHA256 del payload

Proceso de verificación

  1. Extraer elementos: Separa el header por comas y extrae el timestamp (t) y la firma (v1)
  2. Construir payload: Concatena el timestamp con el payload: {timestamp}.{payload}
  3. Generar firma esperada: Calcula HMAC-SHA256 usando tu secreto de webhook
  4. Comparar firmas: Usa comparación de tiempo constante para evitar ataques de timing
Siempre verifica las firmas de webhook en producción. Nunca proceses webhooks sin verificar su autenticidad.

Ejemplos de implementación

import crypto from "node:crypto";

function verifyWebhookSignature(payload, signature, secret) {
  const elements = signature.split(",");
  const timestamp = elements.find((el) => el.startsWith("t="))?.split("=")[1];
  const v1 = elements.find((el) => el.startsWith("v1="))?.split("=")[1];

  if (!timestamp || !v1) return false;

  const payloadToSign = `${timestamp}.${payload}`;
  const expectedSignature = crypto
    .createHmac("sha256", secret)
    .update(payloadToSign, "utf8")
    .digest("hex");

  // Convert both signatures to Buffer for constant time comparison
  const receivedSignatureBuffer = Buffer.from(v1, "hex");
  const expectedSignatureBuffer = Buffer.from(expectedSignature, "hex");

  // Ensure both buffers are the same length
  if (receivedSignatureBuffer.length !== expectedSignatureBuffer.length) {
    return false;
  }

  // Constant time comparison
  return crypto.timingSafeEqual(
    receivedSignatureBuffer,
    expectedSignatureBuffer
  );
}

// Ejemplo de uso en Express.js
app.post('/webhook', express.raw({type: 'application/json'}), (req, res) => {
  const signature = req.headers['trebol-signature'];
  const payload = req.body.toString();
  
  if (!verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }
  
  // Procesar webhook...
  res.status(200).send('OK');
});
Para mayor seguridad, también puedes verificar que el timestamp no sea demasiado antiguo (por ejemplo, no más de 5 minutos) para prevenir ataques de replay.

Direcciones IP de origen

Trébol envía todos los webhooks desde las siguientes direcciones IP:
  • 35.170.236.123
  • 54.162.134.233
Estas IPs son estáticas y no cambiarán. Puedes configurar tu firewall para permitir únicamente estas direcciones si necesitas restricciones adicionales de seguridad.
Aunque puedes usar las IPs para validación adicional, siempre debes verificar la firma del webhook. Las IPs pueden cambiar en el futuro o ser falsificadas, pero la firma HMAC-SHA256 es la única forma garantizada de verificar la autenticidad.

Crear y gestionar webhooks por API

Usa los endpoints en API Reference → Gestión de Webhooks para administrar tus webhooks.
  • Crear: POST /v2/webhooks
  • Listar: GET /v2/webhooks
  • Obtener: GET /v2/webhooks/{webhookId}
  • Actualizar: PUT /v2/webhooks/{webhookId}
  • Eliminar: DELETE /v2/webhooks/{webhookId}

Tipos de eventos

verification.v2.created

Se dispara cuando se crea una nueva verificación en el sistema. Payload:
{
  "event_name": "verification.v2.created",
  "data": {
    "verification_id": "string",
    "account_id": "string",
    "account_name": "string",
    "created_at": "string (ISO 8601)",
    "status": "string"
  }
}

verification.v2.finished

Se dispara cuando una verificación ha sido completada exitosamente. Payload:
{
  "event_name": "verification.v2.finished",
  "data": {
    "verification_id": "string",
    "account_id": "string",
    "account_name": "string",
    "created_at": "string (ISO 8601)",
    "status": "string"
  }
}

verification_item.v2.completed

Se dispara cuando un item específico dentro de una verificación ha sido completado. Payload:
{
  "event_name": "verification_item.v2.completed",
  "data": {
    "verification_id": "string",
    "item_id": "number",
    "account_id": "string",
    "account_name": "string",
    "item_type": "string",
    "completed_at": "string (ISO 8601)"
  }
}

verification_item.v2.internal_status_changed

Se dispara cuando un item específico dentro de una verificación ha cambiado su estado. Payload:
{
  "event_name": "verification_item.v2.internal_status_changed",
  "data": {
    "verification_id": "string",
    "item_id": "number",
    "item_type": "string",
    "internal_status": "string",
    "updated_at": "string (ISO 8601)",
    "account_name": "string",
    "account_id": "string"
  }
}