Receive WhatsApp messages by webhook
By the end, your system will receive, by webhook, every message that arrives at the connected number. You start a Node.js server, point the API at it and watch the message appear in the terminal.
Prerequisites
Section titled “Prerequisites”- A connected instance (Connection).
- The instance ID and token.
- Node.js 18 or newer.
- A way to give your computer a public HTTPS address, such as a tunnel. The API rejects
localhostand internal network addresses with400andurl_not_allowed.
1. Create the server
Section titled “1. Create the server”Save it as receber.mjs:
import { createServer } from 'node:http'
const PORTA = 3000// Em produção, guarde isso num banco ou no Redis. Aqui basta a memória.const entregasProcessadas = new Set()
function tratar(evento, corpo) { if (evento === 'message.received') { const { from, type, text } = corpo.data console.log(`Mensagem de ${from} (${type}): ${text ?? '[sem texto]'}`) } else { console.log(`Evento recebido: ${evento}`) }}
createServer((req, res) => { if (req.method !== 'POST' || req.url !== '/webhook') { res.writeHead(404).end() return } const pedacos = [] req.on('data', (pedaco) => pedacos.push(pedaco)) req.on('end', () => { // Confirme primeiro, trabalhe depois. res.writeHead(200).end('ok')
const entrega = req.headers['x-nigora-delivery'] if (entregasProcessadas.has(entrega)) return try { tratar(req.headers['x-nigora-event'], JSON.parse(Buffer.concat(pedacos).toString('utf8'))) entregasProcessadas.add(entrega) } catch { console.error('Corpo ilegível, ignorado.') } })}).listen(PORTA, () => console.log(`Ouvindo na porta ${PORTA}, rota /webhook`))The server answers 200 before processing. The API expects a 2xx response within 10 seconds. If it does not come, the delivery counts as a failure and is retried. That is why the code also keeps the x-nigora-delivery: if the same delivery arrives again, it is ignored.
2. Run it and open the tunnel
Section titled “2. Run it and open the tunnel”node receber.mjsExpected output:
Ouvindo na porta 3000, rota /webhookIn another terminal, open a tunnel to port 3000. It gives you a public HTTPS address. Use that address, with /webhook at the end, in the next step.
3. Point the API at the server
Section titled “3. Point the API at the server”PUT /v1/instances/{instanceId}/webhooks replaces the whole configuration. So always send the complete set:
curl -X PUT https://api.zap.nigora.com.br/v1/instances/INSTANCIA_ID/webhooks \ -H "Authorization: Bearer TOKEN" \ -H "Content-Type: application/json" \ -d '{ "events": { "message.received": { "url": "https://SEU_ENDERECO_PUBLICO/webhook", "enabled": true } }, "notifySentByMe": false, "receiveFilters": { "ignoreGroups": true } }'The response is 200 and carries the saved configuration, with the secret. You will use the secret in the signature validation tutorial.
4. Test it
Section titled “4. Test it”From another phone, send a message to the connected number. The server terminal shows something like:
Mensagem de 5511999999999@s.whatsapp.net (text): Olá!Did nothing show up? Check the history with GET /v1/instances/{instanceId}/webhooks/deliveries. Each delivery shows the status and the last response from your server. To repeat a delivery, use POST /v1/instances/{instanceId}/webhooks/deliveries/{id}/resend.
Next steps
Section titled “Next steps”- Validate the webhook signature: make sure the call came from the API.
- Webhooks: all events, filters, retries and resending.
- Sending messages: reply to whoever wrote.
Send a WhatsApp message with Python Next
Validate the webhook signature in Node.js, PHP and Python