Why Your WhatsApp API Messages Show Sent but Not Delivered

You sent a batch of several thousand shipping updates or OTPs. Your server received a 200 OK from Meta with a message ID. You check your system logs, and the status is stuck at "sent." On the user's side, there is nothing. No notification, no sound, and no message in their chat history.
If you run a business in Pakistan or India, this is a daily headache. Your customer support team gets flooded with complaints from users who did not receive their login codes. You look at your database, see the single grey tick status, and wonder where the system broke.
The system did not break. It is working exactly how Meta designed it. To fix this, you need to understand what happens in the seconds after your server hits Meta's API endpoint.
The WhatsApp API Delivery Pipeline
Many developers confuse the API response with the actual message status. When you send a message, it goes through a multi-stage pipeline. Each stage triggers a specific event.
| Stage | What It Means | Webhook Status | Visual Indicator |
|---|---|---|---|
| API Response | Meta accepted your JSON payload. | None (HTTP 200 OK) | None |
| Sent | Meta queued the message for delivery. | sent | Single grey tick |
| Delivered | The user's device acknowledged receipt. | delivered | Double grey tick |
| Read | The user opened the chat session. | read | Double blue tick |
When you send a POST request to Meta's Cloud API, Meta checks your authentication token, your billing status, and your payload formatting. If those are correct, Meta returns a success response containing a message ID. This only means Meta accepted the job. It does not mean the message left Meta's servers.
A fraction of a second later, Meta's infrastructure routes the message to the user's account. At this point, Meta fires a webhook to your server with the status "sent". If the message never moves to "delivered", the breakdown is happening between Meta's servers and the physical handset of your customer.
A Worked Example with Real Numbers
Let us look at real data to understand how this plays out in production. Imagine you run an e-commerce platform in Lahore or Mumbai. You send 1,200 automated order dispatch alerts on a Friday afternoon using a pre-approved utility template.
Here is how those 1,200 messages typically break down over a 24-hour period:
- 1,094 messages transition to "delivered" within 15 seconds. These users have active internet connections and their phones are awake.
- 106 messages remain stuck on "sent" after one hour.
If you analyze those 106 stuck messages, you will find a predictable pattern based on local user habits and infrastructure limitations:
- 62 users have turned off their mobile data. In South Asia, many prepaid users turn off mobile data when they leave Wi-Fi zones to save battery or conserve their daily data allowances.
- 24 users have no network coverage. They might be traveling, inside concrete buildings with poor reception, or experiencing a power outage. In Pakistan, load shedding can temporarily disable local cellular towers, leaving entire neighborhoods without data coverage for hours.
- 12 users have uninstalled WhatsApp or changed their SIM cards without migrating their WhatsApp accounts. The phone number still accepts cellular voice calls, but the WhatsApp client no longer exists on that device.
- 8 users have blocked your business profile.
Meta keeps trying to deliver those messages. By Saturday afternoon, 45 of those 106 stuck messages will finally transition to "delivered" as users turn their phones back on or enter Wi-Fi zones. The rest will eventually time out.
The Real Technical Reasons for Stuck Messages
Understanding the root causes helps you write better error-handling logic. Here is why your messages are not landing on the destination devices.
1. The Destination Phone is Offline
This is the most common reason. If a phone is powered off, has no internet connection, or is in airplane mode, Meta cannot deliver the payload. The message sits in Meta's cloud queue, showing a status of "sent."
2. Aggressive Battery Optimization
Many Android devices, especially budget models from Xiaomi, Realme, Vivo, and Infinix, use aggressive battery-saving software. These operating systems put background apps into a deep sleep. If a user has not opened WhatsApp for several hours, the OS may kill the background push notification service. The message remains "sent" until the user physically unlocks their phone and opens WhatsApp.
3. The User Blocked Your Business Number
Meta does not send a webhook saying "User blocked you." Doing so would violate user privacy. Instead, if a user has blocked your business, any template or session message you send them will get a sent status and stay there forever. If a specific phone number in your database always remains on sent across multiple campaigns over several weeks, that user has blocked your business.
4. Temporary Regional Internet Restrictions
In India and Pakistan, local authorities sometimes suspend mobile internet services during public holidays, protests, or exams. During these blackouts, voice calls and SMS might work, but mobile data is cut. Your API requests will succeed, but messages will pile up in the "sent" state until mobile internet service is restored.
5. The Number is Not Registered on WhatsApp
If you purchase a database or use old customer records, some numbers will not have active WhatsApp accounts. If you attempt to send a message to a non-existent WhatsApp account, the API may still accept the request, but the message will never transition to "delivered."
What Does Not Work and What to Avoid
When developers face delivery issues, they often try fixes that make the problem worse. Avoid these common mistakes.
Do not retry sending the same message immediately. If an OTP is stuck on "sent" because the user has no internet, sending it four more times will not help. When the user finally connects to Wi-Fi, their phone will buzz five times with five different codes. This annoys the customer and often leads them to block your number or report your business as spam.
Do not use unofficial WhatsApp automation scripts or "scrapers" to verify if numbers are active. Meta actively monitors network traffic for automated scrapers. If you use unofficial tools to check numbers, Meta will flag your IP addresses and may suspend your official WhatsApp Business Account (WABA).
Do not ignore your Quality Rating in the Meta Business Suite. If you keep sending messages to dead numbers or users who have blocked you, your quality rating will drop from Green to Yellow, and eventually to Red. Once your rating is Red, Meta will restrict your messaging limits or pause your templates entirely, stopping your campaigns.
We built WA Link to help businesses manage their official Meta Cloud API integrations, but even our platform cannot force a message onto a phone that has no battery or has blocked your sender ID. No legitimate provider can bypass these native Meta delivery checks.
How to Handle Stuck Messages in Your Code
You cannot control whether a customer turns off their phone. You can, however, make your software smart enough to handle these situations without degrading the user experience.
Implement an Automatic Failover to SMS
If you are sending time-sensitive information like OTPs or password reset links, you cannot wait hours for a WhatsApp delivery status. You must build a failover mechanism.
- Send the WhatsApp API message.
- Listen to your webhook for the
deliveredstatus. - Start a timer in your application logic (for example, 45 seconds).
- If the webhook does not return
deliveredwithin those 45 seconds, trigger an SMS gateway to send the code via cellular network instead.
This ensures your users get their codes even if they have turned off their mobile data to save battery.
Clean Your Database Based on Webhook Logs
Do not waste money and reputation sending messages to dead numbers. Write a background script that runs once a week. If a phone number has stayed on the sent status without a single delivered status for three consecutive campaigns, flag that contact as "inactive" in your database and exclude them from future WhatsApp broadcasts.
The Financial Side: Do You Pay for Undelivered Messages?
Meta's billing model is based on 24-hour conversation windows. A conversation is only charged when a message is successfully delivered to the user's device.
If you send a business-initiated template message, and it stays stuck on "sent" forever, you are not charged for that conversation. Meta only bills you when the message successfully lands on the handset, triggering the double tick and the delivered webhook status.
If you are already inside an active 24-hour conversation window, sending additional messages that stay on "sent" does not cost you extra, but it does not extend your 24-hour window either. You can read the official Meta developer documentation on WhatsApp API Pricing to verify how these conversation windows are calculated.
Frequently Asked Questions
How long does Meta try to deliver a message before it expires?
Meta keeps messages in its queue for up to 30 days. If the destination phone does not connect to the internet within that period, the message is permanently dropped. For transactional messages, however, any delivery that takes longer than a few minutes is practically useless to your customer.
Can I check if a number is on WhatsApp before I send a message?
Yes. Meta offers a contact verification endpoint. You can send a POST request to check if a phone number has a valid WhatsApp account. You should use this endpoint during user registration or when a customer first updates their profile, rather than running your entire database through it before every single broadcast, as Meta rate-limits this endpoint.
Why does my personal WhatsApp show two ticks but the API shows only one?
If you can message a user from your personal phone but your API messages stay on a single tick, check your WhatsApp Business Account status in the Meta Business Manager. Your business phone number may be restricted, your template may have been paused due to low-quality flags, or the user has blocked your business profile specifically while keeping personal chats open.
Does a "sent" status mean the user has blocked me?
Not always. It usually means the phone is offline or out of coverage. However, if you see that a user's status never changes to "delivered" over several weeks while they remain active on other channels, they have likely blocked your business number.
Can I use WA Link to bypass these delivery limits?
No. WA Link provides the portal, scheduling engines, and webhook parsers to manage your campaigns using the official Meta Cloud API. We make it easy to see your delivery rates and debug your webhooks, but we cannot force a message onto a phone that is offline or has blocked your sender ID.
Your Next Step
Stop guessing why your delivery rates are low. Open your server logs, locate your webhook receiver code, and log the exact time difference between your API requests and your delivered webhook events. If you want a clean dashboard to monitor these delivery logs and manage your webhooks without writing database schemas from scratch, set up a developer account on WA Link and test your status updates in real-time.