Skip to main content

Get WhatsApp Message Status

Returns the current status of a message you previously sent through the public API. Use this to track delivery progression — queuedsentdeliveredread (or failed).

Which endpoint do I call?

GET to /v1/whatsapp/messages/{id} over HTTPS, where id is the message id returned from a previous Send Message or Send Template call. Today this requires the whatsapp:send scope; a separate whatsapp:read scope is reserved for a future release.

GET /v1/whatsapp/messages/{id}

What does the request look like?

curl https://api.mojeeb.app/v1/whatsapp/messages/01c45011-d803-4eb0-a762-3228a4c392f3 \
-H "Authorization: Bearer mk_live_YOUR_KEY_HERE"

What does a success response look like?

HTTP 200 OK:

{
"id": "01c45011-d803-4eb0-a762-3228a4c392f3",
"status": "delivered",
"agent_id": "12345678-1234-1234-1234-123456789012",
"to": "",
"type": "template",
"platform_message_id": "wamid.EXAMPLE_PLACEHOLDER_FROM_META_REPLACE_AT_RUNTIME==",
"created_at": "2026-04-30T09:18:31Z",
"sent_at": "2026-04-30T09:18:32Z",
"failed_at": null
}

What do the status values mean?

statusMeaning
queuedAccepted by Mojeeb; not yet handed to Meta
sentMeta acknowledged receipt — platform_message_id is now populated
deliveredMeta confirmed delivery to the customer's device
readCustomer opened the message (only if read receipts are enabled on their side)
failedSend failed at some stage — check failed_at for the timestamp

Status moves forward only — once delivered, it stays delivered or progresses to read. It won't roll back to sent.

What is platform_message_id?

Meta's wamid for the message. It's null while the status is queued; populated once the status reaches sent or later. Use it for cross-referencing in Meta's WhatsApp Business Manager logs if you ever need to trace a delivery issue with Meta support.

How often should I poll?

For most workflows, polling every 5–10 seconds for the first minute is enough — most messages reach sent within seconds. After that, slow down: poll every 30 seconds for delivery confirmation, or stop polling entirely if you don't need it.

Status lookups count against your rate limit (60/min/key by default), so don't hammer the endpoint. If you need real-time updates for many messages, contact support — we may add webhook delivery callbacks in a future release.

What does a not-found response look like?

HTTP 404 Not Found with the standard envelope:

{
"error": {
"type": "not_found_error",
"code": "message_not_found",
"message": "No message found with the supplied id.",
"correlation_id": "req_01KQ..."
}
}

You'll see this if:

  • The id doesn't exist
  • The id belongs to a different organization (we deliberately return 404 instead of 403 to avoid leaking message existence across orgs)
  • You malformed the URL — IDs must be valid UUIDs

Common questions

Why is to empty?

Currently the status response doesn't echo the recipient phone — the field is reserved in the contract but populated as an empty string. This is a known gap that will be filled in a future release without breaking the v1 contract. The original to you sent is preserved internally and visible in the dashboard.

Why is sent_at populated but failed_at also null on a failed message?

sent_at populates when Mojeeb dispatched the request to Meta — independent of whether Meta accepted it. If Meta rejected delivery later, failed_at populates and status becomes failed, but sent_at stays as the original handoff timestamp. To detect a final failure, branch on status === "failed", not on whether failed_at is null.

Can I look up a message I sent through the dashboard, not the API?

Currently, the API only surfaces messages that originated from the public API (via api_send_log). Dashboard sends and webhook-handled messages aren't returned. This is intentional for v1 — surfacing every message would expose internal types we haven't committed to.

Does this endpoint count against rate limits?

Yes. All /v1/ endpoints share the per-key budget. See Rate Limits for details.

Can I bulk-look-up many messages at once?

Not in v1. Each lookup is a separate request. Bulk lookup is reserved as an additive POST /v1/whatsapp/messages/lookup endpoint for a future release if customers need it.