SMPP Server API

Connect your ERP or system to SMSDESK via SMPP protocol

SMPP Protocol: SMSDESK provides an inbound SMPP server for customers who need to connect via SMPP protocol but are not licensed to connect directly to Mobile Network Operators (MNOs).
Transport Security: SMPP connections are plain TCP (not TLS). Customers requiring encrypted transport should use a VPN or network-level encryption, or use the REST API which is served over HTTPS.
Quick Reference:

Overview

The SMSDESK SMPP Server allows external systems to connect and submit SMS messages (SUBMIT_SM) using the industry-standard SMPP v3.4 protocol. This is ideal for:

Key Features

Send SMS

Submit SMS messages via SUBMIT_SM PDU

Receive SMS

Not available - incoming SMS (MO) is not forwarded over SMPP

Queue Receipts

Delivery report (DELIVER_SM) confirms your message was accepted into the send queue - stat:ACCEPTD. Handset delivery status via HTTP API

Authentication

API key based (first 8 chars). Plain TCP — use VPN for encrypted transport

Connection Details

Get Your Credentials: SMPP access must be enabled for your account. Contact your account administrator or visit the web portal to enable SMPP access.

Server Configuration

Protocol Version SMPP v3.4
Server Address {host} (your SMSDESK deployment domain)
Port 2775 (standard SMPP port)
Supported Bind Types TRANSMITTER, TRANSCEIVER (BIND_RECEIVER is refused with ESME_RBINDFAIL). Use TRANSCEIVER if you want queue-acceptance receipts (DELIVER_SM)
Max Sessions 100 concurrent sessions total, maximum 10 sessions per IP address
Session Timeout 300 seconds (5 minutes) of inactivity - send ENQUIRE_LINK every 30-60s
Bind Deadline 30 seconds - connections that do not bind within 30s are closed
Bind Throttle 5 failed binds per IP within 5 minutes → ESME_RTHROTTLED until the window expires
Max PDU Size 70,000 bytes (accommodates message_payload TLV for long messages)
Throughput 300 messages per minute per session (ESME_RTHROTTLED when exceeded)

PDU Parameters

Destination TON 1 (International)
Destination NPI 1 (ISDN/Telephone)
Source TON 0 (Unknown) or 5 (Alphanumeric)
Source NPI 0 (Unknown)
Data Coding 8 = UCS2/Unicode; all other values (including 0, 1, 3) are decoded as ISO-8859-1 Latin-1
Character Set ISO-8859-1 (Latin-1) or UCS-2 (data_coding=8). GSM 7-bit packed encoding (data_coding=0) is not unpacked — send Latin-1 encoded bytes

Authentication

SMPP authentication uses your SMSDESK API credentials:

Credentials

System ID: C1409138              (recommended - shown in portal as "SMPP System ID")
           OR your-email@example.com  (also accepted)
Password:  your-api-key (first 8 characters only)
System ID format: SMPP 3.4 limits system_id to 16 octets (15 characters + terminator), and most client libraries enforce this limit by truncating longer values. If your email address is longer than 15 characters it will be truncated on the wire and authentication will fail — always use the C<id> form shown in the portal (e.g., C1409138). Both forms are accepted by the server; the C<id> form is guaranteed to fit the protocol limit.
Important: Due to SMPP protocol limitations, only the first 8 characters of your API key are used as the password. The full API key is displayed in the web portal with masking (e.g., rqym••••••••).
Getting Your Credentials: Your API key and SMPP System ID are available in the web portal under Account Settings → SMPP Access. SMPP access must be enabled for your account.

Bind Process

  1. Connect to server address on port 2775
  2. Send BIND_TRANSMITTER or BIND_TRANSCEIVER PDU within 30 seconds of connecting
  3. Include your SMPP System ID (C<id>, recommended) or email as system_id
  4. Include the first 8 characters of your API key as password
  5. Server validates credentials and responds with BIND_RESP (on success the response carries system_id=SMSDESK)
  6. Server retrieves your default channel for message routing

Bind Response Codes

0x00000000 ESME_ROK Bind successful
0x00000005 ESME_RALYBND Session is already bound
0x0000000E ESME_RINVPASWD Invalid credentials - wrong system_id or password (check System ID format and the first 8 chars of your API key)
0x0000000F ESME_RINVSYSID Missing system_id
0x0000000D ESME_RBINDFAIL Credentials valid but account not permitted to bind - user or account inactive, SMPP not enabled, no default channel, or client account not ACTIVE
0x00000008 ESME_RSYSERR Internal server error - retry or contact support
0x00000058 ESME_RTHROTTLED Too many failed binds from your IP - wait 5 minutes

