Webhook JAAK KYC

Manual Completo para Configuración y Uso de Webhooks

⏱️ Tiempo estimado: 45-60 minutos para configuración completa


¿Qué aprenderás en este manual?

Este manual te enseñará a configurar y usar el sistema de webhooks para recibir automáticamente los resultados de las verificaciones KYC. No necesitas conocimientos técnicos avanzados - solo sigue los pasos.


Antes de Empezar - Lista de Verificación

Asegúrate de tener estos elementos listos:

  • Servidor web con URL pública accesible (HTTPS obligatorio)
  • Capacidad para recibir peticiones HTTP POST
  • Conocimiento básico de APIs REST
  • Acceso a tu plataforma JAAK configurada
  • Editor de código o sistema para manejar peticiones HTTP

Índice de Contenidos

SecciónQué harásTiempo
Paso 1Entender qué son los webhooks5 min
Paso 2Configurar webhook en JAAK15 min
Paso 3Preparar endpoint para recibir datos20 min
Paso 4Probar funcionamiento10 min
Paso 5Interpretar respuestas15 min

PASO 1: ¿Qué es un Webhook?

Concepto Básico

Un webhook es como un "mensajero automático" que JAAK envía a tu sistema cada vez que una verificación KYC se completa.


1.1 ¿Cómo funciona?

1. Cliente completa KYC en JAAK → 
2. JAAK procesa la información → 
3. JAAK envía resultado a tu URL → 
4. Tu sistema recibe y procesa datos

1.2 Beneficios del Webhook

✅ Con Webhook❌ Sin Webhook
Recibes resultados automáticamenteDebes consultar manualmente cada resultado
Procesamiento en tiempo realDemoras en obtener información
Actualizaciones inmediatasRiesgo de perder notificaciones
Menor carga en tu sistemaMás llamadas API necesarias

1.3 Información que Recibirás

  • Estado de la verificación: APROBADO/RECHAZADO/PENDIENTE
  • Datos extraídos: Nombre, fecha de nacimiento, número de documento
  • Puntuaciones de confianza: Qué tan seguro lo determinó el sistema
  • Metadatos: Timestamps, identificadores únicos
  • Detalles de validación: Razones específicas de aprobación/rechazo

PASO 2: Configurar Webhook en JAAK

Objetivo

Configurar la URL donde JAAK enviará los resultados de las verificaciones.


Ruta de navegación

Dashboard Principal → Ajustes → Mi Compañía → Editar


2.1 Acceder a Configuración de Empresa

Paso 1: En el menú lateral ve hasta el botón de "Ajustes"


Paso 2: Haz clic en "Mi Compañía"


Paso 3: Presiona el botón "Editar" (ícono de lápiz)


2.2 Configurar Webhook en KYC Tradicional

En la sección "Configuración de Productos KYC" encontrarás:


📊 Campos de Webhook

CampoDescripciónEjemplo¿Es obligatorio?
URL WebhookDirección donde JAAK enviará resultadoshttps://tu-servidor.com/webhook/kycRecomendado
Auth KeyClave de seguridad para autenticar llamadasmi-clave-secreta-123Recomendado

2.3 Configurar URL Webhook

Formato Correcto de URL

✅ URLs Válidas:

https://mi-empresa.com/api/webhook/kyc
https://api.mi-empresa.com/kyc/results
https://servidor.mi-empresa.com:8080/webhook

❌ URLs Inválidas:

http://mi-empresa.com/webhook    (no HTTPS)
mi-empresa.com/webhook           (sin protocolo)
localhost:3000/webhook           (no accesible públicamente)

Configurar Auth Key

La Auth Key es una clave secreta que JAAK incluirá en cada petición para que puedas verificar que el webhook realmente viene de JAAK.

Recomendaciones:

  • Usa una combinación de letras, números y símbolos
  • Mínimo 16 caracteres
  • No uses información personal o predecible
  • Guárdala en un lugar seguro

Ejemplo de Auth Key segura: JK2024-webhook-Auth-789XYZ


2.4 Guardar Configuración

  1. Completa los campos URL Webhook y Auth Key
  2. Haz clic en "Guardar Cambios"
  3. Verás un mensaje de confirmación
  4. La configuración estará activa inmediatamente

PASO 3: Preparar Endpoint para Recibir Datos

Objetivo

Configurar tu servidor para recibir y procesar las peticiones HTTP POST de JAAK.


3.1 Especificaciones Técnicas

📡 Método HTTP y Headers

POST /tu-endpoint-webhook
Content-Type: application/json
Authorization: Bearer [TU-AUTH-KEY]
User-Agent: JAAK-Webhook/1.0

