Skip to content

Manejo de errores

Formato de respuesta de error

Todos los errores de la API siguen una estructura JSON consistente con un código de estado HTTP apropiado:

json
{
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable description of what went wrong"
  }
}

El campo code es un identificador estable y legible por máquinas que puedes usar en tu lógica de manejo de errores. El campo message proporciona contexto adicional y puede variar entre ocurrencias del mismo código de error.

Categorías de errores

Errores de autenticación (401)

Se devuelven cuando la solicitud no puede ser autenticada.

CódigoDescripción
UNAUTHORIZEDEl encabezado Authorization falta, está mal formado o contiene un token inválido.
KEY_EXPIREDLa clave API era válida pero ha pasado su fecha de expiración. Crea una nueva clave para continuar.
json
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Missing or invalid Authorization header"
  }
}

Errores de autorización (403)

Se devuelven cuando el usuario autenticado no tiene permiso para acceder al recurso solicitado.

CódigoDescripción
FORBIDDENEstás intentando acceder o modificar un recurso que pertenece a otro usuario (por ejemplo, revocar la clave API de otra persona).

Errores de no encontrado (404)

Se devuelven cuando el recurso solicitado no existe.

CódigoDescripción
NOT_FOUNDEl recurso identificado en la URL (extracción, clave API, etc.) no existe o ha sido eliminado.

Errores de validación (400)

Se devuelven cuando el cuerpo de la solicitud o los parámetros son inválidos.

CódigoDescripción
VALIDATION_ERROREl cuerpo de la solicitud no pasó la validación del esquema. El campo message describe qué campos son inválidos.
MAX_KEYS_REACHEDHas alcanzado el máximo de 10 claves API activas. Revoca una clave existente antes de crear una nueva.
json
{
  "error": {
    "code": "MAX_KEYS_REACHED",
    "message": "Maximum of 10 active API keys allowed"
  }
}

Errores de límite de uso (429)

Se devuelven cuando se han excedido los límites de uso.

CódigoDescripción
USAGE_LIMIT_EXCEEDEDSe ha alcanzado tu límite mensual de extracciones. Mejora tu plan o espera hasta el próximo período de facturación.
json
{
  "error": {
    "code": "USAGE_LIMIT_EXCEEDED",
    "message": "Monthly extraction limit reached (25/25). Upgrade your plan for more extractions."
  }
}

Errores del servidor (500)

Se devuelven cuando algo inesperado ocurre en el lado del servidor.

CódigoDescripción
INTERNAL_ERROROcurrió un error inesperado del servidor. Estos se registran e investigan automáticamente.
EXTRACTION_FAILEDEl pipeline de procesamiento con IA encontró un error al extraer datos de tu documento. El documento puede estar corrupto, ilegible o en un formato no compatible.

Errores reintentables

No todos los errores deben reintentarse. Aquí hay un desglose:

CódigoReintentableAcción
INTERNAL_ERRORReintentar con retroceso exponencial
EXTRACTION_FAILEDReintentar -- la IA puede producir un resultado diferente. Si persiste, verificar la calidad del documento
USAGE_LIMIT_EXCEEDEDNoMejorar tu plan o esperar hasta el próximo período de facturación
UNAUTHORIZEDNoCorregir tus credenciales de autenticación
KEY_EXPIREDNoCrear una nueva clave API
FORBIDDENNoEstás accediendo a un recurso que no te pertenece
NOT_FOUNDNoEl recurso no existe -- verificar el ID
VALIDATION_ERRORNoCorregir el cuerpo de la solicitud para que coincida con el esquema esperado
MAX_KEYS_REACHEDNoRevocar una clave existente antes de crear una nueva

Estrategia de reintento

Para errores reintentables, usa retroceso exponencial para evitar sobrecargar el servidor. Aquí hay una implementación reutilizable:

typescript
interface ApiResponse<T> {
  data?: T;
  error?: { code: string; message: string };
}

async function fetchWithRetry<T>(
  url: string,
  options: RequestInit,
  maxRetries = 3,
): Promise<ApiResponse<T>> {
  let lastError: Error | null = null;

  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      const response = await fetch(url, options);
      const body = await response.json();

      if (response.ok) {
        return body as ApiResponse<T>;
      }

      const errorCode = body?.error?.code;

      // Only retry server errors
      if (
        (errorCode === "INTERNAL_ERROR" || errorCode === "EXTRACTION_FAILED") &&
        attempt < maxRetries
      ) {
        const delayMs = 1000 * Math.pow(2, attempt); // 1s, 2s, 4s
        console.log(`Retrying in ${delayMs}ms (attempt ${attempt + 1}/${maxRetries})...`);
        await new Promise((resolve) => setTimeout(resolve, delayMs));
        continue;
      }

      // Non-retryable error -- return immediately
      return body as ApiResponse<T>;
    } catch (err) {
      lastError = err as Error;

      if (attempt < maxRetries) {
        const delayMs = 1000 * Math.pow(2, attempt);
        await new Promise((resolve) => setTimeout(resolve, delayMs));
        continue;
      }
    }
  }

  throw lastError ?? new Error("Max retries exceeded");
}

Uso:

typescript
const result = await fetchWithRetry<ExtractionResult>(
  "https://api.docmap.io/v1/extractions/run",
  {
    method: "POST",
    headers: {
      Authorization: `Bearer ${apiKey}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      templateId: "tmpl_abc123",
      fileName: "invoice.pdf",
      pdfBase64: encodedPdf,
      mimeType: "application/pdf",
    }),
  },
);

if (result.error) {
  console.error(`Extraction failed: [${result.error.code}] ${result.error.message}`);
} else {
  console.log("Extracted data:", result.data);
}

Mejores prácticas

  • Siempre verifica primero el código de estado HTTP. Un estado 2xx significa éxito; cualquier otra cosa es un error. No asumas que el cuerpo de la respuesta tiene un campo data sin verificar.

  • Analiza el cuerpo del error para obtener el campo code. Usa code (no message) en tu flujo de control. Los mensajes de error pueden cambiar con el tiempo, pero los códigos de error son estables.

  • Maneja códigos de error específicos. Ramifica según códigos conocidos como USAGE_LIMIT_EXCEEDED o KEY_EXPIRED para mostrar mensajes específicos a tus usuarios o activar flujos de trabajo particulares.

  • Registra los errores desconocidos. Si encuentras un código de error que no manejas explícitamente, registra la respuesta completa (código de estado, código de error y mensaje) para depuración.

  • No reintentes errores 4xx. Los errores de autenticación, autorización, validación y no encontrado no se resolverán por sí solos. Corrige el problema subyacente antes de reintentar.

  • Establece un límite de reintentos. Nunca reintentes indefinidamente. Tres reintentos con retroceso exponencial (1s, 2s, 4s) es un valor predeterminado razonable para errores del servidor.

Documentación de la API de DocMap