← Blog

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? \n funciona; <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 provocarDeve acontecer
Chave de API errada no header401 — parar e alertar, nunca retentar em laço
Nome de instância inexistente404 — falhar com mensagem clara, não retentar
number com 3 dígitos400 — registrar como inválido e seguir
Texto vazio400 — não deveria nem sair da sua validação
Disparar 70 requisições em um minuto429 — pausar e reenfileirar, não descartar
Desconectar a instância e enviar502 — 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 200 imediatamente 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:

  1. Seu monitoramento percebe (por evento de conexão, não por reclamação).
  2. A fila para de consumir em vez de acumular 502.
  3. Alguém é avisado.
  4. Você reconecta pelo QR Code.
  5. 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.

  1. Dez destinatários internos. Você e o time, com dado real de produção. Um dia.
  2. Cinquenta clientes reais, escolhidos entre os mais tolerantes. Uma semana. Meça resposta e descadastro.
  3. 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, 429 e 502 provocados de propósito
  • Retentativa só nos erros temporários
  • Chave única impedindo envio duplicado
  • Webhook responde 200 na 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.