Skip to content
Nigora Zap API

    Sign in Create account

    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.

    • 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 localhost and internal network addresses with 400 and url_not_allowed.

    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.

    Terminal window
    node receber.mjs

    Expected output:

    Ouvindo na porta 3000, rota /webhook

    In 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.

    PUT /v1/instances/{instanceId}/webhooks replaces the whole configuration. So always send the complete set:

    Terminal window
    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.

    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.