EN VIVO · CON AUDITORÍA · UE
SISTEMA · 99,99% UPTIME
v 1.0 ↗ HECHO EN UE

Errores + límites de tasa

Un único envoltorio de error en todos los endpoints. Códigos de estado HTTP estándar + una cadena code estructurada para la coincidencia programática. Cabeceras de límite de tasa en cada respuesta para que pueda regular su ritmo antes de alcanzar un 429.

Envoltorio de error

{
  "detail": "Human-readable summary.",
  "code": "billing.subscription_past_due",
  "field_errors": {
    "scheduled_for": ["Must be a future ISO 8601 timestamp."]
  }
}
  • detail: siempre presente, seguro para mostrar a personas (está traducido cuando el idioma está disponible).
  • code: presente para estados de error distinguibles. Estable entre versiones de la API; haga coincidir con este para la lógica de reintento.
  • field_errors: presente solo en los fallos de validación 400. Mapa de nombre-de-campo → lista de mensajes.

Matriz de códigos de estado

EstadoClase¿Reintentar?Causas comunes
400ValidaciónNoFalta un campo obligatorio, formato incorrecto, violación de regla de negocio
401AutenticaciónNoCredencial ausente / incorrecta / revocada
402FacturaciónNoSuscripción vencida, límite del plan gratuito alcanzado
403PermisoNoLa credencial carece del ámbito, o el recurso está en otra organización
404No encontradoNoEl recurso no existe, o no es visible para su credencial
409ConflictoA vecesDiscrepancia en la reutilización de Idempotency-Key, violación de máquina de estados
422No procesableNoCombinación semánticamente no válida de campos válidos
429Límite de tasaSí, con backoffEstrangulamiento por credencial o por organización alcanzado
500Error de servidorSí, con backoffInesperado: abra un ticket si persiste
502 / 503 / 504TransitorioSí, con backoffUpstream / despliegue / carga

Códigos de error notables

CódigoEstadoQué significa
billing.subscription_past_due402La suscripción de Stripe de la organización está vencida. Dirija al administrador a /admin/billing.
billing.free_plan_minutes_exhausted402El nivel Gratuito / Piloto ha usado sus 5 inspecciones.
billing.signature_pack_exhausted402Créditos del pack de firmas agotados; pague por firma o compre otro pack.
permission_denied403La credencial carece del ámbito. Consulte field_errors.required_scope.
idempotency.key_mismatch409Misma clave, cuerpo distinto. Use una clave nueva.
session.already_ended409Llamar a end en una sesión no abierta (normalmente seguro: end es idempotente, esto es para los casos límite).
kyb.not_verified403Se solicitó una firma QES en una organización que no ha superado el KYB.
rate_limited429Estrangulamiento por credencial (60 rpm) o por organización (600 rpm) alcanzado.

Cabeceras de límite de tasa

Cada respuesta, con éxito o error, lleva el estado del estrangulamiento:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 47
X-RateLimit-Reset: 1716461235
  • X-RateLimit-Limit: el tope que se aplica a esta petición.
  • X-RateLimit-Remaining: cuántas llamadas quedan en la ventana actual.
  • X-RateLimit-Reset: marca de tiempo Unix en la que se reinicia Remaining.

En un 429, también se establece Retry-After (en segundos) según RFC 6585.

Ámbitos de estrangulamiento

ÁmbitoLímiteVentana
Por credencial601 minuto
Por organización (en todas las credenciales)6001 minuto

Admite ráfagas durante el primer segundo de un minuto. Alcance el tope y las peticiones siguientes dentro de la ventana devuelven 429.

Estrategia de reintento

Backoff exponencial con jitter para 429 / 5xx; no reintente los 4xx (salvo 408, 425, 429):

async function withRetry<T>(fn: () => Promise<T>, max = 5): Promise<T> {
  let lastErr: unknown;
  for (let i = 0; i < max; i++) {
    try {
      return await fn();
    } catch (err: any) {
      const status = err?.status;
      if (status >= 400 && status < 500 && ![408, 425, 429].includes(status)) {
        throw err; // not retryable
      }
      const base = status === 429 ? (err.retryAfterMs ?? 1000) : 250 * 2 ** i;
      const jitter = Math.random() * base * 0.2;
      await new Promise((r) => setTimeout(r, base + jitter));
      lastErr = err;
    }
  }
  throw lastErr;
}

Los SDK implementan esto internamente en 429 + 5xx; si prefiere gestionar los reintentos usted mismo, establezca retries: 0 en las opciones del SDK.

Correlación de errores

Cada respuesta lleva una cabecera X-Request-Id (UUID). Cítela en cualquier ticket de soporte: podemos extraer la traza completa de la petición solo con ese id.

Qué sigue