Skip to content

Automate WhatsApp with an API, webhooks and n8n

Build WhatsApp automation that survives retries: idempotent requests, signed webhooks you verify properly, duplicates handled, and no-code options.

Written by
By WavesFlo team
Last updated
Updated
Reading time
5 min read

To automate WhatsApp reliably, make every send safe to retry with an Idempotency-Key, verify each webhook's signature over its timestamp and raw body, and deduplicate events, which arrive at least once and not always in order. In n8n, the Webhook, Crypto and Remove Duplicates nodes handle the last two.

Most WhatsApp automations fail in the same few places: a retry that sends twice, a webhook nobody verified, an event handled twice or out of order. None of these is exotic, and each has a standard fix. This guide walks through them, then covers the options that need no code at all.

Make every send safe to retry

Networks time out. When a send times out, you cannot tell whether it went. In WavesFlo's API, sends and other create actions accept an Idempotency-Key, and a retry carrying the same key within 24 hours returns the first result instead of repeating the action. That single header is the difference between a safe retry and a duplicate message.

Which WhatsApp webhook events can I subscribe to?

Webhooks push changes to you instead of making you poll. WavesFlo publishes twenty signed events in six categories, and every event carries the id of the connected number it happened on:

WavesFlo's twenty webhook events by subscription category, as of October 2026
CategoryEventsFires when
Messagingmessage.received, message.sent, message.ack, message.reaction, message.media_storedA message arrives; a message is sent, even one typed on the phone; a sent message's receipt changes, such as delivered or read; someone reacts or removes a reaction; arriving media is stored
Engagementpoll.voteSomeone votes in a poll, or changes their vote
Groupsgroup.participant_joined, group.participant_left, group.settings_changed, group.membership_requestSomeone joins a group a connected number is in; someone leaves or is removed; the group's subject, description or admin-only settings change; someone asks to join a group with approval turned on
Consentconsent.withdrawn, consent.grantedSomeone asks to stop hearing from you; consent is recorded or restored
Campaignscampaign.started, campaign.completed, campaign.failed, campaign.approval_requiredA campaign starts sending, including after an approval; finishes its queue; stops without completing; is waiting on a person's decision
Accountsaccount.connected, account.disconnected, account.qr_required, account.send_blockedA number finishes linking and can send; drops off; needs re-linking before it can send again; has a send refused by the sending checks

Subscribe each destination only to the categories it acts on. A sync to your customer database needs consent and messaging events; an operations channel needs campaign and account events. message.received fires for direct chats and groups alike, so it can feed an alert while the team replies from the shared inbox.

How do I verify a WhatsApp webhook signature?

Each delivery carries an X-Wavesflo-Timestamp header and an X-Wavesflo-Signature header of the form sha256=<hex>: an HMAC-SHA256 of the timestamp, a dot, and the raw request body. Verify all three together. A signature over the body alone lets a captured request be replayed later; checking that the timestamp is recent closes that.

import { createHmac, timingSafeEqual } from "node:crypto";

function verify(rawBody, headers, secret) {
  const ts = headers["x-wavesflo-timestamp"];
  const sig = String(headers["x-wavesflo-signature"] ?? "").replace("sha256=", "");
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
  const digest = createHmac("sha256", secret).update(`${ts}.${rawBody}`).digest();
  const sent = Buffer.from(sig, "hex");
  return sent.length === digest.length && timingSafeEqual(sent, digest);
}
Node.js
Verify against the raw bytes before parsing JSON. Re-serialising the body changes it, and the signature will not match.

In n8n, as its docs stood in October 2026: turn on the Webhook node's Raw Body option, compute the HMAC with the Crypto node's Hmac action, which takes its key from a Crypto credential's Hmac Secret, and compare the result with the header minus its sha256= prefix. The n8n group workflows guide has the full recipe, including where a Code node is needed for a constant-time comparison.

Why do webhook events arrive twice or out of order?

  • Delivery is at least once, so you will see some events twice. Deduplicate on the event identifier, which stays the same across retries; in n8n, the Remove Duplicates node's Remove Items Processed in Previous Executions operation does it.
  • Order is not guaranteed. Order by the event's own timestamp, not by when it arrived.
  • Failed deliveries are retried with backoff, only to the endpoints that failed.
  • Redirects are not followed, and an endpoint that fails twenty times in a row is disabled with the reason recorded.

Can I automate WhatsApp without code?

Yes, through a connector that does the delivery work for you. n8n's built-in WhatsApp Business Cloud node is one option for a business number set up through a Meta developer app: its operations send messages, send and wait for a response, send pre-registered messages, and upload, download or delete media. It has no group operations. For numbers linked from a phone, and the groups they belong to:

  • HubSpot and Zoho CRM: a native integration under Integration → CRM. Nothing syncs until a workspace admin switches it on; then incoming and outgoing one-to-one chats and opt-outs can be logged as notes on the matching contact. Group, status and channel messages never are. Other CRMs use webhooks with n8n or Power Automate.
  • n8n: connect through the REST API and signed webhooks. An HTTP Request node sends messages and manages groups and contacts, and a Webhook node starts a workflow from any of the twenty events. See n8n workflows for WhatsApp groups.
  • Power Platform: a custom connector generated from the API's own OpenAPI description, usable in Power Automate, Power Apps and Logic Apps. The Power Automate WhatsApp connector guide compares it with the catalogue options and walks through the import.
  • Slack or Microsoft Teams: approval requests, campaign results and number alerts, such as a number disconnecting or a send being blocked, posted to a channel.
  • Google Sheets: a sheet as a campaign source, one personalised message per row. See Google Sheets to WhatsApp.

The full reference, including request samples, is on the developers page, and the FAQ answers the common integration questions.

Two destinations for message.received are walked through step by step: WhatsApp to Google Sheets and, for teams that want an n8n workflow rather than the native integration, WhatsApp leads into Zoho CRM.

Questions

How do I verify a WavesFlo webhook?

Compute an HMAC-SHA256 of the X-Wavesflo-Timestamp header, a dot and the raw body with your signing secret, compare it with the X-Wavesflo-Signature header in constant time, and reject stale timestamps.

Can I verify a webhook signature in n8n without code?

Mostly. Turn on the Webhook node's Raw Body option, then use the Crypto node's Hmac action (SHA256, hex, keyed by a Crypto credential's Hmac Secret) on the X-Wavesflo-Timestamp header, a dot and the raw body, and compare the result with the X-Wavesflo-Signature header minus its sha256= prefix. Reject timestamps more than five minutes old; a Code node is needed only for a constant-time comparison.

Does n8n's built-in WhatsApp node work with groups?

No. The WhatsApp Business Cloud node sends messages, waits for responses, sends pre-registered messages and handles media for a number set up through a Meta developer app. None of its operations reaches groups.

Can I automate WhatsApp campaigns without writing code?

Yes, with WavesFlo: Google Sheets as a campaign source, approval requests and campaign alerts in Slack or Microsoft Teams, and a Power Platform custom connector; n8n connects through the REST API and signed webhooks. HubSpot or Zoho CRM contacts with an international phone number can also be imported into the audience, though an import never records consent.

Sources

Keep reading

See it on your own numbers.