recurso

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 una notificación cuando una verificación KYC se completa. 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 una notificación a tu URL →
4. Tu sistema consulta los detalles en la URL incluida

1.2 Beneficios del Webhook

✅ Con Webhook❌ Sin Webhook
Recibes una notificación automáticaDebes 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

El webhook te entrega una notificación compacta con los identificadores y el resultado global de la sesión. Los detalles completos (datos del usuario, documento, validaciones) los consultas después en la URL que viene dentro del mismo payload.

  • Identificador de la sesión: id y shortKey
  • Marcas de tiempo: Inicio, fin y duración
  • Modo de validación: Cómo fue resuelta la sesión (automática, manual o pendiente de revisión)
  • Etapa final (stage): Aprobado, rechazado, en revisión, etc.
  • Scores: Puntuaciones numéricas por componente (liveness, documento, 1:1, etc.)
  • URL de detalles: Enlace firmado al endpoint de JAAK con toda la información extendida

PASO 2: Configurar Webhook en JAAK

Objetivo

Configurar la URL donde JAAK enviará la notificación cuando se complete cada verificación.

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á la notificaciónhttps://tu-servidor.com/webhook/kycRecomendado
Auth KeyClave de seguridad para autenticar llamadasmi-clave-secreta-123Opcional

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 como header Api-AuthKey para que puedas verificar que el webhook realmente viene de JAAK. Si dejas el campo vacío, JAAK enviará el webhook sin header de autenticación — tu endpoint debe entonces aceptar la petición sin credenciales o validar por otro mecanismo (IP allowlist, firma, etc.).

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

Información

Una vez guardada, la Auth Key queda encriptada en nuestros servidores y no se muestra de vuelta en el dashboard. Verás solo un indicador "Configurado". Para cambiarla presiona "Cambiar" y escribe la nueva clave; si dejas el campo vacío al guardar, la clave anterior se conserva.