Estructura de Datos que Recibirás

{
  "event": "kyc.session.completed",
  "timestamp": "2024-01-15T10:30:00Z",
  "sessionId": "ABC123X",
  "data": {
    "status": "APPROVED",
    "confidence": 95.5,
    "user": {
      "name": "María González Pérez",
      "documentNumber": "ABCD123456789",
      "dateOfBirth": "1990-05-15",
      "nationality": "MEX"
    },
    "document": {
      "type": "INE",
      "country": "MEX",
      "isValid": true,
      "expirationDate": "2029-05-15"
    },
    "validation": {
      "documentAuthenticity": "PASS",
      "faceMatch": "PASS",
      "liveness": "PASS"
    }
  }
}

3.2 Implementación del Endpoint

Ejemplo en Python (Flask)

from flask import Flask, request, jsonify
import json

app = Flask(__name__)

# Tu Auth Key configurada en JAAK
AUTH_KEY = "JK2024-webhook-Auth-789XYZ"

@app.route('/webhook/kyc', methods=['POST'])
def webhook_kyc():
    # Verificar autenticación
    auth_header = request.headers.get('Authorization', '')
    if not auth_header.startswith('Bearer '):
        return jsonify({"error": "Missing authorization"}), 401
    
    received_key = auth_header.replace('Bearer ', '')
    if received_key != AUTH_KEY:
        return jsonify({"error": "Invalid auth key"}), 401
    
    # Procesar datos
    try:
        data = request.get_json()
        
        # Extraer información importante
        session_id = data.get('sessionId')
        status = data['data']['status']
        user_name = data['data']['user']['name']
        
        print(f"KYC Completado - Sesión: {session_id}")
        print(f"Usuario: {user_name}")
        print(f"Estado: {status}")
        
        # Aquí añades tu lógica de negocio
        process_kyc_result(data)
        
        return jsonify({"received": True}), 200
        
    except Exception as e:
        print(f"Error procesando webhook: {e}")
        return jsonify({"error": "Processing failed"}), 500

def process_kyc_result(data):
    """Tu lógica personalizada aquí"""
    status = data['data']['status']
    
    if status == "APPROVED":
        # Cliente aprobado - activar cuenta, enviar bienvenida, etc.
        activate_user_account(data['data']['user'])
    elif status == "REJECTED":
        # Cliente rechazado - enviar instrucciones, solicitar documentos, etc.
        handle_rejection(data['sessionId'])
    elif status == "PENDING":
        # Revisión manual requerida - notificar equipo de compliance
        notify_manual_review(data['sessionId'])

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=443, ssl_context='adhoc')

Ejemplo en Node.js (Express)

const express = require('express');
const app = express();

// Tu Auth Key configurada en JAAK
const AUTH_KEY = "JK2024-webhook-Auth-789XYZ";

app.use(express.json());

app.post('/webhook/kyc', (req, res) => {
    // Verificar autenticación
    const authHeader = req.headers.authorization || '';
    if (!authHeader.startsWith('Bearer ')) {
        return res.status(401).json({ error: 'Missing authorization' });
    }
    
    const receivedKey = authHeader.replace('Bearer ', '');
    if (receivedKey !== AUTH_KEY) {
        return res.status(401).json({ error: 'Invalid auth key' });
    }
    
    try {
        const data = req.body;
        
        // Extraer información importante
        const sessionId = data.sessionId;
        const status = data.data.status;
        const userName = data.data.user.name;
        
        console.log(`KYC Completado - Sesión: ${sessionId}`);
        console.log(`Usuario: ${userName}`);
        console.log(`Estado: ${status}`);
        
        // Tu lógica de negocio aquí
        processKycResult(data);
        
        res.status(200).json({ received: true });
        
    } catch (error) {
        console.error('Error procesando webhook:', error);
        res.status(500).json({ error: 'Processing failed' });
    }
});

function processKycResult(data) {
    const status = data.data.status;
    
    switch(status) {
        case 'APPROVED':
            // Cliente aprobado
            activateUserAccount(data.data.user);
            break;
        case 'REJECTED':
            // Cliente rechazado
            handleRejection(data.sessionId);
            break;
        case 'PENDING':
            // Revisión manual
            notifyManualReview(data.sessionId);
            break;
    }
}

app.listen(443, () => {
    console.log('Webhook server running on port 443');
});

Ejemplo en PHP

<?php
header('Content-Type: application/json');

// Tu Auth Key configurada en JAAK
$AUTH_KEY = "JK2024-webhook-Auth-789XYZ";

