Skip to content
OmniChannels.ai

Free tool

SMS delivery report (DLR) decoder

Paste one SMPP delivery receipt or a whole batch. See what every field means, how long delivery took, which webhook status it matches, and what an SMPP command_status error is telling you.

Free · no sign-up · runs in your browser

Paste the short_message text of one or more deliver_sm receipts, one per line. A bare command_status such as 0x00000058 is decoded too.

Decoded receipts

Receipts: 4 · Delivery rate: 25%

Receipts
4
Delivery rate
25%
DELIVRD ÷ receipts with a known stat
Median latency
1 h 7 min
Need attention
0

By stat

  • DELIVRD1
  • ACCEPTD1
  • UNDELIV1
  • EXPIRED1

By closest webhook status

  • SENT1
  • DELIVERED1
  • FAILED2
  1. Line 1stat:DELIVRDClosest webhook status: DELIVEREDFinal

    Delivered to the handset.

    Indicative mapping to the normalised statuses of our API.

    Message ID
    2610101200457381
    Matches the message_id returned in submit_sm_resp.
    sub (submitted)
    001
    Messages originally submitted, usually 001.
    dlvrd (delivered)
    001
    Messages delivered, usually 001 or 000. Many SMSCs fill it loosely, so trust stat.
    Submit date
    Oct 10, 2026, 12:00:05 PM261010120005
    SMSC clock. The receipt carries no time zone (usually UTC).
    Done date
    Oct 10, 2026, 12:00:09 PM261010120009
    SMSC clock. The receipt carries no time zone (usually UTC).
    Delivery latency
    4 s
    err
    000
    No error.
    text
    Your code is 482913
    First 20 characters of the original message, often truncated or empty.
  2. Line 2stat:UNDELIVClosest webhook status: FAILEDFinal

    Undeliverable: invalid or inactive number, barred subscriber or network failure.

    Indicative mapping to the normalised statuses of our API.

    Message ID
    2610101200457382
    Matches the message_id returned in submit_sm_resp.
    sub (submitted)
    001
    Messages originally submitted, usually 001.
    dlvrd (delivered)
    000
    Messages delivered, usually 001 or 000. Many SMSCs fill it loosely, so trust stat.
    Submit date
    Oct 10, 2026, 12:00 PM2610101200
    SMSC clock. The receipt carries no time zone (usually UTC).
    Done date
    Oct 10, 2026, 2:15 PM2610101415
    SMSC clock. The receipt carries no time zone (usually UTC).
    Delivery latency
    2 h 15 min
    err
    001
    Non-zero err values are specific to the SMSC or network (often derived from GSM network causes). Check your provider's error list.
    text
    Your order has shipp
    First 20 characters of the original message, often truncated or empty.
  3. Line 3stat:expiredClosest webhook status: FAILEDFinal

    The validity period ended before the handset could be reached (often switched off or out of coverage).

    Indicative mapping to the normalised statuses of our API.

    Message ID
    2610101200457383
    Matches the message_id returned in submit_sm_resp.
    sub (submitted)
    001
    Messages originally submitted, usually 001.
    dlvrd (delivered)
    000
    Messages delivered, usually 001 or 000. Many SMSCs fill it loosely, so trust stat.
    Submit date
    Oct 10, 2026, 12:01 PM2610101201
    SMSC clock. The receipt carries no time zone (usually UTC).
    Done date
    Oct 11, 2026, 12:01 AM2610110001
    SMSC clock. The receipt carries no time zone (usually UTC).
    Delivery latency
    12 h
    err
    000
    No error.
    text
    Flash sale ends toni
    First 20 characters of the original message, often truncated or empty.
  4. Line 4stat:ACCEPTDClosest webhook status: SENTIntermediate

    Accepted by the network. A final receipt usually follows.SMPP v3.4 formally defines ACCEPTD as read manually on behalf of the subscriber by customer service, but most SMSCs and aggregators send it as an intermediate “accepted by the network” receipt.

    Indicative mapping to the normalised statuses of our API.

    Message ID
    2610101200457384
    Matches the message_id returned in submit_sm_resp.
    sub (submitted)
    001
    Messages originally submitted, usually 001.
    dlvrd (delivered)
    000
    Messages delivered, usually 001 or 000. Many SMSCs fill it loosely, so trust stat.
    Submit date
    Oct 10, 2026, 12:02 PM2610101202
    SMSC clock. The receipt carries no time zone (usually UTC).
    Done date
    Oct 10, 2026, 12:02 PM2610101202
    SMSC clock. The receipt carries no time zone (usually UTC).
    Delivery latency
    0 s
    err
    000
    No error.
    text
    —
    First 20 characters of the original message, often truncated or empty.
  5. Line 5 · command_status0x00000058ESME_RTHROTTLEDTemporary

    Throttling error (ESME has exceeded allowed message limits)

    Retry later with exponential backoff, never in a tight loop.

