JAAK KYC Mosaic Web


1. Introducción

JAAK KYC Mosaic Web es una solución completa de verificación de identidad que permite integrar procesos de KYC (Know Your Customer) en aplicaciones web de manera rápida y segura. Esta guía está diseñada para ayudarle a elegir e implementar la modalidad de integración que mejor se adapte a sus necesidades.

¿Qué es JAAK KYC Mosaic?

JAAK KYC Mosaic es una plataforma de verificación de identidad que ofrece:

  • Extracción automática de datos de documentos de identidad
  • Verificación de autenticidad de documentos
  • Verificación de identidad facial en vivo
  • Comparación facial One-to-One (OTO)
  • Verificación contra listas negras

Beneficios principales

  • Integración flexible: 3 modalidades para diferentes casos de uso
  • Implementación rápida: Desde minutos hasta horas según la modalidad
  • Alta precisión: 99% de exactitud en verificaciones
  • Seguridad robusta: Autenticación con API Keys y comunicación HTTPS
  • Soporte completo: Documentación detallada y equipo de soporte técnico

2. Modalidades de Integración

JAAK KYC Mosaic ofrece tres modalidades de integración para adaptarse a diferentes necesidades y casos de uso. A continuación se presenta una comparación para ayudarle a elegir la mejor opción:

ModalidadCasos de UsoComplejidad
Embed (iframe)Integración rápida sin salir del sitio. Control total del layout.⭐⭐ Media
Direct (nueva pestaña)Experiencia pantalla completa. Apps móviles nativas.⭐⭐ Media
Link (URLs)Campañas email/SMS. Enlaces compartidos. Cero código.⭐ Baja

2.1 Modalidad Embed (iframe)

La modalidad Embed integra el flujo KYC completo dentro de un iframe en su página web, manteniendo al usuario en su dominio durante todo el proceso.

Ventajas:

  • Integración rápida (minutos a horas)
  • Usuario permanece en su sitio web
  • Comunicación bidireccional en tiempo real
  • Control total del posicionamiento y diseño

Cuándo usar Embed:

  • Necesita mantener al usuario en su dominio
  • Requiere control del flujo de usuario
  • Quiere personalizar el contenedor del iframe

2.2 Modalidad Direct (nueva pestaña)

La modalidad Direct abre el flujo KYC en una ventana separada o nueva pestaña, ofreciendo una experiencia de pantalla completa optimizada.

Ventajas:

  • Máximo rendimiento (sin overhead de iframe)
  • Experiencia de usuario fluida
  • Perfecto para aplicaciones móviles (WebView)
  • Soporte completo de todos los pasos KYC

Cuándo usar Direct:

  • Necesita máximo rendimiento
  • Integra en aplicaciones móviles nativas
  • Prefiere flujo independiente sin embedding

2.3 Modalidad Link (URLs)

La modalidad Link permite generar URLs autocontenidas que incluyen toda la configuración necesaria. Es la opción más simple y no requiere código del lado del cliente.

Ventajas:

  • Cero código del lado del cliente
  • Perfecto para campañas de email/SMS
  • URLs compartibles y autocontenidas
  • Implementación inmediata

Cuándo usar Link:

  • Campañas automatizadas de verificación
  • Envío de enlaces por email, SMS o WhatsApp
  • Códigos QR para verificación
  • No tiene recursos de desarrollo

3. Prerrequisitos

3.1 Requisitos técnicos

RequisitoEspecificación
NavegadorChrome 80+, Firefox 75+, Safari 13+, Edge 80+
HTTPSObligatorio en producción (requerido para cámara)
JavaScriptES6+ (para Embed y Direct)
API KeyProporcionada por JAAK (requerida para crear sesiones)
Short KeyGenerado automáticamente al crear sesión

3.2 Obtener su API Key

La API Key es un token de autenticación único que permite a su aplicación crear sesiones de verificación en JAAK KYC.

Pasos para obtener su API Key:

  1. Acceda a su Dashboard de JAAK

  2. Navegue a la sección de API

    • En el menú lateral, seleccione "API Keys" o "Configuración"
    • Encontrará su API Key en la sección de credenciales
  3. Copie su API Key

    • Haga clic en "Copiar" o seleccione el token completo
    • Guárdelo en un lugar seguro

⚠️ Importante sobre seguridad:

  • Mantenga su API Key segura y nunca la exponga en código del lado del cliente
  • No la comparta públicamente ni la incluya en repositorios de código abierto
  • Use variables de entorno para almacenarla
  • Rote sus claves periódicamente para mayor seguridad
  • La API Key debe usarse únicamente en su backend

4. Autenticación

Todas las llamadas a la API de JAAK requieren autenticación mediante un Bearer Token que se incluye en el header Authorization.

Formato de autenticación

Authorization: Bearer YOUR_API_KEY

