Códigos de erro

Toda resposta de erro da API segue o mesmo formato:

{
  "error": "string_identificadora",
  "message": "Mensagem em português explicando o problema (opcional)",
  "...": "campos extras dependendo do erro"
}

O campo error é uma string estável que você pode usar pra ramificar lógica no seu código. O message é pra humanos e pode mudar.

Códigos HTTP

Status Significado
200 Sucesso. Mesmo erros de "negócio" (ex: atribuição de carteira falhou mas contato foi criado) podem vir aqui com campo ..._error no payload.
400 Body inválido, falta campo obrigatório, formato errado.
401 Autenticação faltando ou inválida.
402 Plano não permite essa feature (trial expirado, plano não tem WhatsApp, etc).
403 Autenticado mas sem permissão (ex: contato fez opt-out, fluxo inativo).
404 Recurso não existe (connection_id errado, etc).
409 Conflito de estado (ex: contato já está numa run ativa de automação).
422 Validação semântica falhou (ex: número de telefone fora do formato).
429 Rate limit excedido. Veja rate limits.
500 Erro no nosso lado. Tente novamente; se persistir, abra um chamado.

Erros mais comuns

/contacts

error Quando
At least one of 'email' or 'phone' is required Body não tem nem email nem phone.
'fields' must be a non-null object Mandou fields como array, string ou null.
unknown_fields Chaves em fields não estão cadastradas em Campos personalizados. Resposta inclui unknown_fields: [...] com a lista das chaves rejeitadas.
plan_limit_exceeded Org com trial expirado ou plano cancelado.

Sucesso parcial: se assigned_user_email falhar (email não é membro da org, role inválida), o contato é criado/atualizado mesmo assim e a resposta inclui assignment_error: "..." em vez de assigned_user_id.

/contacts-schema

error Quando
Invalid API key API key inválida ou revogada.
Too many requests 60 req/min excedido.

/automation-trigger

error Quando
phone is required Body sem phone.
Invalid token Token errado ou fluxo não tem webhook habilitado.
opted_out Contato fez opt-out global; fluxo não dispara.
Webhook trigger disabled for this flow Fluxo não tem trigger webhook ativo.
Flow is not active Fluxo está em draft ou pausado.
Already in flow Contato já está numa run ativa desse fluxo.
cooldown Contato saiu desse fluxo há menos tempo que o cooldown configurado. Resposta inclui retry_at (ISO8601).

/send-template e /send-message

error Quando
connection_id is required Falta connection_id no body.
Invalid API key API key não existe ou foi revogada.
Connection not found connection_id não pertence à sua org.
plan_limit_exceeded Plano sem WhatsApp ou trial expirado. Resposta inclui feature e current_plan.

Se o Meta rejeitar a mensagem (template não aprovado, fora da janela de 24h pra texto livre, etc), a resposta vem com HTTP 200 mas status: "failed" e error com a mensagem do Meta. Trate ambos os casos.

Idempotência

Os endpoints de envio (/send-template, /send-message) aceitam idempotency_key. Se você fizer retry com a mesma chave dentro de 30 dias, recebe o resultado do envio original sem reenviar. Recomendado pra não duplicar mensagens em caso de timeout de rede.

await fetch("/send-template", {
  method: "POST",
  headers: { /* ... */ },
  body: JSON.stringify({
    connection_id: "...",
    template_name: "boas_vindas",
    to: "+5511999999999",
    idempotency_key: "lead-12345-welcome",
  }),
});