When you send an SMS, the API response you get back is not proof of delivery. It only means your message was accepted for processing. Everything you learn after that point comes from a delivery report — usually called a DLR. Understanding these reports is the difference between guessing why your OTP codes are not arriving and knowing exactly where they stop.
What a delivery report actually is
A DLR is a status notification that travels back through the same chain your message took: handset to operator, operator to aggregator, aggregator to your SMS provider, and finally to you through an API callback or webhook. Each hop can add delay or lose detail. That is why the status you see in a panel is a summary of what the upstream network reported, not a direct reading from the recipient's phone.
Two things follow from this. First, a DLR is asynchronous — it may arrive seconds or minutes after submission. Second, its accuracy depends on the route. Some operators and some international destinations return only coarse statuses, or fabricate a "delivered" state as soon as the message leaves their gateway. This is one of the practical reasons why route quality matters more than headline pricing for OTP traffic.
The core status codes
Most platforms map their statuses onto the SMPP standard, so you will see the same short names again and again:
ACCEPTD/SUBMITTED— the message was accepted by the platform and queued. No network confirmation yet.ENROUTE— the message is moving through the operator network. A normal transitional state.DELIVRD— the operator confirmed delivery to the handset. This is the state you are aiming for.UNDELIV— the network attempted delivery and failed permanently. Common causes: the number does not exist, the subscriber is barred, or the route does not support that destination.EXPIRED— the validity period ran out before the handset could be reached. Typically a phone that stayed switched off or out of coverage.REJECTD— the operator refused the message before attempting delivery. Usually a content, sender ID or filtering issue.DELETED— the message was removed from the queue, often by an operator anti-spam system.UNKNOWN— the network returned no usable information. Treat it as inconclusive, not as failure.
Alongside the status you may receive an error code — a numeric field that explains the failure in more detail. These codes are not standardised across operators, so the same number can mean different things on different routes. Always read them against your provider's documentation rather than assuming a universal meaning.
Why "delivered" does not always mean read
A DLR reports handset receipt, not human attention. The message may land on a phone that is in a drawer, in a second SIM slot, or inside a spam folder created by the device manufacturer. For OTP flows this distinction is important: if your delivery rate is high but your verification completion rate is low, the problem is probably not the network. It may be the message wording, the sender ID, the code length, or the timeout you allow the user.
Reading failure patterns instead of single messages
One failed message tells you very little. Patterns tell you a lot:
- Failures concentrated on one operator — likely a routing or sender ID registration issue for that network.
- Failures concentrated in one country — often a local regulation: some markets require pre-registered alphanumeric sender IDs or block them entirely.
- Many
EXPIREDresults — devices are unreachable. Consider a shorter validity period so your application can fail fast and offer a retry or a voice fallback. - Sudden spike in
REJECTD— check for content filtering triggers: shortened URLs, unusual characters, or a changed sender ID. - High
UNKNOWNratio — the route offers weak reporting. For transactional traffic, weak visibility is itself a problem.
Building the webhook side properly
If your provider pushes DLRs to a callback URL, a few engineering habits will save you trouble:
- Respond quickly with a 2xx status and process asynchronously; slow endpoints cause retries and duplicates.
- Make handling idempotent — use the message ID as a key, because the same DLR can arrive more than once.
- Expect out-of-order statuses; a final state should never be overwritten by a stale intermediate one.
- Store the raw payload. When you later dispute a delivery issue, the original operator response is your evidence.
- Secure the endpoint, and verify that callbacks come from your provider before trusting them.
Using reports to improve, not just to log
Delivery data becomes useful when it feeds decisions. Set a threshold per country and per operator, alert when delivery rates drop below it, and keep a fallback path for critical flows — for example an alternative channel or a voice call for one-time passwords that repeatedly fail on SMS.
UIPAPP provides real-time delivery reports through its web panel and REST API, with webhook callbacks so your own system can react the moment a status changes. For teams sending OTP traffic across Turkey, Cyprus, Europe and more than 200 countries, that visibility is what turns delivery problems into something you can actually diagnose and fix.