Skip to main content

SMS-C API Reference

← Back to Documentation Index | Main README

Complete reference for all SMS-C REST API endpoints with request/response examples.

Table of Contents

API Overview

The SMS-C REST API provides programmatic access to message submission, routing, and management functions.

Base URL

https://api.example.com:8443/api

Default Port: 8443 (configurable) Protocol: HTTPS (TLS required in production)

Content Type

All requests and responses use JSON:

Content-Type: application/json

API Versioning

The current API is version 1 (implicit). Future versions will use URL versioning:

https://api.example.com:8443/api/v2/...

Authentication

Production deployments should use TLS client certificate authentication:

curl --cert client.crt --key client.key \
https://api.example.com:8443/api/status

API Key Authentication

Custom API key authentication via X-API-Key header:

curl -H "X-API-Key: your_api_key_here" \
https://api.example.com:8443/api/status

IP Whitelisting

Restrict API access to trusted IP addresses at the firewall level.

Common Response Formats

Success Response

{
"data": {
...
}
}

Error Response

{
"errors": {
"detail": "Error message describing what went wrong"
}
}

List Response

{
"data": [
{...},
{...}
]
}

Status Endpoint

Health check endpoint for monitoring and load balancers.

Get API Status

Request:

GET /api/status

Response (200 OK):

{
"status": "ok",
"application": "OmniMessage",
"timestamp": "2025-10-30T12:34:56Z"
}

Example:

curl https://api.example.com:8443/api/status

Use Cases:

  • Load balancer health checks
  • Monitoring system connectivity
  • Service availability verification

Message Queue API

Core message submission and management endpoints.

List Messages

Retrieve messages from the queue.

Request:

GET /api/messages

Optional Headers:

  • smsc: frontend_name - Filter by destination SMSC
  • include-unrouted: true|false|1|0 - Include messages without location registration (default: false)
    • false (default): Only return messages with explicit routing or location registration
    • true: Include messages without location registration (backward compatible mode)

Query Parameters (list mode — only when no smsc header is sent):

  • status - Filter by a single status (default: all). One of: queued, backoff, sent, delivered, expired, dropped, auto_replied, balance_rejected, deleted
  • limit - Max records to return (default: 100, max: 1000)
  • offset - Records to skip for pagination (default: 0)

Results are returned newest-first by message id. The endpoint is paginated by default: without limit it returns at most 100 records, never the whole store.

Response (200 OK) — a JSON array of messages:

[
{
"id": 12345,
"source_msisdn": "+15551234567",
"destination_msisdn": "+447700900000",
"message_text": "Hello World",
"source_smsc": "api_client",
"dest_smsc": "uk_gateway",
"status": "queued",
"send_time": "2025-10-30T12:00:00Z",
"deliver_time": null,
"delivery_attempts": 0,
"inserted_at": "2025-10-30T12:00:00Z"
}
]

Examples:

Get pending messages for specific SMSC (only with explicit routing or location):

curl -H "smsc: uk_gateway" \
https://api.example.com:8443/api/messages

Get pending messages including unrouted messages (backward compatible):

curl -H "smsc: uk_gateway" \
-H "include-unrouted: true" \
https://api.example.com:8443/api/messages

Get all delivered messages:

curl "https://api.example.com:8443/api/messages?status=delivered&limit=50"

Get Single Message

Retrieve details for a specific message.

Request:

GET /api/messages/:id

Response (200 OK):

{
"data": {
"id": 12345,
"source_msisdn": "+15551234567",
"destination_msisdn": "+447700900000",
"message_body": "Hello World",
"source_smsc": "api_client",
"dest_smsc": "uk_gateway",
"source_imsi": null,
"dest_imsi": null,
"message_parts": 1,
"message_part_number": 1,
"tp_data_coding_scheme": "00",
"tp_user_data_header": null,
"status": "queued",
"send_time": "2025-10-30T12:00:00Z",
"deliver_time": null,
"expires": "2025-10-31T12:00:00Z",
"deadletter": false,
"delivery_attempts": 0,
"deliver_after": "2025-10-30T12:00:00Z",
"raw_data_flag": false,
"raw_sip_flag": false,
"raw_pdu": null,
"inserted_at": "2025-10-30T12:00:00Z",
"updated_at": "2025-10-30T12:00:00Z"
}
}

Example:

