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.

Formato do erro
{
  "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"
  }
}
CampoDescrição
codeCódigo estável. Trate por aqui, não pela mensagem.
messageDescrição legível, voltada a quem depura. Pode mudar entre versões.
detailsDetalhes adicionais quando existirem — em erros de validação, a lista de campos com problema.
errorEventIdIdentificador ú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ódigoSignificadoAção
200Sucesso — inclui o caso de recurso reaproveitado por idempotênciaSeguir
201Recurso criadoSeguir
400Requisição inválida — payload malformado, estado incompatível, arquivo inválidoCorrigir e reenviar
401Não autenticado — chave ausente, inválida, revogada ou expiradaCorrigir a credencial. Sem retry
403Sem permissão para a operaçãoVerificar o papel do usuário
404Recurso inexistente neste workspaceVerificar o identificador
409Conflito — registro duplicado ou referenciado por outros dadosAjustar conforme a mensagem
422Falha de validação de negócioCorrigir os campos indicados em details
429Limite de requisições ou de tentativas de autenticaçãoVer abaixo
500Erro internoRetry com backoff; persistindo, abrir chamado com o errorEventId
503Dependência temporariamente indisponívelRetry com backoff

Catálogo de códigos

codeHTTPQuando ocorre
UNAUTHORIZED401Header X-API-KEY ausente, inválido ou chave inativa
TOO_MANY_AUTH_FAILURES42920 tentativas inválidas do mesmo IP em 5 minutos
RATE_LIMIT_EXCEEDED429Acima de 60 requisições por minuto no workspace
SERVICE_UNAVAILABLE503Controle de limite ou streaming de status indisponível
VALIDATION_ERROR400 / 422Campo obrigatório ausente, formato inválido, regra de negócio violada
BAD_REQUEST400Operação incompatível com o estado atual do recurso
NOT_FOUND404Lote, item, negociação ou agente inexistente no workspace
FORBIDDEN403Papel insuficiente para a operação
DUPLICATE_ERROR409Violação de unicidade
FOREIGN_KEY_CONSTRAINT409Registro referenciado por outros dados
INTERNAL_SERVER_ERROR500Falha 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:

422 Unprocessable Entity
{
  "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.

Item inválido dentro de um lote aceito
{
  "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.