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",
}),
});