curl https://api.example.com:8443/api/messages/12345

Submit Message (Synchronous)

Submit a message and receive the message ID immediately.

Request:

POST /api/messages
Content-Type: application/json

Body:

{
"source_msisdn": "+15551234567",
"destination_msisdn": "+447700900000",
"message_body": "Hello World",
"source_smsc": "api_client"
}

Optional Fields:

  • dest_smsc - Override routing decision
  • send_time - Schedule for future delivery (ISO 8601)
  • message_parts - Total parts for multi-part message
  • message_part_number - Part number (1-indexed)
  • tp_data_coding_scheme - SMS DCS (default: "00")
  • source_imsi - Source subscriber IMSI
  • dest_imsi - Destination subscriber IMSI

Response (201 Created):

{
"data": {
"id": 12345,
"source_msisdn": "+15551234567",
"destination_msisdn": "+447700900000",
"message_body": "Hello World",
"source_smsc": "api_client",
"dest_smsc": "uk_gateway",
"status": "queued",
"send_time": "2025-10-30T12:00:00Z",
"inserted_at": "2025-10-30T12:00:00Z"
}
}

Example:

curl -X POST https://api.example.com:8443/api/messages \
-H "Content-Type: application/json" \
-d '{
"source_msisdn": "+15551234567",
"destination_msisdn": "+447700900000",
"message_body": "Hello World",
"source_smsc": "api_client"
}'

Performance: ~70 messages/second, 14ms average response time

Use When:

  • Need message ID immediately
  • Processing messages/second
  • Require immediate confirmation

Submit Message (Asynchronous)

Submit a message with high throughput (batch processing).

Request:

POST /api/messages/create_async
Content-Type: application/json

Body: Same as synchronous endpoint

Response (202 Accepted):

{
"data": {
"status": "accepted",
"message": "Message queued for processing"
}
}

Example:

curl -X POST https://api.example.com:8443/api/messages/create_async \
-H "Content-Type: application/json" \
-d '{
"source_msisdn": "+15551234567",
"destination_msisdn": "+447700900000",
"message_body": "Bulk notification message",
"source_smsc": "bulk_api"
}'

Performance: ~4,650 messages/second, 0.22ms average response time

Latency: Message appears in database within 100ms (configurable)

Use When:

  • High-volume bulk messaging ( > 100 msg/sec)
  • Don't need message ID in API response
  • Throughput more important than instant confirmation

Update Message

Partially update message fields.

Request:

PATCH /api/messages/:id
Content-Type: application/json

Body:

{
"dest_smsc": "alternate_gateway",
"deliver_after": "2025-10-30T14:00:00Z"
}

Updatable Fields:

  • dest_smsc - Change destination
  • deliver_after - Delay delivery
  • message_body - Update message text
  • status - Change status

Response (200 OK):

{
"data": {
"id": 12345,
"dest_smsc": "alternate_gateway",
"deliver_after": "2025-10-30T14:00:00Z",
...
}
}

Example:

curl -X PATCH https://api.example.com:8443/api/messages/12345 \
-H "Content-Type: application/json" \
-d '{
"dest_smsc": "backup_gateway"
}'

Mark Message Delivered

Mark a message as successfully delivered.

Request:

POST /api/messages/:id/mark_delivered
Content-Type: application/json

Body:

{
"dest_smsc": "uk_gateway"
}

Response (200 OK):

{
"data": {
"id": 12345,
"status": "delivered",
"deliver_time": "2025-10-30T12:05:30Z",
"dest_smsc": "uk_gateway",
...
}
}

Example:

curl -X POST https://api.example.com:8443/api/messages/12345/mark_delivered \
-H "Content-Type: application/json" \
-d '{
"dest_smsc": "uk_gateway"
}'

Use Case: Called by frontend systems after successful delivery

Increment Delivery Attempt

Record a failed delivery: increments the attempt counter, moves the message to backoff, and schedules the next retry.

Request:

PUT /api/messages/:id

Response (200 OK) — the updated message:

{
"id": 12345,
"status": "backoff",
"delivery_attempts": 2,
"deliver_after": "2025-10-30T12:08:00Z"
}

Backoff: exponential, capped at 30 minutes, and never scheduled past the message's expires:

deliver_after = min(now + min(2^attempts, 30) minutes, expires)

