recurso

Errores

Esta guía describe los códigos de error que pueden retornar las APIs de JAAK, junto con recomendaciones para resolverlos.

Formato de respuesta de error

Todas las respuestas de error siguen el mismo formato JSON:

{
  "error": {
    "code": "invalid_token",
    "message": "El token ha expirado",
    "status": 401,
    "details": {
      "expiredAt": "2024-01-15T10:30:00Z"
    }
  }
}
CampoDescripción
codeCódigo de error único para identificar el problema
messageDescripción legible del error
statusCódigo de estado HTTP
detailsInformación adicional específica del error (opcional)

Códigos de estado HTTP

400 Bad Request

La solicitud contiene errores de sintaxis o parámetros inválidos.

{
  "error": {
    "code": "invalid_request",
    "message": "El campo 'email' es requerido",
    "status": 400,
    "details": {
      "field": "email",
      "reason": "required"
    }
  }
}

Solución:

  • Verifica que todos los campos requeridos estén presentes
  • Comprueba que los tipos de datos sean correctos (string, number, etc.)
  • Revisa que los valores estén en formato válido (email, URL, fecha ISO 8601)

401 Unauthorized

Las credenciales son inválidas o no fueron proporcionadas.

{
  "error": {
    "code": "invalid_credentials",
    "message": "API Key o API Secret inválidos",
    "status": 401
  }
}

Solución:

  • Verifica que estés enviando los headers de autenticación correctos
  • Comprueba que las credenciales sean las correctas para el ambiente (sandbox vs producción)
  • Revisa que los tokens no hayan expirado

403 Forbidden

No tienes permisos para acceder al recurso solicitado.

{
  "error": {
    "code": "forbidden",
    "message": "No tienes permisos para acceder a este recurso",
    "status": 403
  }
}

Solución:

  • Verifica que tu plan incluya acceso a esta funcionalidad
  • Comprueba que el usuario tenga los permisos necesarios
  • Contacta a soporte si crees que deberías tener acceso

404 Not Found

El recurso solicitado no existe.

{
  "error": {
    "code": "not_found",
    "message": "Sesión no encontrada",
    "status": 404,
    "details": {
      "resourceType": "session",
      "resourceId": "ses_abc123xyz"
    }
  }
}

Solución:

  • Verifica que el ID del recurso sea correcto
  • Comprueba que el recurso exista en el ambiente correcto
  • El recurso pudo haber sido eliminado o expirado

422 Unprocessable Entity

La solicitud es válida pero no puede ser procesada debido a reglas de negocio.

{
  "error": {
    "code": "session_already_completed",
    "message": "La sesión ya fue completada y no puede modificarse",
    "status": 422,
    "details": {
      "sessionId": "ses_abc123xyz",
      "status": "completed"
    }
  }
}

Solución:

  • Revisa el estado actual del recurso antes de intentar modificarlo
  • Consulta la documentación para entender las transiciones de estado válidas

429 Too Many Requests

Has excedido el límite de solicitudes permitidas.

{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Has excedido el límite de solicitudes. Intenta de nuevo en 60 segundos",
    "status": 429,
    "details": {
      "retryAfter": 60,
      "limit": 100,
      "window": "1m"
    }
  }
}

Solución:

  • Implementa backoff exponencial en tu código
  • Respeta el header Retry-After en la respuesta
  • Considera cachear respuestas cuando sea posible
  • Contacta a soporte si necesitas un límite mayor

500 Internal Server Error

Error interno del servidor. No es tu culpa.

{
  "error": {
    "code": "internal_error",
    "message": "Ha ocurrido un error interno. Por favor intenta de nuevo",
    "status": 500,
    "details": {
      "requestId": "req_xyz789"
    }
  }
}

Solución:

  • Reintenta la solicitud después de unos segundos
  • Si el error persiste, contacta a soporte con el requestId

Request ID

Todas las respuestas incluyen un header X-Request-Id. Inclúyelo al contactar a soporte para que podamos identificar rápidamente tu solicitud.


Códigos de error específicos

Errores de autenticación