Ejemplo de header completo

POST /api/v1/kyc/flow HTTP/1.1
Host: sandbox.kyc.jaak.ai
Content-Type: application/json
Authorization: Bearer sk_test_abc123xyz456def789...

Ambientes disponibles

AmbienteURL BaseUso
Sandboxhttps://sandbox.kyc.jaak.aiDesarrollo y pruebas
Producciónhttps://kyc.jaak.aiAplicaciones en vivo

⚠️ Importante: Siempre pruebe en ambiente Sandbox antes de migrar a producción.


5. Proceso para Crear una Sesión KYC

El flujo para iniciar una verificación KYC consta de los siguientes pasos:

Paso 1: Crear Sesión KYC

Inicializa una nueva sesión de verificación para un cliente desde su backend.

Endpoint

POST /api/v1/kyc/flow

Headers requeridos

Content-Type: application/json
Authorization: Bearer YOUR_API_KEY

Request Body

{
  "name": "María González Pérez",
  "flow": "Cliente-001-Onboarding",
  "redirectUrl": "https://tu-empresa.com/kyc-completado",
  "countryDocument": "MEX",
  "flowType": "KYC",
  "verificationType": "email",
  "verification": {
    "SMS": "",
    "EMAIL": "[email protected]",
    "WHATSAPP": ""
  }
}

Parámetros detallados

CampoTipoRequeridoDescripciónEjemplo
namestringNombre completo del cliente"María González Pérez"
flowstringIdentificador único de la sesión"Cliente-001-Onboarding"
redirectUrlstringURL donde redirigir al finalizar"https://tu-empresa.com/success"
countryDocumentstringPaís del documento (código Alpha-3)"MEX", "USA", "COL"
flowTypestringTipo de verificación"KYC"
verificationTypestringMétodo de notificación"email", "whatsapp", "sms", ""
verificationobjectDatos de contacto según método elegidoVer opciones abajo

Opciones de notificación

MétodoCampo requeridoFormatoEjemplo
Emailverification.EMAILemail válido"[email protected]"
WhatsAppverification.WHATSAPP+[código país][número]"+525551234567"
SMSverification.SMS+[código país][número]"+525551234567"
ManualDejar verificationType vacío--

Response esperado

{
  "sessionUrl": "https://sandbox.kyc.jaak.ai/session/ABC123X"
}

💡 Nota: El shortKey se extrae de la URL de sesión: ABC123X (últimos 7 caracteres)

Ejemplo completo con cURL

curl -X POST https://sandbox.kyc.jaak.ai/api/v1/kyc/flow \
  -H "Authorization: Bearer sk_test_abc123xyz456..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "María González Pérez",
    "flow": "Cliente-001-Onboarding",
    "redirectUrl": "https://tu-empresa.com/kyc-completado",
    "countryDocument": "MEX",
    "flowType": "KYC",
    "verificationType": "email",
    "verification": {
      "SMS": "",
      "EMAIL": "[email protected]",
      "WHATSAPP": ""
    }
  }'

Ejemplo con JavaScript (Node.js)

async function createKYCSession(clientData) {
  try {
    const response = await fetch('https://sandbox.kyc.jaak.ai/api/v1/kyc/flow', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${process.env.JAAK_API_KEY}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        name: clientData.name,
        flow: clientData.flow,
        redirectUrl: clientData.redirectUrl,
        countryDocument: 'MEX',
        flowType: 'KYC',
        verificationType: 'email',
        verification: {
          SMS: '',
          EMAIL: clientData.email,
          WHATSAPP: ''
        }
      })
    });

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const data = await response.json();
    return data;
  } catch (error) {
    console.error('Error creating KYC session:', error);
    throw error;
  }
}

// Uso
const sessionData = await createKYCSession({
  name: 'María González Pérez',
  flow: 'Cliente-001-Onboarding',
  email: '[email protected]',
  redirectUrl: 'https://tu-empresa.com/kyc-completado'
});

console.log('Session URL:', sessionData.sessionUrl);

Paso 2: Extraer el ShortKey

El shortKey es el identificador de 7 caracteres que se encuentra al final de la URL de sesión.

Ejemplo de extracción

URL de sesión: https://sandbox.kyc.jaak.ai/session/ABC123X
                                                    ↑
                                              ShortKey: ABC123X

Función de extracción en JavaScript

function extractShortKey(sessionUrl) {
  // sessionUrl: "https://sandbox.kyc.jaak.ai/session/ABC123X"
  const parts = sessionUrl.split('/');
  return parts[parts.length - 1]; // "ABC123X"
}

// Uso
const sessionUrl = "https://sandbox.kyc.jaak.ai/session/ABC123X";
const shortKey = extractShortKey(sessionUrl);
console.log(shortKey); // "ABC123X"

