Flujo de onboarding KYC
Implementa un flujo completo de verificación de identidad con captura de documentos, prueba de vida y comparación facial.
Visión general
El flujo de onboarding KYC de JAAK consiste en los siguientes pasos:
1. Crear sesión de verificación
Configura el flujo de verificación según tus necesidades:
const session = await jaak.verification.create({
type: 'full_kyc',
config: {
// Tipos de documento aceptados
documentTypes: ['ine', 'ine_reverso', 'passport'],
// Habilitar prueba de vida pasiva
livenessCheck: {
enabled: true,
type: 'passive' // 'passive' o 'active'
},
// Habilitar comparación facial
faceMatch: {
enabled: true,
threshold: 0.85 // Umbral de similitud (0-1)
},
// Consultar bases oficiales
officialSources: {
ine: true, // Validar en padrón INE
renapo: true, // Validar CURP
sat: false // Validar RFC
},
// Opciones de captura
capture: {
allowUpload: false, // Solo permitir cámara
quality: 'high',
retries: 3
}
},
// Datos del usuario (opcional)
userData: {
email: 'usuario@ejemplo.com',
phone: '+525512345678'
},
// Metadatos para tu sistema
metadata: {
userId: 'usr_abc123',
applicationId: 'app_xyz789'
},
// URL de redirección al terminar
redirectUrl: 'https://tuapp.com/onboarding/completado',
// Webhook para notificaciones
webhookUrl: 'https://tuapp.com/webhooks/jaak'
});2. Redirigir al usuario
Redirige al usuario a la URL de verificación. JAAK se encarga de toda la experiencia:
// En tu frontend
window.location.href = session.verificationUrl;
// O en React/Next.js
import { useRouter } from 'next/navigation';
const router = useRouter();
router.push(session.verificationUrl);Tip: También puedes embeber el flujo en un iframe o usar nuestro SDK de Web para una experiencia integrada.
3. Procesar resultados
Recibe el resultado de la verificación vía webhook:
{
"event": "verification.completed",
"timestamp": "2025-01-09T10:30:00Z",
"data": {
"sessionId": "ses_abc123",
"status": "approved", // approved, rejected, pending_review
"document": {
"type": "ine",
"number": "XXXX1234567890",
"name": "JUAN PEREZ GARCIA",
"birthDate": "1990-05-15",
"address": "CALLE EJEMPLO 123, CDMX",
"curp": "PEGJ900515HDFRRL09",
"claveElector": "PRGRJN90051509H800",
"validUntil": "2029-12-31",
"isValid": true,
"securityFeatures": {
"hologram": true,
"microprint": true,
"uvElements": true
}
},
"biometrics": {
"livenessScore": 0.98,
"livenessResult": "live",
"faceMatchScore": 0.95,
"faceMatchResult": "match"
},
"officialSources": {
"ine": {
"status": "valid",
"matchedFields": ["name", "curp", "photo"]
},
"renapo": {
"status": "valid",
"curpValid": true
}
},
"evidence": {
"documentFront": "https://evidence.jaak.ai/doc_front_xxx.jpg",
"documentBack": "https://evidence.jaak.ai/doc_back_xxx.jpg",
"selfie": "https://evidence.jaak.ai/selfie_xxx.jpg",
"livenessVideo": "https://evidence.jaak.ai/liveness_xxx.mp4"
},
"metadata": {
"userId": "usr_abc123",
"applicationId": "app_xyz789"
}
}
}4. Manejar los resultados
app.post('/webhooks/jaak', async (req, res) => {
const { event, data } = req.body;
if (event === 'verification.completed') {
const { sessionId, status, document, biometrics } = data;
switch (status) {
case 'approved':
// Verificación exitosa
await updateUserStatus(data.metadata.userId, 'verified');
await saveVerificationData(sessionId, document);
await sendWelcomeEmail(document.name);
break;
case 'rejected':
// Verificación rechazada
await updateUserStatus(data.metadata.userId, 'rejected');
await notifyRejection(data.metadata.userId, data.rejectionReason);
break;
case 'pending_review':
// Requiere revisión manual
await createReviewTask(sessionId, data);
break;
}
}
res.status(200).send('OK');
});Mejores prácticas
- Siempre valida la firma HMAC del webhook antes de procesar
- Guarda el sessionId para consultas futuras y auditorías
- Implementa idempotencia en tu endpoint de webhook
- Usa el ambiente sandbox para pruebas antes de producción