The message stays in backoff until deliver_after passes, then becomes eligible again. It keeps retrying every ≤30 minutes until expires is reached, after which it is no longer served (failed deliveries are not dead-lettered).

Example:

curl -X PUT https://api.example.com:8443/api/messages/12345

Use Case: Called by frontend after delivery failure to schedule retry

Delete Message

Remove message from queue.

Request:

DELETE /api/messages/:id

Response (204 No Content)

Example:

curl -X DELETE https://api.example.com:8443/api/messages/12345

Warning: Deleting messages removes them permanently. Use with caution.

Raw SMS PDU API

Submit SMS messages as raw PDU (Protocol Data Unit) for maximum compatibility with legacy systems.

Submit Raw SMS (Synchronous)

Request:

POST /api/messages_raw
Content-Type: application/json

Body:

{
"pdu": "0001000B916407007009F0000004D4F29C0E",
"source_smsc": "legacy_system"
}

PDU Format: Hex-encoded SMS TPDU (Transport Protocol Data Unit)

Response (201 Created):

{
"data": {
"id": 12346,
"source_msisdn": "+447700900000",
"destination_msisdn": "+447700900000",
"message_body": "Test",
"source_smsc": "legacy_system",
"raw_pdu": "0001000B916407007009F0000004D4F29C0E",
...
}
}

Example:

curl -X POST https://api.example.com:8443/api/messages_raw \
-H "Content-Type: application/json" \
-d '{
"pdu": "0001000B916407007009F0000004D4F29C0E",
"source_smsc": "legacy_system"
}'

Submit Raw SMS (Asynchronous)

Request:

POST /api/messages_raw/async
Content-Type: application/json

Body: Same as synchronous

Response (202 Accepted):

{
"data": {
"status": "accepted",
"message": "PDU queued for processing"
}
}

Example:

curl -X POST https://api.example.com:8443/api/messages_raw/async \
-H "Content-Type: application/json" \
-d '{
"pdu": "0001000B916407007009F0000004D4F29C0E",
"source_smsc": "legacy_gateway"
}'

PDU Handling

The system automatically:

  1. Decodes PDU using SMS standards (3GPP TS 23.040)
  2. Extracts phone numbers, message text, DCS
  3. Detects delivery reports (CP-ACK, RP-ACK, etc.)
  4. Performs IMSI to MSISDN lookup if needed
  5. Applies routing rules
  6. Stores original PDU for reference

Delivery Report Detection:

  • CP-ACK, CP-ERROR - Connection Protocol acknowledgments
  • RP-ACK, RP-ERROR, RP-SMMA - Relay Protocol responses
  • Delivery reports are logged but not stored as messages

Location Management API

Manage subscriber location information for mobile-terminated message delivery.

List Locations

Request:

GET /api/locations

Response (200 OK):

{
"data": [
{
"id": 1,
"msisdn": "+15551234567",
"imsi": "001001000000001",
"location": "msc1.region1.example.com",
"ran_location": "cell_tower_12345",
"imei": "123456789012345",
"ims_capable": true,
"csfb": false,
"registered": true,
"expires": "2025-10-30T13:00:00Z",
"user_agent": "Samsung Galaxy",
"inserted_at": "2025-10-30T12:00:00Z",
"updated_at": "2025-10-30T12:00:00Z"
}
]
}

Example:

curl https://api.example.com:8443/api/locations

Get Location

Request:

GET /api/locations/:id

Response (200 OK):

{
"data": {
"id": 1,
"msisdn": "+15551234567",
"imsi": "001001000000001",
...
}
}

Example:

curl https://api.example.com:8443/api/locations/1

Create/Update Location

Creates new location or updates existing based on IMSI (unique identifier).

Request:

POST /api/locations
Content-Type: application/json

Body:

{
"msisdn": "+15551234567",
"imsi": "001001000000001",
"location": "msc1.region1.example.com",
"ran_location": "cell_tower_12345",
"imei": "123456789012345",
"ims_capable": true,
"csfb": false,
"registered": true,
"expires": "2025-10-30T13:00:00Z",
"user_agent": "Samsung Galaxy"
}

Required Fields:

  • imsi - Unique subscriber identifier
  • msisdn - Phone number