📌 Nota importante: El shortKey se genera automáticamente y no es personalizable.

Paso 3: Configurar el flujo KYC

Define qué pasos de verificación quieres incluir en tu flujo personalizado utilizando el shortKey obtenido.

Configuración para modalidades Embed y Direct

const config = {
  steps: [
    { key: 'DOCUMENT_EXTRACT' },
    { key: 'DOCUMENT_VERIFY' },
    { key: 'IVERIFICATION' }
  ],
  shortKey: 'ABC123X'  // El shortKey obtenido en el paso 2
};

Configuración para modalidad Link

Formato de URL con pasos:

https://mosaic.sandbox.jaak.ai/link?shortKey=ABC123X&steps=DOCUMENT_EXTRACT,DOCUMENT_VERIFY,IVERIFICATION

Parámetros de URL:

  • shortKey: Tu código de sesión (requerido)
  • steps: Pasos separados por comas en orden de ejecución
  • redirectUrl: URL donde redirigir al completar (opcional)

Ejemplo completo de URL

https://mosaic.sandbox.jaak.ai/link?shortKey=ABC123X&steps=DOCUMENT_EXTRACT,DOCUMENT_VERIFY,IVERIFICATION,OTO&redirectUrl=https://mi-app.com/success

Flujo completo de integración (ejemplo práctico)

// ====================================
// BACKEND: Crear sesión y obtener shortKey
// ====================================
async function initializeKYCSession(userData) {
  // Paso 1: Crear sesión en el backend
  const session = await fetch('https://sandbox.kyc.jaak.ai/api/v1/kyc/flow', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.JAAK_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      name: userData.name,
      flow: `user-${userData.id}-${Date.now()}`,
      redirectUrl: 'https://tu-empresa.com/kyc-success',
      countryDocument: 'MEX',
      flowType: 'KYC',
      verificationType: 'email',
      verification: {
        SMS: '',
        EMAIL: userData.email,
        WHATSAPP: ''
      }
    })
  });

  const data = await session.json();
  
  // Paso 2: Extraer shortKey de la URL
  const shortKey = extractShortKey(data.sessionUrl);
  
  return { shortKey, sessionUrl: data.sessionUrl };
}

function extractShortKey(sessionUrl) {
  const parts = sessionUrl.split('/');
  return parts[parts.length - 1];
}

// ====================================
// FRONTEND: Usar shortKey en tu integración
// ====================================
async function startKYCVerification(userId, userName, userEmail) {
  try {
    // Llamar a tu backend para crear sesión
    const response = await fetch('/api/kyc/create-session', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        userId: userId,
        name: userName,
        email: userEmail
      })
    });
    
    const { shortKey } = await response.json();
    
    // Opción A: Usar con Embed (iframe)
    const embedConfig = {
      steps: [
        { key: 'DOCUMENT_EXTRACT' },
        { key: 'DOCUMENT_VERIFY' },
        { key: 'IVERIFICATION' }
      ],
      shortKey: shortKey
    };
    
    document.getElementById('kycMosaic').contentWindow.postMessage({
      type: 'CONFIG',
      data: embedConfig
    }, '*');
    
    // Opción B: Generar Link para campaña
    const kycLink = `https://mosaic.sandbox.jaak.ai/link?shortKey=${shortKey}&steps=DOCUMENT_EXTRACT,DOCUMENT_VERIFY,IVERIFICATION`;
    console.log('Link de verificación:', kycLink);
    
    // Opción C: Abrir en Direct mode
    const directUrl = `https://mosaic.sandbox.jaak.ai/direct`;
    const directWindow = window.open(directUrl, 'kyc', 'width=800,height=600');
    
    // Esperar señal READY y enviar config
    window.addEventListener('message', function(event) {
      if (event.data.type === 'READY' && directWindow) {
        directWindow.postMessage({
          type: 'CONFIG',
          data: embedConfig
        }, '*');
      }
    });
    
  } catch (error) {
    console.error('Error al iniciar KYC:', error);
    alert('No se pudo iniciar la verificación. Intente nuevamente.');
  }
}

6. Pasos del Flujo KYC

JAAK KYC Mosaic ofrece diferentes pasos que puede configurar según sus necesidades. Los pasos se ejecutan en el orden que usted especifique.

PasoDescripción
WELCOMEPantalla de bienvenida con instrucciones
DOCUMENT_EXTRACTCaptura y extracción de datos del documento de identidad
DOCUMENT_VERIFYVerificación de autenticidad del documento
BLACKLISTVerificación contra listas negras de seguridad
IVERIFICATIONVerificación de identidad facial en vivo (liveness)
LOCATION_PERMISSIONSSolicitud de permisos de geolocalización
OTOComparación facial One-to-One (documento vs. rostro en vivo)
FINISHPantalla de finalización exitosa

