ReferenciaErrores

Errores

Todos los códigos de error de la API de Certivant explicados: forma de la respuesta, correspondencia con los códigos de estado HTTP, orientación de manejo para cada código y un envoltorio de reintento robusto que puede incorporar en su integración.

Cada respuesta de error de la API de Certivant sigue la misma forma. Cree un único manejador de errores que procese esta forma y podrá gestionar todos los endpoints de manera uniforme.

Forma de la respuesta

{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Body validation failed.",
    "fields": {
      "applicant.dateOfBirth": "Invalid date format. Expected YYYY-MM-DD.",
      "applicant.nationality": "Must be a 2-character ISO 3166-1 alpha-2 code."
    }
  }
}
CampoTipoNotas
successbooleanSiempre false en los errores
error.codestringLegible por máquinas. Use este valor para el control de flujo
error.messagestringLegible por personas. Es seguro registrarlo en logs; no es seguro mostrarlo directamente a los solicitantes
error.fieldsobjectSolo está presente en VALIDATION_ERROR. Asocia las rutas de campo en notación de puntos con los mensajes de error de cada campo

Las cadenas message de error no están garantizadas como estables entre versiones. Use code para cualquier lógica; trate message como ayuda para registros y para el desarrollador.

Código de estado HTTP → código de error

HTTPerror.code habitualSignificado
400VALIDATION_ERROREl cuerpo de la solicitud no superó la validación de Zod. Revise fields
400BAD_REQUESTSolicitud incorrecta genérica (por ejemplo, enviar antes de cargar todos los documentos)
401UNAUTHORIZEDClave de API ausente, mal formada, revocada o caducada
402verification_unavailableLa organización no tiene crédito disponible y no está configurada para continuar sin crédito
403FORBIDDENLa clave es válida pero no tiene el ámbito requerido, procede de una dirección fuera de su lista de IP permitidas, está restringida a otros formularios o el recurso pertenece a otra organización
404NOT_FOUNDEl recurso (req_…, doc_…, etc.) no existe o no es visible para la organización de esta clave
409CONFLICTTransición de estado no permitida (por ejemplo, enviar una solicitud dos veces) o infracción de una restricción de unicidad (externalRef ya en uso)
413BAD_REQUESTCarga de archivo superior a 10 MB
415BAD_REQUESTContent-Type no admitido por el endpoint (por ejemplo, un cuerpo JSON enviado a un endpoint multipart)
429RATE_LIMITEDSe superó el límite de solicitudes por minuto. Consulte Límites de solicitudes
500INTERNAL_ERRORError inesperado del servidor. Siempre se registra en nuestro lado; reintentar es seguro
502BAD_GATEWAYUn servicio de origen (proveedor de sanciones, pasarela de pago, registro) no está disponible. Reintente tras una espera
503SERVICE_UNAVAILABLEBase de datos degradada. Reintente con retroceso exponencial

Catálogo de códigos de error

UNAUTHORIZED

La clave de API del encabezado Authorization falta, está mal formada o ha sido revocada.

{ "success": false, "error": { "code": "UNAUTHORIZED", "message": "Invalid or revoked API key." } }

error.reason le indica cuál de los casos es: missing_api_key, invalid_api_key, api_key_revoked, api_key_expired o api_key_rotated (la clave fue rotada y su periodo de solapamiento ha terminado). La lista completa está en Autenticación.

Cómo actuar: Confirme que el encabezado es Authorization: Bearer ck_live_… (o ck_test_…; las claves antiguas empiezan por kyk_). Compruebe en el panel el estado de la clave. Si aparece como revocada o caducada, cree una clave nueva o rótela.

FORBIDDEN

La clave es válida pero no tiene el ámbito requerido, o el recurso pertenece a una organización distinta de la de la clave.

{ "success": false, "error": { "code": "FORBIDDEN", "message": "This API key does not include the kyc:manage scope required for this endpoint." } }

error.reason es insufficient_scope (a la clave le falta un ámbito), ip_not_allowed (la dirección del llamador no está en la lista de IP permitidas de la clave) o form_not_allowed (la clave está restringida a otros formularios).

Cómo actuar: Revise los ámbitos y restricciones de su clave en el panel (KYC → Desarrollador, el icono del lápiz). Puede editar los permisos de una clave, sus restricciones de formularios y workflows, la lista de IP permitidas y la caducidad sin cambiar su secreto; el secreto y el entorno (producción o pruebas) no pueden cambiarse.

verification_unavailable (HTTP 402)

Su organización no tiene crédito disponible y no está configurada para continuar sin crédito, así que Certivant no puede aceptar una nueva verificación. La respuesta usa el código verification_unavailable:

{ "success": false, "error": { "code": "verification_unavailable", "message": "This organization is temporarily unable to accept new verifications. Please contact them to continue." } }

