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. Consulta la documentación completa del endpoint, incluyendo parámetros y ejemplos de respuesta, en API Reference → Gestión de Webhooks.2
Guardar el secreto
En la respuesta de creación, encontrarás el campo
secret que contiene tu
secreto único. Este secreto es esencial para verificar la autenticidad de los
webhooks que recibes.3
Configurar en tu aplicación
Almacena el secreto de forma segura en tu aplicación:
Environment Variables
Configuration
Gestión de secretos
¿Qué hacer si pierdes tu secreto?
¿Qué hacer si pierdes tu secreto?
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.
- Crea un nuevo webhook con la misma configuración
- Actualiza tu aplicación con el nuevo secreto
- Elimina el webhook anterior una vez que confirmes que el nuevo funciona correctamente
Rotación de secretos
Rotación de secretos
Para mayor seguridad, puedes implementar una rotación periódica de secretos:
- Crea un nuevo webhook con un nuevo secreto
- Actualiza tu aplicación para aceptar ambos secretos temporalmente
- Una vez confirmado que el nuevo webhook funciona, elimina el anterior
- Actualiza tu aplicación para usar solo el nuevo secreto
Secretos en diferentes entornos
Secretos en diferentes entornos
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
Verificación de firmas de webhook
Para garantizar la seguridad y autenticidad de los webhooks, Trébol incluye una firma HMAC-SHA256 en el headerTrebol-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 headerTrebol-Signature contiene múltiples elementos separados por comas:
t: Timestamp Unix de cuando se generó la firmav1: Firma HMAC-SHA256 del payload
Proceso de verificación
- Extraer elementos: Separa el header por comas y extrae el timestamp (
t) y la firma (v1) - Construir payload: Concatena el timestamp con el payload:
{timestamp}.{payload} - Generar firma esperada: Calcula HMAC-SHA256 usando tu secreto de webhook
- Comparar firmas: Usa comparación de tiempo constante para evitar ataques de timing
Ejemplos de implementación
Direcciones IP de origen
Trébol envía todos los webhooks desde las siguientes direcciones IP:35.170.236.12354.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.
Reintentos automáticos
Cuando tu endpoint no responde con un código de estado exitoso (2xx), Trébol reintentará automáticamente la entrega del webhook usando un esquema de backoff exponencial.
Comportamiento de reintentos
| Reintento | Tiempo de espera | Tiempo acumulado |
|---|---|---|
| 1 | 30 segundos | 30 segundos |
| 2 | 60 segundos | 1.5 minutos |
| 3 | 120 segundos | 3.5 minutos |
| 4 | 240 segundos | 7.5 minutos |
| 5 | 480 segundos | 15.5 minutos |
¿Cuándo se reintenta un webhook?
Trébol reintentará la entrega cuando:- Tu servidor responde con un código de error (
4xxo5xx) - Tu servidor no responde (timeout de conexión)
- Hay un error de red que impide la entrega
Evitar reintentos innecesarios
Para evitar que Trébol reintente webhooks que ya procesaste:- Responde con
200 OKinmediatamente después de validar la firma - Procesa el evento de forma asíncrona (ver Mejores prácticas)
- Maneja errores internamente sin retornar códigos de error HTTP
Mejores prácticas
Responde rápidamente con un código 2xx
Tu endpoint debe retornar un código de estado exitoso (2xx) inmediatamente antes de ejecutar cualquier lógica compleja que pueda causar un timeout. Si tu servidor tarda demasiado en responder, Trébol asumirá que la entrega falló y reintentará el envío.
❌ Incorrecto - Procesar antes de responder:
Maneja eventos duplicados
Ocasionalmente, tu endpoint puede recibir el mismo evento más de una vez. Para protegerte contra el procesamiento duplicado, debes implementar idempotencia en tu sistema. Estrategia recomendada: Usa la firma del headerTrebol-Signature como clave de deduplicación, ya que es única por evento.
Procesa eventos de forma asíncrona
Configura tu handler para procesar eventos entrantes con una cola asíncrona. Podrías encontrar problemas de escalabilidad si procesas eventos de forma síncrona, especialmente durante picos de tráfico.Ejemplo con RabbitMQ/SQS
Ejemplo con RabbitMQ/SQS
Ejemplo con Celery (Python)
Ejemplo con Celery (Python)
No dependas del orden de los eventos
Trébol no garantiza que los eventos lleguen en el orden en que fueron generados. Por ejemplo, podrías recibirverification_item.v2.completed antes de verification.v2.created.
Asegúrate de que tu integración pueda manejar eventos en cualquier orden y usa la API para obtener el estado actual si es necesario.
Crear y gestionar webhooks por API
Usa los endpoints enAPI 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:
verification.v2.finished
Se dispara cuando una verificación ha sido completada exitosamente.
Payload:
verification_item.v2.completed
Se dispara cuando un item específico dentro de una verificación ha sido completado.
Payload:
item_error(opcional): Indica errores públicos relacionados con el procesamiento del ítem. Valores permitidos:password_protected_pdf: El PDF subido está protegido con contraseña y no puede ser procesado.get_input_file_info_failed: Falló la obtención de información del archivo de entrada.
verification_item.v2.internal_status_changed
Se dispara cuando un item específico dentro de una verificación ha cambiado su estado.
Payload:
item_error(opcional): Indica errores públicos relacionados con el procesamiento del ítem. Valores permitidos:password_protected_pdf: El PDF subido está protegido con contraseña y no puede ser procesado.get_input_file_info_failed: Falló la obtención de información del archivo de entrada.
verification_people.curp_search_completed
Cuándo se dispara:
Este webhook se envía cuando el proceso de búsqueda de CURP para una persona de verificación ha finalizado. Esto puede ocurrir en los siguientes escenarios:
-
Después de extraer accionistas mediante procesamiento de tipos de acta: Cuando se procesan documentos como actas constitutivas (
ac_mx), actas de asamblea (aa_mx), o poderes notariales (pw_mx), y se extraen accionistas de estos documentos, Trébol realiza automáticamente una búsqueda de CURP para cada persona extraída. Una vez completada la búsqueda, se envía este webhook. -
Después de extraer personas desde items
person_id: Cuando se procesa un item de tipoperson_id(documentos de identidad como INE o pasaportes), y se crea o actualiza un registro de persona en la verificación, Trébol realiza una búsqueda de CURP para esa persona. Al finalizar la búsqueda, se envía este webhook.
Este webhook te permite estar al tanto de cuándo la información de CURP está
disponible para las personas en una verificación, lo cual es útil para acceder
a los datos de
external_identities que contienen la información obtenida de
RENAPO. Puedes usar el campo people_id para obtener a la persona en la
respuesta del endpoint people.verification_id(string): ID único de la verificación donde se actualizó la búsqueda de CURP.item_id(number, opcional): ID del item que originó la búsqueda de CURP. Puede ser un item de tipoperson_ido un item de tipo acta que extrajo personas.people_id(number): ID único de la persona de verificación para la cual se completó la búsqueda de CURP.people_error(string, opcional): Código de error si la búsqueda de CURP falló. Solo está presente cuando ocurre un error. Valores permitidos:curp_scrapper_error: Error al extraer información del CURP desde el servicio externo.curp_format_error: El formato del CURP proporcionado no es válido.curp_service_unavailable: El servicio de búsqueda de CURP no está disponible.
people_error_message(string, opcional): Mensaje descriptivo del error. Solo está presente cuandopeople_errortiene un valor.shareholder_id(number, opcional): ID del accionista relacionado, si la persona está asociada a un accionista en la verificación.account_name(string): Nombre de la cuenta asociada a la verificación.account_id(string): ID único de la cuenta.verification_tag(string): Etiqueta personalizada de la verificación.
Obtener datos CURP
Una vez que recibas el webhookverification_people.curp_search_completed, puedes obtener los datos de CURP consultando el endpoint de personas.
1
Recibir el webhook
Extrae
verification_id y people_id del payload del webhook:2
Consultar el endpoint de personas
Usa el
verification_id para llamar al endpoint de personas:3
Buscar la persona en full_list
En la respuesta JSON, localiza la persona cuyo
people_id coincida con el del webhook dentro del array full_list. Ahí es donde encontrarás el objeto completo de la persona junto con sus identidades externas.4
Acceder a los datos de CURP
Una vez que tengas la persona, puedes acceder a los datos de CURP en el objeto
external_identities.curp: