Send a message

One message to one recipient. The workhorse for OTPs, alerts and confirmations.

POSThttps://api.mobilesasa.com/v1/send/message

Parameters

FieldTypeRequiredDescription
senderIDstringYesAn approved sender ID on your account (case-sensitive).
phonestringYesThe recipient. 07…, 2547… and +2547… formats all accepted.
messagestringYesThe text. Long messages are split into parts automatically (billed per part).
# Paste your token once (it starts with mbs_):
export MOBILESASA_TOKEN="mbs_your_token_here"

curl -X POST https://api.mobilesasa.com/v1/send/message \
  -H "Authorization: Bearer $MOBILESASA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "senderID": "MOBILESASA",
    "phone": "0712345678",
    "message": "Your verification code is 482913. Valid for 10 minutes."
  }'

Response

200: Accepted
{
  "status": true,
  "responseCode": "0200",
  "message": "Accepted",
  "messageId": "3c51beb1-a674-41d0-9e45-f5581418fb56"
}

Keep messageId. It is the only handle you have on the send. Pass it to delivery reports to find out what actually happened to the message.

Validation failure
{
  "status": false,
  "responseCode": "0422",
  "message": "The phone is not a valid phone number."
}

Sending the fields as a form

JSON is what these examples use, but the endpoint takes form-encoded and multipart bodies too — which is how most of the older SDKs post it. The field names are the same, and the token can travel in the form alongside them instead of in a header:

bash
# Paste your token once (it starts with mbs_):
export MOBILESASA_TOKEN="mbs_your_token_here"

curl -X POST "https://api.mobilesasa.com/v1/send/message" \
  -d "api_token=$MOBILESASA_TOKEN" \
  -d "senderID=MOBILESASA" \
  -d "phone=0712345678" \
  -d "message=Your verification code is 482913."

Escape quotes in JSON

If you build the JSON body by hand, a double quote inside the message must be escaped as \". An unescaped one makes the whole body unparseable and the send is rejected with 0422 — send the fields as a form if escaping is awkward.

GET variant, for ERPs and legacy systems

GEThttps://api.mobilesasa.com/v1/send/messageget

Many ERPs, accounting packages and older systems can only fire a plain URL, no request body, sometimes not even a header. This endpoint accepts the exact same fields as the POST, but as query-string parameters, with the token passed as api_token:

The whole integration is one URL
https://api.mobilesasa.com/v1/send/messageget?api_token=PASTE_YOUR_mbs_TOKEN_HERE&senderID=MOBILESASA&phone=0712345678&message=Invoice+INV-2041+of+KES+12%2C400+is+ready.
curl
# Paste your token once (it starts with mbs_):
export MOBILESASA_TOKEN="mbs_your_token_here"

curl -G "https://api.mobilesasa.com/v1/send/messageget" \
  --data-urlencode "api_token=$MOBILESASA_TOKEN" \
  --data-urlencode "senderID=MOBILESASA" \
  --data-urlencode "phone=0712345678" \
  --data-urlencode "message=Invoice INV-2041 of KES 12,400 is ready."

The response envelope is identical to the POST. If your system can set headers, Authorization: Bearer still works here and is preferred over api_token in the URL.

URL-encode the message

Spaces, commas, ampersands and non-ASCII characters must be percent-encoded or the message will be truncated at the first special character. Every language above has a URL-encoding helper. Use it (curl's is --data-urlencode). Also remember URLs (query string included) end up in proxy and server logs; keep GET sends for systems that genuinely cannot POST.

Things worth knowing

  • Accepted ≠ delivered. 0200 means queued with the carrier. Confirm delivery via delivery reports.
  • Duplicates are blocked (0409). The same sender + text + number delivers at most once per day, unless the sender allows repeats. See Responses.
  • Balance is checked first. An 0402 response bills nothing.
  • Need your own reference on the send, or the cost back? Use v2.

OTP senders

Register a dedicated transactional sender for OTPs and enable duplicate sends on it. Verification codes legitimately repeat, so without that the second code to the same number is refused as a duplicate.