Optional Fields:

  • location - MSC/VLR address
  • ran_location - Cell tower/sector ID
  • imei - Device identifier
  • ims_capable - IMS VoLTE capability
  • csfb - Circuit-switched fallback flag
  • registered - Currently registered
  • expires - Registration expiry
  • user_agent - Device model/info

Response (201 Created or 200 OK):

{
"data": {
"id": 1,
"msisdn": "+15551234567",
...
}
}

Example:

curl -X POST https://api.example.com:8443/api/locations \
-H "Content-Type: application/json" \
-d '{
"msisdn": "+15551234567",
"imsi": "001001000000001",
"location": "msc1.region1.example.com",
"ims_capable": true,
"registered": true
}'

Use Case: Called by mobility management systems (HSS, MME, etc.) when subscriber registers

Update Location

Request:

PATCH /api/locations/:id
Content-Type: application/json

Body: Partial update with any location fields

Response (200 OK):

{
"data": {
"id": 1,
...
}
}

Example:

curl -X PATCH https://api.example.com:8443/api/locations/1 \
-H "Content-Type: application/json" \
-d '{
"location": "msc2.region2.example.com",
"ran_location": "cell_tower_67890"
}'

Delete Location

Request:

DELETE /api/locations/:id

Response (204 No Content)

Example:

curl -X DELETE https://api.example.com:8443/api/locations/1

Use Case: Called when subscriber de-registers or times out

Frontend Registration API

Track and manage frontend SMSC connections.

List All Frontends

Request:

GET /api/frontends

Response (200 OK):

{
"data": [
{
"id": 1,
"frontend_name": "uk_gateway_1",
"frontend_type": "smpp",
"ip_address": "10.0.1.50",
"hostname": "gateway1.uk.example.com",
"uptime_seconds": 86400,
"configuration": {
"max_throughput": 1000,
"bind_type": "transceiver"
},
"status": "active",
"expires_at": "2025-10-30T12:02:00Z",
"last_seen_at": "2025-10-30T12:00:30Z",
"inserted_at": "2025-10-29T12:00:00Z",
"updated_at": "2025-10-30T12:00:30Z"
}
]
}

Example:

curl https://api.example.com:8443/api/frontends

List Active Frontends Only

Request:

GET /api/frontends/active

Response (200 OK): Same format, only active frontends

Example:

curl https://api.example.com:8443/api/frontends/active

Use Case: Get list of available destinations for routing

Get Frontend Statistics

Request:

GET /api/frontends/stats

Response (200 OK):

{
"data": {
"active_count": 5,
"expired_count": 2,
"unique_frontends": 7,
"total_registrations": 1523
}
}

Example:

curl https://api.example.com:8443/api/frontends/stats

Get Frontend History

Request:

GET /api/frontends/history/:name

Response (200 OK):

{
"data": [
{
"id": 1,
"frontend_name": "uk_gateway_1",
"status": "active",
"inserted_at": "2025-10-30T12:00:00Z",
...
},
{
"id": 2,
"frontend_name": "uk_gateway_1",
"status": "expired",
"inserted_at": "2025-10-29T12:00:00Z",
...
}
]
}

Example:

curl https://api.example.com:8443/api/frontends/history/uk_gateway_1

Register Frontend

Register or update frontend connection.

Request:

POST /api/frontends/register
Content-Type: application/json

Body:

{
"frontend_name": "uk_gateway_1",
"frontend_type": "smpp",
"ip_address": "10.0.1.50",
"hostname": "gateway1.uk.example.com",
"uptime_seconds": 86400,
"configuration": {
"max_throughput": 1000,
"bind_type": "transceiver",
"system_id": "gateway1"
}
}

Required Fields:

  • frontend_name - Unique identifier for frontend
  • frontend_type - Type: smpp, sip, http, etc.

Optional Fields:

  • ip_address - Frontend IP
  • hostname - Frontend hostname
  • uptime_seconds - Uptime since start
  • configuration - Custom config object

Response (201 Created):

{
"data": {
"id": 1,
"frontend_name": "uk_gateway_1",
"status": "active",
"expires_at": "2025-10-30T12:01:30Z",
...
}
}

Example:

curl -X POST https://api.example.com:8443/api/frontends/register \
-H "Content-Type: application/json" \
-d '{
"frontend_name": "uk_gateway_1",
"frontend_type": "smpp",
"ip_address": "10.0.1.50",
"hostname": "gateway1.uk.example.com"
}'

