/webhooks/whatsapp and /webhooks/meta — that behave identically except for the source label used when recording events. You register one of these URLs in the Meta App Dashboard, and Meta sends all WhatsApp Business Platform events there: inbound messages, delivery status updates, template status changes, and more. Switchbord validates every delivery, persists the raw envelope, normalizes the payload into a known event family, and enqueues a processing job.
GET /webhooks/whatsapp
Meta calls this endpoint with a one-time challenge before it starts sending events. You must complete this handshake before Meta will deliver any webhook payloads.Must be
subscribe for the verification handshake.The token you configured in the Meta App Dashboard. Switchbord compares this against the
meta-verify-token workspace secret.An arbitrary string that Meta expects you to echo back in the response body.
| Status | Condition | Body |
|---|---|---|
200 | Token matches | The raw hub.challenge string (plain text, not JSON) |
400 | Token mismatch or missing | {"ok": false, "error": "verification_failed"} |
Register the path (e.g.,
https://api.your-switchbord.example.com/webhooks/whatsapp) in the Meta App Dashboard under Webhooks. Set the verify token to the same value you store in your meta-verify-token workspace secret.POST /webhooks/whatsapp
Meta sends all WhatsApp Business Platform events to this endpoint as POST requests.Request headers
HMAC-SHA256 signature of the raw request body, prefixed with
sha256=. Switchbord validates this against your webhook-signing-secret workspace secret using a timing-safe comparison.Must be
application/json.Unique delivery identifier from Meta. Used for deduplication.
Request body
The body must be a valid Meta webhook envelope:Always
"whatsapp_business_account" for WhatsApp events.Array of WABA entry objects.
What Switchbord does with your delivery
- Reads the raw body as text and computes the expected HMAC-SHA256 signature.
- Compares it to the
X-Hub-Signature-256header using a timing-safe comparison. - Persists the raw envelope (headers, body hash, delivery ID, normalization status) regardless of signature validity.
- If the signature is valid, normalizes the envelope to extract messages and status updates, then enqueues a
process_webhook_eventoutbox job. - Returns HTTP
200in all cases — Meta’s platform requires a200response to stop retrying; events with invalid signatures are recorded for operator review.
Responses
| Status | Condition |
|---|---|
200 | Delivery accepted and recorded (valid or invalid signature) |
429 | Rate limit exceeded (secureWebhook guard) |
POST /webhooks/meta
This path is an alternative ingress endpoint with the same behavior asPOST /webhooks/whatsapp. The only difference is the source label attached to recorded webhook events ("meta" instead of "whatsapp"). Use whichever path you register in the Meta App Dashboard — both work identically.
Computing the signature
To generate a validX-Hub-Signature-256 header for local testing, compute an HMAC-SHA256 of the raw request body using your WEBHOOK_SIGNING_SECRET:
Supported event topics
Switchbord normalizes inbound envelopes into one of the following topics based on the content of the entry changes:| Topic | Description |
|---|---|
messages | One or more inbound messages from a WhatsApp user |
message_status | Delivery, read, or failure status updates for outbound messages |
unknown | Changes that do not match a recognized field |
invalid_json | The request body could not be parsed as JSON |
invalid_payload | The parsed body did not match the expected webhook envelope shape |
