Como testar sua integração de WhatsApp antes de ir para produção
Integração de WhatsApp tem uma característica cruel: o erro é público e imediato. Um bug num endpoint interno gera log. Um bug no disparo manda Olá {{nome}}, sua fatura de R$ undefined vence hoje para oitocentas pessoas — e não tem como recolher.
Não existe ambiente de homologação do WhatsApp: mensagem enviada é mensagem entregue. O que existe é um roteiro para descobrir os problemas antes que eles tenham plateia. Este guia é esse roteiro.
Regra zero: número de teste separado
Antes de qualquer coisa, tenha uma instância só para desenvolvimento, conectada a um chip que não é o do seu atendimento.
Não é preciosismo. Testar na instância de produção significa que um laço mal escrito manda cem mensagens do número que atende seus clientes — e o WhatsApp lê isso como comportamento de spam. Você não perde só o teste: perde o número que sustenta a operação. As práticas que reduzem esse risco estão em como evitar banimento.
Um chip pré-pago barato resolve. Custa menos que uma hora de reconexão apressada.
E use chaves de API diferentes para teste e produção. Assim você pode revogar a de desenvolvimento sem derrubar nada, e o log deixa claro de onde veio cada envio.
Nível 1: sem enviar nada
O primeiro nível de teste não toca a API. Isole a montagem da mensagem em uma função pura e teste só ela:
function montarConfirmacao(pedido) {
return [
`Pedido #${pedido.numero} confirmado!`,
`Valor: ${formatarBRL(pedido.total)}`,
`Previsão de envio: ${formatarData(pedido.previsao)}`,
].join("\n");
}
Agora teste os casos que sempre passam em branco:
- Pedido sem previsão de envio — vira "Previsão: undefined"?
- Total zero ou negativo — cupom que zerou o carrinho.
- Nome com acento e emoji.
- Nome muito longo, que estoura o limite de 4096 caracteres do campo de texto.
- Campo nulo vindo do banco.
O bug do undefined na mensagem é o mais comum e o mais constrangedor de todos, e ele morre inteiro neste nível — sem gastar uma requisição.
Teste também a normalização de telefone com as variações reais que existem na sua base: com e sem o 55, com e sem o nono dígito, com parênteses e traço. É a fonte silenciosa de "mandei e não chegou".
Nível 2: enviar de verdade, para você
Com a instância de teste conectada, mande para o seu próprio celular. O que observar não é se "chegou" — é o detalhe:
- A quebra de linha ficou como você esperava?
\nfunciona;<br>não. - O negrito com asterisco renderizou? No WhatsApp é
*texto*, não**texto**de markdown. - O link ficou clicável? Precisa do
https://na frente. - Como aparece na prévia da notificação? É o que a pessoa lê de relance, e o que o vizinho de mesa lê junto.
- A mensagem faz sentido para quem não tem seu número salvo?
Faça isso com a mensagem real, com dado real de um pedido real. Ler no celular revela coisas que ler no código não revela.
Nível 3: provocar os erros de propósito
Esta é a etapa que quase todo mundo pula, e é a que separa integração que aguenta produção da que quebra na primeira sexta-feira. Você precisa causar cada erro e verificar o que o seu código faz.
| Como provocar | Deve acontecer |
|---|---|
| Chave de API errada no header | 401 — parar e alertar, nunca retentar em laço |
| Nome de instância inexistente | 404 — falhar com mensagem clara, não retentar |
number com 3 dígitos | 400 — registrar como inválido e seguir |
| Texto vazio | 400 — não deveria nem sair da sua validação |
| Disparar 70 requisições em um minuto | 429 — pausar e reenfileirar, não descartar |
| Desconectar a instância e enviar | 502 — segurar a fila até reconectar |
O teste do 429 é o mais revelador. Um laço curto que estoura o limite de 60 requisições por minuto mostra na hora se a sua fila reenfileira ou se perde a mensagem em silêncio. Vale ler os cabeçalhos X-RateLimit-Remaining e X-RateLimit-Reset durante esse teste e conferir se o seu código os respeita — o padrão está em rate limit e fila.
E o teste do 401: cuidado com código que trata qualquer falha como temporária. Chave revogada em laço de retentativa gera milhares de requisições inúteis até alguém perceber.
Nível 4: testar o recebimento sem depender de mensagem real
Testar webhook é chato porque exige alguém do outro lado escrevendo. Duas formas de evitar isso.
Simule o payload. Guarde um evento real que chegou uma vez e reenvie contra o seu endpoint quantas vezes quiser:
curl -X POST https://seu-servidor.com.br/webhooks/whatsapp \
-H "Content-Type: application/json" \
-d @evento-exemplo.json
Veja o que realmente chega. Se você ainda nem tem endpoint, o testador de webhook dá uma URL temporária e mostra o corpo exato das requisições — útil para descobrir o formato antes de escrever o código que o consome.
Os casos de recebimento que precisam de teste:
- Evento duplicado. A mesma mensagem chega duas vezes. Seu código responde duas vezes? Cria dois registros?
- Mensagem que não é texto. Áudio, imagem, figurinha, localização. Se o seu código faz
texto.trim()sem verificar, ele quebra. - Endpoint lento. Segure a resposta por 30 segundos de propósito e veja o comportamento. O certo é responder
200imediatamente e processar depois — quem espera para responder recebe reentrega e responde ao cliente em duplicata. - Endpoint fora do ar. Derrube e veja se o evento se perde. O encaminhamento tenta três vezes, com esperas de 1, 5 e 25 segundos, e registra a falha depois disso — mas se a sua janela de indisponibilidade for maior, você precisa saber o que perdeu.
O formato dos eventos e o tratamento correto estão em webhook de WhatsApp.
Nível 5: o ensaio de queda
Antes de subir, faça o exercício completo: desconecte a instância de propósito — pelo aplicativo, em Aparelhos conectados — e observe.
O que precisa acontecer:
- Seu monitoramento percebe (por evento de conexão, não por reclamação).
- A fila para de consumir em vez de acumular
502. - Alguém é avisado.
- Você reconecta pelo QR Code.
- A fila retoma os pendentes, na ordem, sem duplicar.
O passo 5 é o que mais falha. É comum a fila retomar e reenviar mensagens que já tinham saído antes da queda — o cliente recebe a confirmação do pedido três vezes. O procedimento completo está em instância desconectou.
Nível 6: o piloto controlado
Não vá de zero a oitocentos. Vá de zero a dez.
- Dez destinatários internos. Você e o time, com dado real de produção. Um dia.
- Cinquenta clientes reais, escolhidos entre os mais tolerantes. Uma semana. Meça resposta e descadastro.
- Aumente aos poucos. Dobre por semana, não por dia.
Número novo pede ainda mais cautela: instância recém-conectada que dispara em volume é o padrão mais associado a bloqueio. Aquecer devagar não é superstição, é a diferença entre operar por anos e perder o número na primeira semana.
Antes de apertar o botão
- Instância e chave de teste separadas da produção
- Montagem da mensagem testada com nulo, zero, acento e texto longo
- Normalização de telefone testada com as variações da sua base
- Mensagem lida no celular, não só no console
-
400,401,404,429e502provocados de propósito - Retentativa só nos erros temporários
- Chave única impedindo envio duplicado
- Webhook responde
200na hora e processa depois - Webhook aguenta evento duplicado e mensagem sem texto
- Ensaio de queda feito, com retomada sem duplicar
- Piloto com dez pessoas antes do volume
Resumo
Não existe ambiente de teste do WhatsApp, então o roteiro substitui o ambiente: isole a montagem da mensagem e teste sem enviar, envie para si mesmo e leia no celular, provoque cada código de erro de propósito, simule o webhook em vez de esperar mensagem real, ensaie uma queda e só então aumente o volume aos poucos.
O item mais valioso da lista é o terceiro. Quase toda integração funciona no caminho feliz — o que decide a estabilidade é o que ela faz quando a chave é revogada, o limite estoura ou o número cai.