Webhooks
Webhooks push events to your server as they happen, so you don’t have to poll.
- In the panel open Developer → Webhooks and add your endpoint: a public https URL (up to 5 per account). URLs that point to a private or local address are refused.
- Choose the events you want. If you pick none, the endpoint gets all four events.
- Copy the signing secret — shown once — and use it to verify every request.
- Press Send test to receive a
webhook.testevent.
Each endpoint has an On / Off switch. While it is off, no events are queued for it.
Delivery
Section titled “Delivery”Each event is an HTTP POST with a JSON body:
{ "id": "3b0f4c52-9a7e-4f0e-8a51-2d4b6f1c9e77", "event": "message.received", "created_at": "2026-10-26T10:16:40.512Z", "data": { … }}| Header | Value |
|---|---|
Content-Type |
application/json |
User-Agent |
MeAPI-Webhooks/1.0 |
X-MeAPI-Event |
The event name |
X-MeAPI-Delivery |
The event id — the same on every retry, use it to ignore duplicates |
X-MeAPI-Timestamp |
Unix seconds when this attempt was signed |
X-MeAPI-Signature |
sha256= + HMAC — see Verifying signatures |
Every delivery also carries the same four values as X-Webhook-Event, X-Webhook-Delivery, X-Webhook-Timestamp and X-Webhook-Signature — use whichever names you prefer.
Respond with any 2xx within 10 seconds. Do slow work afterwards (queue it). Redirects are not followed, and a response body over 64 KB counts as a failure. The URL is checked again before every attempt; if it no longer resolves to a public address, the attempt fails.
Retries. Anything else — a non-2xx status, a timeout, a connection error — is retried after 1, 5, 30, 120, 360 and 720 minutes (7 attempts over about 20 hours). After that the delivery is marked failed; you can retry it from the delivery log in the panel. Events can arrive more than once and out of order: deduplicate on X-MeAPI-Delivery and use the timestamps in the payload.
Events
Section titled “Events”message.received
Section titled “message.received”A customer sent you a message.
{ "message": { "id": 81240, "wamid": "wamid.HBgMOTE5ODEyMzQ1Njc4FQIAEhgg…", "type": "text", "text": "Is the blue kurta available in L?", "caption": null, "filename": null, "has_media": false, "timestamp": "2026-10-26T10:16:39.000Z", "referral": null, "reply": null }, "contact": { "id": 3310, "phone": "+919812345678", "name": "Asha Patel" }, "channel": { "id": 12, "phone": "+91 22 4000 1234" }, "conversation_id": 5521}type:text,image,video,audio,document,sticker,location,contacts,interactive,button,reaction,order,editorunsupported.text: the text, or a short description of anything else:- media: the caption, or
[image],[video]… when there is none - location: its name, or
[location] 18.52, 73.85 - contact card:
[contact] Name - button or list reply: the title tapped
- reaction:
[reaction] 👍 - submitted WhatsApp Flow form:
📋 Form submitted; cart order:🛒 Order received edit: the new text of a message the customer edited (the inbox shows it on the original message)unsupported(polls, view-once and anything else WhatsApp does not pass to the API):Unsupported message — open WhatsApp on your phone to view it
- media: the caption, or
has_media: a file arrived; it is stored in the panel’s inbox (files are not included in the webhook).reply: for a tapped button / list row,{ "id", "title" }— see Interactive messages.referral: set when the customer came from a Click-to-WhatsApp ad (Meta’s referral object: ad id, headline, source URL…).
Receiving a message opens the 24-hour window for free-form replies. When Meta delivers the same message twice, you get one event.
message.status
Section titled “message.status”A message you sent changed status.
{ "message": { "id": 81234, "wamid": "wamid.HBgMOTE5…", "status": "read", "error": null }, "recipient": "+919812345678", "channel": { "id": 12 }, "conversation_id": 5521, "timestamp": "2026-10-26T10:17:05.000Z"}status is delivered, read or failed (with Meta’s reason in error). You rarely get sent: MeAPI already marks a message sent when Meta accepts it. Statuses only move forward; a late delivered after read is not sent. failed is always sent, even more than once.
This covers messages sent from the API, the inbox and automations — match on message.id. Campaign messages are included only when the campaign has Show these messages in the Inbox turned on.
contact.opted_out / contact.opted_in
Section titled “contact.opted_out / contact.opted_in”The customer sent a text message that is only an opt-out or opt-in keyword (not case-sensitive):
- Opt out:
STOP,STOPALL,UNSUBSCRIBE,UNSUB,CANCEL,END,QUIT,OPTOUT,OPT OUT,OPT-OUT,बंद,बंद करो,रोको,रुको - Opt in:
START,SUBSCRIBE,RESUME,UNSTOP,OPTIN,OPT IN,OPT-IN,चालू,शुरू,शुरू करो
MeAPI already stops automated messages to opted-out contacts; use this to update your own lists. The event fires for every keyword message, even if the contact was already in that state. keyword is the customer’s text as sent, trimmed.
{ "contact": { "id": 3310, "phone": "+919812345678", "name": "Asha Patel" }, "keyword": "STOP", "channel": { "id": 12 }}reminder.sent / reminder.failed / reminder.skipped
Section titled “reminder.sent / reminder.failed / reminder.skipped”An auto reminder went out, failed for good (after its retries), or was skipped on purpose. Subscribe to them in Developer → Webhooks; existing endpoints get them only once you tick them. Test sends from the panel are never reported.
{ "reminder": { "id": 9182, "external_id": "inv-1042", "source": "rule", "sequence": 1, "rule": { "id": 14, "name": "Payment due" }, "reason": null, "scheduled_at": "2026-11-10T04:30:00.000Z", "message_id": 77310, "cost_estimate": { "amount": 0.115, "currency": "INR", "category": "utility" } }, "contact": { "id": 3310, "phone": "+919812345678", "name": "Asha Patel" }, "channel": { "id": 12 }}source is rule, one_off (set from the inbox) or api. sequence counts from 0 within the rule’s sequence for that contact. For failed and skipped, reason says why and message_id may be null. cost_estimate is an estimate from Meta’s list rates; Meta bills per delivered message — follow message.status (by message_id) for delivery.
webhook.test
Section titled “webhook.test”Sent by Send test in the panel: { "message": "Test event from MeAPI — your webhook is reachable." }. It goes only to that endpoint, whatever events it subscribes to. You cannot subscribe to it.
Was this page helpful?
Thank you — we read every comment.
Could not send right now. Please try again later.
© 2026 MeAPI by TheWebStore028 · RADHAMADHAV WEBSTORE LLP · GSTIN 27ABJFR6148J1ZO · Contact us ·Cookie settings