⚠️ Importante: El paso OTO requiere que se hayan ejecutado previamente DOCUMENT_EXTRACT (para la foto del documento) e IVERIFICATION (para la foto en vivo). Si estos pasos se ejecutaron en sesiones anteriores, Mosaic obtiene las imágenes automáticamente.

Ejemplo de configuración de pasos

const config = {
  steps: [
    { key: 'WELCOME' },
    { key: 'DOCUMENT_EXTRACT' },
    { key: 'DOCUMENT_VERIFY' },
    { key: 'IVERIFICATION' },
    { key: 'OTO' },
    { key: 'FINISH' }
  ],
  shortKey: 'ABC123X'
};

7. Guías de Implementación

7.1 Implementación Embed (iframe)

Paso 1: Agregar el iframe a su página

<iframe 
  id="kycMosaic" 
  src="https://mosaic.sandbox.jaak.ai/"
  width="100%" 
  height="600"
  allow="camera; geolocation">
</iframe>

Paso 2: Configurar y enviar configuración

const config = {
  steps: [
    { key: 'DOCUMENT_EXTRACT' },
    { key: 'DOCUMENT_VERIFY' },
    { key: 'IVERIFICATION' }
  ],
  shortKey: 'ABC123X'  // shortKey obtenido de la API
};

document.getElementById('kycMosaic')
  .contentWindow.postMessage({
    type: 'CONFIG',
    data: config
  }, '*');

Paso 3: Escuchar eventos

window.addEventListener('message', function(event) {
  switch(event.data.type) {
    case 'FLOW_COMPLETE':
      console.log('KYC completado', event.data);
      // Procesar resultados
      break;
      
    case 'ERROR':
      console.error('Error', event.data);
      // Manejar error
      break;
  }
});

7.2 Implementación Direct (nueva pestaña)

Paso 1: Abrir ventana Direct

let directWindow = null;

function openDirectKYC() {
  const url = 'https://mosaic.sandbox.jaak.ai/direct';
  const features = 'width=800,height=600';
  
  directWindow = window.open(url, 'kyc', features);
}

Paso 2: Esperar señal READY y enviar configuración

window.addEventListener('message', function(event) {
  if (event.data.type === 'READY') {
    const config = {
      steps: [
        { key: 'DOCUMENT_EXTRACT' },
        { key: 'IVERIFICATION' }
      ],
      shortKey: 'ABC123X'  // shortKey obtenido de la API
    };
    
    directWindow.postMessage({
      type: 'CONFIG',
      data: config
    }, '*');
  }
});

Paso 3: Manejar eventos

window.addEventListener('message', function(event) {
  switch(event.data.type) {
    case 'FLOW_COMPLETE':
      console.log('KYC completado en Direct', event.data);
      break;
      
    case 'ERROR':
      console.error('Error en Direct', event.data);
      break;
  }
});

7.3 Implementación Link (URLs)

La modalidad Link es la más simple: solo necesita generar una URL con los parámetros adecuados.

Formato de URL

https://mosaic.sandbox.jaak.ai/link?shortKey=ABC123X&steps=DOCUMENT_EXTRACT,IVERIFICATION

Parámetros disponibles

ParámetroDescripción
shortKeySu código de sesión (requerido)
stepsPasos separados por comas en orden de ejecución
redirectUrlURL donde redirigir al completar (opcional)

Ejemplo completo

https://mosaic.sandbox.jaak.ai/link?shortKey=ABC123X&steps=DOCUMENT_EXTRACT,DOCUMENT_VERIFY,IVERIFICATION,OTO&redirectUrl=https://mi-app.com/success

Generación programática

function generateKYCLink(shortKey, steps, redirectUrl) {
  const baseUrl = 'https://mosaic.sandbox.jaak.ai/link';
  const params = new URLSearchParams({
    shortKey: shortKey,
    steps: steps.join(',')
  });
  
  if (redirectUrl) {
    params.append('redirectUrl', redirectUrl);
  }
  
  return `${baseUrl}?${params.toString()}`;
}

// Uso
const link = generateKYCLink(
  'ABC123X',
  ['DOCUMENT_EXTRACT', 'IVERIFICATION', 'OTO'],
  'https://mi-app.com/success'
);

console.log(link);

8. Eventos y Respuestas

Las modalidades Embed y Direct envían eventos mediante postMessage para informar sobre el progreso del flujo KYC.

8.1 Eventos principales

EventoDescripción
READYMosaic está listo para recibir configuración
STEP_COMPLETEUn paso individual fue completado exitosamente
FLOW_COMPLETEEl flujo KYC completo fue finalizado exitosamente
ERROROcurrió un error durante el proceso
SESSION_EXPIREDLa sesión expiró por inactividad (14 minutos)

8.2 Ejemplo de manejo de eventos

