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.

V2 Recommended

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.

V1 Legacy

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 Accepted response
  • ✓ 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

✓ Accepted

International

256700123456

✓ Accepted

E.164

+256700123456

✓ Accepted

Supported Uganda prefixes

Airtel: 70, 74, 75 MTN: 76, 77, 78, 79 Other: 71, 72, 73, 39, 20

HTTP Status Codes & Errors

All error responses return JSON with a message key describing the problem.

StatusMeaningCommon causeFix
202AcceptedRequest processed successfullyCheck sent_count and failed_count in response
401UnauthorizedBad API key or wrong email/passwordRegenerate your key in Settings or check your credentials
422UnprocessableValidation failed or insufficient balanceCheck required fields, valid numbers, and your credit balance
500Server ErrorUnexpected server-side problemRetry after a few seconds; contact support if persistent
// Error response example
{
 "message": "Insufficient SMS balance."
}
V2

Send SMS

Send a message to one or many recipients at once.

POST https://shamasms.com/api/v2/sms/send Requires API Key

Request Headers

Content-Type: application/json
Authorization: Bearer YOUR_API_KEY

Request Parameters

FieldTypeRequiredDescription
sender_idstringoptionalSender name shown on recipient phone. Max 32 chars.
messagestringrequired*The message text. Max 765 chars (5 SMS segments). Use message_body as alias.
numbersarray|stringrequired*Phone numbers. Can be array, comma-separated string, or use recipients instead.
recipientsarrayrequired*Array of objects with phone key. Use this for personalized SMS.
personalizedbooleanoptionalSet true to render placeholders per recipient.
sandboxbooleanoptionalForce 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
}
V2

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.

V2

Check Balance

Retrieve the SMS credit balance for the account linked to the API key.

GET 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"
}
V1 Legacy

Send SMS

Authenticates using your account email and password directly in the request body. Supports the same personalization and bulk features as V2.

POST 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
}
⚠ Security note: V1 sends your login password over the API. Use V2 with API keys for better security — keys can be revoked without changing your password.
V1 Legacy

Check Balance

Returns the SMS credit balance for the authenticated account.

POSThttps://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

Example: A 200-character message sent to 500 recipients = 2 segments × 500 = 1,000 credits used.

Ready to start sending?

Create a free account, generate an API key in Settings, and send your first message in minutes.