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
| Estado | Classe | Retentar? | Causas comuns |
|---|---|---|---|
| 400 | Validação | Não | Campo obrigatório em falta, formato inválido, violação de regra de negócio |
| 401 | Autenticação | Não | Credencial em falta / inválida / revogada |
| 402 | Faturação | Não | Subscrição em atraso, limite do plano gratuito atingido |
| 403 | Permissão | Não | A credencial não tem o scope, ou o recurso está numa organização diferente |
| 404 | Não encontrado | Não | O recurso não existe, ou não é visível para a sua credencial |
| 409 | Conflito | Por vezes | Reutilização incompatível de Idempotency-Key, violação da máquina de estados |
| 422 | Não processável | Não | Combinação semanticamente inválida de campos válidos |
| 429 | Taxa limitada | Sim, com backoff | Throttle por credencial ou por organização atingido |
| 500 | Erro de servidor | Sim, com backoff | Inesperado — abra um ticket se persistir |
| 502 / 503 / 504 | Transitório | Sim, com backoff | Upstream / deploy / carga |
Códigos de erro notáveis
| Código | Estado | O que significa |
|---|---|---|
billing.subscription_past_due | 402 | A subscrição Stripe da organização está em atraso. Encaminhe o administrador para /admin/billing. |
billing.free_plan_minutes_exhausted | 402 | O escalão Free / Pilot usou as suas 5 inspeções. |
billing.signature_pack_exhausted | 402 | Créditos do pacote de assinaturas esgotados; pague por assinatura ou compre outro pacote. |
permission_denied | 403 | A credencial não tem o scope. Ver field_errors.required_scope. |
idempotency.key_mismatch | 409 | Mesma chave, corpo diferente. Use uma chave nova. |
session.already_ended | 409 | Chamar end numa sessão não aberta (normalmente seguro — end é idempotente, isto é para os casos-limite). |
kyb.not_verified | 403 | Assinatura QES pedida numa organização que ainda não passou o KYB. |
rate_limited | 429 | Throttle 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 queRemainingé reposto.
Num 429, Retry-After também é definido (em segundos) conforme o RFC 6585.
Scopes de throttle
| Scope | Limite | Janela |
|---|---|---|
| Por credencial | 60 | 1 minuto |
| Por organização (em todas as credenciais) | 600 | 1 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
- Autenticação — rotação de credenciais se estiver a ver 401s
- Paginação + idempotência — os padrões que interagem com as retentativas