Cómo actuar: Recargue el saldo de crédito en Configuración → Créditos y uso (sus propietarios y administradores también reciben una notificación y un correo, como máximo una vez al día). Los solicitantes que se encuentren con la misma situación en un formulario o en una página alojada verán una página que les pide contactar con su organización; la página nunca menciona créditos ni dinero. Consulte Facturación y créditos.

NOT_FOUND

{ "success": false, "error": { "code": "NOT_FOUND", "message": "Request not found." } }

Cómo actuar: Verifique el ID del recurso. Una causa habitual es usar un ID de otro entorno: los IDs de staging no existen en producción, y viceversa.

VALIDATION_ERROR

El cuerpo de la solicitud no superó la validación del esquema. El mapa fields enumera cada campo fallido con su mensaje.

{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Body validation failed.",
    "fields": {
      "type": "Required",
      "applicant.email": "Invalid email format"
    }
  }
}

Cómo actuar: Muestre fields junto a los campos de su formulario. Las rutas de campo usan notación de puntos para los campos anidados y [N] para los índices de array (directors[0].dateOfBirth).

BAD_REQUEST

Solicitud incorrecta genérica que no encaja en las otras categorías.

{ "success": false, "error": { "code": "BAD_REQUEST", "message": "Cannot submit a request with pending documents. Upload the remaining documents first." } }

Cómo actuar: Lea el message. Normalmente indican un problema de secuencia: llame primero al endpoint prerrequisito.

CONFLICT

Una transición de estado que no es legal desde el estado actual, o una infracción de una restricción de unicidad.

{ "success": false, "error": { "code": "CONFLICT", "message": "externalRef already in use by request req_…" } }

Cómo actuar: Consulte el estado actual de la solicitud mediante GET /requests/:id y ajústelo. En caso de infracción de unicidad de la referencia, o bien recupere la solicitud existente (con ?externalRef=… en el endpoint de listado), o bien elija otra referencia.

RATE_LIMITED

{ "success": false, "error": { "code": "RATE_LIMITED", "message": "Rate limit exceeded. Max 120 requests per 60s. Retry in 14s." } }

Las cabeceras de esta respuesta incluyen X-RateLimit-Limit, X-RateLimit-Remaining y X-RateLimit-Reset (segundos hasta que el cubo se rellena de nuevo). Consulte Límites de solicitudes para la estrategia de reintento.

INTERNAL_ERROR

Algo falló en nuestro lado. Certivant registra cada 500 con todo el contexto.

{ "success": false, "error": { "code": "INTERNAL_ERROR", "message": "An unexpected error occurred. Please try again." } }

Cómo actuar: Reintente una vez tras una breve espera. Si persiste, consulte la página de estado y contacte con soporte indicando el ID de la solicitud.

BAD_GATEWAY y SERVICE_UNAVAILABLE

Una dependencia de origen no está disponible (API del registro mercantil, proveedor de datos de sanciones, almacenamiento) o la base de datos está degradada.

{ "success": false, "error": { "code": "BAD_GATEWAY", "message": "Sanctions screening provider is unreachable. The request remains in PENDING state — Certivant will retry automatically." } }

Cómo actuar: Trátelos como transitorios. Implemente un retroceso exponencial (1 s, 2 s, 4 s, 8 s, 16 s) y deténgase tras unos 5 intentos. La solicitud no se pierde: la cola propia de Certivant reanudará el procesamiento cuando el servicio de origen se recupere.

Un manejador de errores robusto

async function callCertivant<T>(
  fn: () => Promise<Response>,
  options: { maxRetries?: number } = {},
): Promise<T> {
  const maxRetries = options.maxRetries ?? 3;
  let attempt = 0;
  let delay = 500;

  while (true) {
    const res = await fn();

    if (res.ok) return (await res.json()) as T;

    const body = (await res.json().catch(() => null)) as
      | { error?: { code: string; message: string } }
      | null;
    const code = body?.error?.code ?? "INTERNAL_ERROR";

    // Retry on transient errors
    if (
      attempt < maxRetries &&
      (res.status === 429 || res.status >= 500)
    ) {
      const retryAfter =
        res.status === 429
          ? Number(res.headers.get("X-RateLimit-Reset") ?? 60) * 1000
          : delay;
      await sleep(retryAfter);
      delay *= 2;
      attempt += 1;
      continue;
    }

    // Bubble everything else up
    throw new CertivantError(code, body?.error?.message ?? "Unknown error", res.status);
  }
}

Este patrón gestiona todos los errores documentados anteriormente:

  • Respuestas de clase 200 → procesar y devolver.
  • 429 → esperar a X-RateLimit-Reset y reintentar.
  • 5xx → retroceso exponencial y reintento.
  • 4xx → lanzar de inmediato (su código es incorrecto; ningún reintento lo arreglará).