WhatsApp Webhooks: A Complete Guide
How WhatsApp webhooks work, what a production endpoint has to handle, and the failure modes — replay, retry storms, out-of-order events — that bite integrations in month two.
A WhatsApp webhook is an HTTPS request sent to your server when something happens on a connected WhatsApp account — a message arriving, a file finishing its sync, a session dropping. This guide covers what a production endpoint has to handle, and the failure modes that show up after launch rather than during it.
Why webhooks instead of polling
Polling a conversations endpoint every thirty seconds gives you messages up to thirty seconds late, spends most of its requests on empty responses, and cannot tell you the moment a session dropped — only that something changed between two snapshots.
Webhooks invert it. The event arrives when it exists, carrying exactly what changed. The cost is that your endpoint has to be correct about a handful of things that polling let you ignore.
The event catalogue
Subscribe narrowly. An endpoint that receives every event and ignores most of them is doing work for nothing, and makes your delivery log harder to read when something goes wrong.
Verifying that an event is genuine
Your endpoint URL is not a secret. It appears in logs, in configuration, in a screenshot in a ticket. The signature is what makes a discovered URL harmless.
Three details matter more than the algorithm:
- Verify the raw body. Frameworks that parse JSON before your handler runs will break signature checks, because re-serialization changes whitespace and key order.
- Reject stale timestamps. Without a tolerance window, a captured request stays valid forever and can be replayed.
- Compare in constant time. String equality short-circuits on the first differing byte, which leaks information to an attacker who can measure it.
Responding correctly
The contract is simple: return 2xx quickly if you have durably accepted the event. Anything else is a failure and will be retried.
Durably accepted means written somewhere that survives a process restart — a queue, a table, a log. It does not mean fully processed. Fully processing inside the handler is the single most common design error in webhook consumers.
The four failure modes
1. The retry storm
Your CRM has a slow afternoon. Your handler calls it synchronously and starts timing out. Every timeout is a failed delivery, so every event is retried, so your handler receives more traffic than before, so it times out more. Acknowledging before processing breaks this loop entirely.
2. Out-of-order arrival
A status update can reach you before the message it refers to, especially during a reconnect catch-up. Code that assumes arrival order will drop the status or crash on a missing foreign key.
Key on the message identifier and upsert. If the status arrives first, create a stub and let the message event fill it in.
3. Duplicate processing
Retries carry the same idempotency key, and the same message can arrive through realtime, reconnect replay and history backfill. Record the key before processing and check it first. This is five lines of code and prevents the failure that destroys trust in the data.
4. Silent disconnection
The most damaging failure is not an error — it is nothing at all. A session is unlinked, messages keep arriving on the phone, and your endpoint receives silence. Nothing alerts, because nothing failed.
Subscribe to connection events and treat connection.disconnected as an outage alert. A dead-man's-switch on event volume per connection catches the rarer case where events stop without a state change.
Testing a webhook endpoint
- Point the webhook at a tunnel to your machine and send yourself a message. Log the raw body before doing anything else.
- Verify the signature against a known-good payload, then deliberately corrupt one byte and confirm you reject it.
- Replay the same delivery twice and confirm your database has one row.
- Return a 500 on purpose and watch the retry schedule in the delivery log.
- Disconnect the session and confirm your alert fires.
The last two are the ones teams skip, and they are the ones that matter at 3am.
Observability
A delivery log — what was sent, what your endpoint returned, how long it took — turns "the integration is broken" from an argument into a lookup. Combine it with your own logging of the idempotency key and you can trace any individual message end to end.
A minimal production checklist
- Signature verified over the raw body, with a timestamp tolerance
- 2xx returned in milliseconds, processing deferred to a worker
- Idempotency key recorded and checked before any write
- Writes keyed on the message identifier, implemented as upserts
- Connection events routed into existing alerting
- Delivery failures visible on a dashboard someone actually looks at
Six items. An endpoint that does all six will run for years without attention, which is the entire point of building it properly the first time.
Frequently asked
What is a WhatsApp webhook?
A WhatsApp webhook is an HTTPS request that a platform sends to your server when something happens on a connected WhatsApp account, such as a message arriving, media finishing its sync, or a session disconnecting.
How do I verify a WhatsApp webhook signature?
Compute an HMAC-SHA256 over the timestamp and the raw request body using your signing secret, then compare it to the value in the signature header using a constant-time comparison. Verify before parsing the JSON.
What should a webhook endpoint return?
A 2xx status as soon as the event has been durably accepted — written to a queue or table. Process asynchronously, because anything other than a fast 2xx is treated as a failed delivery and retried.