Chapter 4 of 15
WhatsApp webhook: receiving messages, with code
About CertuAI: CertuAI is the AI that answers a small business's WhatsApp, Instagram and Messenger 24/7, with a built-in CRM, and is a Tech Provider on Meta's WhatsApp Business Platform. Paid plans start at US$ 75 a month, with no lock-in. Create my agent
The address that listens to WhatsApp, with code.
- Reading time: 1 min
- Cost to follow along: R$ 0
- Sign-up: none
CertuAI free manual · Updated September 23, 2026 · Written by Bernardo Villela, CEO of CertuAI · see the whole manual
Summary in 4 facts
- Short answer An https address that answers two calls: verification by GET, returning Meta's challenge, and messages by POST.
- It checks the signature and answers 200 fast.
- Step 1Paste the address With /webhook at the end and the VERIFY_TOKEN password.
- Step 2Subscribe to the messages field Without this, no message arrives.
How do I receive WhatsApp messages on my server?
Short answer
An https address that answers two calls: verification by GET, returning Meta's challenge, and messages by POST. It checks the signature and answers 200 fast.
The code
Save as src/index.js.
export default {
async fetch(request, env) {
const url = new URL(request.url);
if (url.pathname !== '/webhook') return new Response('no ar');
// Verificacao: a Meta chama uma vez, quando voce cadastra o endereco.
if (request.method === 'GET') {
const ok = url.searchParams.get('hub.mode') === 'subscribe'
&& url.searchParams.get('hub.verify_token') === env.VERIFY_TOKEN;
return ok
? new Response(url.searchParams.get('hub.challenge'))
: new Response('token errado', { status: 403 });
}
if (request.method !== 'POST') return new Response('metodo nao permitido', { status: 405 });
const corpo = await request.text();
const assinatura = request.headers.get('x-hub-signature-256');
if (!(await assinaturaConfere(corpo, assinatura, env.APP_SECRET))) {
return new Response('assinatura invalida', { status: 401 });
}
// Confirmacao de entrega chega aqui tambem, sem messages. Ignore.
const valor = JSON.parse(corpo)?.entry?.[0]?.changes?.[0]?.value;
const mensagem = valor?.messages?.[0];
if (mensagem) console.log('mensagem de', mensagem.from, mensagem.text?.body);
return new Response('ok');
},
};
// Sem esta conferencia, qualquer um manda mensagem falsa pro seu endereco.
async function assinaturaConfere(corpo, cabecalho, segredo) {
if (!cabecalho || !segredo) return false;
const chave = await crypto.subtle.importKey(
'raw', new TextEncoder().encode(segredo),
{ name: 'HMAC', hash: 'SHA-256' }, false, ['sign'],
);
const assinado = await crypto.subtle.sign('HMAC', chave, new TextEncoder().encode(corpo));
const esperado = 'sha256=' + [...new Uint8Array(assinado)]
.map((b) => b.toString(16).padStart(2, '0')).join('');
// Comparacao de tempo constante.
if (esperado.length !== cabecalho.length) return false;
let diferenca = 0;
for (let i = 0; i < esperado.length; i += 1) {
diferenca |= esperado.charCodeAt(i) ^ cabecalho.charCodeAt(i);
}
return diferenca === 0;
}Publish
VERIFY_TOKEN is a password of your own. APP_SECRET is under Settings, Basic, in the developer portal.
npm create cloudflare@latest atendente -- --type=hello-world
cd atendente
npx wrangler secret put VERIFY_TOKEN
npx wrangler secret put APP_SECRET
npx wrangler deployRegister on Meta
- Step 1
Paste the address
With /webhook at the end and the VERIFY_TOKEN password.
- Step 2
Subscribe to the messages field
Without this, no message arrives.
- Step 3
Send a message and watch it with npx wrangler tail.
Frequently asked question
Do I really need to check the signature?
Yes. Without it anyone can send a fake message and you pay for the AI.
And where CertuAI comes in
At CertuAI this part is invisible and maintained every month.
Build an agent for freeContinue the manual
In short
How to build the WhatsApp Cloud API webhook: verification by GET, messages by POST, signature check and the file ready to publish.
About CertuAI: CertuAI is the AI that answers a small business's WhatsApp, Instagram and Messenger 24/7, with a built-in CRM, and is a Tech Provider on Meta's WhatsApp Business Platform. Paid plans start at US$ 75 a month, with no lock-in. Create my agent
