SMSTAPSA Bulk SMS API

Developer Documentation – Reliable SMS for Tanzania

1. Introduction

SMSTAPSA provides a reliable, high‑throughput SMS gateway for Tanzanian phone numbers. Our API allows you to:

Key features

2. Quick Start

Get started in three steps:

  1. Sign up for a SMSTAPSA account and obtain your API key from the dashboard.
  2. Top up your account balance – each SMS costs 30 TZS.
  3. 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.

5. Sending SMS

POST /v1/sms/send

Send an SMS message to one or more phone numbers.

Authentication

X-API-Key: <YOUR_API_KEY>

Headers

Content-Type: application/json

Request Body

FieldTypeRequiredDescription
phoneNumbersarray of strings or stringYesRecipient numbers. Can be an array or a comma‑separated string.
messagestringYesThe SMS text (max 160 characters).
senderIdstringNoSender 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 CodeExample ResponseDescription
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

6. Checking Balance

GET /v1/account/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 CodeExample ResponseDescription
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:

  1. Request the sender ID via the SMSTAPSA dashboard.
  2. Wait for approval – we review requests to prevent misuse.
  3. Once approved, you can use it in the senderId field of the SMS endpoint.

Rules for custom sender IDs

Approval statuses

8. Error Handling

All error responses follow a consistent JSON format:

{
  "message": "Human‑readable description of the error"
}

Common HTTP status codes:

CodeMeaning
200Success
400Bad request – invalid parameters, insufficient balance, unapproved sender ID
401Unauthorised – missing or invalid API key
429Too Many Requests – rate limit exceeded
500Internal 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

Billing

10. Security Best Practices

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.

For urgent issues, please include your API key (masked) and request timestamps in your message.


Happy integrating! 🚀