BroadNet
SMPPWire format

SMPP TLV optional parameters

Updated 3 min readStandards-based
Direct answer

TLVs (optional parameters, introduced in v3.4) extend a PDU beyond its mandatory fields. Each is encoded as a 2-byte Tag, a 2-byte Length and a Length-byte Value, all big-endian. TLVs appear after the mandatory body, in any order, and let SMPP carry payloads, concatenation metadata and receipt correlation without changing the fixed field layout.

§01

The TLV format

A TLV (also called an optional parameter) is a self-describing field: a 2-octet Tag identifies the parameter, a 2-octet Length gives the size of the Value in octets, and the Value follows. Both Tag and Length are big-endian. Because they are tagged, TLVs can appear in any order after the mandatory parameters and a receiver simply skips tags it does not recognise.

message_payload TLV carrying a 5-byte valuehex
04 24        Tag    = 0x0424 (message_payload)
00 05        Length = 5 octets
48 65 6C 6C 6F   Value = "Hello"
§02

Common TLV tags

A handful of TLVs do most of the work in production. message_payload carries a message too long for short_message. receipted_message_id and message_state make delivery receipts machine-parseable. user_message_reference lets you attach your own correlation id. The sar_* set provides standards-based concatenation without UDH bytes in the body.

Frequently used optional parameters
TagNameValueUse
0x0424message_payloadOctet StringMessage body when it exceeds short_message
0x001Ereceipted_message_idC-Octet String (65)Original message_id in a delivery receipt
0x0427message_stateInteger (1)Final/interim state in a receipt (see below)
0x0204user_message_referenceInteger (2)ESME-assigned correlation reference
0x020Csar_msg_ref_numInteger (2)Concatenation: shared reference across segments
0x020Esar_total_segmentsInteger (1)Concatenation: total number of segments
0x020Fsar_segment_seqnumInteger (1)Concatenation: this segment's sequence
0x0423network_error_codeOctet String (3)Network-specific failure detail in a receipt
0x0426more_messages_to_sendInteger (1)Signals more segments follow
0x020Asource_portInteger (2)Application port addressing (source)
0x020Bdest_portInteger (2)Application port addressing (destination)
§03

message_state values

The message_state TLV (0x0427) reports a message's lifecycle state numerically — the machine-readable companion to the DLR text's stat keyword. These values also appear in query_sm_resp.

message_state values
ValueStateDLR stat keyword
1ENROUTE(in transit)
2DELIVEREDDELIVRD
3EXPIREDEXPIRED
4DELETEDDELETED
5UNDELIVERABLEUNDELIV
6ACCEPTEDACCEPTD
7UNKNOWNUNKNOWN
8REJECTEDREJECTD
9SKIPPED (v5.0)—
§04

SAR concatenation vs UDH

SMPP offers two ways to concatenate a long message. The UDH method puts a 6-byte User Data Header inside short_message and sets the esm_class UDHI bit. The SAR method keeps the body clean and carries the three sar_* TLVs instead. Pick one and be consistent per route — some networks accept only UDH, others only SAR. Never mix the two on the same message.

§05

Rules and gotchas

Do not populate both short_message and message_payload — providers reject that. Custom TLVs outside the ranges your provider approves are commonly stripped or cause parse errors downstream, so only send metadata in agreed tags. A receiver must tolerate unknown TLVs by skipping Length bytes; a malformed Length is the classic cause of a corrupted parse of everything after it.

FAQ

Frequently asked

What does TLV stand for in SMPP?

Tag-Length-Value. Each optional parameter is encoded as a 2-byte tag, a 2-byte length, and that many bytes of value. TLVs were introduced in SMPP v3.4 and appear after the mandatory body of a PDU.

When should I use message_payload instead of short_message?

Use the message_payload TLV (0x0424) when the message exceeds the 254-octet short_message field, or when your provider prefers it for long content. Do not set both fields on the same PDU.

How do I correlate a delivery receipt back to my submitted message?

Match the receipted_message_id TLV (0x001E) in the receipt against the message_id you stored from submit_sm_resp. Normalise formats first, since some SMSCs return the id in hex on submit and decimal in the receipt.

Are sar_* TLVs better than UDH for concatenation?

Neither is universally better — they are two encodings of the same idea. SAR keeps the message body free of header bytes; UDH is more widely accepted. Use whichever your route supports and stay consistent.

Can I add my own custom TLVs?

Only within the vendor-specific tag range your provider approves. Unapproved custom TLVs are frequently stripped or rejected in transit, so agree the tags and their meaning with the provider first.

References

Source specifications

The published standards this page is grounded in. Opens in a new tab.

BNMaintained by the BroadNet engineering team·Carrier-grade messaging since 2003
Put it on the wire

Build with a real SMPP bind and REST API.

Request test access with real test keys: send to your own verified number first, then move to production across 200+ countries once your sender identity and routes are approved.