SMPP API
SMPP endpoints exposed by the Devotel CPaaS API Base path:/api/v1/messaging/smpp
Endpoint count: 15
title: “Worked request and response samples” description: “Worked samples for the bring-your-own-carrier bind lifecycle: register a carrier (201), list the live bind rows, delete to take it out of rotation (204), and the 404 for an unknown carrier id.”
Worked request and response samples
Copy a request as written, substitute your own ids, and compare the response envelope. Errors follow Devotel Orbit’s{ error, ... } envelope with the error.code your client branches on. The chain a carrier/SMPP integrator runs: register → list the live bind → delete to retire it.
1. Register a carrier bind
POST /api/v1/messaging/smpp/carriersstatus='active'. Devotel reads the routing fields (scope, priority — lower wins) and reconciles the SMPP bind within about 30 seconds; once live, GET on this row reports the reconciler-observed bindStatus (BOUND / UNBOUND / BIND_FAILED) and lastSeenAt. The password you sent is never on the wire again — reads redact it to remotePasswordSet: true.
Most registrations on this platform connect to the inbound side (your SMSC binds to Orbit for MO and delivery receipts) — for that, create a credential (POST /api/v1/messaging/smpp/credentials) instead; a carrier is for outbound termination only.
2. List the live bind rows
GET /api/v1/messaging/smpp/carriersdata as an array of the full wire shape (see step 1 for every field). Rows come back in priority order, then newest-first within the same priority. There is no pagination envelope on this endpoint — the row set is a small per-tenant list. Filter status='active' client-side to find the routes currently eligible for outbound traffic.
3. Delete the carrier (204, hinted rebind)
DELETE /api/v1/messaging/smpp/carriers/{id}204 No Content
Delete is a soft delete — the row stays in your tenant for the audit chain with status='inactive', and routing stops sending through the carrier once the reconciler’s next ~30-second tick removes the underlying connector. Retired it by mistake? Re-activate with PATCH /api/v1/messaging/smpp/carriers/{id} and {"status": "active"} — a hinted rebind, no re-registration needed.
4. Unknown carrier id → 404
Reading, updating, testing, or deleting an id that is not a carrier in your tenant returns the 404 error envelope:404
List SMPP carriers
GET /api/v1/messaging/smpp/carrierspriority value first). A carrier is your own downstream SMSC — SMPP bind or HTTP API — that outbound MT traffic routes through when the row is active, and Devotel charges $0/message on those sends. Each item carries the full wire shape (id, label, type, connection block, scope, scopeFilter, priority, status, reconciler-observed bindStatus / lastSeenAt, timestamps) with credential material redacted to remotePasswordSet / httpCredentialsSet booleans. Use it to render a carrier table or confirm reconciliation state before a change.
string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to
true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.Get SMPP carrier
GET /api/v1/messaging/smpp/carriers/{id}id_smppcr_ id, returning the full configuration: label and carrier type (smpp or http), the connection block for that type (SMPP: remoteHost / remotePort / remoteSystemId / bindType / TLS flags; HTTP: httpUrl / httpAuthType), routing (scope, scopeFilter.mccs, priority), lifecycle status, and the reconciler-observed bindStatus / lastSeenAt. Credential material is redacted to remotePasswordSet / httpCredentialsSet booleans — never the value. Use it to hydrate a detail or edit view. Returns 404 when the id is not a carrier in this tenant.
string
required
—
string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to
true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.Get SMPP carrier route scores
GET /api/v1/messaging/smpp/carriers/route-scorespriority or scope on the carrier itself.
string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to
true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.List SMPP credentials
GET /api/v1/messaging/smpp/credentialssystemId + password, generated at create) your SMSC uses to open an SMPP bind against Orbit for inbound (MO / delivery-receipt) traffic. The list view carries the full wire shape per credential (id, systemId, description, tpsLimit, allowedCidrs, dlrMode, dlrWebhookUrl, status, timestamps, bindCount, smppHost, smppPort, passwordRevealableUntil) — password material is never on the wire. Use it to hydrate a credentials table or to find a credential id before update / rotate / revoke.
string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to
true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.Get SMPP credential
GET /api/v1/messaging/smpp/credentials/{id}smppcred_ id, returning the full configuration: bind identity (systemId), description, throughput cap (tpsLimit), CIDR allow-list, DLR delivery mode and webhook URL, lifecycle status, timestamps, bind count, and the smppHost / smppPort pair your SMSC binds to. passwordRevealableUntil tells you whether GET /:id/reveal can still return the plaintext. Use it to hydrate a detail or edit view. Returns 404 when the id is not a credential in this tenant.
string
required
—
string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to
true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.Reveal SMPP credential password
GET /api/v1/messaging/smpp/credentials/{id}/revealPOST /:id/rotate. Use it when the create / rotate response was not persisted. Returns 404 when the id is not a credential in this tenant and 410 when the reveal window has expired.
string
required
—
string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to
true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.Create SMPP or HTTP-API carrier
POST /api/v1/messaging/smpp/carrierstype='smpp' with remoteHost, remotePort, remoteSystemId, remotePassword, optional bindType and TLS flags) or an HTTP API (type='http' with httpUrl, httpAuthType, httpCredentials) — that outbound MT traffic routes through while the row is active, at $0/message from Devotel. Routing fields pick what the carrier serves: scope='all' or scope='by_country_mcc' with a scopeFilter.mccs list (1–50 three-digit MCCs), plus a priority (lower wins). Submit status='inactive' to stage the row before flipping it live. The reconciler picks the row up on its next 30-second tick and opens the bind / installs the route. Owner / admin only, rate-limited to 20/hour per tenant; a missing connection block for the declared type is a 422.
string
Stripe-style idempotency token. Pass a stable, client-generated value (1-255 chars) to dedupe retries on transient timeouts. The same key+credential+path replays the original response for 24h on 2xx (5min on 4xx, 30s on 5xx). Returns 409 if a concurrent request with the same key is already in flight; replayed responses include the
Idempotency-Replay: true response header.string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to
true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.any
Human-readable name, 1–64 characters (required).
any
Carrier type:
smpp (SMPP bind, default) or http (HTTP API).any
SMPP: upstream host — hostname, IPv4 or IPv6 literal, no scheme or port (required for
type='smpp').any
SMPP: upstream port, 1–65535 (required for
type='smpp').any
SMPP: bind system_id, 1–15 characters per SMPP 3.4 (required for
type='smpp').any
SMPP: bind password, 1–8 characters (SMPP 3.4 C-Octet cap); encrypted at rest, never echoed back (required for
type='smpp').any
HTTP: upstream endpoint, HTTPS-only (required for
type='http').any
HTTP: auth scheme —
basic, bearer or custom (required for type='http').any
HTTP: opaque credential material the auth scheme consumes; encrypted at rest (required for
type='http').any
Routing scope:
all (default) or by_country_mcc.any
Routing filter
{ mccs: string[] } of 1–50 three-digit MCCs; required when scope='by_country_mcc'.any
Route priority, 0–10000 (lower wins; default 100).
any
Initial lifecycle status —
active, suspended or inactive; submit inactive to stage before going live.Test SMPP carrier bind
POST /api/v1/messaging/smpp/carriers/{id}/testok, the observed bindStatus (BOUND / UNBOUND / BIND_FAILED), a failure reason when it did not bind, and the bind round-trip time in durationMs. Run it right after creating or updating a carrier — and again when the dashboard flags a degraded route — before routing live traffic through it. Owner / admin only, rate-limited to 6/minute per tenant so a stuck upstream cannot be hammered; returns 404 when the id is not a carrier in this tenant.
string
required
—
string
Stripe-style idempotency token. Pass a stable, client-generated value (1-255 chars) to dedupe retries on transient timeouts. The same key+credential+path replays the original response for 24h on 2xx (5min on 4xx, 30s on 5xx). Returns 409 if a concurrent request with the same key is already in flight; replayed responses include the
Idempotency-Replay: true response header.string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to
true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.Dry-run LCR route quote
POST /api/v1/messaging/smpp/carriers/route-quotedecision='byo' names the carrier that would win (cost $0 — you pay your upstream directly); decision='devotel' returns a Devotel-termination cost estimate off the pricing resolver (unitPriceCents/totalCents), or an explicit devotelQuote: null when pricing couldn’t resolve. The request body is { destination, messageCount } (messageCount defaults to 1). Nothing is billed — the endpoint is read-only and never debits your wallet.
string
Stripe-style idempotency token. Pass a stable, client-generated value (1-255 chars) to dedupe retries on transient timeouts. The same key+credential+path replays the original response for 24h on 2xx (5min on 4xx, 30s on 5xx). Returns 409 if a concurrent request with the same key is already in flight; replayed responses include the
Idempotency-Replay: true response header.string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to
true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.string
required
The destination phone-number string (E.164 like
+44... or the short-form you would actually send — the scope-match + price resolver interpret it exactly the way the live send does).integer
How many messages to price (defaults to 1 so a single-send dry run reads a per-message unit price).
Create SMPP credential
POST /api/v1/messaging/smpp/credentialssystemId, smppcred_…) plus a generated password your SMSC uses to bind to Orbit for inbound (MO / delivery-receipt) traffic. All body fields are optional config: description, tpsLimit (1–1000, plan-tier-capped), allowedCidrs (up to 16 IPv4/IPv6 CIDRs that gate the bind source), dlrMode (bind delivers receipts on the SMPP bind, webhook POSTs them, both), and dlrWebhookUrl (HTTPS-only, SSRF-checked; required when dlrMode is webhook or both). THE PLAINTEXT PASSWORD IS RETURNED EXACTLY ONCE in this response together with the credential record — store it now. Within 60 seconds it remains re-fetchable via GET /:id/reveal; after that it is unrecoverable and you must call /rotate. Owner / admin only — an owner/admin dashboard session, or an API key scoped smpp:write — rate-limited to 10/hour per tenant.
string
Stripe-style idempotency token. Pass a stable, client-generated value (1-255 chars) to dedupe retries on transient timeouts. The same key+credential+path replays the original response for 24h on 2xx (5min on 4xx, 30s on 5xx). Returns 409 if a concurrent request with the same key is already in flight; replayed responses include the
Idempotency-Replay: true response header.string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to
true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.any
Human-readable label, 1–200 characters (optional).
any
Inbound throughput cap, 1–1000 messages/second; additionally plan-tier-capped service-side (optional).
any
Up to 16 IPv4/IPv6 CIDR strings that gate which source IPs may bind (optional; empty means any).
any
Delivery-receipt delivery mode:
bind, webhook or both (optional, defaults to bind).any
HTTPS webhook endpoint for DLRs; required when
dlrMode is webhook or both (optional otherwise).Rotate an SMPP credential’s password and return the new plaintext once
POST /api/v1/messaging/smpp/credentials/{id}/rotatesystemId and every config field stay unchanged; only the password is replaced. The new plaintext is returned EXACTLY ONCE in this response — store it now. Owner / admin only — an owner/admin dashboard session, or an API key scoped smpp:write — rate-limited to 10 per hour per tenant. A 409 fires when the credential is revoked (create a new one instead), and 404 when no credential holds the id.
string
required
—
string
Stripe-style idempotency token. Pass a stable, client-generated value (1-255 chars) to dedupe retries on transient timeouts. The same key+credential+path replays the original response for 24h on 2xx (5min on 4xx, 30s on 5xx). Returns 409 if a concurrent request with the same key is already in flight; replayed responses include the
Idempotency-Replay: true response header.string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to
true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.Update SMPP carrier
PATCH /api/v1/messaging/smpp/carriers/{id}scope / scopeFilter / priority, and/or status). Nullable fields (description, httpUrl, httpAuthType, scopeFilter) accept null to clear them; remotePassword rotation logs the field name but never the value. A status flip to active (back) reconciles the Jasmin connector on the next tick; inactive is the soft-deleted state. Use it to retune routing priority or rotate the upstream endpoint without dropping the row. Owner / admin only; returns 404 when the id is not a carrier in this tenant.
string
required
—
string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to
true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.any
New human-readable name, 1–64 characters.
any
New SMPP upstream host (hostname / IPv4 / IPv6 literal).
any
New SMPP upstream port, 1–65535.
any
New SMPP system_id, 1–15 characters.
any
New SMPP bind password, 1–8 characters; encrypted at rest.
any
New routing scope:
all or by_country_mcc.any
New
{ mccs: string[] } filter (1–50 three-digit MCCs), or null to clear.any
New route priority, 0–10000 (lower wins).
any
New lifecycle status —
active, suspended or inactive.Update SMPP credential
PATCH /api/v1/messaging/smpp/credentials/{id}description, tpsLimit, allowedCidrs, dlrMode, dlrWebhookUrl and/or status). Nullable fields (description, dlrWebhookUrl) accept null to clear them. A status flip is reconciler-routed: active enables the Jasmin user, suspended disables it, revoked removes it (soft delete). Use it to retune throughput, rotate the CIDR allow-list, move DLR delivery between bind and webhook, or suspend a credential without revoking it. Owner / admin only — an owner/admin dashboard session, or an API key scoped smpp:write; returns 404 when the id is not a credential in this tenant.
string
required
—
string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to
true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.any
New human-readable label (1–200 chars), or null to clear.
any
New inbound throughput cap, 1–1000 messages/second.
any
Replacement CIDR allow-list (up to 16 IPv4/IPv6 CIDR strings).
any
New delivery-receipt mode:
bind, webhook or both.any
HTTPS webhook endpoint for DLRs, or null to clear; required when
dlrMode is webhook or both.any
New lifecycle status —
active, suspended or revoked; reconciler-routed to Jasmin.Delete SMPP carrier
DELETE /api/v1/messaging/smpp/carriers/{id}status='inactive'). The row stays for the audit chain while the reconciler removes the Jasmin smppc connector and the mtrouter rule on its next ~30-second tick, which stops new sends routing through this carrier. Use it to take a carrier out of rotation; re-activate it via PATCH /:id with status='active' if you retired it by mistake. Owner / admin only; returns 404 when the id is not a carrier in this tenant and 204 No Content on success.
string
required
—
string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to
true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.204 No Content
Revoke SMPP credential
DELETE /api/v1/messaging/smpp/credentials/{id}smpp:write; returns 404 when the id is not a credential in this tenant and 204 No Content on success.
string
required
—
string (enum: true|false)
Sandbox opt-in for Clerk-session-authenticated requests. Set to
true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.204 No Content