REST API v1

API Reference

The Mobile Sasa REST API lets you send SMS, manage contacts, run campaigns, and build complete integrations. Use your API token as a Bearer token on every request.

JSON responses Bearer token auth SMPP support Granular scopes

Overview

All API endpoints are served over HTTPS. Requests and responses use JSON. The base URL for all endpoints is:

https://api.yourdomain.com/api/v1

Response envelope

Every response is wrapped in a consistent envelope. Check success before reading data.

// Success
{ "success": true, "data": { ... } }

// Error
{ "success": false, "error": "human-readable message" }

Rate limiting

API requests are not rate-limited at the HTTP layer, but SMS sends consume your team's SMS unit balance. Campaigns run asynchronously via a worker queue.

Authentication

The API supports two authentication methods. API tokens are the recommended approach for integrations and scripts. JWTs are issued at login and are intended for the dashboard UI.

API Token (recommended)

Generate tokens from Dashboard → API Tokens. Tokens start withmbs_. Pass the token as a Bearer token or as the X-API-Key header.

# Bearer token
curl -H "Authorization: Bearer mbs_your_token_here" \
     https://api.yourdomain.com/api/v1/messages

# X-API-Key header (alternative)
curl -H "X-API-Key: mbs_your_token_here" \
     https://api.yourdomain.com/api/v1/messages

Each token is scoped to specific resources (messages, contacts, campaigns, etc.). Requests to resources outside the token's scopes return 403 Forbidden.

Token scopes

ScopeGrants access to
messagesSend and list SMS messages
contactsCreate, read, update, delete contacts
groupsManage contact groups and memberships
campaignsCreate and manage bulk campaigns
surveysRead survey definitions and responses
ussdRead USSD code and extension info
reportsRead usage reports and statistics

Errors & Status Codes

HTTP status codes signal the class of error. The error field in the response body contains a human-readable description.

StatusMeaning
200OK — request succeeded
400Bad request — validation error or missing required field
401Unauthenticated — missing or invalid token
402Payment required — insufficient SMS unit balance
403Forbidden — token lacks the required scope / permission
404Not found
409Conflict — duplicate or already-exists error
429Too many attempts
500Internal server error

Messages

Send individual SMS messages and retrieve message history. Requires themessages scope.

Send a message

POST/messages
Request body
toreq
string

Recipient phone number in E.164 format (e.g. +254712345678)

messagereq
string

Message text. Long messages are automatically split into multiple parts.

sender_id
string

Your approved sender name (e.g. MYAPP) or sender UUID. Omit to use the team default.

curl -X POST https://api.yourdomain.com/api/v1/messages \
  -H "Authorization: Bearer mbs_your_token_here" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+254712345678",
    "message": "Hello from Mobile Sasa!",
    "sender_id": "MYAPP"
  }'
{
  "success": true,
  "data": {
    "uuid": "msg-uuid",
    "to": "+254712345678",
    "message": "Hello from Mobile Sasa!",
    "sender_id": "TextBlast",
    "status": "queued",
    "parts": 1,
    "created_at": "2026-05-11T09:00:00Z"
  }
}

List messages

GET/messages
Query params
page
integer

Page number (default 1)

page_size
integer

Results per page (default 20, max 100)

phone
string

Filter by recipient phone number

status
string

Filter by status: queued, sent, delivered, failed

curl "https://api.yourdomain.com/api/v1/messages?page=1&page_size=20" \
  -H "Authorization: Bearer mbs_your_token_here"

Get a message

GET/messages/{uuid}
curl https://api.yourdomain.com/api/v1/messages/msg-uuid \
  -H "Authorization: Bearer mbs_your_token_here"

Resend a message

POST/messages/{uuid}/resend

Retries a failed message. Returns the new message object.

curl -X POST https://api.yourdomain.com/api/v1/messages/msg-uuid/resend \
  -H "Authorization: Bearer mbs_your_token_here"

Contacts

Store and manage your contact list. Add contacts individually or bulk-import from CSV or XLSX. Requires thecontacts scope.

List contacts

GET/contacts
Query params
page
integer

Page number (default 1)

page_size
integer

Results per page (default 20)

search
string

Filter by name or phone

curl "https://api.yourdomain.com/api/v1/contacts?search=John&page_size=50" \
  -H "Authorization: Bearer mbs_your_token_here"

Create a contact

POST/contacts
Request body
phonereq
string

Phone number in E.164 format

first_name
string

First name

last_name
string

Last name

email
string

Email address

notes
string

Free-text notes about the contact