// Verificar método HTTP
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(405);
    echo json_encode(['error' => 'Method not allowed']);
    exit;
}

// Verificar autenticación
$authHeader = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
if (!str_starts_with($authHeader, 'Bearer ')) {
    http_response_code(401);
    echo json_encode(['error' => 'Missing authorization']);
    exit;
}

$receivedKey = str_replace('Bearer ', '', $authHeader);
if ($receivedKey !== $AUTH_KEY) {
    http_response_code(401);
    echo json_encode(['error' => 'Invalid auth key']);
    exit;
}

// Procesar datos
try {
    $input = file_get_contents('php://input');
    $data = json_decode($input, true);
    
    if (!$data) {
        throw new Exception('Invalid JSON');
    }
    
    // Extraer información importante
    $sessionId = $data['sessionId'];
    $status = $data['data']['status'];
    $userName = $data['data']['user']['name'];
    
    error_log("KYC Completado - Sesión: $sessionId");
    error_log("Usuario: $userName");
    error_log("Estado: $status");
    
    // Tu lógica de negocio aquí
    processKycResult($data);
    
    http_response_code(200);
    echo json_encode(['received' => true]);
    
} catch (Exception $e) {
    error_log('Error procesando webhook: ' . $e->getMessage());
    http_response_code(500);
    echo json_encode(['error' => 'Processing failed']);
}

function processKycResult($data) {
    $status = $data['data']['status'];
    
    switch($status) {
        case 'APPROVED':
            // Cliente aprobado
            activateUserAccount($data['data']['user']);
            break;
        case 'REJECTED':
            // Cliente rechazado
            handleRejection($data['sessionId']);
            break;
        case 'PENDING':
            // Revisión manual
            notifyManualReview($data['sessionId']);
            break;
    }
}
?>

3.3 Requisitos de Respuesta

Respuesta Exitosa

Tu endpoint debe responder con:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "received": true
}

Timeout y Reintentos

  • Timeout: JAAK esperará máximo 30 segundos por tu respuesta
  • Reintentos: Si no respondes con 200 OK, JAAK reintentará:
    • 1° reintento: después de 1 minuto
    • 2° reintento: después de 5 minutos
    • 3° reintento: después de 15 minutos
    • Máximo 3 reintentos totales

PASO 4: Probar Funcionamiento

Objetivo

Verificar que tu webhook está funcionando correctamente con una sesión KYC de prueba.


4.1 Preparar Prueba

Checklist Pre-Prueba

  • URL webhook configurada en JAAK
  • Auth Key configurada en JAAK
  • Endpoint implementado y funcionando
  • Servidor accesible desde internet (HTTPS)
  • Logs habilitados para monitoreo

4.2 Crear Sesión de Prueba

  1. Ir a JAAK Dashboard: KYC → Sesiones → Crear nueva sesión

  2. Completar formulario:

    • Nombre del contacto: "Test Webhook"
    • Nombre del flujo: "Prueba-Webhook-001"
    • URL redirección: Tu página de confirmación
    • País de documentación: Tu país configurado
    • Tipo de flujo: "KYC Tradicional"
  3. Guardar y copiar URL: Se generará una URL como https://sandbox.kyc.jaak.ai/session/ABC123X


4.3 Completar Verificación

  1. Abrir URL de sesión en navegador
  2. Seguir proceso KYC:
    • Permitir acceso a cámara
    • Capturar documento (frente y reverso)
    • Capturar selfie/biometría
    • Esperar procesamiento
  3. Monitorear logs de tu servidor durante el proceso

4.4 Verificar Recepción del Webhook

Qué Buscar en tus Logs

Si todo funciona correctamente, deberías ver:

[INFO] POST /webhook/kyc - Autenticación exitosa
[INFO] KYC Completado - Sesión: ABC123X
[INFO] Usuario: Test Webhook
[INFO] Estado: APPROVED
[INFO] Respuesta 200 enviada a JAAK

Si hay problemas, podrías ver:

[ERROR] POST /webhook/kyc - Auth Key inválida
[ERROR] JSON malformado en webhook
[ERROR] Timeout procesando webhook

4.5 Validar en JAAK Dashboard

  1. Ir a: KYC → Sesiones
  2. Buscar tu sesión: "Prueba-Webhook-001"
  3. Verificar estado: Debe aparecer como completada
  4. Revisar logs: Si hay errores de webhook, aparecerán aquí

PASO 5: Interpretar Respuestas del Webhook

Objetivo

Entender completamente los datos que recibes en el webhook para implementar la lógica de negocio adecuada.


