# WhatsApp webhook without Meta approval: is it possible?

> Get every incoming WhatsApp message on your own number as a signed JSON webhook, no Meta app or review. Payload, Node.js handler, 8 retries over 3 days.

Source: https://unlimitedmessaging.app/articles/whatsapp-webhook-incoming-messages

WhatsApp webhook

# Receive WhatsApp messages on your server,  
_from the number you already use._

Meta's webhooks come with a Meta app, a business portfolio and a number moved to the API. Link your existing WhatsApp instead, and each incoming message arrives at your URL as signed JSON.

[Create a free account](https://app.unlimitedmessaging.app)[See paid plans](https://unlimitedmessaging.app/pricing)

The short answer

## Can you get a WhatsApp webhook without Meta's Business API?

Yes. Unlimited Messaging links your existing WhatsApp number as a linked device, like WhatsApp Web, and posts every incoming message to your URL as a [Standard Webhooks](https://www.standardwebhooks.com) signed JSON event called message.received. There is no Meta app to create, no business verification and no fee per message. Webhooks are on the paid Medium and Max plans.

The official route is Meta's WhatsApp Cloud API. To receive its webhooks you create a Meta app with the WhatsApp use case, attach a business portfolio and a WhatsApp Business Account, answer a GET verification request with hub.challenge, and serve a valid TLS certificate: Meta does not accept self-signed ones. A new business portfolio can then message only 250 people a day first (outside the 24-hour window) until it is verified, and a company building this for clients needs Meta's App Review on top.

Unlimited Messaging takes the other path: you scan a QR code from WhatsApp, Linked devices, and the number keeps working on your phone. Each message that reaches it is stored and pushed to your endpoint with the sender, the text, the conversation, and for a photo or a voice note a mediaUrl that serves the file. Your answer goes back through POST /message from the same number, so the customer sees one ordinary chat.

The trade-off is honest: this is the unofficial linked-device protocol, not a Meta product. It suits replies and notifications to people who already talk to you. Mass messaging strangers gets numbers banned, whatever the tool.

Before you build: [the free WhatsApp API options compared](https://unlimitedmessaging.app/articles/free-whatsapp-api), and [how to keep a linked number safe from bans](https://unlimitedmessaging.app/articles/avoid-whatsapp-ban).

![Illustration: a phone showing a WhatsApp-style chat next to a green chat badge, with the headline “WhatsApp webhook, no Meta app”.](https://unlimitedmessaging.app/_next/image?url=%2Fassets%2Farticles%2Fcovers%2Fwhatsapp-webhook-incoming-messages-en.png&w=3840&q=75)

Definition
WhatsApp webhook

An HTTP POST that a WhatsApp gateway sends to your server each time something happens on a number: a message received, a status change, a reaction. Your code reacts instead of polling.

Also searched as WhatsApp incoming message webhook, receive WhatsApp messages by API, or WhatsApp callback URL.

[Source: Meta, Graph API webhooks↗](https://developers.facebook.com/docs/graph-api/webhooks/getting-started)

The events

## Which WhatsApp events can you receive by webhook?

Ten event types, each chosen per endpoint: an endpoint only receives what is in its eventTypes list. These are the ones a WhatsApp inbox needs.

1. 01  
### message.received  
A message arrived, in a 1:1 chat or a group: text, image, video, document, audio, voice note (ptt), sticker or location. Fired once per message; a media message is announced once its file is stored, with mediaUrl.
2. 02  
### message.self\_sent  
You typed a message on the phone itself, outside the API. Same shape as message.received with direction OUT, so your CRM sees both sides of the chat.
3. 03  
### message.reaction, message.edited, message.deleted  
Someone reacted with an emoji (or took it back), edited a message, or deleted it for everyone. Each names its target by externalId, and can arrive before the message it changes.
4. 04  
### message.sent and message.status  
A message you sent by API reached WhatsApp, then moved to DELIVERED, READ, FAILED or UNDELIVERABLE. message.status carries previousStatus so you can ignore a stale receipt.
5. 05  
### account.status\_changed  
The number connected, disconnected, was logged out or restricted by WhatsApp (BLOCKED, with blockedUntil). Subscribe to it so a silent inbox never goes unnoticed.

POST https://example.com/webhooks/umJSON

```
{
  "type": "message.received",
  "eventId": "whd_6f1c2a9e-1b7d-4c55-9a43-2f0e8b7d3c11",
  "occurredAt": "2026-11-09T10:00:01.000Z",
  "data": {
    "message": {
      "id": "msg_0e55ff33-854a-482c-8510-68226e09cdcb",
      "externalId": "3EB0A1C2D3E4F5061728",
      "direction": "IN",
      "fromMe": false,
      "content": "Hi! Is my order ready for pickup?",
      "sentAt": "2026-11-09T10:00:00.000Z",
      "receivedAt": "2026-11-09T10:00:01.000Z",
      "sender": "+447700900123",
      "senderId": "447700900123@s.whatsapp.net",
      "senderName": "Lea",
      "participant": null,
      "replyTo": null,
      "transcript": null
    },
    "channel": {
      "type": "WHATSAPP",
      "account": { "id": "acc_373bc415-447a-4813-9b61-a3a09ea9aaf3", "name": "Support" },
      "conversation": {
        "id": "447700900123@s.whatsapp.net",
        "isGroup": false,
        "address": "+447700900123"
      }
    }
  }
}
```

A real message.received body, built from the published schema. sender is +E.164, or null when WhatsApp hides the number, in which case senderId identifies the person. Events are not delivered in order: sort on sentAt.

Set it up

## How do you receive incoming WhatsApp messages in Node.js?

Three steps: link the number, register an endpoint, verify and handle each POST. Answer within 10 seconds and do the work after.

1. 01  
### Link your WhatsApp  
In the web app, add a WhatsApp account and scan the QR code from WhatsApp, Settings, Linked devices. The number stays on your phone.
2. 02  
### Register the endpoint  
POST /webhooks with your URL and eventTypes, or add it on the Webhooks page of the dashboard. The secret (whsec\_...) is shown once.
3. 03  
### Verify, acknowledge, act  
Check the webhook-signature header, return 2xx, then deduplicate on eventId: delivery is at least once.

POST /webhookscurl

```
curl https://api.unlimitedmessaging.app/webhooks \
  -H "Authorization: Bearer $UM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/webhooks/um",
    "eventTypes": ["message.received", "account.status_changed"],
    "description": "Incoming WhatsApp"
  }'

# The response carries "secret": "whsec_..." once. Store it as UM_WEBHOOK_SECRET.
```

accountIds is optional: without it the endpoint covers every account you have, including numbers linked later. PATCH /webhooks/{id} replaces the eventTypes list.

webhook handlerNode.js / Express

```
import crypto from 'node:crypto';
import express from 'express';
import { UnlimitedMessagingApiClient } from '@unlimited-messaging/sdk';

const um = new UnlimitedMessagingApiClient({ token: process.env.UM_API_KEY! });
const key = Buffer.from(process.env.UM_WEBHOOK_SECRET!.replace(/^whsec_/, ''), 'base64');
const seen = new Set<string>(); // use your database in production

// Standard Webhooks: HMAC-SHA256 of "id.timestamp.rawBody", base64.
function verify(raw: string, id: string, ts: string, header: string) {
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
  const expected = crypto.createHmac('sha256', key).update(`${id}.${ts}.${raw}`).digest('base64');
  return header.split(' ').some((entry) => {
    const sig = entry.startsWith('v1,') ? entry.slice(3) : '';
    return sig.length === expected.length &&
      crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
  });
}

const app = express();
app.post('/webhooks/um', express.raw({ type: 'application/json' }), async (req, res) => {
  const raw = req.body.toString('utf8');
  const ok = verify(raw, req.get('webhook-id') ?? '', req.get('webhook-timestamp') ?? '',
    req.get('webhook-signature') ?? '');
  if (!ok) return res.sendStatus(401);
  res.sendStatus(200); // answer within 10 s, work afterwards

  const event = JSON.parse(raw);
  if (seen.has(event.eventId)) return; // at-least-once delivery
  seen.add(event.eventId);

  if (event.type === 'message.received' && event.data.channel.type === 'WHATSAPP') {
    const { id, content } = event.data.message;
    if (content?.toLowerCase().includes('order')) {
      // Answers in the same chat, from the same linked number.
      await um.messages.messageSend({ replyToMessageId: id, text: 'Checking your order now.' });
    }
  }
});
app.listen(3000);
```

The signature check follows the documented scheme: HMAC-SHA256 over id.timestamp.rawBody with the base64-decoded secret, timestamps older than 5 minutes rejected. Any Standard Webhooks library does the same. replyToMessageId answers in the same chat.

Vibe coding

## Building with Cursor, Claude Code, Lovable or Bolt? Paste this

The prompt gives your AI editor the endpoint, the signature scheme and the event shape, so it writes the webhook route instead of guessing.

Prompt to copy

Add an Unlimited Messaging webhook to this app so it receives incoming WhatsApp messages from my own number.

1. Create a POST route at /webhooks/um that reads the RAW request body (no JSON parsing before verification).
2. Verify the Standard Webhooks signature: key = base64-decode(UM_WEBHOOK_SECRET without its "whsec_" prefix); expected = base64(HMAC-SHA256(key, `${webhook-id}.${webhook-timestamp}.${rawBody}`)); accept if any space-separated entry of the webhook-signature header equals `v1,${expected}` (constant-time compare); reject timestamps more than 5 minutes off. Return 401 if invalid.
3. Return 200 at once, then process. Deduplicate on body.eventId.
4. On type "message.received" with data.channel.type "WHATSAPP", read data.message.content, data.message.sender (+E164 or null), data.message.senderName and data.message.mediaUrl, and save them.
5. To reply, install @unlimited-messaging/sdk, read UM_API_KEY from env, and call `new UnlimitedMessagingApiClient({ token }).messages.messageSend({ replyToMessageId: data.message.id, text })`.
6. Add UM_API_KEY and UM_WEBHOOK_SECRET to .env and .env.example, never hardcode them.

Docs: https://docs.unlimitedmessaging.app (Webhooks section). Register the URL with POST https://api.unlimitedmessaging.app/webhooks and eventTypes ["message.received"].

What people build

## What can you do with incoming WhatsApp messages?

Anything that starts with "when a customer writes". A few that fit the linked-number model well.

### An AI auto-responder on your real number

Pass content to Claude or GPT, send the answer back with replyToMessageId. Customers keep writing to the number they saved, and you can take over from the phone at any time.

### WhatsApp into your CRM or helpdesk

Store every message.received and message.self\_sent against the contact, keyed on sender or senderId, so the whole conversation lives next to the deal or the ticket.

1. 01  
### Order and booking lookups  
Match a keyword or an order number in the text, look it up, answer in seconds. Media arrive as a stored file you can fetch.
2. 02  
### Group monitoring  
In a group, participant names who posted and channel.conversation.participants lists the members, refreshed when the group changes.
3. 03  
### Team alerts  
Forward an urgent message to Slack or by email, or wake someone up when account.status\_changed reports a disconnection.
4. 04  
### No-code flows  
Point the webhook at n8n, Make or Zapier and branch on type and channel.type without writing a server.

The table

## Incoming WhatsApp webhooks: Meta Cloud API vs Twilio vs Unlimited Messaging

Meta and Twilio are the official Business Platform, with its approvals and per-message pricing. Unlimited Messaging links the number you already have.

__Incoming WhatsApp webhooks: Meta Cloud API vs Twilio vs Unlimited Messaging__
| [Meta Cloud API](https://developers.facebook.com/docs/whatsapp/cloud-api)Official, direct | [Twilio WhatsApp](https://www.twilio.com/en-us/whatsapp/pricing)Official, via a provider | Unlimited MessagingLinked device, paid plans                           |                                                           |
| ----------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | --------------------------------------------------------- |
| What you set up first                                                                     | Meta app, business portfolio, WhatsApp Business Account                                  | Twilio account, Meta Business Portfolio, a WABA created through Twilio | A QR code scan from your phone                            |
| Your current number                                                                       | Registered to the platform                                                               | Must not already be registered with WhatsApp                           | Kept, still usable on your phone                          |
| Approval and limits                                                                       | 250 business-initiated recipients a day until verified; App Review for tech providers    | Meta business verification before production                           | None from Meta; WhatsApp's own anti-spam rules apply      |
| Endpoint handshake                                                                        | GET verification with hub.challenge, valid TLS, no self-signed                           | Webhook URL set on the sender                                          | None: register the URL, receive                           |
| Signature                                                                                 | X-Hub-Signature-256, HMAC-SHA256 with the app secret                                     | X-Twilio-Signature, HMAC-SHA1 with the auth token                      | Standard Webhooks, HMAC-SHA256 with a per-endpoint secret |
| Body format                                                                               | JSON, nested entry/changes                                                               | Form-encoded (application/x-www-form-urlencoded)                       | JSON, same envelope for email and SMS                     |
| Retries                                                                                   | Decreasing frequency for up to 7 days                                                    | Not stated on the webhook docs                                         | 8 attempts over a little more than 3 days                 |
| Cost of receiving and replying                                                            | Service replies free up to 1,000 per number a month, then charged; templates charged     | $0.005 per message, inbound or outbound, plus Meta's fees              | No per-message fee; webhooks need Medium or Max           |

Checked on 9 November 2026 on Meta's webhook, messaging-limit and pricing docs, Twilio's WhatsApp self sign-up guide, pricing and webhook security pages (links in the sources).

The catch

## What are the limits of a linked-number WhatsApp webhook?

Skipping Meta removes the approvals. It does not remove WhatsApp's rules or the realities of a linked device.

1. 01  
### Webhooks are a paid feature  
The Free plan sends and shows incoming messages in the web app, but pushing them to your server needs Medium (€19 a month, or €17 a month billed yearly) or Max. No per-message fee on either.
2. 02  
### It is unofficial  
The linked-device protocol is the one WhatsApp Web uses, not a Meta API. WhatsApp can restrict a number that spams or gets reported: account.status\_changed tells you when it happens, with blockedUntil when known.
3. 03  
### A linked device follows WhatsApp's rules  
WhatsApp logs linked devices out if the main phone stays offline for 14 days. Open WhatsApp on the phone now and then and the link keeps running with the phone off.
4. 04  
### Order and duplicates are your job  
Delivery is at least once and not in order: a text sent right after a photo usually arrives first, since the photo waits for its file to be stored. Deduplicate on eventId, sort on sentAt.
5. 05  
### History is opt-in  
Only messages received after linking are announced, unless the account was linked with syncHistory, which sends past chats as message.history batches of up to 100 (history media are described, not stored).

How to choose

### Meta's Cloud API or your linked number?

You need green-tick branding, template campaigns at scale, or a contract with Meta behind you: go through the Cloud API or a provider like Twilio, and budget for verification and per-message fees. You want the messages your customers already send to your number to reach your code today, with replies from that same number: link it and subscribe to message.received.

FAQ

## Questions about WhatsApp webhooks

Yes. Unlimited Messaging links your existing number as a linked device and sends each incoming message to your URL as a signed JSON POST (message.received). No Meta app, business portfolio or verification is involved. Webhooks require the Medium or Max plan.

An envelope with type, eventId and occurredAt, then data.message (id, externalId, direction, fromMe, content, sentAt, receivedAt, sender, senderId, senderName, participant, replyTo, transcript, and media fields such as mediaUrl, mediaType and mimeType) and data.channel (type WHATSAPP, account, conversation).

Yes, per the Standard Webhooks spec. Each request has webhook-id, webhook-timestamp and webhook-signature headers; the signature is v1, followed by a base64 HMAC-SHA256 of id.timestamp.rawBody, keyed with your whsec\_ secret base64-decoded. Reject timestamps more than 5 minutes off.

A 429, a 5xx, a timeout or a network error is retried after 30 s, 2 min, 10 min, 1 h, 6 h, 1 day and 2 days: 8 attempts over a little more than 3 days. Any other 4xx is final. Delivery attempts are kept for 30 days and visible in the dashboard.

Yes. A media message is announced once its file is stored, with mediaUrl, mediaType (image, video, document, audio, ptt, sticker), mimeType and size. Files above 64 MB come with mediaError too\_large instead. The transcript field is reserved and null for now.

Yes. Group messages arrive as message.received with isGroup true, participant naming who posted, and channel.conversation.participants listing the members. group.updated reports name, topic and membership changes.

Call POST /message with replyToMessageId set to data.message.id and your text. The reply goes out from the same linked number, in the same chat, and is announced back as message.sent.

It uses the same linked-device protocol as WhatsApp Web, but it is not an official Meta API, and WhatsApp's terms forbid bulk and automated messaging that people did not ask for. Replying to people who write to you is low risk; cold blasts get numbers banned.

Sources

## Sources & references

To check the information in this article for yourself:

1. [01Getting started with webhooks (verification, X-Hub-Signature-256, TLS)↗Meta for Developers](https://developers.facebook.com/docs/graph-api/webhooks/getting-started)
2. [02Set up webhooks for WhatsApp (retries for up to 7 days)↗Meta for Developers](https://developers.facebook.com/docs/whatsapp/cloud-api/guides/set-up-webhooks)
3. [03WhatsApp Cloud API - get started (Meta app, business portfolio)↗Meta for Developers](https://developers.facebook.com/docs/whatsapp/cloud-api/get-started/)
4. [04Messaging limits (250 for new business portfolios)↗Meta for Developers](https://developers.facebook.com/docs/whatsapp/messaging-limits)
5. [05Get started for tech providers (business verification and App Review)↗Meta for Developers](https://developers.facebook.com/docs/whatsapp/solution-providers/get-started-for-tech-providers)
6. [06WhatsApp Business Platform pricing↗Meta for Developers](https://developers.facebook.com/docs/whatsapp/pricing)
7. [07WhatsApp self sign-up (number must not be registered with WhatsApp)↗Twilio Docs](https://www.twilio.com/docs/whatsapp/self-sign-up)
8. [08WhatsApp pricing ($0.005 per message, inbound or outbound)↗Twilio](https://www.twilio.com/en-us/whatsapp/pricing)
9. [09Webhooks security (X-Twilio-Signature, HMAC-SHA1)↗Twilio Docs](https://www.twilio.com/docs/usage/webhooks/webhooks-security)
10. [10Standard Webhooks specification↗standardwebhooks.com](https://www.standardwebhooks.com)
11. [11About linked devices (logout after 14 days without the main phone)↗WhatsApp Help Center](https://faq.whatsapp.com/378279804439436)
12. [12Unlimited Messaging API reference - Webhooks↗Unlimited Messaging](https://docs.unlimitedmessaging.app)

![Ilian, senior software engineer](https://ilianazz.com/images/iliazz.png)

Written by

[Ilian](https://unlimitedmessaging.app/authors/ilian) · Senior Software Engineer

A senior software engineer, he founds and runs several tech companies. He builds products around messaging APIs, automation and AI integration, and shares here what he learns while building.

[View LinkedIn profile↗](https://www.linkedin.com/in/ilianAzz/)Updated November 9, 2026

![](https://unlimitedmessaging.app/assets/logos/whatsapp.svg)![](https://unlimitedmessaging.app/assets/logos/email.svg)![](https://unlimitedmessaging.app/assets/logos/sms.svg)

## Your WhatsApp messages, on your server.

Create an account, link your number by QR code, and turn on webhooks with Medium or Max. Sending stays free on every plan.

[Create a free account→](https://app.unlimitedmessaging.app)

Similar articles
* [![](https://unlimitedmessaging.app/_next/image?url=%2Fassets%2Farticles%2Fcovers%2Fone-webhook-whatsapp-email-sms-en.png&w=3840&q=75)One webhook for WhatsApp, email and SMS: how far does it go?Every reply on your number, mailbox and phone in one signed JSON envelope: build a support inbox, an AI responder or a CRM sync.](https://unlimitedmessaging.app/articles/one-webhook-whatsapp-email-sms)
* [![](https://unlimitedmessaging.app/_next/image?url=%2Fassets%2Farticles%2Fcovers%2Ffree-whatsapp-api-en.png&w=3840&q=75)Free WhatsApp API in 2026: which ones are really free?FreeMeta's free tier, GREEN-API, WAHA, Evolution API, Baileys and a free hosted plan, next to the APIs that are only trials.](https://unlimitedmessaging.app/articles/free-whatsapp-api)
* [![](https://unlimitedmessaging.app/_next/image?url=%2Fassets%2Farticles%2Fcovers%2Fwhatsapp-business-or-api-choose-en.png&w=3840&q=75)WhatsApp Business app or API: which one do you need in 2026?WhatsApp Business app, official API, or Unlimited Messaging: how to choose for your use case.](https://unlimitedmessaging.app/articles/whatsapp-business-or-api-choose)
