O disparo de mensagens em massa pelo WhatsApp é uma das ferramentas de marketing mais eficientes disponíveis hoje — com taxas de abertura acima de 90%. Mas feito de forma errada, pode resultar no banimento da sua conta. Neste guia, você aprende a fazer de forma segura e eficaz.
Regras fundamentais antes de começar
Para evitar banimento, siga estas regras sem exceção:
- Só envie para quem autorizou: opt-in explícito (formulário, compra, cadastro)
- Personalize cada mensagem: nunca envie texto idêntico para todos
- Respeite o ritmo: máximo 1 mensagem por segundo (rate limiting)
- Tenha opt-out claro: "Responda SAIR para não receber mais"
- Horário comercial: não envie antes das 8h ou após as 21h
O que você vai construir
Um sistema de disparo que:
- Lê lista de contatos (JSON ou banco de dados)
- Personaliza cada mensagem com nome e outros dados do contato
- Envia com throttling controlado (delay entre mensagens)
- Registra resultado por contato (sucesso/falha)
- Processa opt-out em tempo real
Passo 1: Estrutura dos contatos
// contatos.json — apenas contatos com opt-in confirmado
[
{ "nome": "Maria Silva", "phone": "5511999998888", "cidade": "Sao Paulo" },
{ "nome": "Joao Santos", "phone": "5521888887777", "cidade": "Rio de Janeiro" },
{ "nome": "Ana Lima", "phone": "5531777776666", "cidade": "Belo Horizonte" }
]
Passo 2: Script de disparo com throttling
const axios = require('axios');
const fs = require('fs');
const TOKEN = process.env.ZAP_TOKEN;
const INSTANCE = process.env.ZAP_INSTANCE;
const api = axios.create({
baseURL: 'https://zap-api.tech/v1',
headers: { Authorization: 'Bearer ' + TOKEN }
});
// Delay entre mensagens — mínimo 1000ms recomendado
const DELAY_MS = 1500;
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// Personalizar mensagem por contato (NUNCA envie mensagem idêntica)
function criarMensagem(contato) {
const primeiroNome = contato.nome.split(' ')[0];
return (
'Oi, ' + primeiroNome + '! Temos novidade para ' + contato.cidade + ':
' +
'50% de desconto em toda a linha premium ate domingo!
' +
'Acesse: https://sua-loja.com/promo-' + contato.cidade.toLowerCase().replace(' ', '-') + '
' +
'Para nao receber mais ofertas, responda SAIR.'
);
}
async function dispararCampanha(contatos) {
const resultados = [];
const total = contatos.length;
console.log('Iniciando disparo para ' + total + ' contatos...
');
for (let i = 0; i < total; i++) {
const contato = contatos[i];
try {
await api.post('/instances/' + INSTANCE + '/send', {
phone: contato.phone,
type: 'text',
body: criarMensagem(contato)
});
resultados.push({ phone: contato.phone, nome: contato.nome, status: 'enviado' });
console.log('[' + (i + 1) + '/' + total + '] Enviado: ' + contato.nome);
} catch (err) {
resultados.push({ phone: contato.phone, nome: contato.nome, status: 'erro', erro: err.message });
console.error('[' + (i + 1) + '/' + total + '] ERRO ' + contato.nome + ': ' + err.message);
}
// Aguardar entre cada mensagem (não remover!)
if (i < total - 1) await sleep(DELAY_MS);
}
return resultados;
}
const contatos = JSON.parse(fs.readFileSync('contatos.json', 'utf8'));
dispararCampanha(contatos).then(resultados => {
const enviados = resultados.filter(r => r.status === 'enviado').length;
const erros = resultados.filter(r => r.status === 'erro').length;
console.log('
=== RESULTADO ===');
console.log('Enviados: ' + enviados + ' | Erros: ' + erros);
fs.writeFileSync('relatorio-campanha.json', JSON.stringify(resultados, null, 2));
console.log('Relatório salvo em relatorio-campanha.json');
});
Passo 3: Disparo com imagem
async function dispararComImagem(contato) {
const primeiroNome = contato.nome.split(' ')[0];
// 1. Enviar imagem com legenda personalizada
await api.post('/instances/' + INSTANCE + '/send', {
phone: contato.phone,
type: 'image',
mediaUrl: 'https://sua-loja.com/banner-promo.jpg',
caption: 'Oi, ' + primeiroNome + '! Sua oferta exclusiva chegou!'
});
await sleep(500); // Breve pausa entre imagem e texto
// 2. Texto com link e opt-out
await api.post('/instances/' + INSTANCE + '/send', {
phone: contato.phone,
type: 'text',
body: 'Aproveite: https://sua-loja.com/promo
Responda SAIR para cancelar.'
});
}
Passo 4: Processar opt-out em tempo real
const express = require('express');
const app = express();
app.use(express.json());
// Em produção: salvar opt-outs no banco de dados
const optOuts = new Set();
app.post('/webhook', async (req, res) => {
res.json({ ok: true });
const { event, data } = req.body;
if (event !== 'message.received' || data.fromMe) return;
// Detectar pedido de opt-out
const texto = (data.body || '').toUpperCase().trim();
if (texto === 'SAIR' || texto.includes('PARAR') || texto.includes('CANCELAR')) {
optOuts.add(data.phone);
console.log('Opt-out registrado: ' + data.phone);
await api.post('/instances/' + INSTANCE + '/send', {
phone: data.phone,
type: 'text',
body: 'Pronto! Voce foi removido da lista e nao receberá mais mensagens nossas.'
});
}
});
app.listen(3000);
Guia de volume: limites seguros
- Até 500 mensagens/dia: envio direto com delay de 1,5s entre cada uma
- 500 a 2.000 mensagens/dia: distribuir ao longo de 8h (~1 mensagem a cada 15s)
- Acima de 2.000 mensagens/dia: usar múltiplas instâncias (números diferentes)
Dica importante: números mais antigos têm mais reputação no WhatsApp. Evite disparos massivos com números recém-criados — comece com volumes pequenos e aumente gradualmente.
Agendar campanha para horário ideal
const cron = require('node-cron');
// Disparar toda terça-feira às 10h
cron.schedule('0 10 * * 2', async () => {
const contatos = await buscarContatosDoBanco(); // sua implementação
await dispararCampanha(contatos);
console.log('Campanha disparada com sucesso!');
});
Conclusão
Disparos em massa pelo WhatsApp feitos com responsabilidade são uma das estratégias de marketing de maior ROI disponíveis. Com a ZAP API, você tem controle total do processo a partir de R$29/mês por instância* — com trial de 7 dias sem cartão.