Registration Timeout: 90 seconds (frontends must re-register every 60-90 seconds)

Use Case: Called periodically by frontend systems to maintain active status

Campaigns API

Bulk messaging: upload a named recipient list, then run a rate-limited campaign against it. See the Bulk Messaging / Campaigns guide for concepts (audience filter, drip rate, lifecycle, statistics).

Recipient Lists

Create a List

Request:

POST /api/campaign_lists
Content-Type: application/json

Each recipient may carry up to four template variables (var1..var4).

Body — supply recipients as a JSON array, a raw CSV string, or both. JSON recipients may be plain MSISDN strings or objects with var1..var4:

{
"name": "VIP customers",
"description": "High value subscribers",
"recipients": [
{ "msisdn": "12025550101", "var1": "Alice", "var2": "Gold" },
"12025550102"
]
}

For CSV, a header row naming an msisdn / destination_msisdn / number / phone column selects the MSISDN column (otherwise the first column is used); the remaining columns become var1..var4 in column order:

{ "name": "Imported", "csv": "msisdn,first,plan\n12025550101,Alice,Gold\n12025550102,Bob,Silver\n" }

Response (201 Created):

{ "id": 1, "name": "VIP customers", "recipient_count": 2 }

List / Get / Append / Delete Lists

GET    /api/campaign_lists           # all lists
GET /api/campaign_lists/:id # one list, includes "recipients": [{msisdn, variables}, ...]
PATCH /api/campaign_lists/:id # append recipients ({"recipients": [...]} and/or {"csv": "..."})
DELETE /api/campaign_lists/:id # delete the list and its recipients

Campaigns

Create a Campaign

Request:

POST /api/campaigns
Content-Type: application/json

Body:

{
"name": "Maintenance notice",
"message": "Planned maintenance tonight 02:00-03:00.",
"source_msisdn": "12345",
"source_smsc": "IMS_SMSC",
"list_id": 1,
"audience": "active_only",
"drip_tps": 50
}

Fields:

  • name, message, source_msisdn, source_smscrequired
  • list_id — recipient list. Omit to target ALL currently active (registered) subscribers.
  • audienceactive_only (default) or all. Ignored when list_id is omitted.
  • drip_tps — messages submitted into the queue per second (default from config).
  • validity_hours — message validity period in hours; sets each message's expires (default from config).
  • deliver_after — optional ISO8601 time to hold messages until before delivery (scheduled send).

Response (201 Created): the campaign in draft status, including a live stats block.

Control a Campaign (start / pause / resume / cancel)

Request:

POST /api/campaigns/control
Content-Type: application/json

Body:

{ "campaign_id": 7, "action": "start" }

action is one of start, pause, resume, cancel. Returns the updated campaign (200), 404 if not found, or 422 if the action is invalid for the current state.

List / Get Campaigns

GET /api/campaigns       # all campaigns (newest first)
GET /api/campaigns/:id # one campaign, including live stats

Response (GET /api/campaigns/:id):

{
"id": 7,
"name": "Maintenance notice",
"list_id": 1,
"audience": "active_only",
"status": "running",
"drip_tps": 50,
"total_targets": 1000,
"stats": {
"total": 1000, "pending": 600, "queued": 300,
"delivered": 90, "failed": 10, "skipped_inactive": 0,
"dispatched": 400, "progress_percent": 40, "delivery_percent": 22
}
}

Delete (Stop) a Campaign

DELETE /api/campaigns/:id

Deleting stops the campaign (cancels delivery) but keeps the record so its history and statistics remain visible; it returns the cancelled campaign (200). The record is purged automatically once it ages past the retention TTL.

Per-Recipient Results

GET /api/campaign_targets/:id              # :id is the campaign ID
GET /api/campaign_targets/:id?state=failed # filter by target state

Returns one entry per recipient with its state (pending / queued / delivered / failed / skipped_inactive), the submitted message_ids, and part counters.

Event Logging API

Track message lifecycle events.

Get Message Events

Request:

GET /api/events/:message_id

Response (200 OK):

{
"data": [
{
"event_epoch": 1698672000,
"name": "message_inserted",
"description": "Message inserted into queue",
"event_source": "node1@server.example.com"
},
{
"event_epoch": 1698672001,
"name": "message_routed",
"description": "Routed to uk_gateway via route_id=42",
"event_source": "node1@server.example.com"
},
{
"event_epoch": 1698672005,
"name": "message_delivered",
"description": "Successfully delivered",
"event_source": "node2@server.example.com"
}
]
}

