SMPP connection guide

For banks, aggregators and high-volume platforms that speak SMPP natively: bind directly and stream traffic without HTTP overhead.

Getting access

  1. In the portal, go to Settings and request SMPP access.
  2. Once enabled, your system_id appears there. The bind password is your mbs_ API token — the same one you create under Settings → API Tokens (it needs the message-send scope).
  3. 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

FieldTypeRequiredDescription
ProtocolSMPP 3.4NoThe industry-standard version. v5.0 features are not required.
Bind typetransceiverNoOne bind for both submit_sm (MT) and deliver_sm (DLRs). Separate TX/RX binds also accepted.
system_idcredentialNoIssued per account when SMPP access is enabled — shown in portal Settings.
passwordmbs_ tokenNoYour mbs_ API token, passed in full as the bind password. Revoking the token instantly kills the bind credentials.
source_addralphanumericNoYour approved sender ID. source_addr_ton=5, source_addr_npi=0 for alphanumeric senders.
destinationE.164No2547XXXXXXXX — 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) or message_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

FieldTypeRequiredDescription
DELIVRDfinalNoDelivered to the handset.
UNDELIV / EXPIREDfinalNoCould not be delivered within the validity period.
REJECTDfinalNoRefused by the carrier.
ACCEPTD / ENROUTEinterimNoIn 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_link every 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.