Saltar al contenido principal

Tipos de eventos

Veridia emite tres tipos de eventos hoy, todos sobre resultados de verificacion. Cada evento tiene un shape base consistente con campos especificos por evento sumados encima.

Referencia rapida

EventoVerdictCuando se dispara
verification.approvedapprovedScore de confianza arriba del threshold de aprobacion, sin flags criticos
verification.rejectedrejectedConfianza debajo del threshold de rechazo, o flag critico disparado
verification.review_requiredreviewConfianza en la franja media — revision manual necesaria

Los thresholds default son configurables por tenant. Out of the box: rejected <60, review 60-80, approved >=80.

Campos comunes

Cada evento incluye estos campos:

CampoTipoSiempreDescripcion
eventstringSiTipo de evento — switcha en este en tu handler
verificationIdstringSiID unico de /init (formato: vf_*)
tenantIdstringSiTu tenant ID (util para routing multi-tenant)
userRefstring | nullSiEl userRef que pasaste a /init, o null si no
verdictstringSiapproved, review, o rejected
confidencenumberSiScore general ponderado de confianza (0-100)
scoresobjectSiBreakdown de senales individuales
flagsarraySiFlags de calidad / riesgo levantados. Vacio [] cuando esta limpio
metadataobjectSiEl metadata que pasaste a /submit, o {}
submittedAtstringSiTimestamp ISO 8601 cuando se llamo a /submit
completedAtstringSiTimestamp ISO 8601 cuando se determino el veredicto

El body es siempre JSON compacto con keys ordenadas alfabeticamente — requerido para verificacion reproducible de la firma.

verification.approved

Enviado cuando una verificacion pasa todos los thresholds de senales y no tiene flags criticos. Este es el evento luz-verde para tu flow de onboarding.

{
"event": "verification.approved",
"verificationId": "vf_AG07CDWRRFQV4T05ZXG2",
"tenantId": "tn_default_demo",
"userRef": "customer-12345",
"verdict": "approved",
"confidence": 87.4,
"scores": {
"ocrConfidence": 78.0,
"faceMatch": 96.2,
"liveness": 91.5,
"docQuality": 85.0
},
"flags": [],
"metadata": {
"campaign": "spring_2026",
"platform": "web"
},
"submittedAt": "2026-05-01T18:39:05Z",
"completedAt": "2026-05-01T18:39:08Z"
}

Handler tipico:

case 'verification.approved':
await db.users.update(payload.userRef, {
kycStatus: 'verified',
kycCompletedAt: payload.completedAt,
kycVerificationId: payload.verificationId,
});
await sendWelcomeEmail(payload.userRef);
break;

verification.rejected

Enviado cuando una verificacion falla — sea confianza debajo del threshold de rechazo, o un flag critico (documento expirado, mismatch MRZ, edad debajo del minimo, etc.).

{
"event": "verification.rejected",
"verificationId": "vf_BX18DEXSGFRX5U16YH3",
"tenantId": "tn_default_demo",
"userRef": "customer-67890",
"verdict": "rejected",
"confidence": 42.1,
"scores": {
"ocrConfidence": 65.0,
"faceMatch": 31.4,
"liveness": 88.0,
"docQuality": 50.5
},
"flags": [
{ "level": "critical", "text": "low_face_match" },
{ "level": "warn", "text": "low_doc_quality" }
],
"metadata": {},
"submittedAt": "2026-05-01T19:02:12Z",
"completedAt": "2026-05-01T19:02:15Z"
}

Handler tipico:

case 'verification.rejected':
await db.users.update(payload.userRef, {
kycStatus: 'rejected',
kycRejectionReasons: payload.flags,
});
await sendRejectionEmail(payload.userRef, payload.flags);
// No le digas al usuario los flags exactos — riesgo de seguridad
break;

:::warning No expongas flags a usuarios finales Decirle a un defraudador que senal lo atrapo lo ayuda a craftear un intento mejor. Mostra a usuarios finales un generico "verificacion fallo, por favor contacta soporte" — guarda los flags detallados para tu cola de revision interna. :::

