Erros
Todos os erros compartilham um envelope único:
{
"error": {
"code": "validation_failed",
"message": "Field 'email' is required",
"details": {
"field": "email"
}
}
}
codeé um identificador machine-readable. Estável entre releases.messageé texto legível em inglês. Não fornecemos strings localizadas — traduza no consumidor.detailsé opcional e específico ao tipo de erro. Para validation errors inclui o campo ofensor; para rate-limit incluiretry_afternumérico.
Códigos padrão
| HTTP | code | Quando |
|---|---|---|
| 400 | bad_request | JSON malformado, Content-Type não suportado, etc. |
| 400 | validation_failed | Body/query falharam na validação. |
| 401 | mtls_required | Certificado cliente ausente/inválido. |
| 401 | invalid_token | JWT malformado ou assinatura inválida. |
| 401 | invalid_audience | aud não corresponde ao ambiente. |
| 401 | token_expired | Claim exp no passado. |
| 401 | token_revoked | jti listado em RevokedTokens. |
| 403 | insufficient_scope | Token sem o scope exigido. |
| 403 | insufficient_permission | A pessoa por trás do token não tem a permissão que o endpoint exige; message é o slug da permissão. |
| 403 | forbidden | Origin shared-secret ausente/errado, ou o token não resolve para nenhum tenant — message é unknown_organization, no_membership ou unknown_workspace. Veja Autenticação. |
| 400 | workspace_required | A organização tem vários workspaces e o X-Workspace-Id não foi enviado. |
| 404 | not_found | Recurso inexistente (ou pertence a outro workspace). |
| 409 | conflict | Conflito de estado (X-Idempotency-Key reutilizada com body diferente, violação de unique constraint). |
| 422 | unprocessable_entity | Violação de regra de negócio (ex.: não dá pra desativar um webhook com retries ativos). |
| 429 | rate_limited | Limite por conta excedido. Inclui header Retry-After. |
| 500 | internal_error | Erro não tratado. ID de correlação em details.request_id. |
| 503 | service_unavailable | Dependência upstream (S3, DB, AI Gateway) com falha. |
Lendo details
details é intencionalmente loose. Padrões comuns:
- Erros de validação —
{ "field": "subscribed_events.0", "issue": "must be a known SystemEvent slug" }. - Rate limiting —
{ "retry_after": 17, "limit": 600, "remaining": 0 }. - Conflito de idempotência —
{ "key": "...", "original_status": 201, "original_response_id": "..." }. - Not found entre workspaces — nunca vaza a existência do recurso; a resposta é indistinguível de um id realmente inexistente.
Correlação
Toda resposta — bem-sucedida ou não — carrega o header X-Request-Id. Inclua-o ao reportar problemas para podermos buscar o trace no OpenTelemetry.
Guia de retry
| Classe de erro | Retry? |
|---|---|
400, 401, 403, 404, 409, 422 | Não — corrija a requisição. |
429 | Sim, após Retry-After segundos. |
500, 503 | Sim, com backoff exponencial (começa em 1s, cap 30s, máx 5 tentativas). |
Para operações idempotentes (GET, PATCH, DELETE) o retry é sempre seguro. Para POST sempre inclua X-Idempotency-Key para que retries não dupliquem.