Example:

curl https://api.example.com:8443/api/events/12345

Event Types:

  • message_inserted - Message created
  • message_routed - Routing decision made
  • message_delivered - Successful delivery
  • message_failed - Delivery failed
  • message_dropped - Dropped by route
  • auto_reply_sent - Auto-reply triggered
  • number_translated - Number transformation applied
  • routing_failed - No route found
  • charging_failed - Charging error

Record Event

Request:

POST /api/events
Content-Type: application/json

Body:

{
"message_id": 12345,
"name": "custom_event",
"description": "Custom event description",
"event_source": "external_system"
}

Response (201 Created):

{
"data": {
"message_id": 12345,
"name": "custom_event",
"description": "Custom event description",
"event_source": "external_system",
"event_epoch": 1698672010
}
}

Example:

curl -X POST https://api.example.com:8443/api/events \
-H "Content-Type: application/json" \
-d '{
"message_id": 12345,
"name": "external_delivery_confirmed",
"description": "Confirmed by downstream system"
}'

Event Retention: 7 days (configurable)

MMS Message API

Manage Multimedia Messaging Service (MMS) messages.

List MMS Messages

Request:

GET /api/mms_messages

Response (200 OK): Similar to SMS messages with additional MMS fields

Create MMS Message

Request:

POST /api/mms_messages
Content-Type: application/json

Body:

{
"source_msisdn": "+15551234567",
"destination_msisdn": "+447700900000",
"subject": "Photo",
"content_type": "image/jpeg",
"content_location": "https://cdn.example.com/media/12345.jpg",
"message_size": 524288
}

Response (201 Created): Full MMS message object

SS7 Event API

Track SS7 signaling events.

List SS7 Events

Request:

GET /api/ss7_events

Response (200 OK):

{
"data": [
{
"id": 1,
"event_type": "MAP_UPDATE_LOCATION",
"imsi": "001001000000001",
"msisdn": "+15551234567",
"timestamp": "2025-10-30T12:00:00Z",
...
}
]
}

Create SS7 Event

Request:

POST /api/ss7_events
Content-Type: application/json

Body:

{
"event_type": "MAP_UPDATE_LOCATION",
"imsi": "001001000000001",
"msisdn": "+15551234567"
}

Response (201 Created): Full event object

Error Codes

HTTP Status Codes

CodeMeaningDescription
200OKRequest successful
201CreatedResource created successfully
202AcceptedRequest accepted for processing
204No ContentSuccessful deletion
400Bad RequestInvalid request format
401UnauthorizedAuthentication required
403ForbiddenInsufficient permissions
404Not FoundResource doesn't exist
422Unprocessable EntityValidation errors
429Too Many RequestsRate limit exceeded
500Internal Server ErrorServer error
503Service UnavailableTemporarily unavailable

Error Response Format

{
"errors": {
"detail": "Validation failed: destination_msisdn is required"
}
}

Common Error Messages

ErrorCauseSolution
"destination_msisdn is required"Missing required fieldInclude destination_msisdn in request
"Invalid phone number format"Malformed numberUse E.164 format: +15551234567
"Message too long"Exceeds size limitSplit into multiple parts
"No route found"Routing failedCheck routing configuration
"Charging failed"OCS errorVerify charging system connectivity
"Message not found"Invalid message IDVerify ID exists
"Frontend not registered"Unknown SMSCRegister frontend first

Rate Limiting

Default Limits