2.4 Guardar Configuración

  1. Completa el campo URL Webhook (y opcionalmente 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
Api-AuthKey: [TU-AUTH-KEY]

Importante

El header de autenticación se llama literalmente Api-AuthKey y la clave va como valor directo (sin prefijo Bearer). Si no configuraste Auth Key en el dashboard, este header no se envía.

Estructura de Datos que Recibirás

{
  "id": "65f8a1b2c3d4e5f600000001",
  "shortKey": "ABC123X",
  "startedAt": "2026-01-15T10:27:36Z",
  "endedAt": "2026-01-15T10:30:00Z",
  "duration": "2.40m",
  "validation": "AUTOMATIC",
  "stage": "approved",
  "scores": {
    "liveness": 96.1,
    "document": 98.2,
    "oneToOne": 94.7,
    "blacklist": 100.0,
    "total": 95.5,
    "status": "PASS",
    "livenessPass": true,
    "documentPass": true,
    "oneToOnePass": true
  },
  "detailsURL": "https://api.jaak.ai/api/v1/kyc/session/65f8a1b2c3d4e5f600000001"
}

Información

El webhook no incluye datos personales del usuario (nombre, fecha de nacimiento, documento). Para obtener esa información consulta el endpoint indicado en detailsURL usando tu API Key de JAAK.

3.2 Implementación del Endpoint

Ejemplo en Python (Flask)

from flask import Flask, request, jsonify

app = Flask(__name__)

# Tu Auth Key configurada en JAAK (si la configuraste)
AUTH_KEY = "JK2024-webhook-Auth-789XYZ"

@app.route('/webhook/kyc', methods=['POST'])
def webhook_kyc():
    # Verificar autenticación (solo si configuraste Auth Key en JAAK)
    if AUTH_KEY:
        received_key = request.headers.get('Api-AuthKey', '')
        if received_key != AUTH_KEY:
            return jsonify({"error": "Invalid auth key"}), 401

    # Procesar datos
    try:
        data = request.get_json()

        # Campos principales del webhook
        session_id = data['id']
        short_key  = data['shortKey']
        stage      = data['stage']          # approved | rejected | in_review | ...
        validation = data['validation']     # AUTOMATIC | MANUAL | NEED_REVIEW
        details_url = data['detailsURL']

        print(f"KYC Completado - Sesión: {session_id} ({short_key})")
        print(f"Stage: {stage} | Validación: {validation}")

        # Lógica de negocio
        process_kyc_result(data)

        # Para obtener datos personales, nombre, documento, etc.
        # haz una petición autenticada a details_url

        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í"""
    stage = data['stage']

    if stage == "approved":
        # Sesión aprobada - activar cuenta, enviar bienvenida, etc.
        activate_user_account(data['id'])
    elif stage == "rejected":
        # Sesión rechazada - notificar, solicitar reintento, etc.
        handle_rejection(data['id'])
    elif stage == "in_review":
        # Revisión manual requerida - notificar equipo de compliance
        notify_manual_review(data['id'])

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 (si la configuraste)
const AUTH_KEY = "JK2024-webhook-Auth-789XYZ";

app.use(express.json());

app.post('/webhook/kyc', (req, res) => {
    // Verificar autenticación (solo si configuraste Auth Key en JAAK)
    if (AUTH_KEY) {
        const receivedKey = req.headers['api-authkey'] || '';
        if (receivedKey !== AUTH_KEY) {
            return res.status(401).json({ error: 'Invalid auth key' });
        }
    }

    try {
        const data = req.body;

        const sessionId  = data.id;
        const shortKey   = data.shortKey;
        const stage      = data.stage;       // approved | rejected | in_review | ...
        const validation = data.validation;  // AUTOMATIC | MANUAL | NEED_REVIEW
        const detailsURL = data.detailsURL;

        console.log(`KYC Completado - Sesión: ${sessionId} (${shortKey})`);
        console.log(`Stage: ${stage} | Validación: ${validation}`);

        processKycResult(data);

        // Para obtener datos personales, nombre, documento, etc.
        // haz una petición autenticada a detailsURL

        res.status(200).json({ received: true });

    } catch (error) {
        console.error('Error procesando webhook:', error);
        res.status(500).json({ error: 'Processing failed' });
    }
});

function processKycResult(data) {
    switch (data.stage) {
        case 'approved':
            activateUserAccount(data.id);
            break;
        case 'rejected':
            handleRejection(data.id);
            break;
        case 'in_review':
            notifyManualReview(data.id);
            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 (si la configuraste)
$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 (solo si configuraste Auth Key en JAAK)
if ($AUTH_KEY !== '') {
    $receivedKey = $_SERVER['HTTP_API_AUTHKEY'] ?? '';
    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');
    }

    $sessionId  = $data['id'];
    $shortKey   = $data['shortKey'];
    $stage      = $data['stage'];
    $validation = $data['validation'];
    $detailsURL = $data['detailsURL'];

    error_log("KYC Completado - Sesión: $sessionId ($shortKey)");
    error_log("Stage: $stage | Validación: $validation");

    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) {
    switch ($data['stage']) {
        case 'approved':
            activateUserAccount($data['id']);
            break;
        case 'rejected':
            handleRejection($data['id']);
            break;
        case 'in_review':
            notifyManualReview($data['id']);
            break;
    }
}
?>

3.3 Requisitos de Respuesta

Respuesta Esperada

JAAK considera la entrega exitosa si recibe un status HTTP 2xx (idealmente 200). El body de la respuesta no es validado por JAAK, pero es buena práctica devolver un JSON confirmatorio:

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

{
  "received": true
}

Timeout y Reintentos

  • Timeout: JAAK espera un máximo de 10 segundos por tu respuesta. Si tu endpoint tarda más, la petición se aborta.
  • Entrega fire-and-forget: JAAK envía el webhook una sola vez. Si tu servidor está caído o responde con error, no hay reintentos automáticos.
  • Recomendaciones:
    • Responde rápido (200 OK) antes de 10 segundos. Si tu lógica es pesada, encóla el evento y procésalo en background.
    • Persiste el id / shortKey en tu lado apenas recibas el webhook para poder reconciliar.
    • Si necesitas re-obtener el resultado de una sesión, consulta el endpoint indicado en detailsURL con tu API Key.

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 (opcional)
  • 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://kyc.sandbox.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: 65f8a1b2c3d4e5f600000001 (ABC123X)
[INFO] Stage: approved | Validación: AUTOMATIC
[INFO] Respuesta 200 enviada a JAAK

Si hay problemas, podrías ver:

[ERROR] POST /webhook/kyc - Api-AuthKey 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 Campos del Webhook

CampoTipoDescripción
idstringIdentificador único de la sesión (ObjectId). Úsalo como llave en tu sistema.
shortKeystringClave corta legible, la misma que aparece en el dashboard de JAAK.
startedAtstring (ISO8601)Fecha/hora de inicio de la sesión.
endedAtstring (ISO8601)Fecha/hora en que finalizó la sesión.
durationstringDuración total en minutos con formato "N.NNm" (ej: "2.40m").
validationstring (enum)Modo de resolución: AUTOMATIC, MANUAL o NEED_REVIEW. (ver 5.2)
stagestring (enum)Etapa final de la sesión: approved, rejected, in_review, expired, etc. (ver 5.3)
scoresobjectPuntuaciones numéricas por componente (ver 5.4).
detailsURLstring (URL)Endpoint de JAAK donde consultar los detalles completos de la sesión.

5.2 Valores de validation

ValorSignificado
AUTOMATICLa sesión fue resuelta automáticamente por el motor de JAAK sin intervención humana.
MANUALLa sesión fue revisada y resuelta manualmente por un operador desde el dashboard de JAAK.
NEED_REVIEWLa sesión quedó pendiente de revisión manual (el motor automático no pudo decidir).

5.3 Valores de stage

Los valores más comunes que recibirás en una sesión finalizada son:

ValorSignificadoAcción recomendada
approved✅ Verificación exitosaActivar cuenta, proceder con onboarding
rejected❌ Verificación fallóSolicitar reintentar o documentos adicionales
in_review⏳ Requiere revisión manualNotificar equipo de compliance
expired⌛ La sesión expiró sin completarseNotificar al usuario, permitir reintentar
lapsedLa sesión venció por inactividadNotificar al usuario

5.4 Campo scores

Puntuaciones numéricas por componente. Los valores por componente van de 0 a 100 (a mayor número, mayor confianza); el status resume el resultado global.

CampoTipoDescripción
livenessnumberScore del chequeo de prueba de vida
documentnumberScore del chequeo del documento
oneToOnenumberScore del match 1:1 (cara vs foto del documento)
blacklistnumberScore del chequeo en listas restrictivas
totalnumberScore global combinado
statusstringResultado agregado: PASS, FAIL, NEED_REVIEW, ERROR, EXPIRED
livenessPassbooleanSi liveness pasó el umbral configurado en tu empresa
documentPassbooleanSi document pasó el umbral configurado
oneToOnePassbooleanSi oneToOne pasó el umbral configurado

5.5 Consultar Detalles Extendidos

El webhook es intencionalmente compacto. Para obtener los datos personales extraídos (nombre, fecha de nacimiento, número de documento), imágenes capturadas o el desglose detallado por paso, consulta el endpoint en detailsURL con una petición autenticada usando tu API Key de JAAK.

curl -X GET "$DETAILS_URL" \
  -H "Authorization: Bearer $JAAK_API_KEY"

5.6 Lógica de Negocio Recomendada

Flujo de Decisión

def process_kyc_webhook(data):
    stage = data['stage']
    validation = data['validation']
    scores = data.get('scores', {}) or {}
    total_score = scores.get('total', 0)

    if stage == "approved":
        if total_score >= 90:
            # Alta confianza - aprobación automática
            auto_approve_user(data)
        elif total_score >= 70:
            # Confianza media - aprobación con monitoreo
            approve_with_monitoring(data)
        else:
            # Baja confianza - revisión manual interna
            queue_for_manual_review(data)

    elif stage == "rejected":
        # Analizar qué componente falló
        if scores.get('livenessPass') is False:
            request_retry_with_instructions(data, "liveness")
        elif scores.get('documentPass') is False:
            request_different_document(data)
        else:
            manual_review_required(data)

    elif stage == "in_review":
        # Requiere revisión manual por parte de JAAK
        notify_compliance_team(data)

    elif stage in ("expired", "lapsed"):
        # Sesión no completada a tiempo
        send_retry_notification(data)

5.7 Casos Especiales

Situaciones a Considerar

Alta confianza global pero algún componente falló:

{
  "stage": "approved",
  "scores": {
    "total": 95.0,
    "status": "PASS",
    "livenessPass": true,
    "documentPass": true,
    "oneToOnePass": false
  }
}

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

Baja confianza aunque la sesión fue aprobada:

{
  "stage": "approved",
  "scores": {
    "total": 65.0,
    "status": "PASS",
    "livenessPass": true,
    "documentPass": true,
    "oneToOnePass": true
  }
}

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

Sesión marcada como in_review:

{
  "stage": "in_review",
  "validation": "NEED_REVIEW"
}

Acción: Esperar a que un operador de JAAK o de tu equipo resuelva la sesión manualmente; recibirás un segundo webhook con el resultado final (approved o rejected).

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 servidorResponder en < 10s y procesar en background
Solo llega una vezFire-and-forget, sin retriesConsultar detailsURL para reconciliar

Errores de autenticación

ErrorDescripciónSolución
"Missing Api-AuthKey"Header Api-AuthKey no presenteVerificar que tu servidor lea el header correcto
"Invalid auth key"El valor de Api-AuthKey no coincideRevisar Auth Key en configuración JAAK
Error 401 constanteAuth Key mal configuradaRegenerar Auth Key en JAAK

Importante

Asegúrate de que tu servidor lea el header Api-AuthKey (JAAK no utiliza Authorization: Bearer).

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('id')} ({data.get('shortKey')})")

        # 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 "Api-AuthKey: JK2024-webhook-Auth-789XYZ" \
  -d '{
    "id": "65f8a1b2c3d4e5f600000001",
    "shortKey": "TEST123",
    "startedAt": "2026-01-15T10:27:36Z",
    "endedAt": "2026-01-15T10:30:00Z",
    "duration": "2.40m",
    "validation": "AUTOMATIC",
    "stage": "approved",
    "scores": {
      "liveness": 96.1,
      "document": 98.2,
      "oneToOne": 94.7,
      "blacklist": 100.0,
      "total": 95.5,
      "status": "PASS",
      "livenessPass": true,
      "documentPass": true,
      "oneToOnePass": true
    },
    "detailsURL": "https://api.jaak.ai/api/v1/kyc/session/65f8a1b2c3d4e5f600000001"
  }'

¿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 consultar los detalles extendidos via detailsURL
  • 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 la notificación
  • Procesar y validar los campos del webhook
  • Manejar diferentes valores de stage y validation
  • Consultar detailsURL para obtener los datos extendidos
  • Solucionar problemas comunes

Próximos Pasos Recomendados

  1. Configurar monitoreo: Logs, alertas, métricas
  2. Implementar procesamiento en background: Para responder rápido en < 10s
  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 automáticamente las notificaciones y consultar los detalles de todas las verificaciones de identidad realizadas en JAAK.