BigRadarDocs
API ReferenceWebhooksReceiving messages
API Reference

Receiving messages

Get incoming messages, delivery receipts and template updates on your server.

Register a webhook URL in Settings → API & webhooks and choose which events it should receive. We send a POST request to your URL for each one, signed with your whsec_ secret in the X-BigRadar-Signature header so you can verify it's genuinely from us.

Events

FieldTypeRequiredDescription
message.receiveddefaultRequiredA customer sent you a WhatsApp message.
message.faileddefaultRequiredAn outbound message could not be delivered. Carries Meta's error code.
message.sentopt-inoptionalMeta accepted an outbound message. High volume.
message.deliveredopt-inoptionalThe message reached the recipient's device. High volume.
message.readopt-inoptionalThe recipient opened it. High volume.
template.status_updatedopt-inoptionalMeta approved, rejected or paused one of your templates.

The three delivery statuses fire on every outbound message, so a campaign to 10,000 contacts produces 30,000 deliveries. They are opt-in for that reason — enable them only if you record read receipts.

Envelope

Every event shares the same shape: an id, the event name, a createdAt timestamp and an event-specific data object.

message.received
json
{ "id": "evt_...", "event": "message.received", "createdAt": "2026-06-25T10:00:00Z", "data": { "conversationId": "a1b2c3d4-...", "contact": { "phone": "919876543210", "name": "Mohit" }, "message": { "type": "text", "text": "Hi there", "waMessageId": "wamid....", "timestamp": "1719312000" } } }

Delivery receipts

message.sent, message.delivered and message.read share one shape. template is filled in when the message came from a template, so you can reconcile a receipt against your own send.

message.delivered
json
{ "id": "evt_...", "event": "message.delivered", "createdAt": "2026-06-25T10:00:02Z", "data": { "waMessageId": "wamid....", "recipient": "919876543210", "status": "delivered", "timestamp": "1719312002", "conversationId": "65868fbf9995a3bf...", "pricing": { "billable": true, "model": "PMP", "category": "utility" }, "template": { "name": "order_shipped", "campaignId": null }, "error": null } }

Failures

message.failed
json
{ "id": "evt_...", "event": "message.failed", "createdAt": "2026-06-25T10:00:03Z", "data": { "waMessageId": "wamid....", "recipient": "919876543210", "status": "failed", "error": { "code": 131047, "title": "Re-engagement message", "message": "More than 24 hours have passed since the last reply." } } }

Template status changes

Sent when Meta approves, rejects or pauses a template — so you learn about a rejection without polling or opening the dashboard.

template.status_updated
json
{ "id": "evt_...", "event": "template.status_updated", "createdAt": "2026-06-25T11:00:00Z", "data": { "name": "order_shipped", "language": "en", "status": "REJECTED", "previousStatus": null, "reason": "INVALID_FORMAT", "templateId": "1234567890" } }

Signature header

Headers
json
X-BigRadar-Signature: t=1719312000,v1=9f3a7c21e8b4...

Verify by computing HMAC_SHA256(secret, t.rawBody) and comparing it to the v1 value. Compare the two digests with a constant-time function, and reject a request whose t is more than a few minutes old — that is what stops a captured request being replayed later.

Retries and duplicates

Reply 2xx as soon as you have stored the event; do your processing afterwards. A non-2xx or a timeout past 10 seconds is retried up to 4 times over roughly 36 minutes, after which the delivery is marked failed and can be replayed from the dashboard. An endpoint that fails repeatedly is disabled automatically.

Deduplicate on data.waMessageId together with the event name rather than on idid is unique per delivery attempt group, while the message id is what identifies the underlying message across retries.