5.1 Estados Principales

Status de Verificación

EstadoSignificadoAcción Recomendada
APPROVED✅ Verificación exitosaActivar cuenta, proceder con onboarding
REJECTED❌ Verificación fallóSolicitar reintentar o documentos adicionales
PENDING⏳ Requiere revisión manualNotificar equipo de compliance
ERROR⚠️ Error técnico durante procesoReintentar verificación

5.2 Campos Importantes del Webhook

Estructura Completa

{
  "event": "kyc.session.completed",
  "timestamp": "2024-07-14T15:30:45Z",
  "sessionId": "ABC123X",
  "data": {
    "status": "APPROVED",
    "confidence": 95.5,
    "processingTime": "45.2",
    "user": {
      "name": "María González Pérez",
      "documentNumber": "GONZ900515MDFRNR08",
      "dateOfBirth": "1990-05-15",
      "nationality": "MEX",
      "gender": "F"
    },
    "document": {
      "type": "INE",
      "country": "MEX",
      "isValid": true,
      "expirationDate": "2029-05-15",
      "issueDate": "2019-05-15"
    },
    "validation": {
      "documentAuthenticity": "PASS",
      "faceMatch": "PASS",
      "liveness": "PASS",
      "blacklistCheck": "PASS"
    },
    "scores": {
      "documentQuality": 98.2,
      "faceMatchScore": 94.7,
      "livenessScore": 96.1,
      "overallConfidence": 95.5
    },
    "metadata": {
      "ipAddress": "192.168.1.100",
      "userAgent": "Mozilla/5.0...",
      "deviceType": "mobile",
      "location": {
        "country": "MX",
        "region": "CDMX",
        "city": "Mexico City"
      }
    }
  }
}

Explicación de Campos

Información del Usuario:

  • user.name: Nombre extraído del documento
  • user.documentNumber: Número de identificación oficial
  • user.dateOfBirth: Fecha de nacimiento
  • user.nationality: Nacionalidad (código ISO)
  • user.gender: Género (M/F)

Información del Documento:

  • document.type: Tipo de documento (INE, passport, etc.)
  • document.country: País emisor
  • document.isValid: Si el documento es válido/vigente
  • document.expirationDate: Fecha de vencimiento

Resultados de Validación:

  • validation.documentAuthenticity: Autenticidad del documento
  • validation.faceMatch: Coincidencia facial con foto del documento
  • validation.liveness: Prueba de vida (no es foto/video)
  • validation.blacklistCheck: Verificación en listas restrictivas

Puntuaciones de Confianza:

  • scores.documentQuality: Calidad de imagen del documento (0-100)
  • scores.faceMatchScore: Precisión de coincidencia facial (0-100)
  • scores.livenessScore: Confianza en prueba de vida (0-100)
  • scores.overallConfidence: Confianza general del sistema (0-100)

5.3 Lógica de Negocio Recomendada

Flujo de Decisión

def process_kyc_webhook(data):
    status = data['data']['status']
    confidence = data['data']['confidence']
    validations = data['data']['validation']
    
    if status == "APPROVED":
        if confidence >= 90:
            # Alta confianza - aprobación automática
            auto_approve_user(data)
        elif confidence >= 70:
            # Confianza media - aprobación con monitoreo
            approve_with_monitoring(data)
        else:
            # Baja confianza - revisión manual
            queue_for_manual_review(data)
            
    elif status == "REJECTED":
        # Analizar razones específicas
        if validations['liveness'] == "FAIL":
            request_retry_with_instructions(data, "liveness")
        elif validations['documentAuthenticity'] == "FAIL":
            request_different_document(data)
        else:
            manual_review_required(data)
            
    elif status == "PENDING":
        # Siempre requiere revisión manual
        notify_compliance_team(data)
        
    elif status == "ERROR":
        # Error técnico - permitir reintento
        send_retry_notification(data)

5.4 Casos Especiales

Situaciones a Considerar

Alta Confianza pero Validación Fallida:

{
  "confidence": 95.0,
  "validation": {
    "documentAuthenticity": "PASS",
    "faceMatch": "FAIL",
    "liveness": "PASS"
  }
}

Acción: Revisar manualmente - posible documento legítimo pero persona diferente.

Baja Confianza pero Validaciones Exitosas:

{
  "confidence": 65.0,
  "validation": {
    "documentAuthenticity": "PASS",
    "faceMatch": "PASS",
    "liveness": "PASS"
  }
}

Acción: Aprobar con monitoreo adicional - posible problema de calidad de imagen.

Metadatos Sospechosos:

