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.
Neste artigo
Integrar a WhatsApp Cloud API é montar três peças: um número autorizado na Meta com um token de acesso, um webhook que recebe mensagens e status de entrega, e chamadas REST para enviar. O webhook chega assinado com HMAC-SHA256 no header X-Hub-Signature-256, a Meta reenvia o que não recebeu 200 e, fora da janela de 24 horas, só sai template aprovado. O resto deste guia é o detalhe de cada peça, com código em Node.js, e a diferença entre fazer tudo direto na Meta ou por um Tech Provider.
O público aqui é quem escreve código. Se você quer entender o produto antes de entrar na técnica, comece pela visão geral da API oficial do WhatsApp.
As três peças de qualquer integração
Toda integração com a Cloud API, em qualquer linguagem e com qualquer provedor, se reduz a isto:
| Peça | O que é | De quem é a regra |
|---|---|---|
| Número autorizado + token | Um número registrado na WhatsApp Business Platform e um token com permissão para operá-lo | Meta |
| Webhook (entrada) | Um endpoint HTTPS seu que a Meta chama a cada mensagem recebida e a cada mudança de status | Meta assina e reenvia; você valida e deduplica |
| API REST (saída) | POST para enviar texto, mídia, botões ou template |
Meta define formato, janela e limites |
A parte que mais engana é a primeira. Enviar e receber é código simples. Chegar a um número autorizado, com o app aprovado e o token certo, é onde a maioria dos tutoriais em português gasta 80% do texto e onde a maioria das integrações trava. Por isso vale separar os dois caminhos antes do código.
Dois caminhos: direto na Meta ou por um Tech Provider
O que você faz sozinho: app, App Review, verificação, token permanente e /register
Integrando direto, a sequência é sua. Você cria um app no Meta for Developers, adiciona o produto WhatsApp, verifica a empresa no Business Manager e pede App Review para as permissões whatsapp_business_management e whatsapp_business_messaging. Sem o review aprovado, o app só fala com números de teste. O token de desenvolvimento expira em horas; para produção você cria um usuário de sistema no Business Manager e gera um token permanente com essas permissões. Depois cadastra o webhook no App Dashboard, escolhe os campos assinados e registra o número com POST /{phone_number_id}/register.
Cada passo tem um jeito de falhar sem erro claro. O mais comum é esquecer o /register: o token funciona, o webhook responde, e todo envio devolve o código 133010, "número não registrado". O segundo é assinar só messages no App Dashboard e depois se perguntar por que aprovação de template e queda de qualidade nunca chegam.
O que o provedor já resolveu: onboarding, token, webhooks, dedup, retry
Por um Tech Provider verificado pela Meta, o número entra pelo Embedded Signup: uma janela da Meta, aberta dentro do site do provedor, onde o dono do número autoriza o app do provedor a operar aquele número. A Meta devolve os ids e um code trocável por token. O App Review é do provedor, o token fica guardado cifrado no provedor, os webhooks da Meta chegam no provedor, e o que chega até você é um evento já deduplicado, com retry e assinatura própria.
Isso não muda o que a Meta cobra. Como Tech Provider, o Frame Conexa não fatura mensagem e não cadastra pagamento na Meta pelo cliente: o cartão entra no Business Manager do dono do número, e a Meta cobra dele direto pela tabela por mensagem. O provedor cobra pelo software. A diferença entre os dois caminhos é quem carrega o App Review, a rotação de token e a fila de reentrega, não quanto custa cada mensagem.
Há uma diferença técnica importante entre as modalidades de número. Em coexistência, o número continua no app WhatsApp Business do celular e entra na API ao mesmo tempo; o app já registrou o número, e chamar /register nele derruba o app do celular. Num número novo, exclusivo da API, o /register é obrigatório. O provedor sabe qual é o caso e faz a chamada certa; integrando direto, você precisa saber.
Receber mensagens: o webhook
O webhook é um endpoint HTTPS público, com certificado válido, que responde a dois verbos. GET é o handshake de cadastro. POST é o que a Meta chama a cada evento.
Handshake de verificação: hub.mode, hub.verify_token, hub.challenge
Ao salvar a URL no App Dashboard, a Meta faz um GET com três parâmetros: hub.mode=subscribe, hub.verify_token com o valor que você mesmo digitou no painel dela, e hub.challenge, um número. Se o token bate, você devolve o hub.challenge como corpo, em texto, com 200. Qualquer outra resposta e o cadastro falha.
app.get('/webhook', (req, res) => {
const mode = req.query['hub.mode'];
const token = req.query['hub.verify_token'];
const challenge = req.query['hub.challenge'];
if (mode === 'subscribe' && token === process.env.VERIFY_TOKEN) {
return res.status(200).send(challenge);
}
return res.sendStatus(403);
});
O verify_token é um segredo que você inventa. Ele só serve para o handshake; não assina evento nenhum. Compare em tempo constante se quiser ser rigoroso, mas o valor importante é o próximo.
Validar a assinatura HMAC-SHA256 sobre o corpo bruto
Toda notificação vem com o header X-Hub-Signature-256, no formato sha256=<hex>. O hex é o HMAC-SHA256 do corpo da requisição, calculado com o App Secret do seu app. Recalcular e comparar é o que garante que o POST veio da Meta e não de qualquer um que descobriu a URL. A regra está na documentação de webhooks da Graph API.
O detalhe que quebra a maioria das implementações: o HMAC é sobre os bytes exatos do corpo. Se um parser JSON rodar antes e você reserializar o objeto, a ordem das chaves e os espaços mudam, e o hash nunca bate. Leia o corpo cru primeiro, valide, e só então faça o parse.
import crypto from 'node:crypto';
import express from 'express';
const app = express();
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const received = req.get('X-Hub-Signature-256') || '';
const expected = 'sha256=' + crypto
.createHmac('sha256', process.env.APP_SECRET)
.update(req.body)
.digest('hex');
const a = Buffer.from(received);
const b = Buffer.from(expected);
if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {
return res.sendStatus(401);
}
res.sendStatus(200);
enqueue(JSON.parse(req.body.toString('utf8')));
});
Dois pontos nesse código são deliberados. timingSafeEqual em vez de ===, porque uma comparação que para no primeiro byte diferente vaza, pelo tempo de resposta, quantos bytes acertaram. E o 200 sai antes do processamento: a Meta mede o tempo de resposta e reenvia o que demora. Grave o evento numa fila ou numa tabela e responda; o processamento acontece depois.
O envelope: messages, statuses, errors
O corpo tem sempre a mesma casca: object, uma lista entry, cada entrada com uma lista changes, e cada mudança com um field e um value. Para o campo messages, o value traz messaging_product, metadata com o número da empresa, e então contacts e messages quando alguém escreveu, ou statuses quando uma mensagem sua mudou de estado. A referência completa está na visão geral dos webhooks do WhatsApp.
Uma mensagem recebida:
{
"object": "whatsapp_business_account",
"entry": [{
"id": "WABA_ID",
"changes": [{
"field": "messages",
"value": {
"messaging_product": "whatsapp",
"metadata": { "display_phone_number": "5585999990000", "phone_number_id": "PHONE_NUMBER_ID" },
"contacts": [{ "profile": { "name": "Ana" }, "wa_id": "5585988880000" }],
"messages": [{
"from": "5585988880000",
"id": "wamid.HBgNNTU4NT...",
"timestamp": "1757340000",
"type": "text",
"text": { "body": "Oi, ainda tem vaga para sábado?" }
}]
}
}]
}]
}
Um status da sua mensagem:
{
"field": "messages",
"value": {
"messaging_product": "whatsapp",
"metadata": { "phone_number_id": "PHONE_NUMBER_ID" },
"statuses": [{
"id": "wamid.HBgNNTU4NT...",
"status": "delivered",
"timestamp": "1757340042",
"recipient_id": "5585988880000",
"conversation": { "id": "CONVERSATION_ID", "origin": { "type": "service" } },
"pricing": { "billable": false, "pricing_model": "PMP", "category": "service" }
}]
}
}
Os quatro valores de status contam uma história em ordem: sent significa que a Meta aceitou e encaminhou; delivered, que chegou ao aparelho; read, que a pessoa abriu, quando ela não desligou a confirmação de leitura; failed, que não foi, e aí statuses[].errors traz o código. É por esse failed que você fica sabendo de um 131047 ou de um 131026 depois que a API já tinha respondido 200 ao seu POST. O envio aceito não é o envio entregue.
O objeto pricing é o que diz se aquela mensagem custa. billable responde se a Meta cobra, category diz a categoria e pricing_model: "PMP" indica o modelo por mensagem, que substituiu o antigo modelo por conversa. Vale guardar: é a única fonte de verdade sobre custo que chega até o seu sistema.
Atenção: mensagens de serviço, as respostas livres dentro da janela de 24 horas, são gratuitas até 30/09/2026. A partir de 01/10/2026 a Meta passa a cobrá-las por mensagem, e o mesmo vale para templates de utilidade enviados dentro da janela. O
pricing.billabledesses status vai mudar defalseparatruenessa data. Detalhes na página oficial sobre mensagens não-template.
Erros aparecem em três lugares: value.errors para problemas do evento inteiro, messages[].type: "unsupported" para conteúdo que a API não representa, e statuses[].errors para falha de entrega. Um receptor que só lê messages[].text.body ignora os três.
Reentregas e duplicatas: por que deduplicar é obrigatório
Quando o seu endpoint não responde 200, a Meta reenvia. A documentação do WhatsApp fala em novas tentativas com frequência decrescente por até sete dias; a documentação genérica de webhooks fala em 36 horas. Nos dois casos, a consequência é a mesma: o mesmo evento pode chegar mais de uma vez, e também pode chegar fora de ordem, um delivered antes do sent.
A chave de deduplicação natural é messages[].id, o wamid, e para status o par statuses[].id mais status. Um INSERT com restrição única e ON CONFLICT DO NOTHING resolve; processar o evento e só depois responder 200 não resolve, porque o timeout da Meta é curto e um processamento lento vira reentrega de algo que você já tratou. Se o seu banco falhar no INSERT, responda 500 e deixe a Meta reenviar. A fila de retry externa é ela.
Enviar mensagens: API REST
O envio é um POST para https://graph.facebook.com/v25.0/{phone_number_id}/messages, com Authorization: Bearer e um corpo JSON que começa com messaging_product: "whatsapp". O número de destino vai em E.164 sem o sinal de mais.
Texto dentro da janela e template fora dela
O que pode sair depende de uma regra que é da Meta, não do provedor: mensagem livre só dentro da janela de 24 horas aberta pela última mensagem da pessoa. Fora dela, só template aprovado, nas categorias marketing, utilidade ou autenticação.
Texto, quando a janela está aberta:
curl -X POST "https://graph.facebook.com/v25.0/$PHONE_NUMBER_ID/messages" \
-H "Authorization: Bearer $META_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"messaging_product": "whatsapp",
"to": "5585988880000",
"type": "text",
"text": { "body": "Tem sim. Sábado às 10h ou às 14h?" }
}'
Template, quando a janela está fechada, em Node.js com fetch nativo:
const res = await fetch(`https://graph.facebook.com/v25.0/${PHONE_NUMBER_ID}/messages`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.META_ACCESS_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
messaging_product: 'whatsapp',
to: '5585988880000',
type: 'template',
template: {
name: 'lembrete_agendamento',
language: { code: 'pt_BR' },
components: [
{ type: 'body', parameters: [{ type: 'text', text: 'sábado, 10h' }] },
],
},
}),
});
const data = await res.json();
if (!res.ok) throw Object.assign(new Error(data.error?.message), { graph: data.error });
const wamid = data.messages[0].id;
O wamid que volta é o mesmo id que vai aparecer nos status do webhook. Guarde-o na hora: é ele que liga o envio ao delivered e ao failed que chegam minutos depois. Como criar um template e o que a Meta olha na aprovação está em template do WhatsApp aprovado.
Idempotência, retry e os códigos 130429, 131047, 133010 e 190
A API responde erro em dois momentos: síncrono, no POST, e assíncrono, num status failed. Os que importam para o código de envio:
| Código | O que significa | O que fazer | De quem é |
|---|---|---|---|
| 130429 | Ritmo de envio acima do que o número suporta | Espere e reenvie com espaçamento; backoff exponencial curto | Meta |
| 131047 | Mais de 24 horas desde a última mensagem da pessoa | Não reenvie o texto; envie um template aprovado | Meta |
| 131026 | Destinatário não é usuário do WhatsApp, não aceitou os termos ou usa app antigo | Tire da lista; reenviar dá o mesmo resultado | Meta |
| 133010 | Número não registrado na plataforma | Chame /register no número novo; nunca em coexistência |
Meta |
| 190 | Token expirado ou revogado | Gere token novo, ou refaça a autorização; nada mais vai sair até lá | Meta |
A lista completa, com o que o painel mostra para cada um, está em erros da API do WhatsApp e na referência oficial de códigos.
Sobre ritmo: um número integrado direto começa em 80 mensagens por segundo, segundo a documentação de throughput da Meta; um número em coexistência fica em 20. Acima disso vem o 130429, e a resposta certa é espaçar, não insistir em loop.
Sobre retry: a Cloud API não tem chave de idempotência nativa. Se o seu POST estourar o timeout sem resposta, você não sabe se a mensagem saiu. Reenviar às cegas duplica; não reenviar pode perder. A saída é registrar a intenção de envio antes do POST, com um id seu, e só marcar como enviada quando o wamid voltar. Um envio sem wamid fica como incerto até um status chegar pelo webhook, ou até você conferir por outro caminho. É trabalhoso, e é exatamente o tipo de coisa que um provedor faz por você.
Como fica com o Frame Conexa
Com o número conectado pelo Embedded Signup, as três peças ficam assim: o token é um fc_ gerado em Configurações, no painel, e enviado em Authorization: Bearer; o webhook é uma URL sua cadastrada por API ou pelo painel; o envio é o mesmo formato da Cloud API, numa rota que já conhece a instância. A documentação tem o quickstart e a referência de cada rota; abaixo vai o que muda em relação à integração direta.
Webhook assinado com instanceId, customerRef e payload cru da Meta
Você cadastra a URL com PUT /api/v1/webhook-config e o corpo { "url": "https://..." }. A resposta traz o webhookSecret, gerado na primeira gravação; POST /api/v1/webhook-config/secret gira o segredo quando você precisar, e o anterior morre na hora.
O que chega no seu endpoint é um envelope assinado no header X-Frame-Signature-256, no mesmo esquema da Meta: sha256= mais o HMAC-SHA256 do corpo bruto, calculado com esse segredo. O código de validação é o mesmo da seção anterior, trocando o nome do header e o segredo:
app.post('/webhooks/frame-conexa', express.raw({ type: '*/*' }), (req, res) => {
const received = req.get('X-Frame-Signature-256') || '';
const expected = 'sha256=' + crypto
.createHmac('sha256', process.env.FRAME_WEBHOOK_SECRET)
.update(req.body)
.digest('hex');
const a = Buffer.from(received);
const b = Buffer.from(expected);
if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) return res.sendStatus(401);
res.sendStatus(200);
enqueue(JSON.parse(req.body.toString('utf8')));
});
O envelope tem seis chaves de topo, e payload é o value cru da Meta, sem nenhum campo nosso dentro:
{
"type": "messages",
"clientId": "8",
"instanceId": "6ed76b84-4d65-4f3d-88c1-8d4174bdce73",
"customerId": null,
"customerRef": null,
"payload": { "messaging_product": "whatsapp", "metadata": {}, "messages": [] }
}
Três tipos de evento chegam por aí. messages é o campo de mesmo nome da Meta, com mensagens recebidas e status de entrega juntos, como ela manda. smb_message_echoes só existe em coexistência: é a mensagem que alguém enviou pelo app do celular, para o seu sistema saber que a conversa foi respondida por ali. instance_status é nosso: connected ou disconnected, emitido uma vez por transição, para o seu sistema descobrir que o número caiu antes do primeiro envio que falha com 409.
Duas decisões desse envelope são de compatibilidade. instanceId é o UUID que aparece como id em GET /api/v1/instances, e é por ele que você casa o evento com uma instância; clientId é uma chave numérica antiga que segue existindo porque trocá-la quebrou consumidores em produção. E customerId/customerRef vêm como null, nunca ausentes: são o cliente final numa parceria de software, e um consumidor estrito trata chave nula e chave ausente como coisas diferentes.
A entrega é durável do nosso lado. O evento entra numa fila antes de sair, o POST tem timeout de 10 segundos, e uma resposta que não seja 2xx agenda nova tentativa com espaçamento crescente, até esgotar; só então o evento vai para uma fila de descarte, visível no painel. Um destino lento ou fora do ar não perde evento nem trava a ingestão dos outros. Do seu lado, continue deduplicando por messages[].id: a Meta pode reentregar para nós, e nós reentregamos para você.
POST /api/v1/instances/:id/messages com token fc_ e Idempotency-Key
O envio é o mesmo corpo da Cloud API, sem messaging_product e sem phone_number_id, porque a instância na URL já diz qual número é:
curl -X POST "https://frameconexa.com/api/v1/instances/$FRAME_CONEXA_INSTANCE_ID/messages" \
-H "Authorization: Bearer fc_SEU_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 9f8d4a11-5e52-4c83-a72c-45d48f4ea6d5" \
-d '{"to":"5585988880000","type":"text","text":{"body":"Tem sim. Sábado às 10h ou às 14h?"}}'
O Idempotency-Key é o que resolve o problema do retry descrito acima. Use um UUID por mensagem. Se a resposta se perder, repita a mesma chave com o mesmo corpo: você recebe o resultado anterior em vez de um envio novo. Chave repetida com corpo diferente responde 409 IDEMPOTENCY_CONFLICT; envio ainda em processamento responde 409 SEND_IN_PROGRESS com ambiguous: true e não é repetido.
Por dentro, o envio é DB-primeiro: a intenção vira linha antes do POST à Meta. Aceite vira accepted, erro explícito vira failed, timeout sem wamid vira unknown, e nesse último caso a resposta traz ambiguous: true. Significa "pode ter saído": não reenvie sem conferir. Quem promove accepted para entregue ou lido é o status do webhook, nunca a resposta do POST.
Template segue o formato da Cloud API: "type": "template" com name, language e components. Duas regras do lado do provedor valem aqui: template de marketing e a criação de templates exigem número do tipo marketing, e a categoria do template é conferida antes do envio. Um número de atendimento envia utilidade e autenticação sem restrição. Os limites de chamada estão em erros e limites: 120 requisições por minuto por token, com Retry-After no 429.
Baixar mídia recebida pelo proxy
Quando alguém manda uma foto ou um documento, o webhook entrega só image.id ou document.id. O binário fica na Meta e exige o token do número para ser baixado, em dois passos: um GET para o metadado, que devolve uma URL de CDN válida por minutos, e um segundo GET nessa URL, também com o token. Integrando direto, você faz os dois. Pelo Conexa, um GET resolve:
curl -L "https://frameconexa.com/api/v1/instances/$FRAME_CONEXA_INSTANCE_ID/media/$MEDIA_ID" \
-H "Authorization: Bearer fc_SEU_TOKEN" \
-o recebido.jpg
O proxy faz stream, com teto de 100 MB, e nunca devolve nem cacheia a URL de CDN. Baixe assim que o evento chegar: a retenção do lado da Meta é limitada.
Se o seu caso é um fluxo de automação em vez de código próprio, as mesmas rotas alimentam o nó HTTP do n8n e do Make. Se é um agente de IA que opera o número por linguagem natural, há um servidor MCP sobre a mesma API, com confirmação dupla antes de qualquer envio.
Checklist de produção
Antes de apontar tráfego real para a integração, confira:
- Assinatura validada sobre o corpo bruto, com comparação em tempo constante, e
401para o que não bate. Um webhook sem validação aceita qualquerPOSTcomo se fosse da Meta. 200rápido e processamento em fila. Guarde primeiro, processe depois. Se não conseguir guardar, responda500e deixe reenviar.- Deduplicação por
wamidpara mensagens e porwamidmaisstatuspara status. Eventos repetidos e fora de ordem são normais. wamidguardado no envio, ligando oPOSTaos status que chegam depois. Sem isso,failednão tem a quem pertencer.- Idempotência no envio: chave por mensagem, e nunca reenviar um resultado incerto às cegas.
- Janela de 24 horas no código, não só na cabeça: o texto livre só sai quando a última mensagem da pessoa tem menos de 24 horas; do contrário, template. Contas com anúncio Click-to-WhatsApp têm uma janela grátis de 72 horas que o painel sinaliza, e o artigo sobre anúncios Click-to-WhatsApp explica a condição para ela existir.
- Tratamento do 190: token revogado significa que nada mais sai até reautorizar. Alerta para o time, não retry.
- Versão da Graph API fixada na URL. Chamada a versão expirada cai para a mais antiga disponível, silenciosamente.
- Custo previsto para outubro de 2026: se a sua integração responde muito dentro da janela, o
pricing.billabledessas mensagens vai virartrueem 01/10/2026. A tabela por mensagem é a publicada pela Meta; confira o rate card oficial. O que um provedor cobra, e o que a Meta cobra, está separado em quanto custa a WhatsApp Business API.
Perguntas frequentes
Preciso criar um app na Meta para integrar a Cloud API?
Integrando direto, sim: app no Meta for Developers, produto WhatsApp, verificação da empresa e App Review para as duas permissões do WhatsApp. Por um Tech Provider verificado, o app é do provedor e o número entra pelo Embedded Signup; você recebe um token do provedor e nunca toca no App Dashboard da Meta. O que não muda em nenhum dos caminhos é o pagamento: o cartão entra no Business Manager do dono do número, e a Meta cobra dele direto.
Como validar a assinatura do webhook do WhatsApp?
Leia o corpo da requisição como bytes, antes de qualquer parser JSON. Calcule o HMAC-SHA256 desses bytes com o App Secret do app, prefixe com sha256= e compare com o header X-Hub-Signature-256 em tempo constante. Se bater, responda 200 e processe; se não, 401. No webhook do Frame Conexa o header é X-Frame-Signature-256 e o segredo é o webhookSecret da sua conta; o código é o mesmo.
Por que recebo o mesmo evento duas vezes?
Porque a Meta reenvia tudo que não recebeu 200 a tempo, com tentativas em frequência decrescente por até sete dias segundo a documentação do WhatsApp. Um processamento lento antes da resposta, um deploy no meio, um timeout de rede: qualquer um gera reentrega. Deduplique por messages[].id e, para status, pelo par id mais status. Se você recebe pelo Conexa, vale a mesma regra: nós reentregamos o que o seu endpoint não confirmou.
Como enviar mensagem fora da janela de 24h pela API?
Só com template aprovado pela Meta, enviado com "type": "template", o nome, o idioma e os parâmetros dos componentes. Texto livre fora da janela responde 131047 e não sai. A categoria do template define o que pode ser dito e quanto custa: marketing para promoção, utilidade para pedido e agendamento, autenticação para código de uso único.
Que versão da Graph API devo usar em 2026?
A mais recente estável que você tiver testado. Em setembro de 2026, a v25.0 foi lançada em 18/02/2026 e vale até 29/07/2028; a v26.0 saiu em 29/07/2026. Cada versão vive cerca de dois anos depois da seguinte. A v20.0 é removida em 24/09/2026, e chamadas a uma versão expirada caem para a mais antiga disponível. A tabela oficial está na lista de versões da Graph API. Pelo Conexa a versão é do provedor, e você não a escreve na URL.
Próximo passo
O quickstart leva do token à primeira mensagem em poucos minutos, e o guia de webhooks tem o envelope completo com o schema de cada tipo de evento. Para conectar um número e gerar o primeiro token, veja os planos por número.
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 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.
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.