window.addEventListener('message', function(event) {
  const message = event.data;
  
  switch(message.type) {
    case 'READY':
      console.log('Mosaic listo');
      // Enviar configuración
      break;
      
    case 'STEP_COMPLETE':
      console.log('Paso completado:', message.data.stepKey);
      console.log('Datos del paso:', message.data.data);
      // Guardar datos del paso si es necesario
      break;
      
    case 'FLOW_COMPLETE':
      console.log('KYC completado exitosamente');
      console.log('Datos finales:', message.data);
      // Procesar resultados finales
      break;
      
    case 'ERROR':
      console.error('Error en KYC:', message.data.error);
      console.error('Mensaje:', message.data.message);
      // Mostrar mensaje de error al usuario
      break;
      
    case 'SESSION_EXPIRED':
      console.warn('Sesión expirada');
      // Reiniciar flujo o mostrar mensaje
      break;
  }
});

Estructura de datos en eventos

STEP_COMPLETE

{
  type: 'STEP_COMPLETE',
  data: {
    stepKey: 'DOCUMENT_EXTRACT',
    data: {
      face: 'data:image/jpeg;base64,...'
      // Datos específicos del paso
    }
  }
}

FLOW_COMPLETE

{
  type: 'FLOW_COMPLETE',
  data: {
    completedSteps: ['DOCUMENT_EXTRACT', 'IVERIFICATION', 'OTO'],
    allData: {
      DOCUMENT_EXTRACT: { /* datos */ },
      IVERIFICATION: { /* datos */ },
      OTO: { /* datos */ }
    }
  }
}

ERROR

{
  type: 'ERROR',
  data: {
    error: 'AUTHENTICATION_FAILED',
    message: 'Invalid shortKey provided'
  }
}

9. Solución de Problemas

9.1 Problemas comunes

El iframe no carga

Soluciones:

  • Verifique que el atributo allow incluya camera y geolocation
  • Confirme que está usando HTTPS en producción
  • Revise la consola del navegador para errores CORS
<!-- Configuración correcta del iframe -->
<iframe 
  id="kycMosaic" 
  src="https://mosaic.sandbox.jaak.ai/"
  allow="camera; geolocation"
  width="100%" 
  height="600">
</iframe>

Error de autenticación

Posibles causas y soluciones:

  • API Key incorrecta: Verifique que su API Key sea correcta y esté actualizada
  • API Key expirada: Contacte a soporte si su API Key ha expirado
  • ShortKey inválido: Asegúrese de extraer correctamente el shortKey de la URL de sesión
  • Ambiente incorrecto: Verifique que esté usando las URLs correctas (sandbox vs producción)
// Verificar que la API Key esté correctamente configurada
const API_KEY = process.env.JAAK_API_KEY;
if (!API_KEY || API_KEY.trim() === '') {
  console.error('API Key no configurada');
}

OTO falla por imágenes faltantes

Soluciones:

  • Asegúrese de ejecutar DOCUMENT_EXTRACT antes de OTO
  • Asegúrese de ejecutar IVERIFICATION antes de OTO
  • Alternativamente, proporcione las imágenes manualmente:
const config = {
  steps: [
    { 
      key: 'OTO',
      data: {
        face: 'data:image/jpeg;base64,...',        // Imagen del documento
        bestFrame: 'data:image/jpeg;base64,...'   // Imagen de liveness
      }
    }
  ],
  shortKey: 'ABC123X'
};

Ventana Direct bloqueada

Soluciones:

  • Asegúrese de que la apertura ocurra por interacción del usuario (click)
  • Verifique la configuración del bloqueador de popups
  • Agregue instrucciones al usuario para permitir popups
// Buena práctica: abrir desde un evento de click
button.addEventListener('click', function() {
  openDirectKYC();
});

PostMessage no funciona

Soluciones:

  • Verifique que está escuchando eventos en la ventana correcta
  • Confirme que el origen del mensaje es el esperado
  • Revise la consola para mensajes de error
window.addEventListener('message', function(event) {
  // Validar origen en producción
  // if (event.origin !== 'https://mosaic.jaak.ai') return;
  
  console.log('Mensaje recibido:', event.data);
});

9.2 Sesión expirada

Las sesiones de JAAK KYC Mosaic expiran después de 14 minutos de inactividad. Cuando esto ocurre:

  • Se envía un evento SESSION_EXPIRED
  • Se muestra un mensaje al usuario en la interfaz
  • Puede reiniciar el flujo enviando una nueva configuración

Manejo recomendado

window.addEventListener('message', function(event) {
  if (event.data.type === 'SESSION_EXPIRED') {
    console.warn('Sesión expirada');
    
    // Opción 1: Reiniciar automáticamente
    setTimeout(() => {
      sendConfiguration();
    }, 2000);
    
    // Opción 2: Mostrar mensaje y esperar acción del usuario
    // showModal('Su sesión ha expirado. ¿Desea reiniciar?');
  }
});

