Referencia de Eventos de Webhook
Referencia completa de los 14 tipos de eventos webhook de Leypal, con ejemplos JSON y tablas de campos anotados.
Referencia de Eventos de Webhook
Leypal envía eventos webhook para dos familias de eventos: eventos de firma (signature.*) e eventos de verificación de identidad (identity_verification.*). Cada webhook sigue una estructura de wrapper estándar, con campos específicos del evento dentro del objeto data.
Esta referencia documenta los 14 tipos de eventos con ejemplos completos de payload JSON y anotaciones a nivel de campo. Usa esta página para construir tu manejador de eventos y entender exactamente qué datos esperar.
¿Es tu primera vez configurando webhooks? Empieza con la Guía de Configuración de Webhook para registrar tu punto final y configurar suscripciones a eventos.
Estructura del Payload Estándar
Cada entrega de webhook — independientemente del tipo de evento — incluye el mismo wrapper de nivel superior:
{
"webhookId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"event": "signature.created",
"timestamp": "2026-03-30T14:23:01.000Z",
"organizationId": 42,
"data": {
// campos específicos del evento
}
}| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
webhookId | string (UUID) | Sí | Identificador único para esta entrega específica de webhook. Úsalo para desduplicar entregas si Leypal reintenta. |
event | string | Sí | Nombre del tipo de evento (p. ej., signature.created). Úsalo para enrutar al manejador correcto. |
timestamp | string (ISO 8601) | Sí | Cuándo ocurrió el evento en los servidores de Leypal, en UTC. |
organizationId | number | Sí | La organización propietaria del recurso. Útil para configuraciones multi-tenant. |
data | object | Sí | Payload específico del evento. La estructura varía según el tipo de evento — consulta las secciones a continuación. |
Siempre verifica el encabezado x-leypal-signature usando HMAC-SHA256 antes de procesar cualquier payload de webhook. Consulta la Guía de Verificación de Webhook para detalles de implementación y código listo para usar.
Eventos de Firma
Los eventos de firma rastrean el ciclo de vida de una solicitud de firma de documento, desde la creación hasta la finalización o el rechazo.
signature.created
Se emite cuando se crea un nuevo documento de firma. En este punto, el documento existe en Leypal pero puede que aún no haya sido enviado a los firmantes.
{
"webhookId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"event": "signature.created",
"timestamp": "2026-03-30T14:23:01.000Z",
"organizationId": 42,
"data": {
"signatureId": 1001,
"status": "pending",
"subject": "Q1 Sales Agreement",
"senderName": "Alice Cooper",
"type": "document",
"signers": [
{
"id": 501,
"email": "bob@example.com",
"name": "Bob Builder",
"status": "pending",
"completedAt": null
},
{
"id": 502,
"email": "charlie@example.com",
"name": "Charlie Brown",
"status": "pending",
"completedAt": null
}
],
"signerId": null,
"signerEmail": null
}
}| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
data.signatureId | number | Sí | ID único del documento de firma. |
data.status | enum | Sí | Estado actual. En la creación, siempre "pending". |
data.subject | string | Sí | Título o asunto del documento que se está firmando. |
data.senderName | string | Sí | Nombre completo de la persona que creó la solicitud de firma. |
data.type | string | Sí | Tipo de documento. Actualmente siempre "document". |
data.signers | array | Sí | Lista de firmantes incluidos en esta solicitud de firma. |
data.signers[].id | number | Sí | Identificador único del firmante. |
data.signers[].email | string | Sí | Dirección de correo electrónico del firmante. |
data.signers[].name | string | Sí | Nombre completo del firmante. |
data.signers[].status | enum | Sí | Estado del firmante: "pending", "signed", o "verified". |
data.signers[].completedAt | string/null | Sí | Marca de tiempo ISO 8601 cuando el firmante completó, o null si aún está pendiente. |
data.signerId | number/null | Sí | ID del firmante específico para eventos relacionados con un firmante. null para signature.created. |
data.signerEmail | string/null | Sí | Correo del firmante específico para eventos relacionados con un firmante. null para signature.created. |
signature.signed
Se emite cuando todos los firmantes han colocado sus firmas. El documento está ahora firmado, pero puede que aún requiera verificación de identidad antes de alcanzar el estado completed.
{
"webhookId": "4ab96g75-6828-5673-c4gd-3d074g77bgb7",
"event": "signature.signed",
"timestamp": "2026-03-30T15:47:22.000Z",
"organizationId": 42,
"data": {
"signatureId": 1001,
"status": "signed",
"subject": "Q1 Sales Agreement",
"senderName": "Alice Cooper",
"type": "document",
"signers": [
{
"id": 501,
"email": "bob@example.com",
"name": "Bob Builder",
"status": "signed",
"completedAt": "2026-03-30T15:30:00.000Z"
},
{
"id": 502,
"email": "charlie@example.com",
"name": "Charlie Brown",
"status": "signed",
"completedAt": "2026-03-30T15:47:22.000Z"
}
],
"signerId": null,
"signerEmail": null
}
}| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
data.status | enum | Sí | "signed" — todos los firmantes han firmado. Puede convertirse en "completed" después de la verificación. |
data.signers[].status | enum | Sí | Todos los firmantes tendrán el estado "signed" en este evento. |
data.signers[].completedAt | string | Sí | Marca de tiempo de cuando cada firmante completó. No es nulo para ningún firmante en este evento. |
Si tu firma requiere verificación de identidad, signature.signed se emite antes de que se complete la verificación. Espera a signature.completed para confirmar que todo el proceso ha finalizado.
signature.completed
Se emite cuando el proceso de firma está completamente terminado — todos los firmantes han firmado y cualquier verificación de identidad requerida ha sido aprobada.
{
"webhookId": "5bc07h86-7939-6784-d5he-4e185h88chc8",
"event": "signature.completed",
"timestamp": "2026-03-30T16:02:45.000Z",
"organizationId": 42,
"data": {
"signatureId": 1001,
"status": "completed",
"subject": "Q1 Sales Agreement",
"senderName": "Alice Cooper",
"type": "document",
"signers": [
{
"id": 501,
"email": "bob@example.com",
"name": "Bob Builder",
"status": "verified",
"completedAt": "2026-03-30T15:30:00.000Z"
},
{
"id": 502,
"email": "charlie@example.com",
"name": "Charlie Brown",
"status": "verified",
"completedAt": "2026-03-30T15:47:22.000Z"
}
],
"signerId": null,
"signerEmail": null
}
}| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
data.status | enum | Sí | Siempre "completed" en este evento. |
data.signers[].status | enum | Sí | "signed" (si no se requirió verificación) o "verified" (si la verificación fue aprobada). |
signature.reminder
Se emite cuando Leypal envía un correo de recordatorio a uno o más firmantes que aún no han firmado. Este evento no cambia el estado del documento.
{
"webhookId": "6cd18i97-8a4a-7895-e6if-5f296i99did9",
"event": "signature.reminder",
"timestamp": "2026-03-30T17:00:00.000Z",
"organizationId": 42,
"data": {
"signatureId": 1001,
"status": "sent",
"subject": "Q1 Sales Agreement",
"senderName": "Alice Cooper",
"type": "document",
"signers": [
{
"id": 501,
"email": "bob@example.com",
"name": "Bob Builder",
"status": "signed",
"completedAt": "2026-03-30T15:30:00.000Z"
},
{
"id": 502,
"email": "charlie@example.com",
"name": "Charlie Brown",
"status": "pending",
"completedAt": null
}
],
"signerId": 502,
"signerEmail": "charlie@example.com"
}
}| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
data.status | enum | Sí | Estado del documento al momento del recordatorio — normalmente "sent" o "pending". |
data.signerId | number | Sí | ID del firmante que recibió el recordatorio. |
data.signerEmail | string | Sí | Correo electrónico del firmante que recibió el recordatorio. |
signature.rejected
Se emite cuando un firmante rechaza explícitamente la solicitud de firma. El documento no puede completarse después del rechazo.
{
"webhookId": "7de29j08-9b5b-8906-f7jg-6g3a7j00eje0",
"event": "signature.rejected",
"timestamp": "2026-03-30T16:15:30.000Z",
"organizationId": 42,
"data": {
"signatureId": 1001,
"status": "rejected",
"subject": "Q1 Sales Agreement",
"senderName": "Alice Cooper",
"type": "document",
"signers": [
{
"id": 501,
"email": "bob@example.com",
"name": "Bob Builder",
"status": "signed",
"completedAt": "2026-03-30T15:30:00.000Z"
},
{
"id": 502,
"email": "charlie@example.com",
"name": "Charlie Brown",
"status": "pending",
"completedAt": null
}
],
"signerId": 502,
"signerEmail": "charlie@example.com"
}
}| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
data.status | enum | Sí | Siempre "rejected" en este evento. |
data.signerId | number | Sí | ID del firmante que rechazó la solicitud. |
data.signerEmail | string | Sí | Correo electrónico del firmante que rechazó la solicitud. |
Referencia de Campos Comunes de Firma
Esta tabla documenta todos los campos posibles en todos los eventos de firma en un solo lugar.
| Campo | Tipo | Presente En | Descripción |
|---|---|---|---|
data.signatureId | number | Todos | Identificador único del documento de firma. |
data.status | enum | Todos | Estado del documento: "pending", "sent", "signed", "verified", "completed", "rejected", "expired". |
data.subject | string | Todos | Asunto/título del documento establecido por el remitente. |
data.senderName | string | Todos | Nombre de la persona que creó la solicitud de firma. |
data.type | string | Todos | Tipo de documento. Actualmente siempre "document". |
data.signers | array | Todos | Array de todos los firmantes asociados con esta firma. |
data.signers[].id | number | Todos | ID único del registro del firmante. |
data.signers[].email | string | Todos | Dirección de correo electrónico del firmante. |
data.signers[].name | string | Todos | Nombre completo del firmante. |
data.signers[].status | enum | Todos | "pending", "signed", o "verified". |
data.signers[].completedAt | string/null | Todos | Marca de tiempo ISO 8601 cuando el firmante completó, null si aún está pendiente. |
data.signerId | number/null | Todos | ID del firmante relevante para este evento. null para eventos a nivel de documento (created, signed, completed). |
data.signerEmail | string/null | Todos | Correo del firmante relevante para este evento. null para eventos a nivel de documento. |
Eventos de Verificación de Identidad
Los eventos de verificación de identidad rastrean el ciclo de vida de una sesión de verificación, desde el inicio hasta el análisis de ML.
identity_verification.created
Se emite cuando se inicia una nueva sesión de verificación de identidad. La sesión está creada pero el usuario aún no ha comenzado el flujo de verificación.
{
"webhookId": "8ef3ak19-ac6c-9a17-g8kh-7h4b8k11fkf1",
"event": "identity_verification.created",
"timestamp": "2026-03-30T14:23:01.000Z",
"organizationId": 42,
"data": {
"id": 2001,
"status": "initiated",
"email": "diana@example.com",
"name": "Diana Prince",
"contactId": null,
"approvedAt": null,
"attemptsUsed": 0,
"maxAttempts": 3,
"expiresAt": "2026-04-30T14:23:01.000Z",
"session": null
}
}| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
data.id | number | Sí | ID único del registro de verificación de identidad. |
data.status | enum | Sí | "initiated" en la creación. |
data.email | string | Sí | Dirección de correo electrónico de la persona que se está verificando. |
data.name | string | Sí | Nombre completo de la persona que se está verificando. |
data.contactId | number/null | Sí | ID del registro de contacto asociado, si está vinculado a un contacto de Leypal. De lo contrario null. |
data.approvedAt | string/null | Sí | Marca de tiempo ISO 8601 de aprobación. null hasta que se apruebe la verificación. |
data.attemptsUsed | number | Sí | Número de intentos de verificación usados. 0 en la creación. |
data.maxAttempts | number | Sí | Máximo de intentos permitidos antes de que expire la sesión. |
data.expiresAt | string | Sí | Marca de tiempo ISO 8601 cuando expira esta sesión. |
data.session | null | Sí | Siempre null en la creación — aún no se ha iniciado ninguna sesión. |
identity_verification.session_started
Se emite cuando el usuario abre el enlace de verificación y comienza la sesión. El objeto session se puebla por primera vez.
{
"webhookId": "9fg4bl2a-bd7d-ab28-h9li-8i5c9l22glg2",
"event": "identity_verification.session_started",
"timestamp": "2026-03-30T14:30:00.000Z",
"organizationId": 42,
"data": {
"id": 2001,
"status": "in_progress",
"email": "diana@example.com",
"name": "Diana Prince",
"contactId": null,
"approvedAt": null,
"attemptsUsed": 1,
"maxAttempts": 3,
"expiresAt": "2026-04-30T14:23:01.000Z",
"session": {
"id": "sess_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "started",
"attemptNumber": 1,
"startedAt": "2026-03-30T14:30:00.000Z",
"completedAt": null,
"livenessPassed": null,
"faceMatchPassed": null,
"faceMatchScore": null,
"idVerificationPassed": null,
"documentClassification": null,
"failureReason": null
}
}
}| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
data.status | enum | Sí | "in_progress" — el usuario ha comenzado el flujo. |
data.attemptsUsed | number | Sí | Se incrementa a 1 cuando comienza la sesión. |
data.session.id | string (UUID) | Sí | Identificador único de sesión para este intento. |
data.session.status | enum | Sí | "started" en este punto. |
data.session.attemptNumber | number | Sí | Número de intento actual (1, 2, o 3). |
data.session.startedAt | string | Sí | Marca de tiempo ISO 8601 de cuando comenzó la sesión. |
data.session.completedAt | null | Sí | null — la sesión aún no está completa. |
data.session.livenessPassed | null | Sí | null — la prueba de vida aún no se ha ejecutado. |
data.session.faceMatchPassed | null | Sí | null — la coincidencia facial aún no se ha ejecutado. |
data.session.faceMatchScore | null | Sí | null — la puntuación aún no se ha calculado. |
data.session.idVerificationPassed | null | Sí | null — la verificación de documento aún no se ha ejecutado. |
data.session.documentClassification | null | Sí | null — el documento aún no ha sido clasificado. |
data.session.failureReason | null | Sí | null — sin fallo en este punto. |
identity_verification.document_front_uploaded
Se emite cuando el usuario sube el anverso de su documento de identidad.
{
"webhookId": "agh5cm3b-ce8e-bc39-i0mj-9j6d0m33hmh3",
"event": "identity_verification.document_front_uploaded",
"timestamp": "2026-03-30T14:31:20.000Z",
"organizationId": 42,
"data": {
"id": 2001,
"status": "in_progress",
"email": "diana@example.com",
"name": "Diana Prince",
"contactId": null,
"approvedAt": null,
"attemptsUsed": 1,
"maxAttempts": 3,
"expiresAt": "2026-04-30T14:23:01.000Z",
"session": {
"id": "sess_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "in_progress",
"attemptNumber": 1,
"startedAt": "2026-03-30T14:30:00.000Z",
"completedAt": null,
"livenessPassed": null,
"faceMatchPassed": null,
"faceMatchScore": null,
"idVerificationPassed": null,
"documentClassification": null,
"failureReason": null
}
}
}| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
data.session.status | enum | Sí | "in_progress" — la carga del documento es parte de la sesión activa. |
identity_verification.document_back_uploaded
Se emite cuando el usuario sube el reverso de su documento de identidad.
{
"webhookId": "bhi6dn4c-df9f-cd4a-j1nk-ak7e1n44ini4",
"event": "identity_verification.document_back_uploaded",
"timestamp": "2026-03-30T14:32:10.000Z",
"organizationId": 42,
"data": {
"id": 2001,
"status": "in_progress",
"email": "diana@example.com",
"name": "Diana Prince",
"contactId": null,
"approvedAt": null,
"attemptsUsed": 1,
"maxAttempts": 3,
"expiresAt": "2026-04-30T14:23:01.000Z",
"session": {
"id": "sess_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "in_progress",
"attemptNumber": 1,
"startedAt": "2026-03-30T14:30:00.000Z",
"completedAt": null,
"livenessPassed": null,
"faceMatchPassed": null,
"faceMatchScore": null,
"idVerificationPassed": null,
"documentClassification": null,
"failureReason": null
}
}
}| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
data.session.status | enum | Sí | "in_progress" — ambas caras del documento subidas, sesión aún activa. |
identity_verification.liveness_started
Se emite cuando el usuario comienza la prueba de vida (el paso de selfie/video en tiempo real para demostrar que está físicamente presente).
{
"webhookId": "cij7eo5d-eg0g-de5b-k2ol-bl8f2o55joj5",
"event": "identity_verification.liveness_started",
"timestamp": "2026-03-30T14:33:05.000Z",
"organizationId": 42,
"data": {
"id": 2001,
"status": "in_progress",
"email": "diana@example.com",
"name": "Diana Prince",
"contactId": null,
"approvedAt": null,
"attemptsUsed": 1,
"maxAttempts": 3,
"expiresAt": "2026-04-30T14:23:01.000Z",
"session": {
"id": "sess_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "in_progress",
"attemptNumber": 1,
"startedAt": "2026-03-30T14:30:00.000Z",
"completedAt": null,
"livenessPassed": null,
"faceMatchPassed": null,
"faceMatchScore": null,
"idVerificationPassed": null,
"documentClassification": null,
"failureReason": null
}
}
}identity_verification.liveness_end
Se emite cuando la prueba de vida está completa. El pipeline de ML aún no se ha ejecutado en este punto — los resultados de aprobado/fallido son null hasta ml_pipeline_completed.
{
"webhookId": "djk8fp6e-fh1h-ef6c-l3pm-cm9g3p66kpk6",
"event": "identity_verification.liveness_end",
"timestamp": "2026-03-30T14:33:45.000Z",
"organizationId": 42,
"data": {
"id": 2001,
"status": "in_progress",
"email": "diana@example.com",
"name": "Diana Prince",
"contactId": null,
"approvedAt": null,
"attemptsUsed": 1,
"maxAttempts": 3,
"expiresAt": "2026-04-30T14:23:01.000Z",
"session": {
"id": "sess_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "in_progress",
"attemptNumber": 1,
"startedAt": "2026-03-30T14:30:00.000Z",
"completedAt": null,
"livenessPassed": null,
"faceMatchPassed": null,
"faceMatchScore": null,
"idVerificationPassed": null,
"documentClassification": null,
"failureReason": null
}
}
}| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
data.session.livenessPassed | null | Sí | Aún null — el pipeline de ML aún no se ha ejecutado. El resultado se poblará en ml_pipeline_completed. |
identity_verification.ml_pipeline_completed
Se emite cuando el pipeline de análisis de ML termina de procesar los documentos subidos y los datos de la prueba de vida. Este es el evento más importante — contiene los resultados finales de aprobado/fallido para cada componente de verificación.
{
"webhookId": "ekl9gq7f-gi2i-fg7d-m4qn-dn0h4q77lql7",
"event": "identity_verification.ml_pipeline_completed",
"timestamp": "2026-03-30T14:35:10.000Z",
"organizationId": 42,
"data": {
"id": 2001,
"status": "completed",
"email": "diana@example.com",
"name": "Diana Prince",
"contactId": 305,
"approvedAt": "2026-03-30T14:35:10.000Z",
"attemptsUsed": 1,
"maxAttempts": 3,
"expiresAt": "2026-04-30T14:23:01.000Z",
"session": {
"id": "sess_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "completed",
"attemptNumber": 1,
"startedAt": "2026-03-30T14:30:00.000Z",
"completedAt": "2026-03-30T14:35:10.000Z",
"livenessPassed": true,
"faceMatchPassed": true,
"faceMatchScore": 97,
"idVerificationPassed": true,
"documentClassification": "national_id",
"failureReason": null
}
}
}| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
data.status | enum | Sí | "completed" (pipeline terminado), "approved" (todas las verificaciones aprobadas), o "rejected" (una verificación falló). |
data.approvedAt | string/null | Sí | Marca de tiempo ISO 8601 de aprobación. null si la verificación falló. |
data.session.status | enum | Sí | "completed" — todos los pasos de verificación finalizados. |
data.session.completedAt | string | Sí | Marca de tiempo ISO 8601 de cuando terminó la sesión. |
data.session.livenessPassed | boolean | Sí | true si la prueba de vida fue aprobada, false si falló. |
data.session.faceMatchPassed | boolean | Sí | true si la selfie coincidió con el documento de identidad, false si no. |
data.session.faceMatchScore | number | Sí | Puntuación de confianza para la coincidencia facial (0–100). Más alto es mejor. |
data.session.idVerificationPassed | boolean | Sí | true si el documento de identidad fue verificado como auténtico. |
data.session.documentClassification | string | Sí | Tipo de documento detectado, p. ej., "national_id", "passport", "driver_license". |
data.session.failureReason | string/null | Sí | Descripción legible del motivo del fallo. null si la verificación fue exitosa. |
Cuando data.session.faceMatchPassed es false, verifica data.session.faceMatchScore para entender qué tan cercana fue la coincidencia. Las puntuaciones por debajo de 70 suelen indicar una discrepancia clara.
identity_verification.ml_pipeline_failed
Se emite cuando el pipeline de ML encuentra un error técnico durante el procesamiento. Esto no es una verificación fallida — indica un error de infraestructura. Leypal puede reintentar automáticamente en algunos casos.
{
"webhookId": "flm0hr8g-hj3j-gh8e-n5ro-eo1i5r88mrm8",
"event": "identity_verification.ml_pipeline_failed",
"timestamp": "2026-03-30T14:35:10.000Z",
"organizationId": 42,
"data": {
"id": 2001,
"status": "in_progress",
"email": "diana@example.com",
"name": "Diana Prince",
"contactId": null,
"approvedAt": null,
"attemptsUsed": 1,
"maxAttempts": 3,
"expiresAt": "2026-04-30T14:23:01.000Z",
"session": {
"id": "sess_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "in_progress",
"attemptNumber": 1,
"startedAt": "2026-03-30T14:30:00.000Z",
"completedAt": null,
"livenessPassed": null,
"faceMatchPassed": null,
"faceMatchScore": null,
"idVerificationPassed": null,
"documentClassification": null,
"failureReason": "ML pipeline timeout: upstream service unavailable"
}
}
}| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
data.status | enum | Sí | "in_progress" — la sesión aún no ha finalizado, puede reintentarse. |
data.session.failureReason | string | Sí | Descripción del error técnico del pipeline de ML. |
ml_pipeline_failed es un error técnico, no un fallo del usuario. La sesión de verificación aún está activa y el usuario puede reintentar si attemptsUsed está por debajo de maxAttempts. No marques al usuario como rechazado basándote únicamente en este evento.
identity_verification.review_requested
Se emite cuando el resultado del pipeline de ML es inconcluso y se ha activado una revisión manual por parte de un humano. La verificación está en espera pendiente de la decisión de un revisor.
{
"webhookId": "gmn1is9h-ik4k-hi9f-o6sp-fp2j6s99nsn9",
"event": "identity_verification.review_requested",
"timestamp": "2026-03-30T14:36:00.000Z",
"organizationId": 42,
"data": {
"id": 2001,
"status": "in_progress",
"email": "diana@example.com",
"name": "Diana Prince",
"contactId": null,
"approvedAt": null,
"attemptsUsed": 1,
"maxAttempts": 3,
"expiresAt": "2026-04-30T14:23:01.000Z",
"session": {
"id": "sess_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "completed",
"attemptNumber": 1,
"startedAt": "2026-03-30T14:30:00.000Z",
"completedAt": "2026-03-30T14:36:00.000Z",
"livenessPassed": true,
"faceMatchPassed": null,
"faceMatchScore": 62,
"idVerificationPassed": null,
"documentClassification": "passport",
"failureReason": null
}
}
}| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
data.status | enum | Sí | "in_progress" — esperando la decisión de revisión manual. |
data.session.faceMatchScore | number | Sí | La puntuación borderline que activó la solicitud de revisión (normalmente 50–75). |
Referencia de Campos Comunes de Verificación de Identidad
Esta tabla documenta todos los campos posibles en todos los eventos de verificación de identidad.
| Campo | Tipo | Presente En | Descripción |
|---|---|---|---|
data.id | number | Todos | ID único del registro de verificación de identidad. |
data.status | enum | Todos | Estado general: "initiated", "in_progress", "completed", "approved", "rejected", "expired". |
data.email | string | Todos | Dirección de correo electrónico de la persona que se está verificando. |
data.name | string | Todos | Nombre completo de la persona que se está verificando. |
data.contactId | number/null | Todos | ID de contacto de Leypal asociado, o null si no está vinculado. |
data.approvedAt | string/null | Todos | Marca de tiempo ISO 8601 de aprobación. null hasta ser aprobado. |
data.attemptsUsed | number | Todos | Número de intentos de verificación consumidos. |
data.maxAttempts | number | Todos | Máximo de intentos permitidos. |
data.expiresAt | string | Todos | Marca de tiempo ISO 8601 de expiración de la sesión. |
data.session | object/null | Todos | null en identity_verification.created; objeto poblado en todos los eventos posteriores. |
data.session.id | string | eventos de sesión | UUID para este intento específico. |
data.session.status | enum | eventos de sesión | "started", "in_progress", o "completed". |
data.session.attemptNumber | number | eventos de sesión | Número de este intento (1–N, donde N es maxAttempts). |
data.session.startedAt | string | eventos de sesión | Marca de tiempo ISO 8601 de cuando el usuario comenzó la sesión. |
data.session.completedAt | string/null | eventos de sesión | Marca de tiempo ISO 8601 de finalización, o null si aún está en progreso. |
data.session.livenessPassed | boolean/null | eventos de sesión | Resultado de la prueba de vida. null hasta que se ejecute el pipeline de ML. |
data.session.faceMatchPassed | boolean/null | eventos de sesión | Si la selfie coincidió con el documento de identidad. null hasta que se ejecute el pipeline de ML. |
data.session.faceMatchScore | number/null | eventos de sesión | Puntuación de confianza 0–100. null hasta que se ejecute el pipeline de ML. |
data.session.idVerificationPassed | boolean/null | eventos de sesión | Si el documento de identidad fue autenticado. null hasta que se ejecute el pipeline de ML. |
data.session.documentClassification | string/null | eventos de sesión | Tipo de documento detectado (p. ej., "national_id", "passport", "driver_license"). null hasta que se ejecute el pipeline de ML. |
data.session.failureReason | string/null | eventos de sesión | Descripción del fallo si la verificación o el pipeline falló. null en caso de éxito. |
Temporización y Secuencias de Eventos
Entender el orden en que se emiten los eventos te ayuda a construir manejadores confiables.
Flujo de Firma
Una firma típica pasa por esta secuencia:
signature.created
↓
signature.reminder (opcional, puede emitirse múltiples veces)
↓
signature.signed (todos los firmantes han firmado)
↓
signature.completed (si no se requiere verificación)
O
[eventos de identity_verification se emiten para cada firmante]
↓
signature.completed (después de que todas las verificaciones sean aprobadas)Si algún firmante rechaza, se emite signature.rejected y el flujo termina. Una firma rechazada no puede completarse.
Flujo de Verificación de Identidad
Una sesión de verificación típica pasa por esta secuencia:
identity_verification.created
↓
identity_verification.session_started
↓
identity_verification.document_front_uploaded
↓
identity_verification.document_back_uploaded
↓
identity_verification.liveness_started
↓
identity_verification.liveness_end
↓
identity_verification.ml_pipeline_completedEn casos excepcionales, ml_pipeline_failed o review_requested pueden emitirse en lugar de o antes de ml_pipeline_completed.
No asumas que los eventos llegan en orden estricto. Los retrasos de red, los reintentos y el procesamiento concurrente pueden hacer que los eventos lleguen fuera de secuencia. Siempre verifica el campo status en el payload para determinar el estado actual — no te bases únicamente en el orden de los eventos.
Próximos Pasos
Ahora que entiendes las estructuras de payload de webhook, implementa la verificación de firma para garantizar la autenticidad de los webhooks:
- Guía de Verificación de Webhook — Implementación de HMAC-SHA256 con código Node.js listo para usar y comparación segura en tiempo
- Guía de Configuración de Webhook — Registra tu punto final, configura suscripciones a eventos y administra secretos
- Referencia de Errores de Webhook — Soluciona problemas de entrega, comportamiento de reintentos y códigos de error