SMPP v3.4 command_status codes

48 codes

CodeNameMeaning (spec)What to do
0x00000000ESME_ROKNo errorSuccess
0x00000001ESME_RINVMSGLENMessage length is invalidFix the request
0x00000002ESME_RINVCMDLENCommand length is invalidFix the request
0x00000003ESME_RINVCMDIDInvalid command IDFix the request
0x00000004ESME_RINVBNDSTSIncorrect bind status for given commandBind or session
0x00000005ESME_RALYBNDESME already in bound stateBind or session
0x00000006ESME_RINVPRTFLGInvalid priority flagFix the request
0x00000007ESME_RINVREGDLVFLGInvalid registered delivery flagFix the request
0x00000008ESME_RSYSERRSystem errorTemporary
0x0000000AESME_RINVSRCADRInvalid source addressFix the request
0x0000000BESME_RINVDSTADRInvalid destination addressFix the request
0x0000000CESME_RINVMSGIDMessage ID is invalidFix the request
0x0000000DESME_RBINDFAILBind failedBind or session
0x0000000EESME_RINVPASWDInvalid passwordBind or session
0x0000000FESME_RINVSYSIDInvalid system IDBind or session
0x00000011ESME_RCANCELFAILcancel_sm failedFix the request
0x00000013ESME_RREPLACEFAILreplace_sm failedFix the request
0x00000014ESME_RMSGQFULMessage queue fullTemporary
0x00000015ESME_RINVSERTYPInvalid service typeFix the request
0x00000033ESME_RINVNUMDESTSInvalid number of destinationsFix the request
0x00000034ESME_RINVDLNAMEInvalid distribution list nameFix the request
0x00000040ESME_RINVDESTFLAGDestination flag is invalid (submit_multi)Fix the request
0x00000042ESME_RINVSUBREPInvalid 'submit with replace' request (submit_sm with replace_if_present_flag set)Fix the request
0x00000043ESME_RINVESMCLASSInvalid esm_class field dataFix the request
0x00000044ESME_RCNTSUBDLCannot submit to distribution listFix the request
0x00000045ESME_RSUBMITFAILsubmit_sm or submit_multi failedTemporary
0x00000048ESME_RINVSRCTONInvalid source address TONFix the request
0x00000049ESME_RINVSRCNPIInvalid source address NPIFix the request
0x00000050ESME_RINVDSTTONInvalid destination address TONFix the request
0x00000051ESME_RINVDSTNPIInvalid destination address NPIFix the request
0x00000053ESME_RINVSYSTYPInvalid system_type fieldBind or session
0x00000054ESME_RINVREPFLAGInvalid replace_if_present flagFix the request
0x00000055ESME_RINVNUMMSGSInvalid number of messagesFix the request
0x00000058ESME_RTHROTTLEDThrottling error (ESME has exceeded allowed message limits)Temporary
0x00000061ESME_RINVSCHEDInvalid scheduled delivery timeFix the request
0x00000062ESME_RINVEXPIRYInvalid message validity period (expiry time)Fix the request
0x00000063ESME_RINVDFTMSGIDPredefined message invalid or not foundFix the request
0x00000064ESME_RX_T_APPNESME receiver temporary app error codeTemporary
0x00000065ESME_RX_P_APPNESME receiver permanent app error codeFix the request
0x00000066ESME_RX_R_APPNESME receiver reject message error codeFix the request
0x00000067ESME_RQUERYFAILquery_sm request failedTemporary
0x000000C0ESME_RINVOPTPARSTREAMError in the optional part of the PDU bodyFix the request
0x000000C1ESME_ROPTPARNOTALLWDOptional parameter not allowedFix the request
0x000000C2ESME_RINVPARLENInvalid parameter lengthFix the request
0x000000C3ESME_RMISSINGOPTPARAMExpected optional parameter missingFix the request
0x000000C4ESME_RINVOPTPARAMVALInvalid optional parameter valueFix the request
0x000000FEESME_RDELIVERYFAILUREDelivery failure (used for data_sm_resp)Temporary
0x000000FFESME_RUNKNOWNERRUnknown errorTemporary

Descriptions follow the SMPP v3.4 specification, section 5.1.3.

