Flowise 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 pergunta ao seu fluxo do Flowise pela Prediction API, e a resposta volta pelo ZapClaw. As mensagens passam pela API Cloud oficial da Meta, e o número continua funcionando no app WhatsApp Business do celular. Funciona com chatflows e agentflows, e você não precisa de app próprio na Meta.
Conecte o seu número em minutos e dê ao seu agente do Flowise o número de WhatsApp que os seus clientes já usam, na nuvem 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 agente do Flowise no WhatsApp
- O número continua no app WhatsApp Business. Pela Coexistência, a sua equipe continua respondendo no app enquanto o Flowise trabalha no mesmo número.
- 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.
- Uma memória por cliente. O relay passa o cliente como
sessionId, e o Flowise mantém uma conversa separada para cada sessão, então o agente lembra o que aquela pessoa disse antes. - Nenhuma biblioteca não oficial por trás do agente. 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 Flowise roda um fluxo pela Prediction API, com a mensagem num campo question, e devolve a resposta no corpo da mesma chamada HTTP. O webhook do ZapClaw traz o próprio JSON e não lê o corpo da resposta, então o relay faz a ponte: transforma cada mensagem numa pergunta, e a resposta num envio pelo ZapClaw.
O relay abaixo tem menos de 70 linhas de Node.js, sem nada para instalar. Se você já usa o n8n, ele pode fazer o papel do relay, como mostramos mais abaixo.
Configure em quatro passos
- No Flowise, salve o seu chatflow ou agentflow e anote o ID do fluxo. Se você atribuiu uma chave de API ao fluxo, anote essa chave também.
- 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 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 pergunta nada ao Flowise. Depois mande uma mensagem de WhatsApp para o seu número de outro celular: o fluxo 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), FLOWISE_URL (o endereço do seu Flowise), FLOW_ID, FLOWISE_API_KEY quando o fluxo tiver uma, 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, Flowise Prediction API, the answer 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 FLOWISE_URL = process.env.FLOWISE_URL || 'http://localhost:3000'; // your Flowise address
const FLOW_ID = process.env.FLOW_ID; // the ID of your chatflow or agentflow
const FLOWISE_API_KEY = process.env.FLOWISE_API_KEY; // only when the flow has an API key
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 answer = async ({ data, account }) => {
// The customer is the session: Flowise keeps one conversation memory per sessionId.
const res = await fetch(new URL(`api/v1/prediction/${FLOW_ID}`, FLOWISE_URL), {
method: 'POST',
headers: {
'Content-Type': 'application/json',
...(FLOWISE_API_KEY && { Authorization: `Bearer ${FLOWISE_API_KEY}` }),
},
body: JSON.stringify({
question: data.text.body,
overrideConfig: { sessionId: data.user_id || data.from },
}),
});
if (!res.ok) throw new Error(`Flowise answered ${res.status}`);
const { text } = await res.json();
if (!text) return;
await 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: account.display_phone_number || account.phone_number_id,
to: data.from || data.user_id,
text: text.slice(0, 4096),
}),
});
};
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 flow 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);
O que ele faz: confere o cabeçalho X-ZapClaw-Signature, responde ao ZapClaw na hora (o ZapClaw espera 10 segundos, e um modelo pode demorar mais) e pergunta ao Flowise uma mensagem de cada vez por cliente, para as respostas manterem a ordem. A resposta do fluxo volta no campo text e sai como uma mensagem de WhatsApp.
Num agentflow, deixe o nó Start em Chat Input: o relay envia a mensagem como question, e um início em Form Input espera um objeto form.
Ou use o n8n como relay
Já usa o n8n? Importe o fluxo da nossa página do n8n e coloque, entre o filtro e a resposta, um nó HTTP Request que envia para a Prediction API do seu fluxo question igual a {{ $json.body.data.text.body }} e overrideConfig.sessionId igual a {{ $json.body.data.user_id || $json.body.data.from }}. Depois desse nó, $json passa a ser a resposta do Flowise, então, na resposta, use {{ $json.text }} em text e faça from e to lerem o nó do webhook: {{ $('ZapClaw webhook').item.json.body.account.display_phone_number || $('ZapClaw webhook').item.json.body.account.phone_number_id }} e {{ $('ZapClaw webhook').item.json.body.data.from || $('ZapClaw webhook').item.json.body.data.user_id }}.
Chamando o ZapClaw de dentro do Flowise
O Flowise também chama a API do ZapClaw por conta própria: pelo nó HTTP de um agentflow, ou por uma Custom Tool que o agente decide usar, com um cabeçalho X-API-Key. Por exemplo, uma ferramenta que avisa um vendedor no WhatsApp quando um cliente pede um orçamento. Dentro de uma Custom Tool, $flow.sessionId traz o cliente, porque o relay passa o cliente como sessão, e uma variável do Flowise lida por $vars pode guardar a sua chave do ZapClaw. A chamada em si, 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": "A customer asked for a quote" }'
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": "Do you deliver on Saturdays?" }
},
"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. Um áudio ou uma imagem traz uma media_url que você baixa com a sua chave de API, se quiser entregar ao Flowise depois. 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 Flowise um agente de IA, um assistente sobre os próprios documentos ou um fluxo de triagem de atendimento e querem levar isso 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
- Typebot no WhatsApp, quando um fluxo roteirizado com botões funciona melhor que um agente de IA.
- WhatsApp no n8n, com um fluxo para importar em vez de um script.
- Webhook para a sua própria IA, quando as pessoas continuam respondendo pelo app.
- Dify no WhatsApp, se você monta os seus agentes no Dify.
- A referência do webhook (em inglês), com cada evento e campo.
Fontes
Documentação do Flowise, em inglês, conferida em 15 de outubro de 2026. Recursos mudam, então confira cada fonte antes de construir.
- Flowise, Prediction: o endpoint, o campo
questione uma memória porsessionId. - Referência da API do Flowise, Prediction: os campos da requisição e o
textda resposta. - Flowise, controle de acesso aos fluxos: a chave de API enviada como token Bearer.
- Flowise, Agentflow V2: as entradas do nó Start e o nó HTTP.
- Flowise, Custom Tool:
$flow.sessionIde$vars. - Código-fonte do Flowise no GitHub: como o
sessionIdde uma prediction é lido. - ZapClaw: webhooks e verificação de assinatura na documentação, e o que você precisa para conectar.
Coloque o seu agente do Flowise 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)