Connect via SMPP
Most Orbit customers send SMS through the REST Messaging API. If you already run SMPP-based sending infrastructure — a legacy platform migration, an aggregator integration, or a high-throughput application built around an SMPP client library — Orbit also exposes a direct SMPP bind, so you don’t have to rewrite that integration to switch providers.Wire protocol: PDUs, not JSON
Your client speaks SMPP 3.4 binary PDUs to Orbit’s edge — there is no HTTP JSON layer on the bind. The frames you exchange:
A minimal
submit_sm for one recipient — the envelope the runnable client examples below put on the wire when they send a single message:
submit_sm PDUs in flight over one bind rather than asking for a batch endpoint — there is none on the wire. Respect the remote window your client negotiates and the credential’s TPS cap; data_coding=8 on submit_sm is how you send UCS-2 (Unicode) text, and esm_class=0x40 (UDHI) marks concatenated segments when a message is longer than one segment.
How it works
Orbit issues you asystem_id and password. Your SMPP client binds to smpp.orbit.devotel.io:2775 with those credentials and submits submit_sm PDUs exactly as it would against any other SMPP provider. Traffic sent this way flows through the same Orbit sending infrastructure as a REST-submitted message — the same routing, delivery tracking, and compliance gates apply either way.
A runnable client: bind, send one message, read the receipt
Orbit issues thesystem_id and password below when you create a credential — use the create curl later in this section. Set the four environment variables, then run either example end to end: it opens a transceiver bind, sends one submit_sm, prints the Orbit message id from submit_sm_resp, and (if the credential’s dlrMode is bind or both) reads the deliver_sm receipt before unbind.
Python with smpplib
logging.DEBUG output is the expected PDU trace — on a healthy run, bind_transceiver_resp (command_status=0), then submit_sm followed immediately by submit_sm_resp:
Node.js with the smpp package
pdu event observes every inbound frame — the expected PDU trace on a healthy run is bind_transceiver_resp command_status=0 first, then submit_sm → submit_sm_resp, then (when dlrMode is bind or both) a deliver_sm receipt such as id:msg_01H4XK6D7Y stat:DELIVRD. Keep one long-lived bind per process and add an enquire_link keepalive every 30–60 seconds before productionizing either snippet — the discipline below and the linked receipts guide both apply.
To send through the snippet, point SMPP_SYSTEM_ID and SMPP_PASSWORD at a credential from the create curl; if the password has aged out of its reveal window, rotate it and use the fresh one.
Ports and connectivity
Orbit’s SMPP edge accepts binds on two ports, and only these two:
Both ports speak the same protocol and take the same credentials, so switching between them is a client-side setting, not a new credential.
Every other port on
smpp.orbit.devotel.io is closed to the internet. Two things follow from that, and they matter when you are debugging a bind:
- A blocked port drops your connection instead of refusing it. You will not get a fast
connection refused. The connection attempt sits open until your own client gives up, so a typo in the port looks exactly like a slow network. Configure an explicit connect timeout — 5 to 10 seconds is plenty — so a wrong port fails in seconds instead of hanging. - Your own network has to allow the outbound side. Permit egress from the machine running your SMPP client to
smpp.orbit.devotel.ioon2775and3550. Corporate firewalls that silently discard traffic to non-web ports produce the identical hang.
The dashboard console
Developer → SMPP is the console for everything on this page. It is organized in three tabs:- Credentials — the default tab. Before it lists your bind credentials it shows a Connection details card with the copyable host (
smpp.orbit.devotel.io) and both ports, so you can hand the endpoint to a client config without leaving the dashboard. Create, update, reveal, and rotate credentials from the same tab. - Carriers — where enterprise tenants register their own upstream carrier connections, and where you fire a bind test against a carrier row (see the testing section below).
- Compliance — a read-only view of how Orbit’s compliance gates (opt-out suppression, quiet hours, consent tracking) apply to the traffic on your SMPP binds. Every
submit_smpasses these gates regardless of the wire path it took.
Reachability and bind testing
The console’s Carriers tab has a Test bind action per carrier row. It exists for upstream carriers, not for verifying your own client; for carrier rows it runs the edge-side checks that fail fast — wrong carrier type, missing SMPP fields, an undecryptable stored password — and returns a structured result:POST /api/v1/messaging/smpp/carriers/{id}/test exposes the same check over the API, rate-limited so a stuck endpoint can’t be hammered. For your own bind credential, use the diagnostic ladder below — the reachability question (bind_transceiver_resp vs. no response at all) is answered from your own client, not the dashboard.
Is it the network or the credential?
Runbind_transceiver and read what comes back:
- You get a
bind_transceiver_resp— including one carrying an error status such asESME_RINVPASWD(wrong password) orESME_RINVSYSID(unknownsystem_id) — then the edge is reachable and the problem is the credential. Check it hasn’t been rotated or revoked in the dashboard under Developer → SMPP. - The TCP connection never completes — nothing reached Orbit. Confirm you are dialling
2775or3550, thatsmpp.orbit.devotel.ioresolves for you, and that your egress firewall allows the port. - The connection opens on
3550but the TLS handshake fails — your client is either verifying against a different hostname or is missing the public CA chain in its trust store. Verify againstsmpp.orbit.devotel.io.
Long-lived bind vs. transient sessions
Run one long-lived bind per sending process and keep it open. Enquire every 30–60 seconds, rebind after any connection drop with exponential backoff, and drain in-flightsubmit_sm before you unbind on shutdown. Opening a fresh bind per batch or per message is the one usage pattern SMPP punishes and HTTP doesn’t — each bind costs a full handshake, and the edge treats a rapid rebind loop the same way every SMPP server does: throttled and flagged. If your architecture genuinely re-connects per batch, switch that path to the REST API instead.
Troubleshooting bind rejects and throughput
Work this list top to bottom — the first row that matches is the fix.
A binding reject comes back in the
bind_*_resp as a non-zero command_status; read the status from that PDU before assuming the network ate it.
When to use SMPP vs. the REST API
Both paths send through the same underlying platform — pick whichever fits the integration you already have, or the one your team is more comfortable operating.
Delivered status goes wherever you point it:
dlrMode = "webhook" posts receipt JSON to your endpoint, dlrMode = "bind" streams deliver_sm frames back on the session, dlrMode = "both" does the two. Everything you would get over the REST path is available no matter which sending wire you chose.
Creating a credential
The response includes the generated
system_id and a one-time password. The password is exactly 8 alphanumeric characters — that is the maximum the SMPP 3.4 bind PDU password field can carry (a 9-octet value including its trailing NUL), so paste it into your client configuration verbatim; your client does not need to truncate it. The password is only ever shown in full at creation or rotation — it can be re-fetched once within a 60-second reveal window (GET /smpp/credentials/{id}/reveal) in case your session closed before you copied it, and after that window it’s gone. If you lose it, rotate the credential to issue a new one:
Throughput limits
Every credential has a TPS (transactions-per-second) cap — 50 by default, adjustable per organization up to a platform ceiling. A single SMPP bind on Orbit’s infrastructure sustainably tops out well below that ceiling, so if you need very high throughput, open several binds (several credentials) rather than pushing one bind past its practical limit.Bring-your-own upstream carriers (advanced)
Enterprise tenants with their own direct carrier relationships can additionally register upstream SMPP (or HTTP-API) carrier connections that Orbit’s routing layer uses when picking the best egress path for that tenant’s traffic — alongside Orbit’s own carrier network, not instead of it. This is a separate, more advanced surface from the bind credentials above; see the SMPP API reference for the carrier endpoints if your organization has a direct carrier agreement you want Orbit to route through. Test a saved carrier from the console’s Carriers → Test bind action before enabling it for routing.Rebinding across regions
Multi-region failover is client-side. A healthy implementation caches a connect latency per region endpoint, rebinds to the lowest-latency healthy region after a drop, and never rotates through endpoints per message — only on failure. Keep the same discipline for regions as for binds: rebind on drop with backoff, drain in-flight work beforeunbind, and let a sticky session do the work of a fleet of ephemeral ones.
Endpoints
See also
- SMPP edge model — how the relay underneath your bind is organized and reconciled
- SMPP: the no-delivery receipt window — per-rule timing for the UNDELIV receipt on absorbed traffic
- SMPP Inbox opt-in — decide whether bind-received messages may open Inbox conversations (default off)
- Keep one-time codes out of the Inbox — per-hop no-inbox stamps for OTP-style bind traffic
- Messaging API — the REST alternative to an SMPP bind
- Messaging credentials & services
- Sender Pools — rotating the
fromaddress across a pool of senders