💡 Recomendación: Implemente un reinicio automático del flujo al recibir SESSION_EXPIRED para mejorar la experiencia del usuario.


10. Mejores Prácticas

10.1 Seguridad

Proteja su API Key

  • NUNCA la incluya en código del lado del cliente
  • ✅ Use variables de entorno o servicios de backend
  • ✅ Rote las claves periódicamente
  • ✅ Almacénela en gestores de secretos (AWS Secrets Manager, Azure Key Vault, etc.)
// ❌ MAL - API Key expuesta en frontend
const apiKey = 'sk_live_abc123xyz456...';

// ✅ BIEN - API Key en backend con variable de entorno
const apiKey = process.env.JAAK_API_KEY;

Valide el origen de mensajes (producción)

window.addEventListener('message', function(event) {
  // Validar origen en producción
  if (event.origin !== 'https://mosaic.jaak.ai') {
    console.warn('Mensaje de origen no confiable');
    return;
  }
  // Procesar mensaje
});

Use HTTPS siempre

  • Obligatorio para acceso a cámara
  • Protege la transmisión de datos sensibles
  • Requerido por navegadores modernos

10.2 Experiencia de Usuario

Proporcione instrucciones claras

  • Explique qué documentos se necesitan
  • Indique los pasos del proceso
  • Muestre tiempo estimado de completación

Manejo de errores amigable

function handleKYCError(error) {
  const friendlyMessages = {
    'AUTHENTICATION_FAILED': 'No pudimos verificar su sesión. Por favor intente nuevamente.',
    'CAMERA_ACCESS_DENIED': 'Necesitamos acceso a su cámara para continuar.',
    'DOCUMENT_NOT_DETECTED': 'No pudimos detectar el documento. Por favor intente de nuevo.',
    'SESSION_EXPIRED': 'Su sesión ha expirado. Por favor reinicie el proceso.'
  };
  
  const message = friendlyMessages[error.error] || 'Ocurrió un error. Por favor intente nuevamente.';
  showUserMessage(message);
}

Indicadores de progreso

window.addEventListener('message', function(event) {
  if (event.data.type === 'STEP_COMPLETE') {
    updateProgressBar(event.data.stepKey);
  }
});

10.3 Rendimiento

Precargue el iframe (Embed)

<!-- Precargar en el head -->
<link rel="preconnect" href="https://mosaic.sandbox.jaak.ai">

Maneje timeout de carga

let iframeLoaded = false;

setTimeout(() => {
  if (!iframeLoaded) {
    showError('El servicio está tardando más de lo usual. Por favor recargue la página.');
  }
}, 10000); // 10 segundos

10.4 Testing

Ambiente de pruebas

  • Use https://mosaic.sandbox.jaak.ai/ para pruebas
  • Solicite API Keys de prueba separadas
  • Pruebe todos los flujos antes de producción

Casos de prueba recomendados

  • ✅ Flujo completo exitoso
  • ✅ Cancelación por usuario
  • ✅ Pérdida de conexión
  • ✅ Timeout de sesión
  • ✅ Diferentes navegadores y dispositivos
  • ✅ Errores de validación de documentos

11. Migración a Producción

11.1 Checklist pre-producción

  • API Key de producción obtenida
  • URL actualizada a https://mosaic.jaak.ai/
  • HTTPS configurado en su dominio
  • Validación de origen implementada
  • Manejo de errores completo
  • Testing en navegadores principales
  • Testing en dispositivos móviles
  • Documentación de integración revisada
  • Plan de rollback preparado
  • Monitoreo y logs configurados

11.2 Configuración de producción

// Configuración de producción recomendada
const PRODUCTION_CONFIG = {
  mosaicUrl: 'https://mosaic.jaak.ai/',
  apiUrl: 'https://kyc.jaak.ai/api/v1',
  apiKey: process.env.JAAK_API_KEY_PROD,
  allowedOrigins: ['https://mosaic.jaak.ai'],
  timeout: 900000, // 15 minutos
  retryAttempts: 3
};

// Uso seguro en producción
function initKYC() {
  if (!PRODUCTION_CONFIG.apiKey) {
    console.error('API Key no configurada');
    return;
  }
  
  // Continuar con inicialización...
}

12. Ejemplos de Casos de Uso

Caso 1: Onboarding de clientes (Embed)

<!DOCTYPE html>
<html>
<head>
  <title>Onboarding - Mi App</title>
  <style>
    #kycContainer {
      max-width: 800px;
      margin: 0 auto;
      padding: 20px;
    }
  </style>
