Erros e boas práticas
Formato das respostas de erro, catálogo de códigos e recomendações para uma integração resiliente.
Toda resposta de erro segue o mesmo envelope, com um código estável que a sua integração pode tratar programaticamente.
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Contact and/or address are required based on the selected delivery method",
"details": [],
"errorEventId": "b1f3c6d8-2a44-4d9e-9f10-7c5b8e2a1d33"
}
}| Campo | Descrição |
|---|---|
code | Código estável. Trate por aqui, não pela mensagem. |
message | Descrição legível, voltada a quem depura. Pode mudar entre versões. |
details | Detalhes adicionais quando existirem — em erros de validação, a lista de campos com problema. |
errorEventId | Identificador único da ocorrência. Também vem no header X-Error-Event-Id. |
Registre o errorEventId
Grave errorEventId no seu log junto com o endpoint e o horário. Ao abrir um chamado, esse valor
permite ao suporte localizar exatamente a requisição que falhou, sem precisar de payloads com dados pessoais.
Códigos HTTP
| Código | Significado | Ação |
|---|---|---|
200 | Sucesso — inclui o caso de recurso reaproveitado por idempotência | Seguir |
201 | Recurso criado | Seguir |
400 | Requisição inválida — payload malformado, estado incompatível, arquivo inválido | Corrigir e reenviar |
401 | Não autenticado — chave ausente, inválida, revogada ou expirada | Corrigir a credencial. Sem retry |
403 | Sem permissão para a operação | Verificar o papel do usuário |
404 | Recurso inexistente neste workspace | Verificar o identificador |
409 | Conflito — registro duplicado ou referenciado por outros dados | Ajustar conforme a mensagem |
422 | Falha de validação de negócio | Corrigir os campos indicados em details |
429 | Limite de requisições ou de tentativas de autenticação | Ver abaixo |
500 | Erro interno | Retry com backoff; persistindo, abrir chamado com o errorEventId |
503 | Dependência temporariamente indisponível | Retry com backoff |
Catálogo de códigos
code | HTTP | Quando ocorre |
|---|---|---|
UNAUTHORIZED | 401 | Header X-API-KEY ausente, inválido ou chave inativa |
TOO_MANY_AUTH_FAILURES | 429 | 20 tentativas inválidas do mesmo IP em 5 minutos |
RATE_LIMIT_EXCEEDED | 429 | Acima de 60 requisições por minuto no workspace |
SERVICE_UNAVAILABLE | 503 | Controle de limite ou streaming de status indisponível |
VALIDATION_ERROR | 400 / 422 | Campo obrigatório ausente, formato inválido, regra de negócio violada |
BAD_REQUEST | 400 | Operação incompatível com o estado atual do recurso |
NOT_FOUND | 404 | Lote, item, negociação ou agente inexistente no workspace |
FORBIDDEN | 403 | Papel insuficiente para a operação |
DUPLICATE_ERROR | 409 | Violação de unicidade |
FOREIGN_KEY_CONSTRAINT | 409 | Registro referenciado por outros dados |
INTERNAL_SERVER_ERROR | 500 | Falha não mapeada |
Uma exceção de formato
O endpoint Confirmar envio do lote devolve, no caso de
recusa de negócio, o formato alternativo { "success": false, "error": "mensagem", "code": "bad_request" },
com error como texto. Trate error como string ou objeto ao interpretar respostas desse endpoint.
Erros de validação
Erros de validação trazem a lista de problemas em details:
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid input: expected string, received undefined",
"details": [
{
"code": "invalid_type",
"path": ["notificationTemplateId"],
"message": "Invalid input: expected string, received undefined"
}
],
"errorEventId": "b1f3c6d8-2a44-4d9e-9f10-7c5b8e2a1d33"
}
}Nos endpoints de lote, a validação é por item: o lote é aceito e cada item recebe seu próprio veredito. Itens inválidos vêm com status: "INVALID" e a lista de erros — nenhum deles interrompe o processamento dos demais.
{
"externalId": "contrato-8842",
"status": "INVALID",
"errors": [
{
"code": "VALIDATION_ERROR",
"field": "contact.taxId",
"message": "CPF/CNPJ inválido"
}
]
}Boas práticas
Trate o código, não a mensagem
Mensagens são para humanos e podem mudar. A lógica da sua integração deve olhar error.code e o status HTTP.
Campos desconhecidos são rejeitados
Os corpos de requisição são validados em modo estrito: enviar um campo que não existe no contrato devolve 422, em vez de ser ignorado em silêncio.
Isso é proposital — um campo silenciosamente descartado faz a integração parecer correta enquanto o valor nunca chega ao destino. Se você recebeu 422 apontando um campo que existia antes, confira se ele não foi substituído (por exemplo, os antigos whatsappTemplateId / emailTemplateId / physicalTemplateId, hoje notificationTemplateId).
Retry apenas onde faz sentido
Repetir um 422 só gera ruído. Reserve o retry para 429, 503 e 5xx, sempre com backoff exponencial e uma chave de idempotência (ver Idempotência).
Timeout generoso em upload
Uploads de planilha e criação de lotes grandes levam mais tempo que uma consulta. Configure o timeout do cliente HTTP para pelo menos 60 segundos nesses endpoints.
Não repita o que já foi aceito
Se um lote foi aceito e você não recebeu a resposta por timeout, não reenvie sem batchCode — consulte a listagem de lotes antes ou reenvie com o mesmo código de idempotência.
Reconcilie de forma assíncrona
Envios são processados em segundo plano. Em vez de aguardar sincronamente, agende uma rotina que consulte o lote periodicamente (obter lote) ou consuma o stream de status.
Valide antes de enviar em massa
Para notificações, validar o documento antes de montar o lote reduz o volume de itens inválidos. Para negociações, consulte o detalhe do agente para saber exatamente quais variáveis são obrigatórias.
Dados pessoais em logs
A Arbitralis opera sob a LGPD e não registra CPF, telefone, e-mail ou conteúdo de notificação em
logs. Recomendamos a mesma disciplina do seu lado: registre o externalId e o errorEventId, não os dados do titular.