Rather not parse receipts yourself? Our SMS API pushes normalised delivery statuses to your webhook, and SMPP binds are available for high volume. Webhook docsSMPP guideSMS API for business

Nothing you type here is sent to our servers.

Short answer

An SMPP delivery report (DLR) is the receipt an SMSC returns in a deliver_sm PDU after you submit an SMS. Its text follows the pattern id, sub, dlvrd, submit date, done date, stat, err and text. The stat field holds the outcome: DELIVRD means delivered to the handset; UNDELIV, EXPIRED, DELETED and REJECTD are final failures; ENROUTE and ACCEPTD are intermediate. Dates use YYMMDDhhmm, sometimes with seconds.

How to decode an SMS delivery receipt

  1. 1

    Copy the receipt text

    Take the short_message of the deliver_sm PDU from your SMPP client or SMSC log, for example id:… sub:001 dlvrd:001 … stat:DELIVRD err:000. Log prefixes are ignored.

  2. 2

    Paste one per line

    Paste a single receipt or hundreds of them. You can also paste a command_status value such as 0x00000058 or ESME_RTHROTTLED on its own line.

  3. 3

    Read the decoded fields

    Each receipt shows the status meaning, whether it is final, the closest webhook status, readable dates, delivery latency and warnings for missing or inconsistent fields.

  4. 4

    Check the batch summary

    See counts by stat and by webhook status, the delivery rate and the median latency, then copy everything as JSON for a ticket or a test fixture.

Anatomy of an SMPP delivery receipt

When you submit an SMS with registered_delivery set to 1, the SMSC later sends a deliver_sm PDU back on a receiver or transceiver bind. Bit 0x04 in its esm_class marks it as a delivery receipt rather than an inbound message, and its short_message carries a text receipt. Appendix B of the SMPP v3.4 specification gives this format as an example, and nearly every SMSC follows it: id:IIIIIIIIII sub:SSS dlvrd:DDD submit date:YYMMDDhhmm done date:YYMMDDhhmm stat:DDDDDDD err:E text:….

Because Appendix B is an example rather than a strict rule, real receipts vary: lowercase keys, extra spaces, submit_date with an underscore, 12-digit dates with seconds, or missing text. This decoder accepts all of those and tells you which fields are missing.

  • id: the message ID the SMSC returned in submit_sm_resp. Use it to match the receipt to your message. The spec example shows 10 characters, but many SMSCs use longer IDs, sometimes in hex.
  • sub and dlvrd: the number of messages originally submitted and delivered, as 3 digits. They matter mainly for distribution lists; for a single SMS they are typically 001 and 001 (or 000).
  • submit date and done date: when the message was submitted and when it reached its final state, in the SMSC's clock.
  • stat: the final or intermediate state, as a 7-letter code such as DELIVRD.
  • err: a 3-character error code, network or SMSC specific; 000 means no error.
  • text: the first 20 characters of the original message, often truncated or blank.
  • Optional TLVs can repeat this data in a cleaner form: receipted_message_id (0x001E), message_state (0x0427) and network_error_code (0x0423).

DLR stat codes and what they mean

SMPP v3.4 defines eight message states. ENROUTE and ACCEPTD are intermediate; the others are final. Our API normalises every channel to six webhook statuses (SUBMITTED, SENT, DELIVERED, READ, FAILED, REJECTED), and the decoder shows the closest match for each stat value. Treat that mapping as indicative: the exact rule for your account is confirmed during onboarding.

  • DELIVRD (message_state 2): delivered to the handset. Closest webhook status: DELIVERED.
  • ACCEPTD (6): formally 'read manually on behalf of the subscriber by customer service', but most SMSCs send it as an intermediate 'accepted by the network' receipt. Closest: SENT.
  • ENROUTE (1): still in transit, for example queued for a retry. Closest: SENT.
  • UNDELIV (5): undeliverable, for example an invalid or inactive number. Closest: FAILED.
  • EXPIRED (3): the validity period ended before the handset could be reached, often because it was off or out of coverage. Closest: FAILED.
  • DELETED (4): deleted before delivery, for example by cancel_sm. Closest: FAILED.
  • REJECTD (8): refused by the network or a firewall, for example an unregistered sender ID or blocked content. Closest: REJECTED.
  • UNKNOWN (7): the SMSC has no final state. Treat it as unconfirmed, not as a proven failure.

err codes: why there is no universal list

The err field is three characters wide and the SMPP specification does not define its values. 000 always means no error, but non-zero values come from the SMSC vendor, the operator or an aggregator in between. Some SMSCs pass through GSM MAP error causes (for example, MAP error 1 is unknown subscriber and 27 is absent subscriber), while others map everything to their own table.

