SMPP connection guide
For banks, aggregators and high-volume platforms that speak SMPP natively: bind directly and stream traffic without HTTP overhead.
Getting access
- In the portal, go to Settings and request SMPP access.
- Once enabled, your
system_idappears there. The bind password is yourmbs_API token — the same one you create under Settings → API Tokens (it needs the message-send scope). - Whitelist of your source IPs may be requested for production binds.
Long passwords are expected
SMPP 3.4 nominally caps passwords at 9 characters;
mbs_ tokens are much longer and our server accepts them in full. Most client libraries pass long passwords through unchanged — if yours enforces the 9-character limit, patch or configure it; a truncated token will be rejected at bind.Connection parameters
Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| Protocol | SMPP 3.4 | No | The industry-standard version. v5.0 features are not required. |
| Bind type | transceiver | No | One bind for both submit_sm (MT) and deliver_sm (DLRs). Separate TX/RX binds also accepted. |
| system_id | credential | No | Issued per account when SMPP access is enabled — shown in portal Settings. |
| password | mbs_ token | No | Your mbs_ API token, passed in full as the bind password. Revoking the token instantly kills the bind credentials. |
| source_addr | alphanumeric | No | Your approved sender ID. source_addr_ton=5, source_addr_npi=0 for alphanumeric senders. |
| destination | E.164 | No | 2547XXXXXXXX — no plus sign. dest_addr_ton=1, dest_addr_npi=1. |
Message encoding
data_coding=0— GSM-7 default alphabet (160 chars/segment).data_coding=8— UCS-2 for Unicode (70 chars/segment).- Long messages: use UDH concatenation (
esm_class=0x40) ormessage_payload; both are supported.
Delivery receipts
Set registered_delivery=1 on submit_sm; DLRs arrive as deliver_sm with the standard receipt text format:
text
id:7c31a2f4 sub:001 dlvrd:001 submit date:2607111015 done date:2607111016 stat:DELIVRD err:000 text:…stat values
| Field | Type | Required | Description |
|---|---|---|---|
| DELIVRD | final | No | Delivered to the handset. |
| UNDELIV / EXPIRED | final | No | Could not be delivered within the validity period. |
| REJECTD | final | No | Refused by the carrier. |
| ACCEPTD / ENROUTE | interim | No | In transit — a final receipt follows. |
Bind and send — code examples
A transceiver bind that submits one message and listens for delivery receipts, in the most common SMPP client stacks. Swap in the host, port and credentials from your portal Settings page.
// go get github.com/linxGnu/gosmpp
package main
import (
"fmt"
"log"
"os"
"time"
"github.com/linxGnu/gosmpp"
"github.com/linxGnu/gosmpp/data"
"github.com/linxGnu/gosmpp/pdu"
)
func main() {
auth := gosmpp.Auth{
SMSC: "smpp.mobilesasa.com:2775",
SystemID: "your_system_id",
Password: os.Getenv("MOBILESASA_TOKEN"), // your mbs_ API token
SystemType: "",
}
trans, err := gosmpp.NewSession(
gosmpp.TRXConnector(gosmpp.NonTLSDialer, auth),
gosmpp.Settings{
EnquireLink: 30 * time.Second, // keepalive
OnPDU: func(p pdu.PDU, _ bool) {
if dsm, ok := p.(*pdu.DeliverSM); ok {
msg, _ := dsm.Message.GetMessage()
fmt.Println("DLR:", msg) // id:… stat:DELIVRD …
}
},
OnRebindingError: func(err error) { log.Println("rebind:", err) },
},
5*time.Second,
)
if err != nil {
log.Fatal(err)
}
defer trans.Close()
sm := pdu.NewSubmitSM().(*pdu.SubmitSM)
sm.SourceAddr = pdu.NewAddressWithAddr("DUKAPAY")
sm.SourceAddr.SetTon(5) // alphanumeric
sm.SourceAddr.SetNpi(0)
sm.DestAddr = pdu.NewAddressWithAddr("254712345678")
sm.DestAddr.SetTon(1) // international
sm.DestAddr.SetNpi(1)
sm.Message, _ = pdu.NewShortMessageWithEncoding(
"Your OTP is 482913", data.GSM7BIT)
sm.RegisteredDelivery = 1 // request DLRs
if err := trans.Transceiver().Submit(sm); err != nil {
log.Fatal(err)
}
select {} // keep the bind alive
}No curl — and notes on Rust and .NET
SMPP is a binary TCP protocol, so there's no curl equivalent — for a quick command-line smoke test of your credentials, send one message through the REST APIinstead; it exercises the same sender and routing. Rust's SMPP crate ecosystem is still young with no de-facto standard client — Rust shops usually integrate over the REST API (see the Rust tabs throughout these docs) or wrap an existing SMPP library via FFI. On .NET the widely deployed client is the commercial Inetlab.SMPP library — it works fine against our bind parameters above — but unless you already own a licence, the REST API (C# and VB.NET tabs throughout these docs) is the faster route.
Keeping the bind healthy
- Send
enquire_linkevery 30 seconds; treat two missed responses as a dead bind and reconnect with backoff. - Respect the throughput agreed for your account; submit windows above it are throttled with
ESME_RTHROTTLED— back off, don't hammer. - Reconnect storms hurt everyone: cap reconnection attempts at one per 5 seconds with jitter.
Do you actually need SMPP?
The REST bulk endpoint happily moves hundreds of thousands of messages a day with far less operational burden. Choose SMPP when you already run an SMPP stack or need sustained multi-hundred-TPS throughput.