Verificación Telefónica por OTP


📱 Descripción General

Este endpoint permite enviar un código de verificación de un solo uso (OTP) al número telefónico del usuario para validar su identidad como parte del proceso KYC. El código se envía simultáneamente por SMS y WhatsApp para garantizar la entrega.


🔐 Autenticación

Este endpoint requiere autenticación mediante Bearer Token de tipo API Key.

¿Cómo obtener tu API Key?

  1. Accede al panel de administración de JAAK
  2. Ve a la sección de Configuración o API Keys
  3. Genera una nueva API Key para tu empresa
  4. Guarda la API Key de forma segura (no se podrá recuperar después)

Formato de autenticación

Todas las peticiones deben incluir el header de autorización:

Authorization: Bearer sk_live_abc123def456ghi789jkl012mno345pqr

⚠️ Seguridad de API Keys

  • NUNCA compartas tu API Key públicamente
  • NO incluyas tu API Key en repositorios de código público
  • NO la expongas en el código frontend (cliente)
  • Usa variables de entorno para almacenarla
  • Rota tus API Keys periódicamente
  • Si sospechas que tu key fue comprometida, regénérala inmediatamente

🎯 ¿Cuándo usar este endpoint?

Utiliza este endpoint cuando necesites:

  • Verificar que el usuario tiene acceso al número telefónico proporcionado
  • Validar la identidad del usuario antes de continuar con el proceso KYC
  • Iniciar el flujo de verificación telefónica en tu aplicación

🔗 Endpoint

POST /api/v1/kyc/phone/send-otp

Base URL: https://api.jaak.mx


📥 Parámetros de Entrada

Headers

HeaderValorRequeridoDescripción
Content-Typeapplication/json✅ SíTipo de contenido
AuthorizationBearer + API Key✅ SíToken de autenticación

Body Parameters

CampoTipoRequeridoDescripción
company_idstring✅ SíID único de tu empresa en JAAK
country_documentstring✅ SíCódigo ISO del país (ejemplo: MEX para México)
phone_numberstring✅ SíNúmero telefónico en formato internacional con código de país

⚠️ Consideraciones importantes

  • El número telefónico debe incluir el código de país con el símbolo +
  • Formato recomendado: código de país seguido del número sin espacios ni guiones
  • Ejemplo válido: "+525512345678" (México)
  • Ejemplo inválido: "5512345678" o "55-1234-5678"

📤 Ejemplo de Request

Request Body

{
  "company_id": "5f8d0d55b54764421b7156c5",
  "country_document": "MEX",
  "phone_number": "+525512345678"
}

cURL Example

curl -X POST "https://api.jaak.mx/api/v1/kyc/phone/send-otp" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk_live_abc123def456ghi789jkl012mno345pqr" \
  -d '{
    "company_id": "5f8d0d55b54764421b7156c5",
    "country_document": "MEX",
    "phone_number": "+525512345678"
  }'

JavaScript Example

fetch('https://api.jaak.mx/api/v1/kyc/phone/send-otp', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer sk_live_abc123def456ghi789jkl012mno345pqr'
  },
  body: JSON.stringify({
    company_id: '5f8d0d55b54764421b7156c5',
    country_document: 'MEX',
    phone_number: '+525512345678'
  })
})
.then(response => response.json())
.then(data => console.log(data));

Python Example

import requests

response = requests.post(
    'https://api.jaak.mx/api/v1/kyc/phone/send-otp',
    headers={
        'Content-Type': 'application/json',
        'Authorization': 'Bearer sk_live_abc123def456ghi789jkl012mno345pqr'
    },
    json={
        'company_id': '5f8d0d55b54764421b7156c5',
        'country_document': 'MEX',
        'phone_number': '+525512345678'
    }
)

print(response.json())

PHP Example

<?php
$ch = curl_init('https://api.jaak.mx/api/v1/kyc/phone/send-otp');

curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
    'company_id' => '5f8d0d55b54764421b7156c5',
    'country_document' => 'MEX',
    'phone_number' => '+525512345678'
]));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'Authorization: Bearer sk_live_abc123def456ghi789jkl012mno345pqr'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);

echo $response;
?>

📨 Respuestas Posibles

✅ 200 - Éxito

El OTP fue enviado correctamente al usuario.

{
  "message": "OTP sent successfully",
  "session_id": "550e8400-e29b-41d4-a716-446655440000",
  "success": true
}

Campos de respuesta:

  • message: Mensaje de confirmación
  • session_id: ID de sesión único que deberás usar para verificar el código OTP
  • success: Indica si la operación fue exitosa
💡

IMPORTANTE: Guarda el session_id ya que lo necesitarás para validar el código OTP que ingrese el usuario.


❌ 400 - Bad Request

Los datos enviados son inválidos o están incompletos.

Causas comunes:

  • Falta algún campo requerido
  • El formato del número telefónico es incorrecto
  • El country_document no es válido
{
  "error": "Invalid phone number format",
  "details": "Phone number must include country code with + prefix"
}

Solución: Verifica que todos los campos estén presentes y en el formato correcto.


❌ 401 - Unauthorized

El Bearer Token es inválido o no fue proporcionado.

{
  "error": "Unauthorized",
  "message": "Invalid or missing API key"
}

