Developer Reference
ShamaSMS API Documentation
Integrate SMS sending into any website, mobile app, school system, billing platform, or CRM using the ShamaSMS REST API. Two versions are available — V2 with API keys is recommended for all new integrations.
Base URL
https://shamasms.com/api
Format
JSON (application/json)
Versions
v1 (legacy) · v2 (recommended)
Authentication
ShamaSMS supports two authentication methods depending on the API version.
API Key (Bearer Token)
Generate keys in your dashboard Settings. Pass the key in the Authorization header.
Authorization: Bearer shama_live_xxxxxxxxxxxx
You can also use the X-API-Key header or the api_key body field, but Bearer is preferred.
Email & Password
Pass your account email and password in the request body. Works but not recommended — anyone with the credentials can send on your behalf.
{ "email": "you@example.com", "password": "..." }
Sandbox vs Live
Every API key has a mode: sandbox or live. You can also force sandbox per-request by passing "sandbox": true in the body.
📷 Sandbox key / sandbox:true
- ✓ Returns
202 Acceptedresponse - ✓ Stores message records with status sandbox
- ✓ Does NOT send real SMS
- ✓ Does NOT deduct credits from balance
- ✓ Safe for development and testing
⚡ Live key
- ✓ Sends real SMS through the ShamaSMS network
- ✓ Deducts credits from your account balance
- ✓ Delivery reports recorded per recipient
- ✓ Full message history stored in Sent
💡 Always build and test with a sandbox key first. Switch to a live key only when you are ready for production.
Phone Number Format
All recipients must be valid Ugandan mobile numbers. ShamaSMS normalises local and international formats automatically before delivery.
Local format
0700123456
✓ AcceptedInternational
256700123456
✓ AcceptedE.164
+256700123456
✓ AcceptedSupported Uganda prefixes
HTTP Status Codes & Errors
All error responses return JSON with a message key describing the problem.
| Status | Meaning | Common cause | Fix |
|---|---|---|---|
| 202 | Accepted | Request processed successfully | Check sent_count and failed_count in response |
| 401 | Unauthorized | Bad API key or wrong email/password | Regenerate your key in Settings or check your credentials |
| 422 | Unprocessable | Validation failed or insufficient balance | Check required fields, valid numbers, and your credit balance |
| 500 | Server Error | Unexpected server-side problem | Retry after a few seconds; contact support if persistent |
// Error response example
{
"message": "Insufficient SMS balance."
}
Send SMS
Send a message to one or many recipients at once.
https://shamasms.com/api/v2/sms/send
Requires API Key
Request Headers
Content-Type: application/json
Authorization: Bearer YOUR_API_KEY
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| sender_id | string | optional | Sender name shown on recipient phone. Max 32 chars. |
| message | string | required* | The message text. Max 765 chars (5 SMS segments). Use message_body as alias. |
| numbers | array|string | required* | Phone numbers. Can be array, comma-separated string, or use recipients instead. |
| recipients | array | required* | Array of objects with phone key. Use this for personalized SMS. |
| personalized | boolean | optional | Set true to render placeholders per recipient. |
| sandbox | boolean | optional | Force sandbox mode for this request regardless of key mode. |
* Either numbers, to, phone, or recipients is required.
Request Body Example
{
"sender_id": "MYSHOP",
"message": "Hello! Your order is ready for pickup.",
"numbers": ["0700000000", "256750000001"],
"sandbox": true
}
Success Response 202
{
"message": "Accepted",
"reference": "api-xxxxxxxx-xxxx-xxxx",
"segments": 1,
"recipient_count": 2,
"sent_count": 2,
"failed_count": 0,
"credits_used": 2,
"balance": 998
}
Personalized SMS
Inject a unique name, balance, amount, or any value per recipient using placeholders in your message template.
Available Placeholders
@name@@
@var1@@
@var2@@
@var3@@
@var4@@
@var5@@
Each recipient row in recipients supplies the values. If a placeholder has no value, it is left blank (not an error).
Request Body — Personalized
POST https://shamasms.com/api/v2/sms/send
Authorization: Bearer YOUR_API_KEY
{
"message": "Hi @name@@, your loan balance is UGX @var1@@. Due @var2@@.",
"personalized": true,
"recipients": [
{ "phone": "0700000000", "name": "Alice", "var1": "450,000", "var2": "10 Jul" },
{ "phone": "0750000001", "name": "Robert", "var1": "820,000", "var2": "15 Jul" }
],
"sandbox": true
}
What each recipient receives
0700000000 (Alice)
"Hi Alice, your loan balance is UGX 450,000. Due 10 Jul."
0750000001 (Robert)
"Hi Robert, your loan balance is UGX 820,000. Due 15 Jul."
Each recipient gets a fully personalized message. Credits are consumed per segment per recipient.
Check Balance
Retrieve the SMS credit balance for the account linked to the API key.
https://shamasms.com/api/v2/balance
Headers
Authorization: Bearer YOUR_API_KEY
Success Response 200
{
"balance": 1450,
"mode": "live",
"unit": "sms_credits",
"sms_unit_price": 65,
"currency": "UGX"
}
Send SMS
Authenticates using your account email and password directly in the request body. Supports the same personalization and bulk features as V2.
https://shamasms.com/api/v1/sms/send
Request Body
{
"email": "you@example.com",
"password": "your-account-password",
"sender_id": "SHAMA",
"message": "Hello from ShamaSMS!",
"numbers": ["0700000000", "0750000001"],
"sandbox": true
}
Personalized V1 Request
{
"email": "you@example.com",
"password": "...",
"message": "Hi @name@@, balance: @var1@@",
"personalized": true,
"recipients": [
{ "phone": "0700000000", "name": "Jane", "var1": "50,000" }
],
"sandbox": true
}
Check Balance
Returns the SMS credit balance for the authenticated account.
https://shamasms.com/api/v1/balance{ "email": "you@example.com", "password": "..." }
Response
{
"balance": 1450,
"unit": "sms_credits",
"sms_unit_price": 65,
"currency": "UGX"
}
Code Examples
Copy-paste examples in common languages. Replace YOUR_API_KEY with your live or sandbox key from Settings.
PHP (cURL)
<?php
$apiKey = "YOUR_API_KEY";
$payload = json_encode([
"sender_id" => "MYAPP",
"message" => "Hello @name@@, your balance is @var1@@.",
"personalized"=> true,
"recipients" => [
["phone" => "0700000000", "name" => "Alice", "var1" => "35,000"],
["phone" => "0750000001", "name" => "Bob", "var1" => "12,000"],
],
"sandbox" => false,
]);
$ch = curl_init("https://shamasms.com/api/v2/sms/send");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"Authorization: Bearer " . $apiKey,
],
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
echo "Sent: " . $response["sent_count"] . ", Credits left: " . $response["balance"];
JavaScript (fetch)
const API_KEY = "YOUR_API_KEY";
const response = await fetch("https://shamasms.com/api/v2/sms/send", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${API_KEY}`,
},
body: JSON.stringify({
sender_id: "MYAPP",
message: "Hello @name@@, your order @var1@@ is ready!",
personalized: true,
recipients: [
{ phone: "0700000000", name: "Alice", var1: "ORD-1042" },
],
sandbox: false,
}),
});
const data = await response.json();
console.log(`Sent: ${data.sent_count}, Balance: ${data.balance}`);
Python (requests)
import requests
API_KEY = "YOUR_API_KEY"
resp = requests.post(
"https://shamasms.com/api/v2/sms/send",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"sender_id": "MYAPP",
"message": "Hi @name@@, your invoice of UGX @var1@@ is due.",
"personalized": True,
"recipients": [
{"phone": "0700000000", "name": "Alice", "var1": "150,000"},
{"phone": "0750000001", "name": "Bob", "var1": "80,000"},
],
"sandbox": False,
}
)
data = resp.json()
print(f"Sent: {data['sent_count']}, Balance: {data['balance']}")
cURL (command line)
# Simple bulk send
curl -X POST https://shamasms.com/api/v2/sms/send \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"sender_id": "SHAMA",
"message": "Test message from ShamaSMS API.",
"numbers": ["0700000000"],
"sandbox": true
}'
# Check balance
curl https://shamasms.com/api/v2/balance \
-H "Authorization: Bearer YOUR_API_KEY"
Credits & SMS Segments
Understand how credits are calculated so you can estimate costs accurately.
1 credit
= 1 SMS segment delivered to 1 recipient
1 segment
= 160 characters (GSM-7) or 70 characters (Unicode)
2 segments
= 161–306 chars. Counts as 2 credits per recipient.
Formula
credits = segments × recipients
Ready to start sending?
Create a free account, generate an API key in Settings, and send your first message in minutes.