Pular para o conteúdo principal

Erros

A Merx API utiliza códigos HTTP padrão para indicar sucesso ou falha. Códigos 2xx indicam sucesso, 4xx indicam erros de cliente, 5xx indicam erros de servidor.

Formato de Erros​

A API não tem um único formato de erro: existem quatro. Antes de escrever o tratamento de erros do seu cliente, confira qual deles se aplica — assumir sempre a chave messages quebra nos outros três.

(a) Objeto com array de mensagens — o mais comum​

Validação de corpo, regra de negócio, recurso não encontrado. É o formato da maioria dos 400, 404, 409 e 502 e do 403 de módulo não contratado:

{
"messages": ["message.name.mandatory"]
}

O conteúdo do array é a chave de mensagem, não uma frase pronta para exibir ao usuário final: a API devolve message.name.mandatory, e não "o nome é obrigatório". Trate essas chaves como códigos estáveis — é nelas que você deve programar, e é você quem escolhe o texto mostrado ao seu usuário. A exceção é o 500 genérico, onde o array pode trazer a mensagem técnica da exceção em vez de uma chave.

O array pode trazer mais de uma mensagem quando vários campos do corpo são reprovados de uma vez.

(b) Objeto de quatro chaves — parâmetro com tipo errado​

Quando um parâmetro de caminho ou query não converte para o tipo esperado (um id que deveria ser UUID, um número, um booleano), o corpo não usa a chave messages:

{
"timestamp": "2024-01-15T10:30:00.123",
"status": 400,
"error": "Bad Request",
"message": "message.creditscoreid.invalid"
}

A chave em message é derivada do nome do parâmetro (message.{parametro}.invalid), com o nome convertido para minúsculas.

(c) Mensagem em texto — 405 e 403 por enumeração desconhecida​

Alguns erros devolvem apenas a mensagem, sem objeto JSON em volta:

"Request method 'PATCH' not supported"

Acontece no 405 (método não suportado) e no 403 por valor de enumeração desconhecido. Nesses casos a API devolve a mensagem da exceção diretamente, sem envelope: um parser que espera objeto falha. O 403 de módulo não contratado não entra aqui: ele vem no formato (a). O tipo do corpo depende da negociação de conteúdo — pode chegar como texto puro ou como string JSON entre aspas — então trate pelo código HTTP, não pelo corpo.

(d) Corpo cru do serviço downstream​

Endpoints que apenas repassam a chamada para outro serviço da Merx (financeiro, carbono, baseline, order) devolvem, em caso de erro lá, o status HTTP original do serviço de origem. Se o corpo daquele serviço já for um objeto ou lista JSON, ele é repassado sem reescrita; caso contrário, é reembrulhado no formato (a). O formato final é o que aquele serviço produzir, e não necessariamente algum dos anteriores.

Códigos de Erro Comuns​

400 — Bad Request​

Validação de campo falhou:

{
"messages": ["message.producer.social-identity.invalid"]
}

Duas chaves frequentes que não aparecem por endpoint, porque valem para qualquer rota:

ChaveQuando ocorre
message.malformed-requestCorpo JSON sintaticamente inválido ou com tipo incompatível num campo. É o erro mais comum em POST e PUT
message.duplicate.keyViolação de restrição de unicidade no serviço de destino

401 — Unauthorized​

Retornado pelo Kong gateway quando a Authorization está ausente ou inválida. A resposta traz body, no formato {"data": [], "error": {...}}. A mensagem dentro de error varia conforme o plugin de autenticação da rota, então trate pelo código HTTP e não pelo texto.

Existe também um 401 repassado de serviço downstream, esse sim sem body: nesse caso o gateway aceitou a chave, mas o serviço interno acionado recusou a credencial. O corpo é justamente o que distingue os dois — o do gateway traz {"data": [], "error": {...}} e o de downstream vem vazio. Ainda assim, trate pelo código HTTP.

403 — Forbidden​

Na API de integração o formato do corpo do 403 depende da origem.

Módulo não contratado — a cooperativa chamou uma rota de um módulo que não contratou. Corpo em formato (a):

{
"messages": ["message.module.not-contracted"]
}

Valor de enumeração desconhecido — a API recebeu um valor de enumeração que não sabe mapear: tipo de pessoa, estado civil, tipo de signatário ou papel de assinatura. Corpo em formato (c): a mensagem da exceção, sem envelope JSON. O corpo é o texto Unexpected value: <valor>, em inglês e sem chave de mensagem, então não programe em cima dele.

O 403 do gateway, por chave de API sem permissão, está descrito em Autenticação.

405 — Method Not Allowed​

Corpo em formato (c): a descrição do método recusado, sem envelope JSON.

"Request method 'PATCH' not supported"

Ocorre quando o verbo HTTP não é suportado pela rota — por exemplo, um PATCH em uma rota que só aceita PUT.

409 — Conflict​

{
"messages": ["descrição do conflito"]
}

Conflito de estado: a operação é válida, mas colide com um registro já existente.

415 — Unsupported Media Type​

Sem body de resposta. Ocorre quando o header Content-Type está ausente ou não é application/json.

Atinge inclusive requisições sem corpo: os endpoints DELETE /api/v1/integration/webhooks/{id} e DELETE /api/v1/integration/owner-details/{id} exigem Content-Type: application/json e respondem 415 sem ele.

404 — Not Found​

{
"messages": ["message.entidade.not-found"]
}

Nota: Nem todo endpoint sem resultado responde da mesma forma. Consultas por identificador retornam 404 em vez de corpo vazio — por exemplo, GET /api/v1/integration/producers/-/documents/{social_identity} retorna {"messages": ["message.producer.not-found"]} quando o documento não corresponde a nenhum produtor. Já os endpoints de listagem (como GET /api/v1/integration/webhooks) retornam 200 com um array vazio.

500 — Internal Server Error​

{
"messages": ["mensagem interna do erro"]
}

Falha não tratada no processamento. A chave messages traz a mensagem interna da exceção — ou message.internal.error quando não há mensagem. Casos conhecidos: valor acima do tamanho da coluna no banco (uma url de webhook com mais de 250 caracteres, um hmac_secret com mais de 120) e o DELETE /api/v1/integration/owner-details/{id}, que falha em toda chamada.

502 — Bad Gateway​

{
"messages": ["message.integration.connection.refused"]
}

Ocorre quando um serviço downstream está indisponível ou recusa a conexão — a chamada nem chega a ser respondida pelo serviço de destino.

Status espelhado do serviço downstream​

Quando o serviço interno responde, mas com erro, a API repassa o status HTTP dele (400, 404, 422, 500 — o que vier) junto com o corpo cru da resposta, no formato (d). Isso significa que:

  • o status recebido pode não constar desta lista;
  • o corpo pode não ter a chave messages;
  • a mesma rota pode devolver o formato (a) para erros de validação da integração e o formato (d) para erros do serviço de origem.

Trate o corpo de erro de forma defensiva: verifique se é um objeto e se a chave messages existe antes de acessá-la.

Exemplos por Domínio​

DomínioErro ComumMensagem
CadastrosProdutor não encontradomessage.producer.not-found
CadastrosCPF/CNPJ duplicadomessage.producer.already-exists
ComercialCarteira não encontradamessage.wallet.not-found
AcessoMódulo não contratadomessage.module.not-contracted
AutenticaçãoHeader ausente ou inválidoAuthorization ausente ou inválido (401 do gateway, com body {"data": [], "error": {...}})