SMPP stands for Short Message Peer-to-Peer: an open, binary protocol that lets an application submit and receive SMS through a Short Message Service Centre (SMSC) over a persistent TCP/IP connection. It is the standard way carriers, aggregators and high-volume senders exchange A2P traffic, and it is the protocol behind an SMPP gateway API like the one SMS.to runs.
Below: versions, roles, binds, PDUs, delivery receipts, addressing, encoding, windowing, ports and security, and when SMPP is worth the extra setup.
What does SMPP stand for, and where did it come from?
SMPP means Short Message Peer-to-Peer. It was originally developed by Aldiscon, an Irish SMSC vendor later acquired by Logica (background on Wikipedia). The specification was then maintained by the SMPP Developers Forum, which later became the SMS Forum, now disbanded. The specifications are still freely available at smpp.org.
Despite the name, day-to-day SMPP is client and server. Your system opens a TCP connection to the provider, authenticates with a system_id and password, and keeps that session open for as long as it sends and receives messages. The SMPP 3.4 specification describes it as an application-layer protocol that relies on the network below (TCP/IP, or X.25 in older networks) for reliable transport.
What are the ESME and the SMSC?
SMPP has two roles:
- ESME (External Short Message Entity): any system outside the mobile network that sends or receives SMS. Your application, an SMS gateway such as Kannel or Jasmin, or an aggregator’s platform all act as ESMEs.
- SMSC (Short Message Service Centre): the message centre that accepts messages, stores and forwards them towards the destination network, and reports back on the outcome.
In A2P messaging the “SMSC” you bind to is usually a provider’s SMPP server, which routes each message onwards to the recipient’s operator. That is why route quality, not just the protocol, decides delivery speed and success.
Which SMPP versions exist: 3.3, 3.4 and 5.0?
| Version | Published | Key changes | Where you meet it |
|---|---|---|---|
| 3.3 | The original public version | Transmitter and receiver binds only; no optional parameters | Legacy SMSCs and older gateway software |
| 3.4 | Issue 1.2, 12 October 1999 | Adds bind_transceiver, optional TLV (tag-length-value) parameters such as message_payload and the SAR fields, and data_sm | The version most SMSCs and client libraries implement today |
| 5.0 | 2003, SMS Forum | Cell broadcast operations, a congestion_state TLV for flow control, “successful delivery only” receipts, extra network and billing TLVs | Limited support; confirm with your provider before relying on it |
Version 3.4 is backwards-aware: the ESME states its version in the interface_version field of the bind (0x34 for 3.4), and the SMSC must not send optional parameters to a peer that binds as 3.3 or earlier. The SMPP 5.0 overview lists what changed in the later version.
What are the SMPP bind types?
After the TCP connection opens, the ESME must “bind” to start a session. The bind type decides which direction traffic can flow:
- Transmitter (
bind_transmitter): the ESME can only submit messages. Delivery receipts and inbound replies need a separate session. - Receiver (
bind_receiver): the ESME only receives, viadeliver_sm. Used for delivery receipts and mobile-originated replies. - Transceiver (
bind_transceiver): both directions on one session. Introduced in 3.4 and now the usual choice because it halves the number of connections to manage.
A rarely used fourth option, outbind, lets the SMSC ask the ESME to bind. In production, run several transceiver binds across two provider hosts so one dropped connection never stops traffic.
Which SMPP PDUs matter in practice?
Every SMPP exchange is a PDU (protocol data unit). Each PDU starts with a 16-octet header: command_length, command_id, command_status and sequence_number. Each request has a matching response with the same sequence number, and response IDs are the request ID with the top bit set (for example submit_sm_resp is 0x80000004). These are the PDUs you will see most:
| PDU | command_id | Sent by | Purpose |
|---|---|---|---|
bind_receiver | 0x00000001 | ESME | Open a receive-only session |
bind_transmitter | 0x00000002 | ESME | Open a send-only session |
bind_transceiver | 0x00000009 | ESME | Open a two-way session |
submit_sm | 0x00000004 | ESME | Submit one message; the response carries the SMSC message_id |
deliver_sm | 0x00000005 | SMSC | Deliver an inbound message or a delivery receipt |
enquire_link | 0x00000015 | Either | Keep-alive and link check |
unbind | 0x00000006 | Either | Close the session cleanly |
generic_nack | 0x80000000 | Either | Reject a PDU that could not be parsed or had an unknown command_id |
Support for query_sm, cancel_sm, replace_sm, submit_multi and data_sm varies by provider. A typical transceiver session:
ESME → SMSC bind_transceiver system_id, password, interface_version=0x34
SMSC → ESME bind_transceiver_resp command_status=0 (ESME_ROK)
ESME → SMSC submit_sm source_addr_ton=5, source_addr=MyBrand,
dest_addr_ton=1, dest_addr_npi=1,
destination_addr=35794000001,
data_coding=0, registered_delivery=1
SMSC → ESME submit_sm_resp message_id assigned by the SMSC
ESME → SMSC enquire_link (every 30-60 seconds when idle)
SMSC → ESME enquire_link_resp
SMSC → ESME deliver_sm esm_class=0x04, "id:... stat:DELIVRD err:000 ..."
ESME → SMSC deliver_sm_resp
ESME → SMSC unbind
SMSC → ESME unbind_resp
How do SMPP delivery receipts work?
To get a delivery receipt (DLR), set registered_delivery in submit_sm: 1 asks for a receipt on final success or failure, 2 asks only on failure. The SMSC later sends the receipt as a deliver_sm with the “SMSC Delivery Receipt” bit set in esm_class (0x04), so your receiver must be bound to see it.
Appendix B of the 3.4 specification gives the typical text format, id:IIIIIIIIII sub:SSS dlvrd:DDD submit date:YYMMDDhhmm done date:YYMMDDhhmm stat:DDDDDDD err:E text:..., with final states such as DELIVRD, EXPIRED, DELETED, UNDELIV, ACCEPTD, UNKNOWN and REJECTD. The specification also says the format is vendor-specific, which matters in practice:
- Match receipts to messages using the
message_idfromsubmit_sm_resp. Where present, thereceipted_message_idTLV is more reliable than parsing text. - Normalise IDs before matching, because implementations differ in case, padding and number base.
- Treat the
errfield as route-specific. Map it to your own categories (absent subscriber, invalid number, blocked, expired) rather than hard-coding one network’s codes. - Always return
deliver_sm_resppromptly, or the provider will resend receipts and may throttle your session.
What are TON and NPI in SMPP?
Each address in a PDU carries a Type of Number (TON) and Numbering Plan Indicator (NPI). Wrong values are one of the most common reasons a sender ID gets rewritten or a message is rejected. The values below come from the 3.4 specification:
| Address | TON | NPI | Example |
|---|---|---|---|
| International mobile number (E.164, no plus sign) | 1 (International) | 1 (ISDN E.163/E.164) | 35794000001 |
| Alphanumeric sender ID | 5 (Alphanumeric) | 0 (Unknown) | MyBrand |
| Short code | 3 (Network specific) or 0 | 0 | Depends on provider and country |
Alphanumeric sender IDs are limited to 11 characters, and many countries require them to be registered first. Send recipient numbers in international format with TON 1 and NPI 1 unless your provider says otherwise.
What does data_coding control?
The data_coding field tells the SMSC how to read the message bytes. The values you will use most are 0 (SMSC default alphabet, normally GSM-7), 8 (UCS2, used for Unicode text such as Arabic, Cyrillic, Chinese or emoji), 3 (Latin-1) and 4 (8-bit binary).
Because 0 means “the SMSC’s default”, not GSM-7 by definition, garbled accents usually point to data_coding. Under 3GPP TS 23.040, a single SMS carries 140 octets: 160 GSM-7 characters or 70 UCS2 characters.
How does SMPP send long messages?
The short_message field holds at most 254 octets, and a single SMS on the radio side holds 140. Longer text becomes a concatenated SMS, and SMPP offers three ways to send it:
- UDH (User Data Header): your application splits the text and adds a concatenation header to each part, setting the UDHI flag in
esm_class(0x40). The header uses 6 octets, so each part carries 153 GSM-7 or 67 UCS2 characters. - SAR TLVs: send each part with
sar_msg_ref_num,sar_total_segmentsandsar_segment_seqnum, and the SMSC builds the headers. message_payload: send the whole text (up to 64K octets per the specification) in one PDU and let the SMSC split it.short_messagemust then be empty.
Pick one method, confirm your provider supports it, and remember that billing is per part. Our guide to SMS pricing and character limits shows how segment counts change cost.
How do windowing and throughput work?
SMPP is asynchronous: you can send the next submit_sm before the previous response arrives. The number of unacknowledged requests allowed at once is the window. The 3.4 specification leaves the maximum to the SMSC and suggests no more than 10 as a guideline; providers set their own limit per account.
A rough ceiling for one bind is window size divided by round-trip time. With a window of 10 and a 50 ms round trip, one session tops out near 200 submits per second, whatever your contracted throughput. To go faster, widen the window within the provider’s limits or open more binds. If you push too hard you will see ESME_RTHROTTLED (0x00000058) or ESME_RMSGQFUL (0x00000014); back off and retry rather than reconnecting in a loop.
Keep sessions healthy with enquire_link. The specification recommends configurable timers for session start, link checks, inactivity and request/response timeouts. In practice, send enquire_link every 30 to 60 seconds when idle and reconnect with backoff if a response does not arrive.
Which port does SMPP use, and how is it secured?
IANA registers TCP port 2775 for SMPP, and it is the usual port for plain connections. Plain SMPP sends credentials and message content unencrypted, so for anything beyond a lab test use one of these:
- SMPP over TLS: the session runs inside a TLS tunnel. There is no standard TLS port, so providers choose their own. One provider, for example, publishes port 3550 for TLS. Always use the host and port in your credentials.
- VPN (typically IPsec): common between carriers and large aggregators. Setup takes longer, but the link is private.
- IP allowlisting: the provider accepts binds only from your registered addresses. Combine it with TLS or a VPN, not instead of them.
SMPP 3.4 passwords are limited to 8 characters, another reason not to rely on the password alone.
When does SMPP make sense instead of an HTTP API?
SMPP is the better fit when you:
- Send sustained high volumes or sharp peaks, such as OTP bursts at login or sign-up.
- Already run SMS gateway software (Kannel, Jasmin or a vendor SMSC) that speaks SMPP.
- Are a carrier, aggregator or reseller exchanging traffic with other providers.
- Want delivery receipts and replies on the same persistent session, without exposing a public webhook.
An HTTPS API usually suits application teams, moderate volumes and serverless workloads better. For a side-by-side comparison with code, read SMPP API vs HTTP API. Before large sends, cleaning lists with HLR and MNP checks helps either way.
How SMS.to handles SMPP
The SMS.to SMPP API is built for carriers, aggregators and high-volume senders that need a persistent connection:
- Throughput: up to 2,000+ messages per second on supported setups. Actual rates depend on routing, content and region.
- Binds: transmitter, receiver and transceiver binds, with advice on the right session model for your target throughput.
- Delivery reports: real-time final and intermediate DLRs over
deliver_sm, with clear state mapping for delivered, failed and undeliverable messages, plus detailed message logs. - Encoding: GSM-7 and Unicode, with UDH concatenation for longer text.
- Security: TLS encryption on the SMPP connection, IP whitelisting, and credentials created and rotated securely.
- Onboarding: test credentials, recommended defaults for window size and
enquire_linkintervals, and config reviews for Kannel, Jasmin or node-smpp clients.
Traffic runs over direct, high-quality connections operated by Intergo Telecom, the licensed operator behind SMS.to, and windows are raised step by step to avoid throttling downstream.
FAQs
What is the full form of SMPP?
SMPP stands for Short Message Peer-to-Peer. It is an open, binary protocol that lets an application (the ESME) submit and receive SMS through a message centre (the SMSC) over a persistent TCP/IP connection.
What port does SMPP use?
IANA assigns TCP port 2775 to SMPP, and many providers use it for plain connections. There is no standard port for SMPP over TLS, so each provider publishes its own; always use the host and port in your credentials.
Is SMPP still used in 2026?
Yes. SMPP 3.4 remains the common interface between carriers, aggregators and high-volume senders for A2P SMS, especially for OTP and alert traffic that needs a persistent, high-throughput connection.
What is the difference between SMPP 3.4 and 5.0?
SMPP 3.4 added the transceiver bind and optional TLV parameters. SMPP 5.0 (2003) added cell broadcast operations, a congestion_state parameter for flow control and extra delivery receipt options, but it is far less widely deployed than 3.4.
Should I use SMPP or an HTTP API?
Use SMPP if you send sustained high volumes, already run SMS gateway software, or need a persistent connection with delivery receipts on the same session. For most applications an HTTPS API is quicker to integrate and easier to operate.
Want to test a bind or compare SMPP with the HTTP API on your own traffic? Create a free account, no credit card needed, then request SMPP credentials from our team.