Internal Services
Bulk SMS Gateway API
Integrate the fastest Bulk SMS API gateway in Kenya. Send transactional SMS, OTP alerts, and marketing campaigns reliably with instant delivery reports (DLR).
Statum's Bulk SMS Gateway API provides developers and businesses in Kenya with a secure, high-throughput channel to deliver transactional alerts, OTPs, and promotional messages globally. By connecting directly to major local carriers (Safaricom, Airtel, Telkom), our API ensures near-zero latency, high delivery success rates, and transparent reporting.
Integrate our RESTful API endpoint to automate your messaging workflows. All requests require authentication and are transmitted securely via HTTPS.
https://api.statum.co.ke/api/v2/sms
SMS Gateway API Features
Statum's SMS gateway is engineered to support critical messaging channels with the following capabilities:
High-Speed Throughput
Process and dispatch thousands of messages per second. Ideal for one-time passwords (OTPs) and time-sensitive security alerts.
Real-time Delivery Reports
Receive granular carrier callbacks (DLRs) directly. Track when messages hit Safaricom, Airtel, or Telkom networks.
Full Unicode Support
Send messages in any language, including localized Kiswahili texts, custom special characters, and emoji elements.
Secure Authentication
Authenticate API requests using standard HTTP Basic Authentication with credentials safely stored as environment variables.
Sender ID Registration in Kenya
In compliance with the Communications Authority of Kenya (CA) regulations, Sender IDs must be registered before you can send custom-branded messages. Statum manages this process on your behalf:
- Requirements: Letter of authorization to Safaricom, Airtel, and Telkom, and a copy of your Business Registration Certificate or Certificate of Incorporation.
- Timeline: Registration takes approximately 2 to 3 business days to resolve across all mobile operators.
- Fallback: While your custom Sender ID is being approved, you can utilize our default fallback ID to test your integration.
SMS Character Limits & Concatenation
Standard SMS messages are billed in units of 160 characters. Understanding character constraints helps you manage messaging costs:
- Single SMS: Up to 160 characters for standard 7-bit GSM encoding.
- Concatenated (Multi-part) SMS: Messages longer than 160 characters are automatically split and rejoined on the receiver's phone. These split parts are capped at 153 characters each due to concatenation header overhead (UDH).
- Unicode Encoding: Messages containing non-GSM characters (e.g., emojis or specialized symbols) use 16-bit UCS-2 encoding and are limited to 70 characters per message part.
SMS API Request Parameters
Send a POST request containing a JSON body with the following parameters:
| Parameter | Type | Required | Description | Example |
|---|---|---|---|---|
| phone_number | String | Yes | Recipient phone number in international format without the leading plus sign. | 254721553678 |
| message | String | Yes | The message body text to deliver. Keep within GSM character standards. | Your verification code is 8847. |
| sender_id | String | Yes | The registered custom Sender ID or short code. | Statum |
Request Implementation Example
curl -X POST https://api.statum.co.ke/api/v2/sms \
-H "Authorization: Basic MmJlOTg5ZD...==" \
-H "Content-Type: application/json" \
-d '{
"phone_number": "254721553678",
"sender_id": "Statum",
"message": "This is a test message through our API."
}'
$consumerKey = "YOUR_CONSUMER_KEY";
$consumerSecret = "YOUR_CONSUMER_SECRET";
$auth = base64_encode($consumerKey . ":" . $consumerSecret);
$client = new \GuzzleHttp\Client();
$response = $client->post('https://api.statum.co.ke/api/v2/sms', [
'headers' => [
'Authorization' => 'Basic ' . $auth,
'Content-Type' => 'application/json'
],
'json' => [
'phone_number' => '254721553678',
'sender_id' => 'Statum',
'message' => 'This is a test message through our API.'
]
]);
$result = json_decode($response->getBody()->getContents(), true);
const axios = require('axios');
const auth = Buffer.from('YOUR_CONSUMER_KEY:YOUR_CONSUMER_SECRET').toString('base64');
axios.post('https://api.statum.co.ke/api/v2/sms', {
phone_number: '254721553678',
sender_id: 'Statum',
message: 'This is a test message through our API.'
}, {
headers: {
'Authorization': `Basic ${auth}`,
'Content-Type': 'application/json'
}
})
.then(response => console.log(response.data))
.catch(error => console.error(error));
SMS Gateway API Response Format
Upon receiving your POST request, the Statum gateway immediately processes and returns a synchronous JSON response containing the status of your request:
| Parameter | Type | Description | Example |
|---|---|---|---|
| status_code | Number | Standard response code (200 = Success, 401 = Unauthorized, etc.) | 200 |
| description | String | Human-readable response message. | Operation successful. |
| request_id | String | A unique 32-character transaction ID used to map webhook callbacks. | 35235f08c981474abd388755ed43a427 |
Sample Response Payload
{
"status_code": 200,
"description": "Operation successful.",
"request_id": "35235f08c981474abd388755ed43a427"
}
Delivery Reports & Webhook Setup
After queuing, the message is sent to the target mobile operator. To receive real-time updates (Delivery Reports), register a callback URL. The gateway will send an asynchronous HTTP POST webhook containing the final status:
| Parameter | Type | Description | Example |
|---|---|---|---|
| request_id | String | The reference ID returned from the initial POST request. | 35235f08c981474abd388755ed43a427 |
| charge | Decimal | The actual financial charge deducted from your wallet for this SMS. | 50 |
| account_balance | Decimal | Your available wallet balance after the charge deduction. | 950.25 |
| result_code | String | Status code representing transaction outcome (200 = Delivered). | 200 |
| result_desc | String | The description detailing status (e.g. Delivered, Rejected, Failed). | Message delivered successfully |
Sample Webhook Payload
When a message is dispatched to the carrier (Safaricom, Airtel, or Telkom), its delivery state updates asynchronously. Statum's server pushes a POST request containing a JSON payload to your registered callback URL. This payload matches the original request using the request_id and provides the final carrier resolution code.
{
"request_id": "35235f08c981474abd388755ed43a427",
"charge": 50,
"account_balance": 950.25,
"result_code": "200",
"result_desc": "Message delivered successfully"
}
Sample Callback Handler Implementation
To process updates programmatically, configure an endpoint on your server that accepts POST requests with a Content-Type: application/json header. Your handler must extract the parameters, update your internal logs, and respond with an HTTP 200 OK status within 3 seconds to avoid retry attempts.
<?php
// Route target: https://yourdomain.com/api/sms/callback
$input = file_get_contents('php://input');
$payload = json_decode($input, true);
if (!$payload) {
http_response_code(400);
exit();
}
$requestId = $payload['request_id'];
$resultCode = $payload['result_code'];
if ($resultCode === '200') {
// SMS was successfully delivered to the device. Update database order/alert status.
updateSmsStatus($requestId, 'delivered');
} else {
// Delivery failed (e.g., number out of service, subscriber absent, etc.)
updateSmsStatus($requestId, 'failed', $payload['result_desc']);
}
// Return 200 to acknowledge receipt of webhook
http_response_code(200);
echo json_encode(['status' => 'acknowledged']);
?>