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/v1Response 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/messagesEach token is scoped to specific resources (messages, contacts, campaigns, etc.). Requests to resources outside the token's scopes return 403 Forbidden.
Token scopes
| Scope | Grants access to |
|---|---|
| messages | Send and list SMS messages |
| contacts | Create, read, update, delete contacts |
| groups | Manage contact groups and memberships |
| campaigns | Create and manage bulk campaigns |
| surveys | Read survey definitions and responses |
| ussd | Read USSD code and extension info |
| reports | Read 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.
| Status | Meaning |
|---|---|
| 200 | OK — request succeeded |
| 400 | Bad request — validation error or missing required field |
| 401 | Unauthenticated — missing or invalid token |
| 402 | Payment required — insufficient SMS unit balance |
| 403 | Forbidden — token lacks the required scope / permission |
| 404 | Not found |
| 409 | Conflict — duplicate or already-exists error |
| 429 | Too many attempts |
| 500 | Internal server error |
Messages
Send individual SMS messages and retrieve message history. Requires themessages scope.
Send a message
toreqRecipient phone number in E.164 format (e.g. +254712345678)
messagereqMessage text. Long messages are automatically split into multiple parts.
sender_idYour 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
pagePage number (default 1)
page_sizeResults per page (default 20, max 100)
phoneFilter by recipient phone number
statusFilter 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
curl https://api.yourdomain.com/api/v1/messages/msg-uuid \
-H "Authorization: Bearer mbs_your_token_here"Resend a message
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
pagePage number (default 1)
page_sizeResults per page (default 20)
searchFilter 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
phonereqPhone number in E.164 format
first_nameFirst name
last_nameLast name
emailEmail address
notesFree-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
Same fields as create. All fields are optional — only provided fields are updated.
Delete a contact
Bulk import contacts
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
curl https://api.yourdomain.com/api/v1/groups \
-H "Authorization: Bearer mbs_your_token_here"Create a group
namereqGroup name (must be unique within your team)
descriptionOptional 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
List all contacts in the group.
Add a contact to the group. Body: { "phone": "+254712345678" }
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
namereqCampaign name (internal reference)
messagereqSMS text to send. Long messages split automatically.
sender_idreqApproved sender ID UUID
group_idsreqArray of contact group UUIDs to target
scheduled_atSchedule 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
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
| Status | Meaning |
|---|---|
| draft | Created but not yet sent |
| sending | Dispatch in progress — messages are being queued |
| completed | All messages have been dispatched to the SMS gateway |
| cancelled | Cancelled before send was triggered |
Surveys
Read survey definitions and responses. SMS surveys are configured in the dashboard. Requires the surveys scope.
List surveys
curl https://api.yourdomain.com/api/v1/surveys \
-H "Authorization: Bearer mbs_your_token_here"Get a survey
Returns the survey definition including all questions and their answer options.
Get survey responses
pagePage number
page_sizeResults per page
phoneFilter 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
curl https://api.yourdomain.com/api/v1/ussd/codes \
-H "Authorization: Bearer mbs_your_token_here"List 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
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
namereqDescriptive name for the token
scopesreqArray of scope strings (messages, contacts, groups, campaigns, surveys, ussd, reports)
expires_atOptional 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"
}
}
}raw_token is shown only once. Store it immediately in a secure location — it cannot be retrieved again.Revoke a token
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
smpp.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 expiredUnicode / 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
| Limit | Value |
|---|---|
| Max concurrent sessions per team | 5 |
| Max submit_sm/s per session | 50 TPS |
| Enquire link interval | 30 s |
| Session idle timeout | 60 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.