Typebot no WhatsApp pela API oficial, com o ZapClaw
Em resumo: o ZapClaw entrega cada mensagem do WhatsApp a um pequeno script intermediário (o relay), que roda o seu Typebot publicado pela Chat API do Typebot, e as respostas do bot voltam pelo ZapClaw. As mensagens passam pela API Cloud oficial da Meta, e o número continua funcionando no app WhatsApp Business do celular. Você mantém o bot que já construiu e não precisa de app próprio na Meta.
Conecte o seu número em minutos e coloque nele o bot que você já construiu, hospedado pelo Typebot ou self-hosted.
Plano Business: R$ 99 por mês, com números ilimitados
Comece grátis Ver o relayO que você precisa para conectar
- O app WhatsApp Business no número, na versão 2.24.17 ou mais recente, em uso normal.
- Autenticação em dois fatores ativa na conta pessoal do Facebook que autoriza a conexão.
- O número fora de outro provedor. Se ele estiver conectado a outra plataforma, desconecte lá primeiro.
- Um computador para fazer a conexão, com o celular em mãos para confirmá-la no app.
Não precisa de CNPJ nem de empresa verificada para conectar. A lista completa.
Por que o ZapClaw para um Typebot no WhatsApp
- O número continua no app WhatsApp Business. Pela Coexistência, a sua equipe continua respondendo no app enquanto o bot trabalha no mesmo número. A integração de WhatsApp do próprio Typebot pede que você traga um app seu na Meta, e a documentação dele (em inglês) diz que um número já usado no app WhatsApp Business não pode ser usado com ela.
- Sem app próprio na Meta. Você conecta o número na janela de Embedded Signup da Meta, pelo painel do ZapClaw, e o ZapClaw cuida do lado da API Cloud.
- O bot que você já construiu. O relay roda o seu bot publicado pela Chat API do Typebot, então você continua construindo e publicando no Typebot como sempre.
- Nenhuma biblioteca não oficial por trás do bot. Integrações que imitam o WhatsApp Web contrariam os termos do WhatsApp e põem o número em risco. O ZapClaw usa a API Cloud da Meta, e as políticas da Meta valem como para qualquer empresa nela.
- Entregas que você confere. Cada evento é assinado com HMAC-SHA256 e tem até 3 tentativas de entrega se o relay não responder, e um evento que falhou pode ser reenviado pelo painel.
Por que existe um relay no meio
O Typebot não consegue receber o webhook do ZapClaw do jeito que ele chega. O bloco Webhook só retoma uma conversa que já está pausada nele, e a Chat API espera uma chamada por mensagem, com uma sessão guardada para cada pessoa.
Então o relay cuida disso do jeito que o guia do Typebot para apps de mensagem (em inglês) descreve: abre uma sessão na primeira mensagem do cliente, continua a mesma sessão nas seguintes e devolve os balões de texto do bot pelo ZapClaw. São menos de 100 linhas de Node.js, sem nada para instalar.
Configure em quatro passos
- No Typebot, publique o seu bot e copie o ID público dele (onde encontrar). Mantenha o fluxo centrado em texto: balões de texto, campos de texto e botões.
- No ZapClaw, conecte o seu número, crie uma chave de API e copie a Chave de assinatura na página Webhook.
- Rode o relay abaixo com esses três valores num servidor com endereço HTTPS público e cole esse endereço em Webhook no ZapClaw. O ZapClaw só entrega em endereço HTTPS público.
- Clique em Enviar evento de teste no ZapClaw: o relay responde
200e não inicia nada. Depois mande uma mensagem de WhatsApp para o seu número de outro celular: o bot responde.
O relay, pronto para rodar
Salve como relay.mjs e inicie com node relay.mjs no Node.js 18 ou mais recente. Ele lê as configurações do ambiente: ZAPCLAW_API_KEY, ZAPCLAW_SECRET (a chave de assinatura), TYPEBOT_PUBLIC_ID, TYPEBOT_API para um Typebot self-hosted, e PORT, a porta em que o relay escuta (8787 por padrão), para a qual o seu proxy HTTPS encaminha.
// relay.mjs: ZapClaw webhook in, Typebot Chat API, replies out through ZapClaw.
// Node.js 18 or newer, nothing to install. Start it with: node relay.mjs
import { createServer } from 'node:http';
import { createHmac, timingSafeEqual } from 'node:crypto';
const ZAPCLAW_API_KEY = process.env.ZAPCLAW_API_KEY; // zc_live_...
const ZAPCLAW_SECRET = process.env.ZAPCLAW_SECRET; // the webhook signing secret
const TYPEBOT_PUBLIC_ID = process.env.TYPEBOT_PUBLIC_ID; // your published bot
const TYPEBOT_API = process.env.TYPEBOT_API || 'https://typebot.co/api';
const sessions = new Map(); // customer: { id, choices }. Use your database in production.
const queues = new Map(); // one message at a time per customer, in order
const isSigned = (raw, header = '') => {
const hmac = createHmac('sha256', ZAPCLAW_SECRET).update(raw).digest('hex');
const expected = Buffer.from(`sha256=${hmac}`);
const given = Buffer.from(String(header));
return given.length === expected.length && timingSafeEqual(given, expected);
};
const typebot = async (path, body) => {
const res = await fetch(`${TYPEBOT_API}/v1/${path}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ ...body, textBubbleContentFormat: 'markdown' }),
});
return res.ok ? res.json() : null;
};
const sendText = (from, to, text) =>
fetch('https://api.zapclaw.app/api/v1/send/text', {
method: 'POST',
headers: { 'X-API-Key': ZAPCLAW_API_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ from, to, text }),
});
const answer = async ({ data, account }) => {
const customer = data.user_id || data.from;
const from = account.display_phone_number || account.phone_number_id;
const to = data.from || data.user_id;
const session = sessions.get(customer);
let reply = null;
if (session) {
// Typebot takes a button by its exact label, so accept its number or any letter case.
const typed = data.text.body.trim();
const choice = session.choices.find(
(label, i) => typed === String(i + 1) || typed.toLowerCase() === label.toLowerCase()
);
reply = await typebot(`sessions/${session.id}/continueChat`, {
message: { type: 'text', text: choice || typed },
});
}
if (!reply) {
// First message, or a session that expired (continueChat answers 404): start the bot.
reply = await typebot(`typebots/${TYPEBOT_PUBLIC_ID}/startChat`, {
prefilledVariables: { name: data.contact_name, phone: to },
});
if (!reply) return;
}
const choices =
reply.input?.type === 'choice input'
? reply.input.items.map((item) => item.content).filter(Boolean)
: [];
if (reply.input) sessions.set(customer, { id: reply.sessionId || session.id, choices });
else sessions.delete(customer); // the flow ended: the next message starts it again
const texts = (reply.messages || [])
.filter((m) => m.type === 'text')
// Typebot writes standard Markdown; WhatsApp reads *bold*, ~strike~ and bare links.
.map((m) => m.content.markdown
.replace(/\*\*(.+?)\*\*/g, (_, t) => `*${t}*`)
.replace(/~~(.+?)~~/g, (_, t) => `~${t}~`)
.replace(/\[([^\]]+)\]\(([^)\s]+)\)/g, (_, label, url) => `${label} (${url})`));
if (choices.length) texts.push(choices.map((label, i) => `${i + 1}. ${label}`).join('\n'));
for (const text of texts) if (text) await sendText(from, to, text);
};
createServer((req, res) => {
const chunks = [];
req.on('data', (chunk) => chunks.push(chunk));
req.on('end', () => {
const raw = Buffer.concat(chunks);
if (!isSigned(raw, req.headers['x-zapclaw-signature'])) return res.writeHead(401).end();
res.writeHead(200).end(); // answer ZapClaw now: it waits 10 seconds, a bot can take longer
let event;
try {
event = JSON.parse(raw.toString('utf8'));
} catch {
return;
}
if (event.event !== 'message.received' || event.data?.type !== 'text') return;
const key = event.data.user_id || event.data.from;
const next = (queues.get(key) || Promise.resolve())
.then(() => answer(event))
.catch((err) => console.error(err));
queues.set(key, next);
});
}).listen(process.env.PORT || 8787);
Num Typebot self-hosted, aponte TYPEBOT_API para o endereço do seu viewer, o app onde as pessoas respondem aos seus bots, seguido de /api.
O que ele faz: confere o cabeçalho X-ZapClaw-Signature, responde ao ZapClaw na hora (o ZapClaw espera 10 segundos, e um bot que chama uma IA pode demorar mais) e trata as mensagens de cada cliente uma de cada vez, em ordem. As opções de um bloco Buttons saem como uma lista numerada, e o cliente responde com o número ou com o texto da opção, em maiúsculas ou minúsculas. Quando o fluxo termina, a próxima mensagem começa tudo de novo.
Crie variáveis chamadas name e phone no seu bot e o relay preenche as duas na primeira mensagem, com o nome do contato no WhatsApp e o número dele. As sessões ficam na memória do relay, então reiniciá-lo recomeça todas as conversas: em produção, guarde as sessões no seu banco de dados, como o guia do Typebot recomenda.
O relay envia os balões de texto. Um balão de imagem traz o endereço dela em content.url, que você pode enviar com POST /api/v1/send/media.
Chamando o ZapClaw de dentro do bot
O bloco HTTP Request do Typebot também chama a API do ZapClaw, com um cabeçalho X-API-Key e um corpo personalizado montado com as suas variáveis: por exemplo, para avisar um vendedor no WhatsApp quando um lead chega ao fim do bot. A mesma chamada como comando curl:
curl -X POST https://api.zapclaw.app/api/v1/send/text \
-H "X-API-Key: zc_live_..." \
-H "Content-Type: application/json" \
-d '{ "from": "15551617409", "to": "15555550100", "text": "New lead from the bot" }'
from é o seu número conectado, que o webhook traz em account.display_phone_number, e to é a pessoa para quem você escreve. Uma mensagem enviada responde 201. Texto livre funciona dentro de 24 horas desde a última mensagem dessa pessoa para o seu número; fora dessa janela, a Meta só aceita um template aprovado, pelo POST /api/v1/send/template.
O que chega no relay
Cada mensagem chega como um evento message.received: o texto em data.text.body, o remetente em data.from (ou data.user_id para um contato que só mostra o nome de usuário), o nome do contato em data.contact_name e o seu número em account.display_phone_number.
{
"event": "message.received",
"sequence": 1042,
"timestamp": "2026-10-15T14:00:00.000Z",
"data": {
"from": "15555550100",
"user_id": "US.1A2B3C4D5E6F7G8H9I0J",
"contact_name": "Maria Silva",
"message_id": "wamid.HBg...",
"type": "text",
"timestamp": "1792072800",
"text": { "body": "Hi" }
},
"account": {
"phone_number_id": "964283400112599",
"display_name": "My Business",
"display_phone_number": "+1 555 161-7409"
}
}
O relay só repassa mensagens de texto recebidas: o evento de teste do painel e qualquer outro evento recebem um 200 e nada mais. Todos os eventos e campos estão na documentação (em inglês).
Quanto custa
- Grátis: 500 mensagens por mês e 1 número, sem cartão e sem prazo para acabar. No limite, o envio pausa e as mensagens novas ficam retidas até você assinar.
- Business: R$ 99 por mês, com 20.000 mensagens incluídas e números ilimitados.
- Agency: R$ 149 por mês para agências, com 3 clientes e 60.000 mensagens incluídos e números ilimitados.
A Meta cobra as tarifas de mensagem do WhatsApp direto de você, sem margem do ZapClaw. Todos os planos e preços.
Para quem é
Equipes que montaram no Typebot fluxos de captação de leads, qualificação, perguntas frequentes ou agendamento e querem levar esses fluxos para o número de WhatsApp que os clientes já usam. Agências conectam os números dos clientes no plano Agency, cada cliente isolado dos outros. Não serve para disparo em massa.
Para ir além
- Flowise no WhatsApp, quando as respostas devem vir de um agente de IA e não de um fluxo roteirizado.
- WhatsApp no n8n, com um fluxo para importar em vez de um script.
- A API oficial do WhatsApp com o ZapClaw: o que você recebe, o preço e os requisitos.
- A referência do webhook (em inglês), com cada evento e campo.
Fontes
Documentação do Typebot, em inglês, conferida em 15 de outubro de 2026. Recursos mudam, então confira cada fonte antes de construir.
- Typebot, integração com apps de mensagem externos pela API HTTP: o padrão do relay, uma sessão por pessoa e o 404 de uma sessão expirada.
- Referência da API do Typebot, Start chat e Continue chat: os campos de requisição e de resposta.
- Typebot, bloco Webhook e bloco HTTP Request.
- Typebot, WhatsApp: a integração própria, o app na Meta que ela pede e o número do app WhatsApp Business.
- Typebot, variáveis (variáveis pré-preenchidas) e configuração self-hosted (o endereço do viewer).
- Código-fonte do Typebot no GitHub: como a resposta a um bloco Buttons é reconhecida.
- ZapClaw: webhooks e verificação de assinatura na documentação, e o que você precisa para conectar.
Coloque o seu Typebot no WhatsApp hoje
Comece no plano grátis: um número, sem cartão. Passe para o plano Business quando precisar de mais números ou de mais mensagens.
Comece grátis Ver a documentação do webhook (em inglês)