Erros e idempotência
Ramifique pelo código de erro, não pelo status. E torne seguras todas as novas tentativas que custam dinheiro.
Ramifique pelo código, não pelo status
Os erros retornam no formato { "error": "<code>" }. O status sozinho não basta
para decidir o que fazer — dois 403 podem exigir correções opostas.
| Status | Code | O que significa e o que fazer |
|---|---|---|
| 401 | invalid_key | Chave desconhecida ou revogada. Crie uma nova; tentar de novo nunca vai resolver. |
| 403 | ip_not_allowed | A chave tem uma lista de IPs permitidos e este endereço não está nela. A chave está correta — adicione o endereço em developers.wasync.app/keys. Não faça a rotação. |
| 403 | insufficient_scope | A credencial não tem o escopo que este endpoint exige. |
| 403 | forbidden_portal_kind | POST /connections em um portal Bitrix24. As conexões ali são criadas pelo administrador do portal. |
| 400 | invalid_phone_number | phoneNumber deve conter apenas dígitos, sem + no início. |
| 400 | invalid_webhook | A URL deve ser HTTPS e estar em um host acessível publicamente. |
| 402 | — | A licença da conexão expirou. Veja Licenças e teste. |
| 409 | already_connected | A sessão está ativa; não há nada para parear. |
| 409 | not_supported_for_provider | Uma operação exclusiva de qr em um número cloud_api. Permanente — não tente de novo. |
| 422 | recipient_not_on_whatsapp | O WhatsApp não encontrou uma conta para o destinatário. Confira se o número está no formato internacional (código do país primeiro, sem zero à esquerda) e se a pessoa usa WhatsApp. Permanente para esse número — não tente de novo sem alterar. |
| 502 | send_failed | O WhatsApp não conseguiu entregar por um motivo que não tem relação com o destinatário (sessão ou provedor). Tente de novo após um breve intervalo; se persistir, verifique o status da conexão. |
| 429 | warmup_limited | Limite horário de aquecimento em um número qr novo. Aguarde alguns minutos antes de tentar de novo. |
| 429 | rate_limited | Limitador contra abuso. Respeite Retry-After quando presente; mantenha sempre um intervalo padrão. |
| 502 | pairing_code_unavailable | Um resultado comum, não uma indisponibilidade — use o QR como alternativa. |
Retry-After não é garantido em todos os 409/429, portanto nunca faça seu
intervalo de espera depender dele.
Idempotência em POST /connections
Criar uma conexão provisiona uma sessão do WhatsApp e consome uma vaga paga. Um
cliente que estoura o tempo limite e tenta de novo criaria uma segunda
conexão — e você pagaria, sem perceber, por duas vagas para um único cliente. O
cabeçalho opcional Idempotency-Key resolve esse problema. Ele é aceito
somente em POST /connections; se você não o enviar, o comportamento é
exatamente o mesmo de antes.
Uma chave é qualquer texto opaco de até 255 caracteres, isolado no seu workspace (dois parceiros que usem o mesmo texto nunca entram em conflito), e vale por 24 horas a partir da primeira requisição que a usou.
201 Created.200 OK com o cabeçalho de resposta Idempotency-Replayed: true. O qr dessa resposta é obtido na hora, não é o código guardado na primeira criação: os códigos de pareamento mudam a cada 20 segundos, aproximadamente, e um QR antigo reenviado simplesmente não seria lido. Trate o 200 como sucesso, não como erro.400 { "error": "idempotency_key_reuse" }. A comparação usa um hash do corpo canônico, então a ordem das chaves do JSON não importa.409 { "error": "idempotency_in_progress" } com Retry-After: 1. Respeite-o e tente de novo com a mesma chave.Uma chave com mais de 255 caracteres é rejeitada com
400 { "error": "idempotency_key_invalid" } — nunca é truncada. Um cabeçalho em
branco ou só com espaços conta como ausente. O formato do corpo da resposta não
muda em nenhum dos casos.
Gere uma chave por tentativa de onboarding de cliente
Um UUID novo (crypto.randomUUID()) criado logo antes da chamada e reutilizado
apenas pelas novas tentativas dessa chamada. Não use uma chave por processo,
por API key, por dia nem uma constante. Uma chave tão ampla faz o segundo
cliente que você cadastrar receber de volta a conexão do primeiro, em vez da
sua própria.
Idempotência nos envios
POST /messages aceita um idempotencyKey no corpo (não em um cabeçalho).
Envie sempre um — um UUID por envio lógico.
- Em qualquer erro ou tempo limite esgotado, tente de novo com a mesma chave. Uma chave nova significa uma segunda mensagem real de WhatsApp no celular de alguém.
- Em
409 in_progress, consulte com a mesma chave: respeiteRetry-Afterquando presente; caso contrário, aguarde cerca de 5 s. - Um envio lento não é um envio com falha. Defina o tempo limite do seu HTTP em pelo menos 180 s.