SMSTAPSA Bulk SMS API
1. Introduction
SMSTAPSA provides a reliable, high‑throughput SMS gateway for Tanzanian phone numbers. Our API allows you to:
- Send bulk SMS messages to one or many recipients.
- Check your account balance and SMS credit usage.
- Manage custom sender IDs (subject to approval).
Key features
- Pay‑as‑you‑go – only 30 TZS per successfully delivered SMS.
- Simple authentication – use an API key in the request header.
- Flexible number formats – accept
07XXXXXXXX,2557XXXXXXXX, or+2557XXXXXXXX. - Rate‑limited to 5 requests per user per minute to ensure fair usage.
- Default sender ID (
TAPSA) is available immediately; custom sender IDs require approval.
2. Quick Start
Get started in three steps:
- Sign up for a SMSTAPSA account and obtain your API key from the dashboard.
- Top up your account balance – each SMS costs 30 TZS.
- Make your first API call – send a test SMS.
curl -X POST https://api.smstapsa.site/v1/sms/send \
-H "X-API-Key: <YOUR_API_KEY>" \
-H "Content-Type: application/json" \
-d '{
"phoneNumbers": ["255712345678"],
"message": "Hello from SMSTAPSA!"
}'
3. Authentication
All API requests must include your API key in the X-API-Key header.
X-API-Key: <YOUR_API_KEY>
Your API key is generated in the SMSTAPSA dashboard after you sign in.
Never expose your API key in client‑side code – keep it secret on your servers.
4. API Key Management
You can generate, list, and revoke API keys through the SMSTAPSA web interface. Each API key is tied to your user account and uses your balance.
- You may have up to 10 active API keys at a time.
- Keys are shown only once upon creation – store them safely.
- Use descriptive names to manage keys for different applications.
5. Sending SMS
Send an SMS message to one or more phone numbers.
Authentication
X-API-Key: <YOUR_API_KEY>
Headers
Content-Type: application/json
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
phoneNumbers | array of strings or string | Yes | Recipient numbers. Can be an array or a comma‑separated string. |
message | string | Yes | The SMS text (max 160 characters). |
senderId | string | No | Sender ID (alphanumeric). Defaults to TAPSA. Must be approved if custom. |
Example request (array)
{
"phoneNumbers": ["255765902829", "0758123456"],
"message": "Your order has been shipped.",
"senderId": "MYSHOP"
}
Example request (comma‑separated string)
{
"phoneNumbers": "255765902829,0758123456",
"message": "Your order has been shipped."
}
Successful response (HTTP 200)
{
"success": true,
"message": "Messages processed.",
"senderId": "MYSHOP",
"recipients": [
{
"number": "+255765902829",
"status": "Success",
"messageId": "msg_12345678"
},
{
"number": "+255758123456",
"status": "Success",
"messageId": "msg_87654321"
}
],
"deducted": 2,
"remainingBalance": 148
}
Error responses
| Status Code | Example Response | Description |
|---|---|---|
| 400 | {"message": "Missing phoneNumbers or message"} | Required fields missing. |
| 400 | {"message": "Insufficient balance"} | Not enough credits. |
| 400 | {"message": "Sender ID not approved"} | Custom sender ID not yet approved. |
| 401 | {"message": "Invalid API key"} | Missing or incorrect API key. |
| 429 | {"message": "Too many requests. Please wait."} | Rate limit exceeded. |
| 500 | {"message": "Internal server error"} | Service issue. |
Important
- SMS credits are deducted only for recipients that receive a success status.
- Local numbers (starting with
0) are automatically converted to international format (255). - The
senderIdmust be 3‑11 characters, letters/numbers/underscores only. - Maximum message length is 160 characters (the provider may split longer messages).
- Rate limit: 5 requests per minute per API key.
6. Checking Balance
Retrieve your current SMS credit balance and pricing information.
Authentication
X-API-Key: <YOUR_API_KEY>
Headers
None besides the API key.
Request
No body.
Successful response (HTTP 200)
{
"success": true,
"balance": 150,
"currency": "TZS",
"smsRate": 30
}
Error responses
| Status Code | Example Response | Description |
|---|---|---|
| 401 | {"message": "Invalid API key"} | Authentication failed. |
| 500 | {"message": "Internal server error"} | Service issue. |
7. Sender IDs
SMSTAPSA provides a default sender ID TAPSA that works immediately for all customers.
To use a custom sender ID (e.g., your brand name), you must:
- Request the sender ID via the SMSTAPSA dashboard.
- Wait for approval – we review requests to prevent misuse.
- Once approved, you can use it in the
senderIdfield of the SMS endpoint.
Rules for custom sender IDs
- 3 to 11 characters.
- Uppercase letters, numbers, and underscores only.
- Must clearly identify your business or service.
Approval statuses
- pending – under review.
- approved – ready to use.
- rejected – see the rejection reason in the dashboard.
8. Error Handling
All error responses follow a consistent JSON format:
{
"message": "Human‑readable description of the error"
}
Common HTTP status codes:
| Code | Meaning |
|---|---|
| 200 | Success |
| 400 | Bad request – invalid parameters, insufficient balance, unapproved sender ID |
| 401 | Unauthorised – missing or invalid API key |
| 429 | Too Many Requests – rate limit exceeded |
| 500 | Internal server error – try again later |
Always check the message field for specific details. Implement retry logic with exponential backoff for 5xx errors.
9. Rate Limits and Billing
Rate limits
- Each API key is limited to 5 requests per minute.
- This applies to both
/v1/sms/sendand/v1/account/balance. - Exceeding the limit returns HTTP 429 – wait before retrying.
Billing
- Each successfully sent SMS costs 30 TZS.
- Charges are applied per successful recipient – if a message fails for one recipient, you are not charged.
- Your balance is updated in real time.
- Top up your account via the SMSTAPSA dashboard (minimum purchase 500 TZS).
10. Security Best Practices
- Store API keys securely – never hard‑code them in source code or client‑side scripts.
- Use environment variables or a secrets manager.
- Regenerate a key immediately if you suspect it has been compromised.
- Restrict API key usage to your server IPs if possible (future feature).
- Use HTTPS – all endpoints are served over TLS.
11. Code Examples
cURL
Send SMS
curl -X POST https://api.smstapsa.site/v1/sms/send \
-H "X-API-Key: <YOUR_API_KEY>" \
-H "Content-Type: application/json" \
-d '{
"phoneNumbers": ["255765902829", "0758123456"],
"message": "Your appointment is confirmed.",
"senderId": "TAPSA"
}'
Check balance
curl -X GET https://api.smstapsa.site/v1/account/balance \
-H "X-API-Key: <YOUR_API_KEY>"
JavaScript (fetch)
const API_KEY = '<YOUR_API_KEY>';
const BASE_URL = 'https://api.smstapsa.site';
async function sendSms(phoneNumbers, message, senderId = 'TAPSA') {
const response = await fetch(`${BASE_URL}/v1/sms/send`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': API_KEY
},
body: JSON.stringify({ phoneNumbers, message, senderId })
});
const data = await response.json();
if (!response.ok) {
throw new Error(data.message || 'Request failed');
}
return data;
}
// Usage
sendSms(['255765902829', '0758123456'], 'Hello from JS!')
.then(result => console.log('Success:', result))
.catch(err => console.error('Error:', err.message));
async function getBalance() {
const response = await fetch(`${BASE_URL}/v1/account/balance`, {
headers: { 'X-API-Key': API_KEY }
});
return response.json();
}
Python (requests)
import requests
API_KEY = '<YOUR_API_KEY>'
BASE_URL = 'https://api.smstapsa.site'
def send_sms(phone_numbers, message, sender_id='TAPSA'):
headers = {
'Content-Type': 'application/json',
'X-API-Key': API_KEY
}
payload = {
'phoneNumbers': phone_numbers,
'message': message,
'senderId': sender_id
}
response = requests.post(f'{BASE_URL}/v1/sms/send', json=payload, headers=headers)
response.raise_for_status()
return response.json()
# Example
try:
result = send_sms(['255765902829', '0758123456'], 'Hello from Python!')
print(result)
except requests.exceptions.RequestException as e:
print('Error:', e.response.json() if e.response else str(e))
def get_balance():
headers = {'X-API-Key': API_KEY}
response = requests.get(f'{BASE_URL}/v1/account/balance', headers=headers)
response.raise_for_status()
return response.json()
PHP (cURL)
<?php
$apiKey = '<YOUR_API_KEY>';
$baseUrl = 'https://api.smstapsa.site';
function sendSms($phoneNumbers, $message, $senderId = 'TAPSA') {
global $apiKey, $baseUrl;
$payload = json_encode([
'phoneNumbers' => $phoneNumbers,
'message' => $message,
'senderId' => $senderId
]);
$ch = curl_init("$baseUrl/v1/sms/send");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
"X-API-Key: $apiKey"
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode >= 400) {
throw new Exception("HTTP error: $httpCode, response: $response");
}
return json_decode($response, true);
}
// Usage
try {
$result = sendSms(['255765902829', '0758123456'], 'Hello from PHP!');
print_r($result);
} catch (Exception $e) {
echo 'Error: ' . $e->getMessage();
}
function getBalance() {
global $apiKey, $baseUrl;
$ch = curl_init("$baseUrl/v1/account/balance");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["X-API-Key: $apiKey"]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
return json_decode($response, true);
}
?>
12. Support
We’re here to help.
- Email: lazaromtaju12@gmail.com
- Dashboard: https://smstapsa.site (for account management)
- API status: Monitor the health of our services (status page coming soon).
For urgent issues, please include your API key (masked) and request timestamps in your message.
Happy integrating! 🚀