curl -X POST https://api.yourdomain.com/api/v1/contacts \
  -H "Authorization: Bearer mbs_your_token_here" \
  -H "Content-Type: application/json" \
  -d '{
    "phone": "+254712345678",
    "first_name": "Jane",
    "last_name": "Doe",
    "email": "[email protected]"
  }'

Update a contact

PUT/contacts/{uuid}

Same fields as create. All fields are optional — only provided fields are updated.

Delete a contact

DELETE/contacts/{uuid}

Bulk import contacts

POST/contacts/import

Upload a CSV or XLSX file. The file must have a phone column. Optional columns: first_name,last_name,email. Returns an upload UUID for polling status.

curl -X POST https://api.yourdomain.com/api/v1/contacts/import \
  -H "Authorization: Bearer mbs_your_token_here" \
  -F "[email protected]"

# Poll import status
curl https://api.yourdomain.com/api/v1/contacts/uploads/{upload_uuid} \
  -H "Authorization: Bearer mbs_your_token_here"

Groups

Organise contacts into groups. Groups are the target for campaigns. Requires the groups scope.

List groups

GET/groups
curl https://api.yourdomain.com/api/v1/groups \
  -H "Authorization: Bearer mbs_your_token_here"

Create a group

POST/groups
Request body
namereq
string

Group name (must be unique within your team)

description
string

Optional description

curl -X POST https://api.yourdomain.com/api/v1/groups \
  -H "Authorization: Bearer mbs_your_token_here" \
  -H "Content-Type: application/json" \
  -d '{ "name": "VIP Customers", "description": "High-value customer segment" }'

Manage group contacts

GET/groups/{uuid}/contacts

List all contacts in the group.

POST/groups/{uuid}/contacts

Add a contact to the group. Body: { "phone": "+254712345678" }

DELETE/groups/{uuid}/contacts/{phone}

Remove a contact from the group by phone number.

# Add contact to group
curl -X POST https://api.yourdomain.com/api/v1/groups/group-uuid/contacts \
  -H "Authorization: Bearer mbs_your_token_here" \
  -H "Content-Type: application/json" \
  -d '{ "phone": "+254712345678" }'

# Remove contact from group
curl -X DELETE "https://api.yourdomain.com/api/v1/groups/group-uuid/contacts/%2B254712345678" \
  -H "Authorization: Bearer mbs_your_token_here"

Campaigns

Send bulk SMS to one or more contact groups. Campaigns run asynchronously — create the campaign, then trigger send. Requires thecampaigns scope.

Create a campaign

POST/campaigns
Request body
namereq
string

Campaign name (internal reference)

messagereq
string

SMS text to send. Long messages split automatically.

sender_idreq
string

Approved sender ID UUID

group_idsreq
string[]

Array of contact group UUIDs to target

scheduled_at
ISO 8601

Schedule for future send. Omit to send immediately after calling /send.

curl -X POST https://api.yourdomain.com/api/v1/campaigns \
  -H "Authorization: Bearer mbs_your_token_here" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "May Promo",
    "message": "Get 20% off all orders this weekend! Use code: MAY20",
    "sender_id": "sender-uuid",
    "group_ids": ["group-uuid-1", "group-uuid-2"]
  }'
{
  "success": true,
  "data": {
    "uuid": "campaign-uuid",
    "name": "May Promo",
    "status": "draft",
    "recipient_count": 2847,
    "cost_units": 2847,
    "created_at": "2026-05-11T09:00:00Z"
  }
}

Send a campaign

POST/campaigns/{uuid}/send

Triggers dispatch. The campaign status moves to sending and thencompleted once all messages are queued. SMS units are reserved at this point.

curl -X POST https://api.yourdomain.com/api/v1/campaigns/campaign-uuid/send \
  -H "Authorization: Bearer mbs_your_token_here"

Campaign statuses

StatusMeaning
draftCreated but not yet sent
sendingDispatch in progress — messages are being queued
completedAll messages have been dispatched to the SMS gateway
cancelledCancelled before send was triggered

Surveys

Read survey definitions and responses. SMS surveys are configured in the dashboard. Requires the surveys scope.

List surveys

GET/surveys
curl https://api.yourdomain.com/api/v1/surveys \
  -H "Authorization: Bearer mbs_your_token_here"

Get a survey

GET/surveys/{uuid}

Returns the survey definition including all questions and their answer options.

Get survey responses

GET/surveys/{uuid}/responses
Query params
page
integer

Page number

page_size
integer

Results per page

phone
string

Filter responses by respondent phone

USSD

Read your team's approved USSD codes and extensions. USSD menus and sessions are managed in the dashboard. Requires theussd scope.

List USSD codes

GET/ussd/codes
curl https://api.yourdomain.com/api/v1/ussd/codes \
  -H "Authorization: Bearer mbs_your_token_here"