{
  "metadata": {
    "ipAddress": "192.168.1.100",
    "location": {
      "country": "RU"  // País diferente al esperado
    }
  }
}

Acción: Activar verificaciones adicionales por ubicación geográfica inusual.


Solución de Problemas Comunes

Problemas Frecuentes

Webhook no se recibe

ProblemaCausa ProbableSolución
No llegan peticionesURL incorrecta en JAAKVerificar configuración en "Mi Compañía"
Error 404/502Endpoint no existe o servidor caídoVerificar que tu servidor está funcionando
Error SSL/TLSCertificado inválidoUsar HTTPS válido o renovar certificado
TimeoutRespuesta lenta del servidorOptimizar procesamiento, responder rápido

Errores de autenticación

ErrorDescripciónSolución
"Missing authorization"No se envía header AuthorizationVerificar implementación del endpoint
"Invalid auth key"Auth Key no coincideRevisar Auth Key en configuración JAAK
Constante error 401Auth Key mal configuradaRegenerar Auth Key en JAAK

Problemas de procesamiento

SíntomaCausaFix
JSON malformadoError al parsear datosAñadir manejo de errores robusto
Datos faltantesCambios en estructuraVerificar campos antes de usar
Timeout al procesarLógica muy lentaMover procesamiento pesado a background

Debugging Avanzado

Logs Detallados

import logging
import json

logging.basicConfig(level=logging.DEBUG)

@app.route('/webhook/kyc', methods=['POST'])
def webhook_kyc():
    logger = logging.getLogger(__name__)
    
    # Log headers completos
    logger.debug(f"Headers recibidos: {dict(request.headers)}")
    
    # Log body raw
    raw_data = request.get_data()
    logger.debug(f"Body raw: {raw_data}")
    
    # Log IP origen
    logger.debug(f"IP origen: {request.remote_addr}")
    
    try:
        data = request.get_json()
        logger.info(f"Webhook procesado: {data.get('sessionId')}")
        
        # Log estructura de datos
        logger.debug(f"Estructura completa: {json.dumps(data, indent=2)}")
        
        return jsonify({"received": True}), 200
        
    except Exception as e:
        logger.error(f"Error procesando webhook: {str(e)}", exc_info=True)
        return jsonify({"error": str(e)}), 500

Webhook de Prueba

Para probar tu endpoint sin hacer una sesión KYC completa:

curl -X POST https://tu-servidor.com/webhook/kyc \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer JK2024-webhook-Auth-789XYZ" \
  -d '{
    "event": "kyc.session.completed",
    "timestamp": "2024-07-14T15:30:45Z",
    "sessionId": "TEST123",
    "data": {
      "status": "APPROVED",
      "confidence": 95.5,
      "user": {
        "name": "Test User",
        "documentNumber": "TEST123456789",
        "dateOfBirth": "1990-01-01",
        "nationality": "MEX"
      }
    }
  }'

¿Necesitas Ayuda Adicional?

Cuándo contactar soporte técnico

  • Errores de configuración que no puedes resolver
  • Problemas de conectividad persistentes
  • Cambios en la estructura de datos del webhook
  • Preguntas sobre integración con sistemas específicos

Información a tener lista al contactar soporte

  • URL de tu webhook configurada
  • Logs de errores específicos con timestamps
  • Ejemplo de petición que está fallando
  • Configuración de ambiente (desarrollo/producción)
  • ShortKey de sesión problemática (si aplica)

Recursos Adicionales

  • Documentación API JAAK: Para integraciones más avanzadas
  • Postman Collection: Para probar endpoints manualmente
  • SDK/Libraries: Si están disponibles para tu lenguaje
  • Status Page: Para verificar el estado del servicio JAAK

Resumen Final

Has Aprendido A:

  • Configurar URL webhook y Auth Key en JAAK
  • Implementar endpoint para recibir datos
  • Procesar y validar información del webhook
  • Manejar diferentes estados de verificación
  • Solucionar problemas comunes
  • Implementar lógica de negocio basada en resultados

Próximos Pasos Recomendados

  1. Configurar monitoreo: Logs, alertas, métricas
  2. Implementar retry logic: Para el procesamiento de webhooks
  3. Añadir validaciones adicionales: Según tus reglas de negocio
  4. Documentar proceso: Para tu equipo y futuras referencias
  5. Probar en producción: Con volúmenes reales de transacciones

¡Felicidades! Ya tienes un sistema completo de webhooks para KYC funcionando. Tu sistema ahora puede recibir y procesar automáticamente los resultados de todas las verificaciones de identidad realizadas en JAAK.