EndpointLimitWindow
POST /api/messages100 req/secPer IP
POST /api/messages/create_async1000 req/secPer IP
POST /api/messages_raw100 req/secPer IP
GET /api/*1000 req/secPer IP

Rate Limit Headers

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1698672060

Rate Limit Exceeded

Response (429 Too Many Requests):

{
"errors": {
"detail": "Rate limit exceeded. Retry after 5 seconds."
}
}

Best Practices

Message Submission

  1. Use Async for Bulk: Use /create_async for > 100 msg/sec
  2. Include source_smsc: Always identify your system
  3. Validate Numbers: Use E.164 format (+country code)
  4. Handle Errors: Implement retry logic for 5xx errors
  5. Check Routing: Test routes before bulk submission

Frontend Integration

  1. Register Regularly: Re-register every 60 seconds
  2. Poll for Messages: Query with smsc header for your messages
  3. Use include-unrouted Wisely: By default, only messages with explicit routing or location registration are returned. Set include-unrouted: true only if you need backward compatible behavior to receive all unrouted messages
  4. Mark Delivered: Always call mark_delivered after success
  5. Increment on Failure: Use PUT endpoint for retry logic
  6. Monitor Events: Check event log for delivery issues

Performance

  1. Connection Pooling: Reuse HTTP connections
  2. Batch Requests: Group multiple messages per request
  3. Parallel Processing: Make concurrent API calls
  4. Monitor Metrics: Watch Prometheus for bottlenecks
  5. Set Timeouts: Use 30-second timeout for API calls

Security

  1. Use TLS: Always use HTTPS in production
  2. Validate Certificates: Don't skip certificate validation
  3. Rotate API Keys: Change keys regularly
  4. IP Whitelist: Restrict to known sources
  5. Log API Activity: Monitor for suspicious patterns

Error Handling

  1. Retry 5xx Errors: Server errors are usually temporary
  2. Don't Retry 4xx: Client errors need code fixes
  3. Exponential Backoff: Wait longer between retries
  4. Circuit Breaker: Stop after repeated failures
  5. Alert on Patterns: Monitor error rates

Example Integration (Python)

import requests
import time

class SMSCClient:
def __init__(self, base_url, api_key=None):
self.base_url = base_url
self.session = requests.Session()
if api_key:
self.session.headers.update({"X-API-Key": api_key})

def submit_message(self, from_num, to_num, text, async_mode=False):
endpoint = "/messages/create_async" if async_mode else "/messages"
url = f"{self.base_url}{endpoint}"

payload = {
"source_msisdn": from_num,
"destination_msisdn": to_num,
"message_body": text,
"source_smsc": "python_client"
}

try:
response = self.session.post(url, json=payload, timeout=30)
response.raise_for_status()
return response.json()["data"]
except requests.exceptions.RequestException as e:
print(f"API Error: {e}")
return None

def get_pending_messages(self, smsc_name, include_unrouted=False):
url = f"{self.base_url}/messages"
headers = {"smsc": smsc_name}

# Include unrouted messages if requested (backward compatible mode)
if include_unrouted:
headers["include-unrouted"] = "true"

try:
response = self.session.get(url, headers=headers, timeout=30)
response.raise_for_status()
return response.json()["data"]
except requests.exceptions.RequestException as e:
print(f"API Error: {e}")
return []

def mark_delivered(self, message_id, smsc_name):
url = f"{self.base_url}/messages/{message_id}/mark_delivered"
payload = {"dest_smsc": smsc_name}

try:
response = self.session.post(url, json=payload, timeout=30)
response.raise_for_status()
return True
except requests.exceptions.RequestException as e:
print(f"API Error: {e}")
return False

# Usage
client = SMSCClient("https://api.example.com:8443/api", api_key="your_key")

# Submit single message
result = client.submit_message("+15551234567", "+447700900000", "Hello")
print(f"Message ID: {result['id']}")

# Submit bulk messages (async)
for i in range(1000):
client.submit_message("+15551234567", f"+44770090{i:04d}", f"Bulk {i}", async_mode=True)

# Frontend polling loop
while True:
# Get messages with explicit routing or location registration
messages = client.get_pending_messages("my_gateway")

# Or use include_unrouted=True for backward compatible behavior
# messages = client.get_pending_messages("my_gateway", include_unrouted=True)

for msg in messages:
# Deliver message via your protocol
success = deliver_via_smpp(msg)

if success:
client.mark_delivered(msg["id"], "my_gateway")
else:
# Increment for retry
requests.put(f"{client.base_url}/messages/{msg['id']}")

time.sleep(5) # Poll every 5 seconds

API Changelog

Version 1 (Current)

  • Initial release
  • Message queue CRUD
  • Raw PDU submission
  • Location management
  • Frontend registration
  • Event logging

Planned Features

  • Batch message submission (single request, multiple messages)
  • Message templates
  • Scheduled delivery API
  • Real-time webhooks for events
  • GraphQL API endpoint
  • OAuth2 authentication

For questions or issues with the API, check the Troubleshooting Guide or contact support.