Causas comunes:

  • No se incluyó el header Authorization
  • La API Key es inválida o expiró
  • El formato del Bearer Token es incorrecto

Solución: Verifica que estés enviando correctamente el header de autorización con una API Key válida.


❌ 403 - Forbidden

La API Key no tiene permisos para realizar esta operación.

{
  "error": "Forbidden",
  "message": "API key does not have permission to access this resource"
}

Solución: Verifica que tu API Key tenga los permisos necesarios para el servicio de verificación telefónica.


❌ 404 - Company Not Found

El company_id proporcionado no existe en el sistema.

{
  "error": "Company not found",
  "company_id": "5f8d0d55b54764421b7156c5"
}

Solución: Verifica que estés usando el company_id correcto proporcionado por JAAK.


❌ 429 - Too Many Requests

Has excedido el límite de solicitudes permitidas.

{
  "error": "Rate limit exceeded",
  "retry_after": 60,
  "limit": "5 requests per 10 minutes per phone number"
}

Solución: Espera el tiempo indicado en retry_after (en segundos) antes de volver a intentar.

Límites de rate limiting:

  • Máximo 5 intentos por número telefónico cada 10 minutos
  • Máximo 100 solicitudes por hora por company_id
  • Máximo 1000 solicitudes por día por API Key

❌ 500 - Internal Server Error

Error interno del servidor.

{
  "error": "Internal server error",
  "request_id": "req_abc123xyz"
}

Solución: Si el error persiste, contacta a soporte técnico con el request_id.


🔄 Flujo de Integración

  1. Usuario ingresa su número telefónico
  2. Tu aplicación valida el formato del número
  3. Tu aplicación llama a /send-otp con Bearer Token
  4. JAAK envía OTP por SMS y WhatsApp
  5. Usuario recibe código (válido por 5 minutos)
  6. Usuario ingresa código en tu app
  7. Tu aplicación verifica el código con el session_id
  8. Verificación completada

⚙️ Mejores Prácticas

✅ Recomendaciones de Seguridad

Almacenamiento de API Key:

  • Usa variables de entorno
  • Nunca expongas la key en código frontend
  • Implementa rotación periódica (cada 90 días)

Validación de número telefónico:

  • Verifica el formato antes de enviar la petición
  • Debe incluir el código de país con el símbolo +
  • Sin espacios ni caracteres especiales

Manejo de errores:

  • Implementa retry logic para errores 429 y 500
  • Usa backoff exponencial entre reintentos
  • Registra errores sin exponer datos sensibles

✅ Recomendaciones de UX

Mensaje al usuario:

"Te enviamos un código de 6 dígitos por SMS y WhatsApp.
El código es válido por 5 minutos."

Consideraciones:

  • Muestra claramente el tiempo de expiración (5 minutos)
  • Guarda el session_id para verificación posterior
  • Solo almacena el session_id, nunca el código OTP
  • Limita los intentos de reenvío

❌ Errores comunes a evitar

  • ❌ Exponer la API Key en el código frontend
  • ❌ No validar el formato del número telefónico
  • ❌ No guardar el session_id
  • ❌ Permitir múltiples solicitudes sin límite
  • ❌ No informar sobre el tiempo de expiración
  • ❌ Hardcodear credenciales en el código
  • ❌ No implementar logging
  • ❌ No manejar rate limiting

🔒 Detalles de Seguridad

API Key

  • Formato: sk_live_ o sk_test_ seguido de 40 caracteres alfanuméricos
  • Almacenamiento: Variables de entorno o gestores de secretos
  • Scope: Cada API Key está asociada a un company_id específico

OTP

  • Código de 6 dígitos numéricos
  • Válido por 5 minutos desde el envío
  • Solo puede usarse una vez (single-use)
  • El session_id expira después de validar el código o transcurridos 10 minutos
  • Máximo 5 intentos de validación por session_id

Rate Limiting

Los límites se aplican por:

  • Número telefónico: 5 solicitudes cada 10 minutos
  • Company ID: 100 solicitudes por hora
  • API Key: 1000 solicitudes por día

📊 Códigos de País Soportados

PaísCódigo ISOFormato de Ejemplo
MéxicoMEX+525512345678
ColombiaCOL+573001234567
ArgentinaARG+541123456789
ChileCHL+56912345678
PerúPER+51987654321
BrasilBRA+551198765432

🧪 Ambiente de Pruebas

Base URL de Testing: https://api-sandbox.jaak.mx

Números de prueba:

  • +525500000001 - Siempre exitoso

📞 Soporte

¿Necesitas ayuda con la integración?

Información para tickets de soporte

  • Request ID (si aplica)
  • Timestamp del error
  • Código de status HTTP
  • Payload sanitizado (sin API keys ni datos sensibles)
  • Logs relevantes

📋 Checklist de Integración

Antes de ir a producción:

  • API Key de producción configurada
  • Bearer Token incluido en todas las peticiones
  • Validación de formato de número telefónico implementada
  • Manejo de todos los códigos de error
  • Retry logic para errores temporales
  • Almacenamiento seguro del session_id
  • Rate limiting implementado
  • Mensajes de error claros
  • Logging implementado
  • Timeout de 5 minutos mostrado
  • Pruebas en sandbox completadas
  • Monitoreo configurado