</head>
<body>
  <div id="kycContainer">
    <h1>Verificación de Identidad</h1>
    <p>Complete el proceso de verificación para activar su cuenta</p>
    
    <iframe 
      id="kycMosaic" 
      src="https://mosaic.sandbox.jaak.ai/"
      width="100%" 
      height="600"
      allow="camera; geolocation">
    </iframe>
  </div>

  <script>
    // Obtener shortKey desde el backend
    async function getShortKey() {
      const response = await fetch('/api/kyc/create-session', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          userId: 'user123',
          name: 'Juan Pérez',
          email: '[email protected]'
        })
      });
      const data = await response.json();
      return data.shortKey;
    }

    // Configurar KYC
    async function initializeKYC() {
      const shortKey = await getShortKey();
      
      const config = {
        steps: [
          { key: 'WELCOME' },
          { key: 'DOCUMENT_EXTRACT' },
          { key: 'DOCUMENT_VERIFY' },
          { key: 'IVERIFICATION' },
          { key: 'OTO' }
        ],
        shortKey: shortKey
      };

      setTimeout(() => {
        document.getElementById('kycMosaic')
          .contentWindow.postMessage({
            type: 'CONFIG',
            data: config
          }, '*');
      }, 1000);
    }

    // Manejar eventos
    window.addEventListener('message', function(event) {
      if (event.data.type === 'FLOW_COMPLETE') {
        window.location.href = '/dashboard?verified=true';
      }
    });

    // Iniciar cuando cargue la página
    window.addEventListener('load', initializeKYC);
  </script>
</body>
</html>

Caso 2: Verificación móvil (Direct)

class KYCVerification {
  constructor(apiEndpoint) {
    this.apiEndpoint = apiEndpoint;
    this.directWindow = null;
    this.setupMessageListener();
  }

  setupMessageListener() {
    window.addEventListener('message', (event) => {
      this.handleMessage(event.data);
    });
  }

  async open(userId, userName, userEmail) {
    try {
      // Obtener shortKey del backend
      const shortKey = await this.getShortKey(userId, userName, userEmail);
      
      const url = 'https://mosaic.sandbox.jaak.ai/direct';
      const features = 'width=800,height=600,scrollbars=yes,resizable=yes';
      
      this.directWindow = window.open(url, 'kycVerification', features);
      
      if (!this.directWindow) {
        alert('Por favor permita ventanas emergentes para continuar');
        return false;
      }
      
      this.shortKey = shortKey;
      return true;
    } catch (error) {
      console.error('Error al abrir KYC:', error);
      return false;
    }
  }

  async getShortKey(userId, userName, userEmail) {
    const response = await fetch(`${this.apiEndpoint}/create-session`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        userId: userId,
        name: userName,
        email: userEmail
      })
    });
    
    const data = await response.json();
    return data.shortKey;
  }

  handleMessage(message) {
    switch(message.type) {
      case 'READY':
        this.sendConfiguration();
        break;
        
      case 'FLOW_COMPLETE':
        this.onComplete(message.data);
        break;
        
      case 'ERROR':
        this.onError(message.data);
        break;
    }
  }

  sendConfiguration() {
    if (this.directWindow && !this.directWindow.closed) {
      this.directWindow.postMessage({
        type: 'CONFIG',
        data: {
          steps: [
            { key: 'DOCUMENT_EXTRACT' },
            { key: 'IVERIFICATION' },
            { key: 'OTO' }
          ],
          shortKey: this.shortKey
        }
      }, '*');
    }
  }

  onComplete(data) {
    console.log('Verificación completada', data);
    this.saveResults(data);
  }

  onError(error) {
    console.error('Error en verificación', error);
    alert('Hubo un error en la verificación. Por favor intente nuevamente.');
  }

  async saveResults(data) {
    try {
      const response = await fetch(`${this.apiEndpoint}/save-results`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(data)
      });
      
      if (response.ok) {
        window.location.href = '/verification-success';
      }
    } catch (error) {
      console.error('Error guardando resultados', error);
    }
  }
}

// Uso
const kycBtn = document.getElementById('startKYC');
kycBtn.addEventListener('click', async function() {
  const kyc = new KYCVerification('/api/kyc');
  await kyc.open('user456', 'María González', '[email protected]');
});

Caso 3: Campaña de email (Link)

