Contratos
Erros
Um envelope só, sempre — code, message e request_id. Aqui estão os 14 codes, com o que fazer em cada um.
Toda resposta de erro da API — em qualquer rota, qualquer status — usa o mesmo formato. Nunca um HTML de erro, nunca um corpo vazio.
O envelope
{
"error": {
"code": "forbidden_scope",
"message": "A chave não tem o(s) escopo(s): contacts.write.",
"request_id": "req-a1b2c3d4e5f6"
}
}code é contrato, message não
code é estável: programe em cima dele (retry, mensagem para o seu usuário, alerta). message é texto em português para humano, e pode mudar de redação sem aviso — não case string dela.
Reportando um erro pra gente
Toda resposta — erro ou sucesso — já vem com o header x-request-id, e nos erros ele aparece de novo dentro do corpo, como request_id (o mesmo valor nos dois lugares). Se algo falhar de um jeito que não faz sentido, esse id é o que a gente precisa para achar a chamada exata nos nossos registros — rota, status, latência, IP. Reportar o id resolve em minutos o que "deu erro hoje de manhã" não resolve num dia.
Uma exceção conhecida: os 429 de /api/v1/docs e /api/v1/openapi.json (as duas rotas que não pedem chave) vêm sem request_id. Se você tipou o envelope, trate o campo como opcional.
Todos os codes
| Status | code | Quando | O que fazer |
|---|---|---|---|
| 400 | validation_error | Corpo ou parâmetro fora do formato, cursor inválido, data ilegível, campo personalizado desconhecido, evento de webhook sem o escopo de leitura. | Não repita igual — a mensagem nomeia o campo. Roda antes da autenticação: corpo inválido sem token dá 400, não 401. |
| 401 | unauthorized | Sem token, token que não começa com gos_, chave desconhecida, revogada, expirada, ou token antigo depois da janela de rotação. | Não faça retry cego: 20 falhas/min pelo mesmo IP viram 429. Confira a chave. |
| 403 | forbidden_scope | A chave não tem o escopo que a rota exige — a mensagem diz qual. | Edite os escopos da chave na tela; vale em até 60 s. |
| 403 | forbidden_ip | A chave tem allowlist de IP e a chamada veio de fora dela. | Some o IP de saída do seu servidor à allowlist. |
| 403 | forbidden_platform | /platform/* chamado por chave que não é do workspace da Accelera. | Não é configuração: a rota é exclusiva daquela conta. |
| 403 | workspace_suspended | O workspace está pausado. | Nada a fazer pela API — retry não adianta enquanto a conta não voltar. |
| 403 | forbidden | Recusa sem código específico: uma regra do Núcleo negou a ação. | Leia a message — é regra de negócio, não permissão de chave. |
| 404 | not_found | Recurso inexistente — ou existente em outro workspace, o que nunca revelamos. É também a resposta de rota inexistente, com a mensagem "Rota não encontrada em /api/v1.". | Confira o id e o caminho. Não retente. |
| 409 | idempotency_conflict | A mesma Idempotency-Key já foi usada nesta rota com um corpo diferente. | Gere uma chave nova — veja idempotência. |
| 409 | conflict | O estado atual não permite: ação duplicada ainda em processamento, ou Ação que terminou em estado inesperado. | Releia o recurso antes de decidir; pode ser retry curto. |
| 413 | payload_too_large | Duas causas. Corpo HTTP acima de 256 KB; ou os argumentos da escrita acima de 7,5 KB — o teto da trilha de auditoria, que é o menor e o que quase sempre dispara. | Reduza campos grandes (notes, customFields). Retry nunca resolve. |
| 415 | unprocessable | Content-Type não é application/json numa rota com corpo. | Mande o header. Repare que o code é o mesmo do 422 — o que distingue é o status. |
| 422 | unprocessable | Passou no formato, mas a regra do CRM recusou: horário ocupado, agenda arquivada, campo personalizado desconhecido, ou o registro foi escrito e não pôde ser lido de volta. | Leia a message — é o balde das regras de negócio. |
| 429 | rate_limited | Estourou o teto global, o teto por rota, o teto diário, ou o balde de autenticação inválida por IP. | Espere o Retry-After (segundos). Veja limites de uso. |
| 500 | internal_error | Bug nosso. | Retente com backoff e guarde o request_id. Todo 5xx já dispara alerta interno do nosso lado. |
Quais status cada tipo de rota pode devolver
O documento OpenAPI declara os status de cada uma das 42 operações, e a referência mostra uma aba por status. O padrão:
| Vale para | Status |
|---|---|
| Todas as 42 operações | 401, 403, 429, 500 |
| As 29 que aceitam querystring ou corpo | + 400 |
As 25 que têm :id no caminho | + 404 |
| As 18 escritas com corpo | + 413, 415 |
| As 17 escritas que passam pelo Núcleo | + 409, 422 |
| As 7 que criam registro | + 201 |
As duas escritas de webhook (POST e PATCH /webhooks) são as que têm 413/415 sem 409/422: elas não passam pelo Núcleo, então nunca emitem idempotency_conflict nem erro de regra de Ação.