Supported Operations

1. Send SMS (SUBMIT_SM)

Submit an SMS message for delivery to a mobile number.

Channel Routing: The source_addr field in the PDU is ignored. Messages are routed using your account's default channel configured in the web portal. This ensures proper billing and routing through your assigned SMS channels.

PDU Structure

SUBMIT_SM PDU:
  service_type: ""
  source_addr_ton: 0 or 5 (alphanumeric)
  source_addr_npi: 0
  source_addr: "Any" (ignored for routing - default channel used; echoed back in DELIVER_SM receipts)
  dest_addr_ton: 1 (international)
  dest_addr_npi: 1 (ISDN)
  dest_addr: "264811234567" (7-15 digits, optional leading +)
  esm_class: 0 (or 0x40 for UDH concatenation)
  protocol_id: 0
  priority_flag: 0 (stored but ignored - priority comes from your account settings)
  schedule_delivery_time: "" (scheduled delivery NOT supported - rejected with 0x00000061)
  validity_period: ""
  registered_delivery: 0 or 1 (set 1 to receive a DELIVER_SM queue-acceptance receipt - transceiver binds only)
  replace_if_present_flag: 0
  data_coding: 8 (UCS2) or anything else = Latin-1
  sm_default_msg_id: 0
  sm_length: [message length, max 254]
  short_message: "Your message text"

Response

SUBMIT_SM_RESP PDU:
  command_status: 0x00000000 (success)
  message_id: "26986088" (sms_outgoing row ID - use with /sms/2/reports)

2. Queue-Acceptance Receipts (DELIVER_SM)

When you set registered_delivery in SUBMIT_SM and are bound as TRANSCEIVER, the server pushes a DELIVER_SM receipt after the message is accepted and persisted to the outbound queue. This confirms SMSDESK's own processing — receipt and database insertion for onward network delivery. It is not a handset delivery report.

Semantics: stat:ACCEPTD means "received and queued". For final network/handset delivery status, poll the HTTP API (/sms/2/reports, /sms/2/logs) with the message_id from SUBMIT_SM_RESP, or use webhooks.

Receipt PDU

DELIVER_SM PDU (server → client):
  esm_class: 0x04 (SMSC delivery receipt)
  source_addr: the message destination number
  destination_addr: your original source_addr
  data_coding: 3 (Latin-1)
  short_message: "id:26986088 sub:001 dlvrd:000 submit date:2510151130
                  done date:2510151130 stat:ACCEPTD err:000 text:Your message"
  TLVs:
    0x001E receipted_message_id = "26986088"  (matches SUBMIT_SM_RESP message_id)
    0x0427 message_state        = 6 (ACCEPTED)

Your client must respond to DELIVER_SM with DELIVER_SM_RESP (standard - most libraries do this automatically). A failed SUBMIT_SM returns a non-zero command_status in SUBMIT_SM_RESP and no receipt is sent.

3. Receiving SMS (MO) — not supported

Incoming SMS is not forwarded over SMPP. BIND_RECEIVER is refused with ESME_RBINDFAIL. Use the HTTP API or webhooks for inbound messages.

4. Enquire Link (ENQUIRE_LINK)

Keepalive mechanism to maintain connection.

ENQUIRE_LINK PDU → ENQUIRE_LINK_RESP

5. Unbind (UNBIND)

Gracefully close the SMPP session.

UNBIND PDU → UNBIND_RESP → Connection closed

6. Long Messages (Concatenation)

Messages longer than 160 GSM characters (or 70 UCS2 characters) are supported via concatenation. The server reassembles the parts and queues a single message. Each part is billed separately by the network.

Per-part acknowledgment: every part is acknowledged with a SUBMIT_SM_RESP. Intermediate parts return a temporary message_id of the form PART-{ref}-{seq}; the final part returns the real queued message ID. The queue-acceptance receipt (DELIVER_SM, if requested) is sent once, after the last part is assembled. If a client disconnects mid-sequence, the already-acknowledged parts are queued as one partial message — they are never dropped.

Using UDH (User Data Header)

Set esm_class to 0x40 (UDH indicator) and include a UDH with concatenation information in the short_message field:

UDH for a 2-part message with an 8-bit reference (6 bytes, prepended to each part):
  05 00 03 A5 02 01   (UDHL=5, IEI=00 concatenation, IEDL=3, ref=0xA5, total=2, seq=1)
  05 00 03 A5 02 02   (same ref and total, seq=2)

Per part: up to 153 GSM characters, or 67 UCS2 characters (134 bytes).

Using SAR TLVs