// Script backend para generar enlaces de campaña
async function generateCampaignLinks(campaign, recipients) {
  const baseUrl = 'https://mosaic.sandbox.jaak.ai/link';
  
  const links = await Promise.all(
    recipients.map(async (recipient) => {
      // Crear sesión para cada destinatario
      const session = await fetch('https://sandbox.kyc.jaak.ai/api/v1/kyc/flow', {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${process.env.JAAK_API_KEY}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          name: recipient.name,
          flow: `${campaign.id}-${recipient.id}`,
          redirectUrl: `https://mi-app.com/campaign-complete?user=${recipient.id}&campaign=${campaign.id}`,
          countryDocument: 'MEX',
          flowType: 'KYC',
          verificationType: 'email',
          verification: {
            SMS: '',
            EMAIL: recipient.email,
            WHATSAPP: ''
          }
        })
      });
      
      const data = await session.json();
      const shortKey = extractShortKey(data.sessionUrl);
      
      const params = new URLSearchParams({
        shortKey: shortKey,
        steps: 'DOCUMENT_EXTRACT,DOCUMENT_VERIFY,IVERIFICATION',
        redirectUrl: `https://mi-app.com/campaign-complete?user=${recipient.id}&campaign=${campaign.id}`
      });
      
      return {
        recipient: recipient.email,
        name: recipient.name,
        link: `${baseUrl}?${params.toString()}`
      };
    })
  );
  
  return links;
}

function extractShortKey(sessionUrl) {
  const parts = sessionUrl.split('/');
  return parts[parts.length - 1];
}

// Generar enlaces para campaña
const campaign = {
  id: 'onboarding-q1-2025',
  name: 'Onboarding Q1 2025'
};

const recipients = [
  { id: 'user123', name: 'Juan Pérez', email: '[email protected]' },
  { id: 'user456', name: 'María González', email: '[email protected]' }
];

const campaignLinks = await generateCampaignLinks(campaign, recipients);

// Enviar emails
campaignLinks.forEach(item => {
  sendEmail({
    to: item.recipient,
    subject: 'Complete su verificación de identidad',
    html: `
      <h2>Hola ${item.name},</h2>
      <p>Para completar su registro, por favor complete el proceso de verificación
      haciendo clic en el siguiente botón:</p>
      <a href="${item.link}" style="background: #0066cc; color: white; padding: 10px 20px; text-decoration: none; border-radius: 5px;">
        Verificar mi identidad
      </a>
      <p>Este enlace es válido por 30 días.</p>
      <p>Saludos,<br>Equipo de Mi App</p>
    `
  });
});

console.log('Enlaces de campaña generados:', campaignLinks);

13. FAQ - Preguntas Frecuentes

¿Cuánto tiempo dura una sesión de KYC? Las sesiones tienen una duración de 14 minutos de inactividad. Después de este tiempo, la sesión expira y debe reiniciarse.

¿Puedo personalizar la apariencia de Mosaic? La modalidad Embed permite controlar el contenedor del iframe. El contenido interno de Mosaic no es personalizable para mantener consistencia y seguridad.

¿Qué documentos son soportados? JAAK KYC Mosaic soporta INE, pasaportes mexicanos, y otros documentos de identidad oficiales. Contacte a soporte para la lista completa.

¿Funciona en todos los navegadores? Sí, funciona en navegadores modernos (Chrome 80+, Firefox 75+, Safari 13+, Edge 80+) que soporten acceso a cámara.

¿Puedo usar Mosaic sin internet? No, Mosaic requiere conexión a internet activa para funcionar correctamente.

¿Los datos están seguros? Sí, todas las comunicaciones utilizan HTTPS y los datos son procesados siguiendo estándares de seguridad internacionales.

¿Puedo ejecutar pasos de forma independiente? Sí, puede configurar cualquier combinación de pasos. Algunos pasos como OTO requieren datos de pasos anteriores.

¿Qué pasa si el usuario cierra el navegador? Si el usuario cierra el navegador antes de completar, puede reiniciar el proceso. Los pasos completados se guardan durante la duración de la sesión (14 minutos).

¿Dónde obtengo mi API Key? Acceda a su Dashboard de JAAK en https://dashboard.jaak.ai, navegue a la sección de API Keys y copie su token de autenticación.

¿Puedo usar la misma API Key en sandbox y producción? No, debe usar API Keys diferentes para cada ambiente. Solicite ambas al equipo de JAAK.

¿Cómo manejo múltiples verificaciones simultáneas? Cree una sesión separada (shortKey único) para cada usuario/verificación. Cada sesión es independiente.


14. Soporte y Recursos

Contacto

ContactoInformación
Email de soporte[email protected]
Sitio webwww.jaak.ai
Horario de atenciónLunes a Viernes, 9:00 - 18:00 (Hora de México)

Información requerida para soporte

Al contactar soporte, incluya la siguiente información:

  • Modalidad de integración utilizada (Embed, Direct, o Link)
  • Navegador y versión utilizada
  • Logs de la consola del navegador
  • Pasos para reproducir el problema
  • Mensajes de error específicos
  • Ambiente utilizado (Sandbox o Producción)

Recursos adicionales

  • Documentación técnica detallada disponible bajo petición
  • Ejemplos de código y casos de uso en nuestro repositorio
  • Webinars y sesiones de capacitación disponibles
  • Dashboard de JAAK: https://dashboard.jaak.ai

Para más información, visite www.jaak.ai o contacte a [email protected]