Erros
Os códigos de resposta da API pública, o formato do corpo de erro e como tratar cada caso.
Os erros da API pública seguem o RFC 7807, servido como
application/problem+json. É um objeto JSON com os mesmos campos, qualquer que
seja o problema. Isso permite um único tratador de erro no seu código, em vez de
um if por endpoint.
{
"type": "/errors/not-found",
"title": "Recurso não encontrado",
"status": 404,
"detail": "Produto com id '8f14e45f-ea6d-4a1c-9c1f-3b7d2a5e9c04' não encontrado",
"instance": "/v1/produto/8f14e45f-ea6d-4a1c-9c1f-3b7d2a5e9c04"
}
| Campo | O que é |
|---|---|
type | Identificador estável da categoria do erro. É por ele que você deve ramificar no código, não pelo texto |
title | Nome curto da categoria, em português |
status | O mesmo código HTTP da resposta |
detail | Descrição do caso concreto. Serve para log e diagnóstico, e o texto pode mudar |
instance | O caminho da requisição que falhou |
Nos corpos de erro os campos são em camelCase (type, status, detail),
diferente das respostas de sucesso, que usam PascalCase. É consequência do
RFC, e um detalhe fácil de esquecer ao escrever o tratador.
| Código | Quando acontece |
|---|---|
200 OK | Leitura, atualização ou ação concluída, com o registro no corpo |
201 Created | Criação concluída, com o registro criado no corpo |
204 No Content | Exclusão concluída. Corpo vazio |
| Código | type | Significado | O que fazer |
|---|---|---|---|
401 | Credenciais ausentes ou inválidas | Conferir os cabeçalhos. Não repetir sem corrigir | |
403 | forbidden | Autenticado, mas a operação não é permitida naquele registro | Não repetir |
404 | not-found | O registro não existe ou pertence a outra conta | Não repetir |
409 | conflict | A operação conflita com o estado atual | Reler o registro antes de decidir |
422 | validation | O corpo ou os parâmetros são inválidos | Corrigir os campos apontados em errors |
429 | Concorrência acima do limite | Repetir com espera crescente | |
500 | internal-error | Falha no servidor | Repetir uma vez. Se persistir, abrir suporte com o traceId |
O type completo é o valor da tabela precedido de
/errors/.
401 não tem corpoFalha de autenticação é a única exceção ao formato. Ela devolve 401 com corpo
vazio e o cabeçalho WWW-Authenticate: X-Chave-Api realm="SunchatPlus". Não há JSON
explicando o motivo, o que é deliberado, para não revelar se uma conta existe.
Trate o 401 pelo código de status e siga o
checklist de autenticação.
404 também significa "de outra conta"Cada chave alcança só os dados da própria conta. Se você usar um ID válido de
outra conta, a resposta é 404, e não 403. Do ponto de vista da sua chave, o
registro não existe. O que foi excluído também responde 404.
422 diz qual campo está erradoO 422 traz um campo extra, errors, com o nome do campo problemático e a lista
de mensagens:
{
"type": "/errors/validation",
"title": "Falha de validação",
"status": 422,
"detail": "Falha de validação",
"instance": "/v1/contatodechat",
"errors": {
"Telefone": ["Telefone é obrigatório"],
"Email": ["Email não é um endereço válido"]
}
}
Um campo pode ter mais de uma mensagem, e vários campos podem falhar na mesma
requisição. Repetir a chamada sem mudar o corpo dá exatamente o mesmo 422.
409 é conflito de estado, não de dadosO 409 aparece quando o registro existe mas está em um estado que não aceita a
operação. Exemplos reais da API:
AgendadaCodigoPrincipal que já existe na contaO detail diz qual é o caso. Como o estado pode mudar entre a sua leitura e a sua
escrita, o tratamento certo é reler o registro e decidir de novo, em vez de
repetir a mesma chamada.
| Código | Repetir? |
|---|---|
401, 403, 404, 409, 422 | Não. Repetir dá o mesmo resultado. Corrija a requisição |
429, 500, 502, 503, 504 | Sim, com espera exponencial e um teto de tentativas |
Ao repetir, respeite duas regras.
Use espera exponencial com variação aleatória, algo como 1s, 2s, 4s, 8s, mais
alguns milissegundos de ruído. Repetição imediata em laço piora o 429.
E cuidado com repetição de escrita. POST não é idempotente. Se a criação deu
certo e a resposta se perdeu no caminho, repetir cria um registro duplicado. Em
envio de mensagem, preencha MessageId com um identificador seu para reconhecer a
duplicata. Nos demais casos, releia antes de recriar.
O 500 inclui um campo traceId:
{
"type": "/errors/internal-error",
"title": "Erro interno",
"status": 500,
"detail": "Erro interno do servidor",
"instance": "/v1/pipelines",
"traceId": "00-8f14e45fea6d4a1c9c1f3b7d2a5e9c04-3b7d2a5e9c04a1c9-01"
}
Registre esse valor no seu log. Ele localiza a requisição exata nos rastros do servidor, e é a primeira coisa que o suporte vai pedir.