Alternatively, use the SAR (Segmentation and Reassembly) TLVs in the PDU:

sar_msg_ref_num: 12345 (reference number, same for all parts)
sar_total_segments: 2 (total number of parts)
sar_segment_seqnum: 1 (sequence number, 1-based)

Using message_payload TLV

For messages longer than 254 bytes, use the message_payload TLV (tag 0x0424) instead of short_message. The server reads the full message from this TLV.

Encoding

Encoding data_coding Single SMS Per concatenated part
GSM 7-bit (Latin) 0 160 chars 153 chars
UCS2 (Unicode) 8 70 chars 67 chars

7. Message Priority

Every queued message carries a priority that decides the order in which it is sent to the mobile networks: the highest priority is dispatched first, and messages of equal priority are sent in the order they were received (FIFO). The priority_flag field in SUBMIT_SM is stored but does not influence queue order. Priority is resolved as follows:

  1. Per-user priority — set by your account administrator on the user's page in the web portal (CRITICAL, HIGH, NORMAL, LOW, BULK). When set, it applies to everything that user submits.
  2. Method default — used when the user has no priority set:
Submission method Default priority
REST API, other API integrations, automatic replies HIGH
SMPP NORMAL
Portal (single send), Email-to-SMS LOW
Portal CSV upload, contact-group sends BULK

Tip: create a dedicated API-only user for OTP traffic and give it CRITICAL priority so one-time passwords are never held up behind campaigns, and give your bulk-campaign user BULK. Priority only changes the order within the queue; it does not throttle or reject any traffic.

Maximum message size: 255 parts, the GSM limit for a concatenated SMS (39,015 GSM-7 characters or 17,085 UCS2 characters; GSM extension characters count double). Larger submissions are rejected with ESME_RINVMSGLEN and nothing is queued. Send long messages as concatenated parts (UDH or sar_* TLVs) or in a single message_payload TLV (up to 65,535 octets). Each part is billed as one SMS, and mobile networks may accept fewer parts than the GSM maximum.

Code Examples

Python (smpplib)

import smpplib.client
import smpplib.consts

# Connect to SMPP server
client = smpplib.client.Client('{host}', 2775)

# Handle queue-acceptance receipts (DELIVER_SM)
def on_deliver(pdu):
    # short_message contains: "id:<id> sub:001 dlvrd:000 ... stat:ACCEPTD ..."
    print(f'Receipt: {pdu.short_message!r}')

client.set_message_received_handler(on_deliver)

# Bind as transceiver (required to receive DELIVER_SM receipts)
# System ID = C<client_user_id> from the portal (spec-safe, max 15 chars)
# Password = first 8 characters of your API key
client.connect()
client.bind_transceiver(
    system_id='C1409138',     # SMPP System ID from portal (or your email, ≤15 chars)
    password='rqym36t4'       # First 8 chars of API key
)

# Send SMS - registered_delivery=1 requests the DELIVER_SM receipt
resp = client.send_message(
    source_addr='Any',            # Ignored for routing - default channel used
    destination_addr='264811234567',  # No + prefix
    short_message=b'Hello from SMPP!',
    data_coding=3,                # Latin-1 (8 = UCS2)
    registered_delivery=1,
)
print(f'Accepted, message_id={resp.message_id}')

# Listen for the DELIVER_SM receipt
client.listen(timeout=10)

# Unbind and disconnect
client.unbind()
client.disconnect()

PHP (php-smpp)

<?php
require_once 'vendor/autoload.php';

use PhpSmpp\Transport\Socket;
use PhpSmpp\Client;
use PhpSmpp\SMPP;

// Create transport
$transport = new Socket(['sms.com.na'], 2775);
$transport->open();

// Create client
$smpp = new Client($transport);

// Bind with SMPP System ID (recommended) or email
$smpp->bindTransceiver(
    'C1409138',    // SMPP System ID from portal (or email if ≤15 chars)
    'rqym36t4'     // First 8 chars of API key
);

// Send SMS (source is ignored, default channel used)
$smpp->sendSMS(
    'Any',  // Ignored - default channel used
    '264811234567',  // No + prefix
    'Hello from SMPP!',
    null,
    SMPP::DATA_CODING_DEFAULT
);

echo "✓ Message sent successfully!\n";

// Unbind
$smpp->close();
?>

Java (jSMPP)

import org.jsmpp.bean.*;
import org.jsmpp.session.SMPPSession;