CódigoDescripciónSolución
invalid_api_keyAPI Key no válidaVerifica que la API Key sea correcta
invalid_api_secretAPI Secret no válidoVerifica que el API Secret sea correcto
invalid_tokenToken JWT inválidoObtén un nuevo token con sign-in
token_expiredToken JWT expiradoUsa el refresh token para renovar
refresh_token_expiredRefresh token expiradoInicia sesión nuevamente
credentials_mismatchCredenciales no coinciden con el ambienteUsa credenciales de sandbox o producción según corresponda

Errores de verificación (KYC)

CódigoDescripciónSolución
session_not_foundSesión no encontradaVerifica el ID de sesión
session_expiredLa sesión ha expiradoCrea una nueva sesión
session_already_completedLa sesión ya fue completadaConsulta el resultado con GET /sessions/{id}
session_cancelledLa sesión fue canceladaCrea una nueva sesión si es necesario
invalid_verification_typeTipo de verificación no válidoUsa uno de: kyc_full, liveness_only, face_match, document_only, document_validation
document_type_not_supportedTipo de documento no soportadoRevisa los tipos de documento permitidos
ine_validation_unavailableValidación con INE no disponibleServicio temporalmente no disponible, intenta más tarde

Errores de firma (Signa)

CódigoDescripciónSolución
template_not_foundPlantilla no encontradaVerifica el ID de plantilla
template_invalidLa plantilla tiene erroresRevisa la configuración de la plantilla en el dashboard
submission_not_foundEnvío no encontradoVerifica el ID de envío
submission_cancelledEl envío fue canceladoEl documento ya no puede firmarse
signer_not_foundFirmante no encontradoVerifica el ID o email del firmante
signature_already_completedEl firmante ya firmóNo se puede firmar dos veces
invalid_signature_typeTipo de firma no válidoUsa uno de: simple, electronic_advanced, electronic_qualified
pdf_processing_errorError al procesar el PDFVerifica que el PDF sea válido y no esté corrupto

Errores de validación

CódigoDescripciónSolución
field_requiredCampo requerido faltanteIncluye todos los campos obligatorios
field_invalidCampo con formato inválidoVerifica el formato del campo
field_too_longCampo excede el límiteReduce la longitud del valor
field_too_shortCampo muy cortoAumenta la longitud del valor
invalid_emailEmail con formato inválidoUsa un email válido
invalid_urlURL con formato inválidoIncluye el protocolo (https://)
invalid_dateFecha con formato inválidoUsa formato ISO 8601
invalid_jsonJSON mal formadoValida el JSON antes de enviar

Rate Limiting

Las APIs de JAAK implementan límites de solicitudes para garantizar la estabilidad del servicio.

Límites por defecto

PlanSolicitudes por minutoSolicitudes por hora
Sandbox601,000
Starter1005,000
Business50025,000
EnterprisePersonalizadoPersonalizado

Headers de rate limit

Cada respuesta incluye headers con información del límite:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1705315200
HeaderDescripción
X-RateLimit-LimitLímite de solicitudes por ventana
X-RateLimit-RemainingSolicitudes restantes en la ventana actual
X-RateLimit-ResetTimestamp Unix cuando se reinicia el límite

Manejo de rate limits

Implementa backoff exponencial cuando recibas un error 429:

async function apiCallWithRetry(fn, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await fn();
    } catch (error) {
      if (error.status === 429 && attempt < maxRetries - 1) {
        const retryAfter = error.details?.retryAfter || Math.pow(2, attempt);
        console.log(`Rate limited. Esperando ${retryAfter} segundos...`);
        await sleep(retryAfter * 1000);
      } else {
        throw error;
      }
    }
  }
}

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

Optimiza tus solicitudes

Para reducir el número de solicitudes:

  • Usa webhooks en lugar de polling
  • Cachea respuestas cuando sea posible
  • Agrupa operaciones cuando la API lo permita

Errores de verificación de identidad

Estos errores ocurren durante el proceso de verificación y se reportan en el resultado de la sesión.

Errores de documento