verification.review_required

Enviado cuando la confianza cae en la franja media. El usuario podria ser legitimo pero el sistema no esta lo suficientemente confiado para auto-aprobar. Tus revisores deberian mirarlo.

{
"event": "verification.review_required",
"verificationId": "vf_CY29EFYTGFSZ6V27ZH4",
"tenantId": "tn_default_demo",
"userRef": "customer-11111",
"verdict": "review",
"confidence": 67.3,
"scores": {
"ocrConfidence": 72.0,
"faceMatch": 79.5,
"liveness": 88.0,
"docQuality": 45.0
},
"flags": [
{ "level": "warn", "text": "heavy_glare" },
{ "level": "info", "text": "name_mismatch" }
],
"metadata": {},
"submittedAt": "2026-05-01T20:15:30Z",
"completedAt": "2026-05-01T20:15:33Z"
}

Handler tipico:

case 'verification.review_required':
await db.users.update(payload.userRef, {
kycStatus: 'pending_review',
});
await reviewQueue.add({
verificationId: payload.verificationId,
userRef: payload.userRef,
flags: payload.flags,
priority: payload.flags.some(f => f.level === 'critical') ? 'high' : 'normal',
});
// Opcionalmente pausa acciones sensibles hasta que el revisor decida
break;

Breakdown de scores

El objeto scores tiene el mismo shape en todos los eventos:

CampoRangoDescripcion
ocrConfidence0-100Confianza VLM auto-reportada en extraccion de texto del documento
faceMatch0-100Similitud biometrica entre selfie y foto del documento
liveness0-100Anti-spoofing — confirma que es una persona viva, no foto
docQuality0-100Calidad de imagen del documento capturado (nitidez, iluminacion, framing)

El confidence general es una combinacion ponderada — principalmente faceMatch y liveness, con ocrConfidence y docQuality como senales de soporte.

Referencia de flags

Los flags se disparan cuando una senal individual cae debajo del threshold o falla un check duro. Cada uno tiene un level:

NivelSignificado
infoFYI para revisores, no afecta el veredicto por si solo
warnIssue notable — contribuye a confianza bajada
criticalFalla dura — empuja el veredicto a rejected sin importar las otras senales

Flags comunes que podes ver en el array flags:

FlagNivelSignificado
heavy_glarewarnDocumento tiene reflejo brilloso oscureciendo el texto
low_face_matchwarn / criticalSelfie y foto del documento no matchean
low_livenesswarnScore anti-spoofing debajo del threshold
low_doc_qualitywarnImagen del documento muy borrosa o de baja resolucion
expired_documentcriticalFecha de expiracion del documento ya paso
mrz_mismatchcriticalChecksum MRZ fallo (pasaporte potencialmente alterado)
name_mismatchwarnEl nombre enviado no hace fuzzy-match con el OCR
age_under_minimumcriticalEdad calculada debajo del minimo del tenant (default 18)

Patron de routing

La mayoria de los handlers de produccion routean por el tipo de evento:

async function handleVeridiaWebhook(payload) {
switch (payload.event) {
case 'verification.approved':
return handleApproved(payload);

case 'verification.rejected':
return handleRejected(payload);

case 'verification.review_required':
return handleReviewRequired(payload);

default:
// Future-proofing: loguea eventos desconocidos pero no falles
logger.warn('Tipo de evento Veridia desconocido', {
event: payload.event,
verificationId: payload.verificationId,
});
}
}

Podemos agregar tipos de evento nuevos en el futuro (ej. verification.expired, verification.refunded). Maneja tipos de evento desconocidos con gracia — loguea e ignora, no falles.

Eventos futuros (todavia no emitidos)

Estos estan documentados para compatibilidad futura. No escribas codigo que dependa de ellos todavia:

  • verification.expired — verificacion expiro sin completar
  • verification.refunded — credito refunded debido a error interno

Que sigue