WhatsApp Business API no n8n e Make: automação oficial
Tutorial: automatize a WhatsApp Business API no n8n e no Make com webhook assinado e API REST, sem risco de bloqueio. Inclui fluxo com IA e CRM.
Neste artigo
Para automatizar a WhatsApp Business API no n8n ou no Make você precisa de duas peças: um webhook que recebe cada mensagem no seu fluxo e uma chamada HTTP que envia a resposta pela API oficial da Meta. Não existe nó mágico. O que muda em relação a uma ferramenta de sessão é que o número está na Cloud API, então o envio segue regras da Meta (janela de 24 horas, template aprovado fora dela) e o risco de bloqueio por "automação não autorizada" desaparece. Este guia monta quatro receitas, do responder simples ao atendimento com IA, com JSON pronto para importar no n8n.
O que você vai montar
Qualquer fluxo de WhatsApp em n8n ou Make se reduz a três movimentos:
- Receber: a mensagem chega num nó Webhook, assinada, com o corpo cru que a Meta entregou.
- Decidir: o fluxo olha o que chegou, consulta o CRM, chama um modelo de IA ou apenas bate uma regra.
- Enviar: um nó HTTP Request faz
POSTna API REST com texto livre ou com um template aprovado.
Com um número conectado ao Frame Conexa, o token da Meta não passa pelo n8n. O fluxo fala com https://frameconexa.com/api/v1 usando um token fc_ de escopo limitado, e o Conexa faz o resto: assina o webhook, deduplica reenvios da Meta, serializa o ritmo de envio e devolve o motivo de cada recusa. Se você quer entender o que existe por baixo, o pilar WhatsApp Cloud API: como integrar com webhook e API REST explica cada peça. Aqui o foco é o fluxo.
Por que não usar a API de sessão nos seus fluxos
Há duas famílias de "API de WhatsApp". Uma é a Cloud API da Meta, em que a empresa cadastra o número na plataforma oficial e envia mensagens por HTTP com regras públicas. A outra é a API de sessão: um servidor abre o WhatsApp Web com o seu número, lê a tela e injeta mensagens como se fosse você digitando. Evolution API, Z-API e similares são exemplos dessa categoria. O comparativo completo está em API oficial vs não oficial do WhatsApp; para um fluxo de automação, três diferenças pesam.
A Meta proíbe a sessão automatizada. As Messaging Guidelines do WhatsApp vetam "clientes não oficiais, envio em massa, mensagens automáticas ou automação que prejudique o WhatsApp ou seus usuários", com sanção que vai do aviso ao banimento permanente, e a Central de Ajuda aponta a WhatsApp Business Platform como a alternativa legítima. Um fluxo de n8n rodando 24 horas por dia sobre uma sessão é exatamente o padrão que a detecção por aprendizado de máquina procura.
A sessão não tem regra, e por isso não tem proteção. Na API oficial, mandar mensagem livre fora da janela de 24 horas devolve o erro 131047 e nada sai. Na sessão, sai. O fluxo "funciona" até o número ser banido, sem nenhum sinal intermediário.
A sessão cai sozinha. Celular sem bateria, WhatsApp Web deslogado, atualização do app: o fluxo para e ninguém avisa. Na Cloud API o número fica na infraestrutura da Meta, e quando a autorização é revogada existe um evento para isso, que é a receita 4 deste guia.
Se o seu número hoje está no aplicativo do celular, não é preciso abrir mão dele: a modalidade de coexistência mantém o app funcionando e liga o mesmo número à API.
Pré-requisitos: número conectado, token de API e URL de webhook
Antes do primeiro nó, três coisas precisam existir:
| Peça | Onde sai | Para que serve |
|---|---|---|
| Número conectado | Painel do Frame Conexa, "Conectar WhatsApp" | É a instância que envia e recebe. O id dela é um UUID que aparece em GET /api/v1/instances |
Token fc_ |
Configurações → API | Autentica cada chamada do fluxo: Authorization: Bearer fc_SEU_TOKEN |
| URL de webhook e segredo | Configurações → API, ou PUT /api/v1/webhook-config |
É para onde o Conexa entrega os eventos. O segredo assina cada entrega |
O token aparece uma única vez e o servidor guarda só o hash. Crie um token por fluxo: se um vazar, você revoga sem derrubar os outros. No n8n, guarde-o numa credencial do tipo Header Auth, nunca dentro do nó, para que ele não vá junto quando você exportar o workflow. As regras completas estão em Autenticação.
A URL de webhook precisa ser HTTPS e pública. IP privado, localhost, credenciais na URL e redirecionamento são recusados na hora de salvar. No n8n Cloud a URL de produção do nó Webhook já atende; num n8n próprio é preciso um proxy com TLS na frente.
Importante: mensagem livre só pode sair dentro da janela de 24 horas que a pessoa abre ao escrever para você. Fora dela, só template aprovado pela Meta. Toda receita abaixo respeita isso, e vale ler a janela de 24 horas antes de desenhar qualquer fluxo que envie horas depois do contato.
Receita 1 (n8n): responder mensagens recebidas
O fluxo mais simples: alguém escreve, o n8n recebe, valida a assinatura, monta uma resposta e envia. Quatro nós.
Nó Webhook, verificação da assinatura, decisão e envio
Nó Webhook. Método POST, caminho próprio, resposta "Immediately" e a opção Raw Body ligada. Os dois últimos são obrigatórios. Responder na hora é o que a doc do Conexa pede: devolva 200 e processe depois. Sem isso, um nó de IA lento na sequência segura a resposta e a entrega entra em retentativa. O corpo cru é necessário porque a assinatura X-Frame-Signature-256 é um HMAC-SHA256 dos bytes exatos que chegaram; se o n8n reformatar o JSON antes, o hash nunca bate.
Nó Code. Recalcula o HMAC com o segredo do webhook, compara em tempo constante e descarta o que não interessa. Aqui mora a decisão mais importante da receita: o evento messages traz tanto mensagens recebidas (payload.messages[]) quanto confirmações de entrega das suas (payload.statuses[]). Responder a um status é conversar sozinho. E o tipo smb_message_echoes é o que você mesmo mandou pelo aplicativo do celular; responder a ele cria um laço infinito em que o fluxo responde à própria resposta.
Nó HTTP Request. POST https://frameconexa.com/api/v1/instances/SUA_INSTANCIA/messages, autenticação pela credencial Header Auth, corpo JSON no formato da Cloud API e o header Idempotency-Key com o id da mensagem recebida. Assim, se a Meta reentregar o webhook e o n8n rodar o fluxo de novo, a segunda tentativa de envio volta como duplicada em vez de mandar duas respostas.
O código do nó Code, que é a parte que mais dá trabalho para acertar:
const crypto = require('crypto');
const item = $input.first();
const raw = Buffer.from(item.binary.data.data, 'base64');
const received = item.json.headers['x-frame-signature-256'] || '';
const expected = 'sha256=' + crypto
.createHmac('sha256', 'SEU_SEGREDO_DO_WEBHOOK')
.update(raw)
.digest('hex');
const a = Buffer.from(received);
const b = Buffer.from(expected);
if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) return [];
const event = JSON.parse(raw.toString('utf8'));
if (event.type !== 'messages') return [];
const msg = (event.payload.messages || [])[0];
if (!msg || msg.type !== 'text') return [];
return [{
json: {
idempotencyKey: msg.id,
body: {
to: msg.from,
type: 'text',
text: { body: `Recebemos sua mensagem: "${msg.text.body}". Já respondemos.` },
},
},
}];
Retornar um array vazio encerra a execução naquele ramo: sem assinatura válida, sem mensagem de texto recebida, nada segue para o envio.
Nota: o nó Code do n8n só enxerga o módulo
cryptose o servidor estiver comNODE_FUNCTION_ALLOW_BUILTIN=crypto. Sem essa permissão, use o nó Crypto (ação HMAC, SHA256, saída em hex) sobre o corpo cru e compare com um nó IF. A comparação deixa de ser em tempo constante, o que é aceitável para um webhook de baixo volume, mas não para um endpoint exposto a muita tentativa.
Workflow JSON pronto para importar
Copie, importe em Workflows → Import from file e troque o id da instância, o segredo e a credencial.
{
"name": "Frame Conexa - responder mensagens",
"nodes": [
{
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [0, 0],
"parameters": {
"httpMethod": "POST",
"path": "frame-conexa",
"responseMode": "onReceived",
"options": { "rawBody": true }
}
},
{
"name": "Validar e decidir",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [260, 0],
"parameters": { "jsCode": "// cole aqui o código do nó Code acima" }
},
{
"name": "Enviar resposta",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [520, 0],
"credentials": { "httpHeaderAuth": { "name": "Frame Conexa" } },
"parameters": {
"method": "POST",
"url": "https://frameconexa.com/api/v1/instances/SUA_INSTANCIA/messages",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{ "name": "Idempotency-Key", "value": "={{ $json.idempotencyKey }}" }
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify($json.body) }}"
}
}
],
"connections": {
"Webhook": { "main": [[{ "node": "Validar e decidir", "type": "main", "index": 0 }]] },
"Validar e decidir": { "main": [[{ "node": "Enviar resposta", "type": "main", "index": 0 }]] }
}
}
A credencial "Frame Conexa" é do tipo Header Auth, com nome Authorization e valor Bearer fc_SEU_TOKEN. Depois de ativar o workflow, cole a URL de produção do nó Webhook em Configurações → API do painel, mande um "oi" para o número de um celular e acompanhe a execução.
Receita 2 (n8n): atendimento com IA que respeita a janela de 24h
A receita 1 vira um atendente com IA trocando o texto fixo por um nó de modelo (OpenAI, Anthropic ou o nó AI Agent do n8n) entre o Code e o HTTP Request. O modelo recebe a mensagem da pessoa, um prompt de sistema com o escopo do negócio e, se você quiser, as últimas mensagens da conversa via GET /api/v1/instances/SUA_INSTANCIA/messages. Ele devolve o texto; o fluxo envia.
O que a IA não pode decidir é o tipo da mensagem. Essa escolha é do fluxo.
Quando a IA pode responder livre e quando precisa de template
A regra é da Meta e tem um único critério: houve mensagem da pessoa nas últimas 24 horas? Se sim, texto livre. Se não, só template aprovado.
Quando o fluxo responde a um webhook de mensagem recebida, a janela está aberta por definição: a pessoa acabou de escrever. O problema aparece nos fluxos que agem depois: o lembrete que sai quatro horas mais tarde, o "ainda tem interesse?" do dia seguinte, o retorno de uma consulta ao estoque que demorou. Para esses, o fluxo precisa guardar o instante da última mensagem recebida por contato (uma Data Table do n8n, um Postgres, um Redis) e, antes de enviar, comparar:
- Menos de 24 horas desde a última mensagem da pessoa:
type: "text", o modelo escreve. - Mais de 24 horas:
type: "template", com um template aprovado pela Meta, e o modelo no máximo preenche variáveis dentro do que o template permite.
Quem chegou por um anúncio Click-to-WhatsApp tem uma janela maior: se a empresa responde em até 24 horas, a Meta abre um período de 72 horas em que qualquer mensagem é gratuita. O contato traz um campo referral na primeira mensagem, e o painel do Conexa sinaliza essa janela na conversa. Na sua automação, trate a extensão como o que ela é: regra documentada pela Meta e aplicada de boa-fé, sem confirmação por mensagem. Os detalhes estão em anúncio Click-to-WhatsApp.
Dois cuidados que não são de código. Primeiro, custo: até hoje a resposta livre dentro da janela não é cobrada pela Meta, mas a partir de 1º de outubro de 2026 ela passa a ser cobrada por mensagem, com a tarifa da categoria de utilidade do país do destinatário; um atendente de IA que manda cinco balões onde um bastaria vai custar cinco vezes mais, e o artigo sobre preço da WhatsApp Business API acompanha a tabela. Segundo, saída humana: o prompt precisa de um caminho para "não sei, vou chamar alguém", e o fluxo precisa avisar o time nesse caso, porque a Meta mede bloqueios e denúncias, e um bot que insiste é o jeito mais rápido de derrubar a qualidade do número.
Dica: o Conexa publica um guia de integração com IA com prompts prontos para o modelo gerar o receptor de webhook e o cliente de envio conforme o contrato da API. Serve tanto para o n8n quanto para código próprio.
O que a Meta diz sobre bots de atendimento e o que é "AI Provider"
Usar IA para atender o seu próprio negócio é uso normal da plataforma. A página da Meta sobre o tema cita como exemplo permitido uma empresa de viagens operando um bot de suporte. Agendar, confirmar pedido, tirar dúvida de produto, fazer triagem: tudo isso é atendimento, com ou sem modelo de linguagem por trás.
O que a Meta passou a restringir, segundo a mesma página, são os AI Providers: empresas cujo produto principal é um assistente de IA de propósito geral distribuído pelo WhatsApp. Esse caso tem termos e cobrança próprios. A Meta também vende um agente de IA dela, o Meta Business Agent, com cobrança separada por uso; é um produto à parte e não entra no que este guia monta. A receita 2 está do lado do atendimento comum.
Receita 3 (Make): lead do CRM vira mensagem de utilidade
No Make a lógica é a mesma, e a receita mais útil nem precisa de webhook: o gatilho é o CRM. Um cenário com dois módulos:
- Gatilho do CRM (HubSpot, Pipedrive, RD Station, o que você usa): "novo negócio" ou "etapa alterada".
- HTTP → Make a request:
POSTna API do Conexa com um template de utilidade, por exemplo a confirmação de que a proposta foi enviada.
Como o lead em geral não escreveu para você nas últimas 24 horas, a mensagem é obrigatoriamente um template. A categoria certa é utilidade, porque a mensagem é consequência de uma ação da pessoa e não uma oferta. O corpo:
{
"to": "5511999990000",
"type": "template",
"template": {
"name": "proposta_enviada",
"language": { "code": "pt_BR" },
"components": [
{
"type": "body",
"parameters": [
{ "type": "text", "text": "Ana" },
{ "type": "text", "text": "PROP-2041" }
]
}
]
}
}
No módulo HTTP, informe os headers Authorization: Bearer fc_SEU_TOKEN, Content-Type: application/json e Idempotency-Key com o id do negócio no CRM, para que uma reexecução do cenário não mande duas vezes. O telefone vai em E.164 sem o sinal de mais: 5511999990000. A quantidade de variáveis tem que ser exatamente a do template aprovado, senão a Meta recusa com o código 132000.
Dois pontos sobre política. Template de utilidade ainda exige que a pessoa tenha dado o número e aceitado receber mensagens da sua empresa; o consentimento é da Business Messaging Policy da Meta, não do provedor. E se o fluxo for um convite comercial, e não uma consequência de algo que a pessoa fez, a categoria é marketing, o que exige um número de marketing no Conexa e entra nas regras de envio em massa oficial.
Para receber webhooks no Make, o módulo Custom Webhook funciona, mas confira se a sua versão consegue expor o corpo bruto para o cálculo do HMAC. Se não conseguir, use um caminho longo e aleatório na URL como barreira mínima e trate o conteúdo como não confiável: antes de qualquer ação com efeito, confirme a mensagem pela API com GET /instances/:id/messages.
Receita 4: avisar o time quando um número cai
Todo número da Cloud API pode perder a autorização: o dono revoga o acesso no Business Manager, a Meta remove o parceiro, ou uma assinatura vence. Quando isso acontece, o envio passa a devolver 409 e nada mais sai. Sem aviso, o time descobre pelo cliente que reclamou.
O Conexa emite um evento instance_status no mesmo webhook, com o mesmo envelope dos demais:
{
"type": "instance_status",
"clientId": "8",
"instanceId": "6ed76b84-4d65-4f3d-88c1-8d4174bdce73",
"customerId": null,
"customerRef": null,
"payload": {
"status": "disconnected",
"phoneNumberId": "1234567890",
"displayPhone": "+55 11 99999-0000",
"kind": "marketing",
"disconnectReason": {
"code": "token_revoked",
"message": "A autorização do Frame Conexa na Meta expirou ou foi revogada. Reconecte este número para emitir uma nova autorização."
}
}
}
O fluxo é curto: no nó Code da receita 1, adicione um ramo para event.type === 'instance_status' e mande payload.displayPhone, payload.status e payload.disconnectReason.message para um nó de Slack, e-mail ou Telegram. Os códigos que chegam em disconnectReason.code são token_revoked, account_offboarded, partner_removed, removed_from_frame_conexa e subscription_expired, e a mensagem já vem escrita para ser mostrada a uma pessoa.
Quando alguém reconecta o número no painel, chega um instance_status com status: "connected". É o evento que permite ao fluxo voltar a enviar sozinho, sem ninguém precisar lembrar de reativá-lo. Guarde o estado por instanceId, que é o mesmo UUID de GET /api/v1/instances; o clientId existe por compatibilidade e não aparece em nenhuma resposta da API.
Atenção: um fluxo que envia com o número caído acumula erros
409e, se tiver retentativa automática, pode disparar dezenas de chamadas inúteis por minuto. Ao receberdisconnected, pause os cenários de envio; ao receberconnected, retome.
Alternativa ao webhook: agente com MCP
Nem toda automação precisa de um fluxo desenhado. Quando a tarefa é do operador, e não do cliente ("resuma o que ficou sem resposta hoje", "confirme as consultas de amanhã"), um agente de IA conectado por MCP faz o trabalho em linguagem natural, sem nó nenhum. O Conexa expõe um servidor MCP em /mcp, autenticado pelo mesmo token fc_, com as mesmas ferramentas da API e uma confirmação dupla antes de qualquer envio: o agente mostra o preview, você aprova, e só então a mensagem ou a campanha sai.
As duas abordagens convivem no mesmo número. O n8n cuida do que precisa acontecer toda vez, sem ninguém olhando; o MCP cuida do que uma pessoa pede quando quer. O guia MCP para WhatsApp mostra a configuração no Claude, no Cursor e no Claude Code.
Erros comuns nos fluxos
Os erros abaixo aparecem em quase todo fluxo novo. A coluna "de quem" importa: a suspeita natural é que o limite seja do provedor, e na maior parte das vezes é da Meta.
| Sintoma | Código | De quem | O que fazer |
|---|---|---|---|
| Fluxo responde à própria mensagem sem parar | nenhum | do fluxo | Ignore smb_message_echoes e payload.statuses; responda só a payload.messages |
| Mesma resposta enviada duas vezes | nenhum | da Meta, esperado | Reentregas são normais. Use messages[].id como Idempotency-Key |
401 em toda chamada |
401 |
do token | Token ausente, revogado ou colado com espaço. Gere outro em Configurações → API |
| "instância desconectada" | 409 (Graph 190) |
da autorização na Meta | Reconecte o número no painel. A receita 4 avisa antes |
| Mensagem livre recusada | 131047 |
da Meta | A janela de 24 horas fechou. Envie um template aprovado |
| Destinatário sem entrega | 131026 |
da Meta | O número não tem WhatsApp ativo. Tire do público, reenviar dá o mesmo resultado |
| Marketing não entregue | 131049 |
da Meta, por pessoa | A pessoa já recebeu marketing demais somando todas as empresas. Espere pelo menos 24 horas |
| Variáveis não batem | 132000 |
do template | A quantidade de parâmetros não é a do template aprovado |
| Muitas chamadas | 429 |
do Conexa | 120 requisições por minuto por token. Respeite o Retry-After |
| "resultado incerto" | 502 com ambiguous: true |
da rede ou da Meta | A mensagem pode ter saído. Não reenvie às cegas; confira em GET .../messages |
O último merece uma regra no fluxo: a retentativa automática do nó HTTP Request do n8n precisa ficar desligada para essa rota, ou ser condicionada a ambiguous ausente. Com Idempotency-Key no envio, repetir a mesma chave e o mesmo corpo é seguro e devolve 409 SEND_IN_PROGRESS enquanto o primeiro ainda roda; sem a chave, cada repetição é uma mensagem nova. O dicionário completo, com o que fazer em cada caso, está em erros da API do WhatsApp e em Erros e limites.
Perguntas frequentes
Dá para usar o nó nativo WhatsApp Business Cloud do n8n com o Frame Conexa?
Não diretamente. O nó nativo do n8n fala com o Graph API da Meta usando o token de acesso e o phone number id da sua conta, que são justamente o que o Conexa guarda cifrado para o número não depender de um token solto num workflow. Com o Conexa, o envio é pelo nó HTTP Request contra https://frameconexa.com/api/v1, e o recebimento é pelo nó Webhook genérico com Raw Body ligado, como na receita 1. O formato do corpo de envio é o mesmo da Cloud API, então quem já montou um payload para o nó nativo só troca a URL e o header.
Meu bot de IA pode responder qualquer mensagem no WhatsApp?
Pode responder o que for atendimento do seu negócio, dentro da janela de 24 horas aberta pela pessoa. É o uso que a Meta descreve como permitido, e o exemplo dela é um bot de suporte de uma empresa de viagens. O que a Meta restringe, segundo a página sobre AI Providers, é oferecer um assistente de IA de propósito geral como produto pelo WhatsApp. E fora da janela nem o bot nem uma pessoa mandam texto livre: é template aprovado ou nada.
O que acontece se o fluxo mandar mensagem fora da janela de 24h?
A Meta recusa com o código 131047 e a mensagem não sai. Não é cobrada, porque a Meta só cobra mensagem entregue, mas também não chega. O Conexa devolve o erro no corpo da resposta com o código da Meta, e o painel mostra o motivo como "janela fechada". A correção é no desenho do fluxo: guardar o instante da última mensagem recebida por contato e trocar para type: "template" quando passaram mais de 24 horas.
Como saber no n8n se a mensagem foi entregue?
Pela confirmação de entrega, que chega no mesmo webhook. A resposta do POST traz o id da mensagem em result.messages[0].id, um valor que começa com wamid.. Depois disso o Conexa entrega eventos messages com payload.statuses[], cada um com o mesmo id e um status que evolui por sent, delivered, read ou failed; em failed, o motivo vem em errors[]. Guarde o id ao enviar e case no webhook. Se preferir consultar em vez de escutar, GET /api/v1/instances/:id/messages lista as mensagens com o estado atual.
Preciso de VPS para rodar a automação?
Não, desde que o webhook tenha uma URL HTTPS pública. O n8n Cloud e o Make já fornecem isso. Um n8n instalado no seu servidor precisa de um proxy com certificado TLS na frente, porque o Conexa recusa URL sem HTTPS, com IP privado ou apontando para localhost. O que não dá é rodar o n8n no seu notebook e esperar que o webhook chegue: a entrega precisa encontrar o endereço na internet.
Próximo passo
Conecte um número e gere o primeiro token nos planos por número; o webhook e a API vêm no mesmo plano, sem cobrança por mensagem da nossa parte. Com o token em mãos, o quickstart mostra a primeira chamada em um minuto, e a receita 1 acima é o workflow para importar em seguida.
Leia também
Integração
Embedded Signup do WhatsApp: conecte à API em minutos
O que é o Embedded Signup do WhatsApp, o que a janela da Meta pede, o papel do Tech Provider e os erros reais do fluxo, como o 2388002 e o prazo de 15 minutos.
Integração
MCP para WhatsApp: conecte Claude e Cursor ao número oficial
O que é um servidor MCP para WhatsApp, como conectar Claude, Cursor ou outro agente de IA ao seu número oficial e por que o envio exige confirmação dupla.
Integração
WhatsApp Cloud API: como integrar com webhook e API REST
Tutorial para desenvolvedores: como integrar a WhatsApp Cloud API com webhook assinado (X-Hub-Signature-256), envio por API REST em Node.js e status de entrega.
Conecte o número que você já usa à API oficial do WhatsApp.
Sem trocar de número, sem perder o aplicativo e sem cobrança por mensagem da nossa parte. Você paga por número; a Meta, você paga direto.