public class SmppExample {
    public static void main(String[] args) throws Exception {
        SMPPSession session = new SMPPSession();
        
        // Connect and bind with API key (first 8 characters)
        session.connectAndBind(
            "{host}", 
            2775,
            new BindParameter(
                BindType.BIND_TRX,
                "C1409138",            // SMPP System ID from portal (or email if ≤15 chars)
                "rqym36t4",            // First 8 chars of API key
                "SMSDESK",
                TypeOfNumber.UNKNOWN,
                NumberingPlanIndicator.UNKNOWN,
                null
            )
        );
        
        // Send SMS (source is ignored, default channel used)
        String messageId = session.submitShortMessage(
            "CMT",
            TypeOfNumber.UNKNOWN,
            NumberingPlanIndicator.UNKNOWN,
            "Any",  // Ignored - default channel used
            TypeOfNumber.INTERNATIONAL,
            NumberingPlanIndicator.ISDN,
            "264811234567",  // No + prefix
            new ESMClass(),
            (byte) 0,
            (byte) 1,
            null,
            null,
            new RegisteredDelivery(SMSCDeliveryReceipt.DEFAULT),
            (byte) 0,
            new GeneralDataCoding(Alphabet.ALPHA_DEFAULT),
            (byte) 0,
            "Hello from SMPP!".getBytes()
        );
        
        System.out.println("✓ Message sent! ID: " + messageId);
        
        // Unbind
        session.unbindAndClose();
    }
}

C# (.NET)

using JamaaTech.Smpp.Net.Client;
using JamaaTech.Smpp.Net.Lib;

class Program
{
    static void Main()
    {
        // Create client
        var client = new SmppClient();
        client.Name = "SMSDESK-Client";
        
        // Connect
        client.Start();
        
        // Bind with SMPP System ID (recommended) or email
        client.Bind(
            "{host}",
            2775,
            "C1409138",      // SMPP System ID from portal (or email if ≤15 chars)
            "rqym36t4"       // First 8 chars of API key
        );
        
        // Send SMS (source is ignored, default channel used)
        var message = new TextMessage
        {
            DestinationAddress = "264811234567",  // No + prefix
            SourceAddress = "Any",  // Ignored - default channel used
            Text = "Hello from SMPP!",
            RegisterDeliveryNotification = false
        };
        
        client.SendMessage(message);
        
        Console.WriteLine("✓ Message sent successfully!");
        
        // Unbind
        client.Shutdown();
    }
}

Error Codes

The SMPP server returns standard SMPP v3.4 error codes. Common errors:

Code Hex Name Description Action
0 0x00000000 ESME_ROK Success - message accepted and queued Continue
1 0x00000001 ESME_RINVMSGLEN Empty message, or >255 parts after assembly Fix message length; do not retry unchanged
2 0x00000002 ESME_RINVCMDLEN Malformed/truncated PDU Fix client encoding
3 0x00000003 ESME_RINVCMDID Unsupported command Check command ID
4 0x00000004 ESME_RINVBNDSTS SUBMIT_SM before bind Bind first
5 0x00000005 ESME_RALYBND Session already bound Continue; bind once
8 0x00000008 ESME_RSYSERR Internal server error Retry; contact support if persistent
11 0x0000000B ESME_RINVDSTADR Invalid destination (must be 7-15 digits) Fix number format; do not retry unchanged
13 0x0000000D ESME_RBINDFAIL Account not bind-eligible (inactive/SMPP off/no channel) Contact administrator
14 0x0000000E ESME_RINVPASWD Invalid system_id or password Use C<id> System ID + first 8 chars of API key
15 0x0000000F ESME_RINVSYSID Missing system_id Supply System ID
69 0x00000045 ESME_RSUBMITFAIL Message could not be queued (server-side failure) Retry; contact support if persistent
88 0x00000058 ESME_RTHROTTLED Rate limit - 300 msg/min per session or failed-bind lockout Retry with delay
97 0x00000061 ESME_RINVSCHED Scheduled delivery not supported Send immediately; omit schedule_delivery_time

View Complete Error Code Reference

Best Practices

Connection Management

Message Handling

Error Handling

// Pseudo-code for error handling
if (response.command_status == ESME_RTHROTTLED) {
    // Wait and retry
    sleep(1000);
    retry_message();
} else if (response.command_status == ESME_RINVDSTADR) {
    // Invalid number - don't retry
    log_error("Invalid destination number");
    mark_as_failed();
} else if (response.command_status == ESME_ROK) {
    // Success
    save_message_id(response.message_id);
}

Performance

Security

Server Security Features

Built-in Protection: The SMPP server includes multiple security layers:
Need Help? Contact support for SMPP access enablement, connection issues, or technical assistance.
Testing: Test your SMPP integration thoroughly in a development environment before deploying to production.