List extensions

GET/ussd/extensions

Returns extensions assigned to your team across all USSD codes.

API Tokens

Programmatically manage API tokens. Useful for token rotation workflows. Requires an existing token with theapi_tokens scope (or a JWT session).

List tokens

GET/tokens

Returns all tokens for your team, including revoked and expired ones.

curl https://api.yourdomain.com/api/v1/tokens \
  -H "Authorization: Bearer mbs_your_token_here"

Create a token

POST/tokens
Request body
namereq
string

Descriptive name for the token

scopesreq
string[]

Array of scope strings (messages, contacts, groups, campaigns, surveys, ussd, reports)

expires_at
ISO 8601

Optional expiry date. Omit for a non-expiring token.

curl -X POST https://api.yourdomain.com/api/v1/tokens \
  -H "Authorization: Bearer mbs_your_token_here" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Zapier Integration",
    "scopes": ["messages", "contacts"],
    "expires_at": "2027-01-01T00:00:00Z"
  }'
{
  "success": true,
  "data": {
    "raw_token": "mbs_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "token": {
      "uuid": "token-uuid",
      "name": "Zapier Integration",
      "scopes": ["messages", "contacts"],
      "expires_at": "2027-01-01T00:00:00Z",
      "created_at": "2026-05-11T09:00:00Z"
    }
  }
}
Important: The raw_token is shown only once. Store it immediately in a secure location — it cannot be retrieved again.

Revoke a token

DELETE/tokens/{uuid}

Immediately invalidates the token. Any in-flight requests using it will receive 401.

curl -X DELETE https://api.yourdomain.com/api/v1/tokens/token-uuid \
  -H "Authorization: Bearer mbs_your_token_here"

SMPP Guide

Mobile Sasa exposes an SMPP v3.4 endpoint for high-throughput integrations. SMPP is ideal for real-time OTP delivery, USSD responses, and systems that need guaranteed latency below 500 ms.

Connection parameters

Hostsmpp.yourdomain.comPort2775 (SMPP)  /  2776 (SMPP over TLS)System IDYour team code (e.g. ACME2024)PasswordYour API token (mbs_...)System typeTRANSCEIVERInterface version0x34 (SMPP 3.4)

Binding

Use bind_transceiver to send and receive in a single session. The server supports both TRX and separate TX/RX binds.

bind_transceiver:
  system_id:      ACME2024
  password:       mbs_your_token_here
  system_type:    (leave empty)
  interface_ver:  0x34
  addr_ton:       0x01  (International)
  addr_npi:       0x01  (ISDN/E.164)
  address_range:  (leave empty)

Sending messages

Use submit_sm. The server returns amessage_id in the response — keep it for DLR correlation.

submit_sm:
  service_type:      (empty)
  source_addr_ton:   0x05  (Alphanumeric)
  source_addr_npi:   0x00
  source_addr:       TextBlast         # your approved sender ID
  dest_addr_ton:     0x01  (International)
  dest_addr_npi:     0x01  (ISDN)
  destination_addr:  254712345678      # no leading +
  esm_class:         0x00
  data_coding:       0x00  (GSM7)  or  0x08  (UCS-2 / Unicode)
  registered_delivery: 0x01            # request delivery receipt
  short_message:     Hello from Mobile Sasa!

Delivery receipts

Set registered_delivery = 0x01 to receive adeliver_sm DLR. Theshort_message body contains the delivery status string.

deliver_sm (DLR):
  short_message: id:MSG123 sub:001 dlvrd:001 submit date:2605110900 done date:2605110900 stat:DELIVRD err:000

# stat values:
#   DELIVRD — delivered to handset
#   UNDELIV — undeliverable (number does not exist or unreachable)
#   REJECTD — rejected by carrier
#   EXPIRED — message TTL expired

Unicode / long messages

For messages with non-GSM7 characters set data_coding = 0x08. Long messages (over 160 GSM7 or 70 UCS-2 characters) must be split into concatenated PDUs using UDH.

# Long message split example (3 parts)
submit_sm[1]:
  esm_class: 0x40  (UDH present)
  sar_msg_ref_num: 42   (same for all parts)
  sar_total_segments: 3
  sar_segment_seqnum: 1
  data_coding: 0x00
  short_message: <part 1 text, max 153 chars>

submit_sm[2]:
  sar_segment_seqnum: 2
  ...

Session limits

LimitValue
Max concurrent sessions per team5
Max submit_sm/s per session50 TPS
Enquire link interval30 s
Session idle timeout60 s
Max message TTL (validity period)24 h

Ready to integrate?

Generate your first API token from the dashboard. You can create tokens with granular scopes so each integration only has the access it needs.