Ambiente de código e hospedagem
WhatsApp no Replit: receptor de webhook com assinatura, Secrets e Reserved VM
O Replit é um ambiente de desenvolvimento no navegador com hospedagem. A documentação (lida em 11/11/2026) explica que cada Secret vira uma variável de ambiente do projeto e que a publicação pode ser Autoscale, Static, Reserved VM ou Scheduled. Para a ZapZap, o ponto forte é rodar um servidor que recebe webhooks e responde mensagens.
Atualizado em
Por que conectar
O Replit é bom para o lado que as ferramentas de front não cobrem: um servidor sempre disponível que recebe cada evento da ZapZap, confere a assinatura, evita processar o mesmo evento duas vezes e aciona a sua lógica ou um modelo de IA. A ZapZap conecta números por um canal não oficial: o WhatsApp pode limitar ou bloquear qualquer número, então ritmo, consentimento e aquecimento contam. São R$15 por número ativo/mês, pré-pago, sem cobrança por mensagem, e você começa com crédito de boas-vindas ao verificar o telefone, sujeito à campanha vigente.
Passo a passo
- 1
Crie o projeto e cadastre os Secrets
No editor do projeto, abra Tools > Secrets (em Setup), clique em New Secret e crie ZAPZAP_API_KEY e ZAPZAP_API_SECRET (de Settings > API em app.zapzapapi.com). Eles ficam disponíveis como variáveis de ambiente. A documentação avisa que quem tem acesso ao projeto, e colaboradores, podem ver os valores: não convide quem não deva vê-los.
- 2
Suba o receptor de webhook
Cole o servidor do exemplo em server.mjs e rode. Ele lê o corpo bruto, valida X-ZapZap-Signature (t=<unix>,v1=<hmac_hex>, HMAC-SHA256 sobre t + ponto + corpo, tolerância de 5 minutos), responde 200 rápido e guarda o delivery_id para ignorar repetições.
- 3
Escolha o tipo de publicação
Para um receptor que precisa estar sempre ligado, a documentação do Replit descreve Reserved VM como recursos constantes para um app que roda continuamente. Autoscale ajusta recursos ao uso: confira se o seu volume de eventos tolera o tempo de partida.
- 4
Cadastre o webhook na instância
Chame PUT https://api.zapzapapi.com/api/v1/instances/{id}/webhook com webhook_url (HTTPS) e events (por exemplo, messages). A resposta traz o webhook_secret (whsec_...): salve como Secret ZAPZAP_WEBHOOK_SECRET. Teste com POST /instances/{id}/webhook/test.
- 5
Responda pela API
Para responder, chame POST /{instanceId}/send/text com number e text depois de ter respondido 200 ao webhook. O envelope traz delivery_id, event_id, instance_id, instance_name, event e data.
- 6
Depure as entregas
GET /instances/{id}/webhook/deliveries mostra as entregas recentes. Se o seu servidor falhar, a ZapZap tenta de novo com intervalos crescentes, por isso a deduplicação por delivery_id importa.
Exemplo
// server.mjs: receives the ZapZap webhook, checks the signature and ignores repeated deliveries.
// Replit Secrets: ZAPZAP_WEBHOOK_SECRET (the whsec_ value returned when you set the webhook)
import { createServer } from "node:http";
import { createHmac, timingSafeEqual } from "node:crypto";
const seen = new Set();
function valid(raw, header) {
const p = Object.fromEntries(String(header || "").split(",").map((kv) => kv.split("=")));
if (!p.t || !p.v1 || Math.abs(Date.now() / 1000 - Number(p.t)) > 300) return false;
const mac = createHmac("sha256", process.env.ZAPZAP_WEBHOOK_SECRET).update(p.t + "." + raw).digest("hex");
return mac.length === p.v1.length && timingSafeEqual(Buffer.from(mac), Buffer.from(p.v1));
}
createServer((req, res) => {
let raw = "";
req.on("data", (c) => (raw += c));
req.on("end", () => {
if (req.method !== "POST" || !valid(raw, req.headers["x-zapzap-signature"])) {
res.writeHead(401).end();
return;
}
const env = JSON.parse(raw);
res.writeHead(200).end("ok"); // answer fast, work afterwards
if (seen.has(env.delivery_id)) return;
seen.add(env.delivery_id);
console.log("event", env.event, "delivery", env.delivery_id);
});
}).listen(process.env.PORT || 3000, "0.0.0.0");Ilustrativo. Os campos e endpoints exatos estão na documentação.
Tipos de publicação do Replit, segundo a documentação (11/11/2026)
| Tipo | O que a documentação diz | Serve para receber webhook? |
|---|---|---|
| Reserved VM | Recursos consistentes para um app que roda continuamente | Sim, é o encaixe natural |
| Autoscale | Ajusta recursos conforme o uso | Pode servir; teste o tempo de partida |
| Static | Sites que não mudam conforme a entrada do usuário | Não: não roda servidor |
| Scheduled | Roda em horários que você escolher | Não para webhook; serve para rotinas |
Perguntas frequentes
Como os Secrets do Replit chegam ao código?
Como variáveis de ambiente, lidas com process.env no Node.js. A documentação lida em 11/11/2026 também avisa que colaboradores com acesso podem ver os valores.
Preciso validar a assinatura?
Sim, se a URL for pública. Sem isso, qualquer pessoa pode simular eventos. A validação usa o webhook_secret devolvido ao configurar o webhook.
Por que o mesmo evento pode chegar duas vezes?
Se o seu servidor não responder com sucesso, a ZapZap tenta de novo. Guarde o delivery_id e ignore repetições.
O Replit serve para campanhas em massa?
O ambiente serve, mas a ZapZap é uma solução não oficial e disparo em massa e mensagens idênticas em sequência aumentam o risco de bloqueio. Envie só a quem tem relação com você.
Quanto custa a ZapZap?
São R$15 por número ativo/mês, pré-pago, sem cobrança por mensagem, e você começa com crédito de boas-vindas ao verificar o telefone, sujeito à campanha vigente.
Comece agora
Crie sua conta, conecte um número em minutos e teste a API com aquecimento e anti-bloqueio. R$15 por número ativo/mês, pré-pago, sem fidelidade.
