---
title: "Set Up WhatsMCP Webhooks for Real-Time WhatsApp — WhatsMCP Blog"
description: "Push every inbound WhatsApp message to your own HTTPS endpoint the instant it arrives — how to register a WhatsMCP webhook, verify the signature, build a receiver that never loses a message, and three things to build on inbound events."
url: "https://whatsmcp.com/blog/whatsmcp-webhooks-setup"
---

Reading messages on a schedule works, but it's always a compromise: poll too often and you waste calls, poll too slowly and you're late to every conversation. Webhooks remove the trade-off. Register an HTTPS endpoint once, and WhatsMCP pushes each inbound message to it the instant it arrives — signed, structured, and ready to act on.

This guide sets one up, shows you how to verify and consume a delivery, and finishes with a few things worth building on top.

## What you're building

A webhook is just an HTTPS URL you own that WhatsMCP calls with a small JSON body every time one of your paired numbers receives a message. Your endpoint does something useful with it — reply, log a ticket, alert a human — and answers `200`. That's the whole contract.

## Set it up

There are two ways, and they configure the same thing.

**From the console.** Open **Console → Webhooks**, paste your endpoint URL, and save. WhatsMCP shows a **signing secret** on creation — copy it now, you'll need it to verify deliveries. Toggle the endpoint on, and inbound messages start flowing.

**From Claude, over MCP.** If you're already connected ([here's how](https://whatsmcp.com/blog/connect-whatsmcp-to-claude)), you can manage webhooks in plain language — Claude uses these tools:

- `wa_set_webhook` — registers your HTTPS endpoint to receive inbound messages.
- `wa_get_webhook` — shows the configured endpoint, whether it's enabled, and when it last succeeded.
- `wa_enable_webhook` — pauses or resumes delivery, keeping the endpoint and its signing secret.
- `wa_delete_webhook` — stops delivery. Messages remain readable through the API.

![Two ways to set up a webhook: from the console (endpoint URL, signing secret, enable) or from Claude with wa_set_webhook, wa_get_webhook, wa_enable_webhook and wa_delete_webhook — plus a reliable-receiver checklist.](https://content.whatsmcp.com/uploads/wh_setup_baa40e56e8.png)

## The delivery, and how to trust it

Each delivery is an HTTP `POST` with a flat JSON body and three headers:

- `X-WAMCP-Event` — the event name, e.g. `message.inbound`.
- `X-WAMCP-Delivery` — a unique id for this delivery attempt.
- `X-WAMCP-Signature` — a signature in the form `t=<unix>,v1=<hex>`.

The body is deliberately self-contained, so a receiver can act without a follow-up read:

```json
{
  "event": "message.inbound",
  "delivery_id": "d-8f3c…",
  "account_phone": "+15551234567",
  "peer": "+15559876543",
  "chat_jid": "15559876543@s.whatsapp.net",
  "kind": "text",
  "body": "Are you open on Sunday?",
  "message_seq": 20591,
  "at": "2026-09-11T14:02:11Z"
}
```

`account_phone` is *your* number that received the message — the field a routing rule or CRM keys on when you run more than one line. `message_seq` is the same cursor `wa_list_messages` uses, which matters for reliability (more below).

**Always verify the signature** before trusting a delivery. The value is computed exactly like Stripe's: an HMAC-SHA256, keyed by your signing secret, over the timestamp and a `.` and the raw request body. Recompute it and compare:

```js
import crypto from "node:crypto";

function verify(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(",").map(kv => kv.split("=")));
  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${parts.t}.${rawBody}`)   // timestamp + "." + raw body
    .digest("hex");
  return crypto.timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected));
}
```

Sign over the **raw** bytes you received, not a re-serialized object — reformatting the JSON changes the signature. Rejecting deliveries whose timestamp is far from now also protects you against replays.

![How a delivery works: an inbound message becomes a signed POST to your endpoint with a flat JSON payload; verify the HMAC-SHA256 signature over the timestamp and raw body.](https://content.whatsmcp.com/uploads/wh_flow_bbbdbb7c8e.png)

## Building a receiver that doesn't lose messages

A webhook endpoint is a small distributed-systems problem. Four habits cover almost everything:

1. **Answer fast, then work.** Return `200` as soon as you've verified and stored the delivery; do the slow parts (calling an LLM, hitting a CRM) afterward. An endpoint that blocks on downstream work will eventually time out and be retried needlessly.
2. **Be idempotent.** Deliveries can repeat. Deduplicate on `delivery_id` for the attempt, or on `message_id` / `message_seq` for the message itself, so a redelivery is harmless.
3. **Fail loudly, not silently.** A non-`2xx` response tells WhatsMCP the delivery failed, and it will retry with exponential backoff. If your handler can't process a message, returning an error is *better* than swallowing it.
4. **Catch up with the cursor.** Webhooks are the fast path, not the only path. If your endpoint was down for a while, don't hope the retries cover it — reconcile by calling `wa_list_messages` from the last `message_seq` you processed. The cursor is the source of truth; the webhook is the low-latency hint.

![Three things to build on inbound events: an AI auto-responder, helpdesk/CRM sync, and keyword routing with alerts.](https://content.whatsmcp.com/uploads/wh_uses_09f1610e4b.png)

## A few things to build

**1. An AI auto-responder.** The classic loop: the webhook fires, your server verifies it, hands the message to Claude (or your own logic), and replies with `wa_send_message`. First-line support, appointment confirmations, and FAQ answering all fit this shape — with a human handoff whenever the model is unsure.

**2. Helpdesk and CRM sync.** Turn every inbound WhatsApp message into a row where your team already works. Key on `account_phone` to route by line, open or update a ticket keyed on `peer`, and drop a notification into Slack. Because the payload is self-contained, you rarely need a second API call to file it.

**3. Keyword routing and alerts.** Act on content the moment it lands: treat `STOP` / `UNSUBSCRIBE` as an opt-out and update your list, page the on-call person when a message contains an urgent keyword, or tag and bucket messages by intent before a human ever sees them. Low latency is the whole point — the alert beats the notification.

## Wrapping up

Point WhatsMCP at an HTTPS endpoint, verify every signature, answer quickly, dedupe, and reconcile with the cursor — and you have a real-time WhatsApp pipeline your systems and your agents can build on. The full tool reference is at **[whatsmcp.com/docs/mcp](https://whatsmcp.com/docs/mcp)**; if you haven't connected Claude yet, start with the **[connection guide](https://whatsmcp.com/blog/connect-whatsmcp-to-claude)**.