CódigoDescripciónRecomendación
DOCUMENT_NOT_READABLENo se pudo leer el documentoPide al usuario que tome una foto más clara
DOCUMENT_EXPIREDEl documento está vencidoPide al usuario que use un documento vigente
DOCUMENT_ALTEREDSe detectaron alteracionesPosible fraude, revisar manualmente
DOCUMENT_NOT_SUPPORTEDTipo de documento no soportadoIndica los tipos de documento aceptados
DOCUMENT_WRONG_COUNTRYDocumento de país no soportadoSolo se aceptan documentos mexicanos
DOCUMENT_PHOTO_MISSINGNo se encontró foto en el documentoVerifica que sea el frente del documento

Errores de liveness

CódigoDescripciónRecomendación
LIVENESS_FAILEDFalló la prueba de vidaPuede ser intento de fraude o mala iluminación
SPOOF_DETECTEDSe detectó intento de suplantaciónPosible fraude con foto o video
FACE_NOT_DETECTEDNo se detectó rostroPide al usuario que centre su rostro
MULTIPLE_FACESSe detectaron múltiples rostrosSolo una persona debe estar en la imagen
FACE_TOO_SMALLRostro muy pequeño en la imagenPide al usuario que se acerque
POOR_LIGHTINGIluminación deficientePide mejor iluminación

Errores de face match

CódigoDescripciónRecomendación
FACE_MISMATCHEl rostro no coincide con el documentoPosible fraude o documento de otra persona
LOW_CONFIDENCEBaja confianza en la coincidenciaConsidera revisión manual
SELFIE_QUALITY_LOWCalidad de selfie insuficientePide una mejor foto
DOCUMENT_PHOTO_QUALITY_LOWCalidad de foto del documento bajaPide mejor foto del documento

Errores de validación INE

CódigoDescripciónRecomendación
INE_NOT_FOUNDINE no encontrada en el padrónVerifica que los datos sean correctos
INE_CANCELLEDINE cancelada o reportadaEl documento no es válido
INE_EXPIREDINE vencida según el padrónEl documento no es válido
INE_SERVICE_UNAVAILABLEServicio de INE no disponibleIntenta más tarde

Manejo de errores en tu código

Ejemplo completo

class JAAKError extends Error {
  constructor(response) {
    super(response.error.message);
    this.code = response.error.code;
    this.status = response.error.status;
    this.details = response.error.details;
  }
}

async function callJAAKAPI(endpoint, options) {
  const response = await fetch(`https://api.jaak.ai${endpoint}`, {
    ...options,
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': API_KEY,
      'X-API-Secret': API_SECRET,
      ...options.headers
    }
  });

  const data = await response.json();

  if (!response.ok) {
    throw new JAAKError(data);
  }

  return data;
}

// Uso con manejo de errores
async function createSession(verificationType) {
  try {
    const session = await callJAAKAPI('/api/v1/sessions', {
      method: 'POST',
      body: JSON.stringify({ verificationType })
    });
    return session;
  } catch (error) {
    if (error instanceof JAAKError) {
      switch (error.code) {
        case 'rate_limit_exceeded':
          console.log('Esperando antes de reintentar...');
          await sleep(error.details.retryAfter * 1000);
          return createSession(verificationType);

        case 'invalid_credentials':
          console.error('Credenciales inválidas. Verifica tu API Key y Secret.');
          throw error;

        case 'forbidden':
          console.error('No tienes acceso a este tipo de verificación.');
          throw error;

        default:
          console.error(`Error de JAAK: ${error.message} (${error.code})`);
          throw error;
      }
    }
    throw error;
  }
}

Contactar a soporte

Si encuentras un error que no puedes resolver:

  1. Incluye el Request-Id del header de respuesta
  2. Describe los pasos para reproducir el error
  3. Incluye el código de error y mensaje completo
  4. Indica el ambiente (sandbox o producción)

Email: soporte@jaak.ai

Horario de soporte

Nuestro equipo de soporte está disponible de lunes a viernes de 9:00 a 18:00 (hora Ciudad de México). Para emergencias fuera de horario, contacta a tu ejecutivo de cuenta.


Siguientes pasos

  • Webhooks - Configura notificaciones en tiempo real
  • Sandbox - Prueba tu integración sin afectar producción