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
| Evento | Verdict | Cuando se dispara |
|---|---|---|
verification.approved | approved | Score de confianza arriba del threshold de aprobacion, sin flags criticos |
verification.rejected | rejected | Confianza debajo del threshold de rechazo, o flag critico disparado |
verification.review_required | review | Confianza 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:
| Campo | Tipo | Siempre | Descripcion |
|---|---|---|---|
event | string | Si | Tipo de evento — switcha en este en tu handler |
verificationId | string | Si | ID unico de /init (formato: vf_*) |
tenantId | string | Si | Tu tenant ID (util para routing multi-tenant) |
userRef | string | null | Si | El userRef que pasaste a /init, o null si no |
verdict | string | Si | approved, review, o rejected |
confidence | number | Si | Score general ponderado de confianza (0-100) |
scores | object | Si | Breakdown de senales individuales |
flags | array | Si | Flags de calidad / riesgo levantados. Vacio [] cuando esta limpio |
metadata | object | Si | El metadata que pasaste a /submit, o {} |
submittedAt | string | Si | Timestamp ISO 8601 cuando se llamo a /submit |
completedAt | string | Si | Timestamp 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:
| Campo | Rango | Descripcion |
|---|---|---|
ocrConfidence | 0-100 | Confianza VLM auto-reportada en extraccion de texto del documento |
faceMatch | 0-100 | Similitud biometrica entre selfie y foto del documento |
liveness | 0-100 | Anti-spoofing — confirma que es una persona viva, no foto |
docQuality | 0-100 | Calidad 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:
| Nivel | Significado |
|---|---|
info | FYI para revisores, no afecta el veredicto por si solo |
warn | Issue notable — contribuye a confianza bajada |
critical | Falla dura — empuja el veredicto a rejected sin importar las otras senales |
Flags comunes que podes ver en el array flags:
| Flag | Nivel | Significado |
|---|---|---|
heavy_glare | warn | Documento tiene reflejo brilloso oscureciendo el texto |
low_face_match | warn / critical | Selfie y foto del documento no matchean |
low_liveness | warn | Score anti-spoofing debajo del threshold |
low_doc_quality | warn | Imagen del documento muy borrosa o de baja resolucion |
expired_document | critical | Fecha de expiracion del documento ya paso |
mrz_mismatch | critical | Checksum MRZ fallo (pasaporte potencialmente alterado) |
name_mismatch | warn | El nombre enviado no hace fuzzy-match con el OCR |
age_under_minimum | critical | Edad 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 completarverification.refunded— credito refunded debido a error interno
Que sigue
- Ejemplos — implementaciones completas de handler
- Verificacion de firma — referencia de algoritmo
- Webhooks overview — volver al overview