AO VIVO · AUDIT CHAIN · UE
SISTEMA · 99,99% DISPONIBILIDADE
v 1.0 ↗ FEITO NA UE

Erros + limites de taxa

Um envelope de erro em todos os endpoints. Códigos de estado HTTP padrão + uma string code estruturada para correspondência programática. Cabeçalhos de limite de taxa em cada resposta para poder regular o seu ritmo antes de atingir um 429.

Envelope de erro

{
  "detail": "Human-readable summary.",
  "code": "billing.subscription_past_due",
  "field_errors": {
    "scheduled_for": ["Must be a future ISO 8601 timestamp."]
  }
}
  • detail — sempre presente, seguro para mostrar a humanos (é traduzido onde o locale está disponível).
  • code — presente para estados de erro distinguíveis. Estável entre versões da API; faça a correspondência neste para a lógica de retentativa.
  • field_errors — presente apenas em falhas de validação 400. Mapa de nome-de-campo → lista de mensagens.

Matriz de códigos de estado

EstadoClasseRetentar?Causas comuns
400ValidaçãoNãoCampo obrigatório em falta, formato inválido, violação de regra de negócio
401AutenticaçãoNãoCredencial em falta / inválida / revogada
402FaturaçãoNãoSubscrição em atraso, limite do plano gratuito atingido
403PermissãoNãoA credencial não tem o scope, ou o recurso está numa organização diferente
404Não encontradoNãoO recurso não existe, ou não é visível para a sua credencial
409ConflitoPor vezesReutilização incompatível de Idempotency-Key, violação da máquina de estados
422Não processávelNãoCombinação semanticamente inválida de campos válidos
429Taxa limitadaSim, com backoffThrottle por credencial ou por organização atingido
500Erro de servidorSim, com backoffInesperado — abra um ticket se persistir
502 / 503 / 504TransitórioSim, com backoffUpstream / deploy / carga

Códigos de erro notáveis

CódigoEstadoO que significa
billing.subscription_past_due402A subscrição Stripe da organização está em atraso. Encaminhe o administrador para /admin/billing.
billing.free_plan_minutes_exhausted402O escalão Free / Pilot usou as suas 5 inspeções.
billing.signature_pack_exhausted402Créditos do pacote de assinaturas esgotados; pague por assinatura ou compre outro pacote.
permission_denied403A credencial não tem o scope. Ver field_errors.required_scope.
idempotency.key_mismatch409Mesma chave, corpo diferente. Use uma chave nova.
session.already_ended409Chamar end numa sessão não aberta (normalmente seguro — end é idempotente, isto é para os casos-limite).
kyb.not_verified403Assinatura QES pedida numa organização que ainda não passou o KYB.
rate_limited429Throttle por credencial (60 rpm) ou por organização (600 rpm) atingido.

Cabeçalhos de limite de taxa

Cada resposta — sucesso ou erro — transporta o estado do throttle:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 47
X-RateLimit-Reset: 1716461235
  • X-RateLimit-Limit — o limite que se aplica a este request.
  • X-RateLimit-Remaining — quantas chamadas restam na janela atual.
  • X-RateLimit-Reset — timestamp Unix em que Remaining é reposto.

Num 429, Retry-After também é definido (em segundos) conforme o RFC 6585.

Scopes de throttle

ScopeLimiteJanela
Por credencial601 minuto
Por organização (em todas as credenciais)6001 minuto

Comporta rajadas no primeiro segundo de um minuto. Atinja o limite e os requests seguintes dentro da janela recebem 429.

Estratégia de retentativa

Backoff exponencial com jitter para 429 / 5xx; não retente 4xx (exceto 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;
}

Os SDKs implementam isto internamente em 429 + 5xx; se preferir tratar as retentativas você mesmo, defina retries: 0 nas opções do SDK.

Correlação de erros

Cada resposta transporta um cabeçalho X-Request-Id (UUID). Cite-o em qualquer ticket de suporte — conseguimos obter o trace completo do request apenas a partir desse id.

O que vem a seguir