If the receipt carries the network_error_code TLV (0x0423), it is more reliable: its first octet gives the network type (3 means GSM) and the next two the error code. A DELIVRD receipt with a non-zero err is inconsistent and worth raising with your provider; the decoder flags it.

command_status errors versus delivery receipts

SMPP reports problems at two moments. The command_status in submit_sm_resp arrives within milliseconds and says whether the SMSC accepted your request; 0x00000000 (ESME_ROK) means accepted, not delivered. The delivery receipt arrives seconds to days later and carries the final outcome.

command_status values are defined in section 5.1.3 of SMPP v3.4. The most common in production are 0x00000058 ESME_RTHROTTLED (you exceeded your agreed messages per second: slow down and retry with exponential backoff), 0x00000014 ESME_RMSGQFUL (queue full: back off), 0x0000000A and 0x0000000B (invalid source or destination address) and 0x0000000D or 0x0000000E (bind failed or wrong password). Values 0x00000400 to 0x000004FF are reserved for SMSC vendor-specific errors, so ask your provider about those.

Dates, time zones and delivery latency

Receipt dates use YYMMDDhhmm, and many SMSCs append seconds (YYMMDDhhmmss). The receipt carries no time zone: the time is whatever the SMSC clock uses, usually UTC. The decoder shows the dates exactly as written and computes latency as done date minus submit date, which is unaffected by the time zone as long as both come from the same clock.

Latency is a useful quality signal. Healthy OTP traffic to a reachable handset usually completes within seconds. Long latencies followed by EXPIRED point to handsets that are switched off or roaming, and a done date earlier than the submit date means the two clocks disagree. Minute-level dates cannot measure sub-minute latency, so prefer SMSCs that send seconds.

Handling receipts reliably in production

Answer every deliver_sm with deliver_sm_resp, even if your processing fails, otherwise the SMSC resends it and may throttle the bind. Store the raw receipt, then process it asynchronously and idempotently by message ID, because receipts can arrive twice or out of order: a late ENROUTE must never overwrite DELIVRD.

If you would rather not parse receipts at all, our REST SMS API delivers the same information as normalised webhook statuses, and missed receipts can be re-pushed with POST /sms/resendDlr. SMPP binds over TLS are available for high-volume senders and resellers.

Delivery report questions

What does stat:DELIVRD mean in an SMS delivery report?

DELIVRD is the SMPP message state 'delivered': the SMSC has confirmation that the message reached the recipient's handset. It does not mean the message was opened or read; plain SMS has no read receipts. In our webhooks it corresponds to DELIVERED.

What is the difference between UNDELIV, EXPIRED and REJECTD?

UNDELIV means the network could not deliver the message, for example because the number is invalid or inactive. EXPIRED means delivery attempts continued until the validity period ended, usually because the phone was off or out of coverage. REJECTD means the network or a firewall refused the message, for example an unregistered sender ID or blocked content.

What does ACCEPTD mean in an SMPP DLR?

In the SMPP v3.4 specification ACCEPTD means the message was read manually on behalf of the subscriber by customer service. In practice most SMSCs and aggregators use it as an intermediate receipt meaning the network accepted the message, and a final DELIVRD or failure receipt follows.

What is SMPP error 0x00000058?

0x00000058 is ESME_RTHROTTLED: you sent more messages per second than your bind allows. It is temporary. Reduce your sending rate, keep a sensible window of outstanding submit_sm PDUs and retry the rejected messages with exponential backoff rather than immediately.

What does err:000 mean, and where can I find other err codes?

err:000 means no error. Non-zero err values are not defined by the SMPP specification; they come from the SMSC vendor, the operator or an aggregator, and some pass through GSM MAP error causes. Ask your provider for their error table, and check the network_error_code TLV if it is present.

What date format does an SMPP delivery receipt use?

submit date and done date use YYMMDDhhmm, for example 2610101201 for 10 October 2026 at 12:01. Many SMSCs add seconds (YYMMDDhhmmss). No time zone is included; it is the SMSC's clock, usually UTC.

Why did I not receive a delivery report?

Common causes are registered_delivery not set to 1 in submit_sm, using a transmitter-only bind without a receiver bind, a destination network that does not return receipts, or your client not acknowledging deliver_sm. Some routes only return intermediate receipts. For REST traffic, check your webhook endpoint and re-push receipts with /sms/resendDlr.

Is my receipt text sent anywhere when I use this tool?

No. The decoder runs entirely in your browser. Nothing you paste, including message IDs or message text, is sent to our servers.

More free tools