Getting Started

API Authentication Guide

Learn how to authenticate requests to the Statum gateway using HTTP Basic Authentication. Secure your M-Pesa, Airtime, and Bulk SMS API integrations.

This comprehensive API Authentication Guide details the exact steps and protocols required to secure all programmatic communication between your server applications and the Statum gateway. To safeguard your organization's transactional database and digital wallet balance, every developer service-including the M-Pesa mobile money integrations, the transactional SMS gateway, and the automated airtime disbursement APIs-enforces strict authentication controls. Our gateway standardizes on HTTP Basic Authentication (Basic Auth), an industry-standard protocol that provides robust transit-layer security for high-throughput, server-to-server API connections.

To authorize requests successfully, developers must first access the secure Statum developer portal and generate a unique pair of credentials comprising a Consumer Key and a Consumer Secret.

How Basic Authentication Works

HTTP Basic Authentication operates by transmitting your verified credentials within the standard HTTP request payload using a designated Authorization header. This header contains the static prefix word Basic, followed by a single whitespace character, and a Base64-encoded string that represents your consumerKey and consumerSecret joined with a colon character.

Authorization: Basic dG9wc2VjcmV0OjEyMzQ=

Authentication Compilation Steps

  1. Combine your Consumer Key and Consumer Secret with a colon separator.
    Format: consumerKey:consumerSecret
  2. Convert the combined string into a Base64-encoded string.
  3. Incorporate the output into your HTTP request header as:
    Authorization: Basic <Base64_String>

Most modern HTTP clients (such as Guzzle in PHP, Axios in JavaScript, or OkHttp in Java) manage this encoding automatically when you pass username and password attributes.

Authentication Implementation Examples

To facilitate a smooth integration workflow, we have provided several multi-language implementation examples demonstrating how to structure and transmit these authorization headers correctly inside your production codebase:

Authenticate Request
# Base64 encode credentials locally
consumer_key="568473daf6614cb196caeb5f8805985f"
consumer_secret="5a07f41de16e40e4b08b4001142a5a10"
credentials=$(echo -n "$consumer_key:$consumer_secret" | base64)

curl -X POST https://api.statum.co.ke/api/v2/sms \
  -H "Authorization: Basic $credentials" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "phone_number": "254712345678",
    "sender_id": "Statum",
    "message": "Hello from Statum!"
  }'
<?php
$consumerKey = "568473daf6614cb196caeb5f8805985f";
$consumerSecret = "5a07f41de16e40e4b08b4001142a5a10";
$credentials = base64_encode($consumerKey . ":" . $consumerSecret);

$curl = curl_init();
curl_setopt_array($curl, [
    CURLOPT_URL => "https://api.statum.co.ke/api/v2/sms",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_CUSTOMREQUEST => "POST",
    CURLOPT_POSTFIELDS => json_encode([
        "phone_number" => "254712345678",
        "sender_id" => "Statum",
        "message" => "Hello from Statum!"
    ]),
    CURLOPT_HTTPHEADER => [
        "Authorization: Basic " . $credentials,
        "Content-Type: application/json",
        "Accept: application/json"
    ],
]);

$response = curl_exec($curl);
curl_close($curl);
echo $response;
?>
const axios = require('axios');

const consumerKey = "568473daf6614cb196caeb5f8805985f";
const consumerSecret = "5a07f41de16e40e4b08b4001142a5a10";
const credentials = Buffer.from(`${consumerKey}:${consumerSecret}`).toString('base64');

axios.post('https://api.statum.co.ke/api/v2/sms', {
    phone_number: "254712345678",
    sender_id: "Statum",
    message: "Hello from Statum!"
}, {
    headers: {
        'Authorization': `Basic ${credentials}`,
        'Content-Type': 'application/json',
        'Accept': 'application/json'
    }
})
.then(response => console.log(response.data))
.catch(error => console.error(error));
import okhttp3.*;
import java.util.Base64;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        OkHttpClient client = new OkHttpClient();

        String consumerKey = "568473daf6614cb196caeb5f8805985f";
        String consumerSecret = "5a07f41de16e40e4b08b4001142a5a10";
        String credentials = Base64.getEncoder().encodeToString((consumerKey + ":" + consumerSecret).getBytes());

        MediaType mediaType = MediaType.parse("application/json");
        RequestBody body = RequestBody.create(mediaType, "{\"phone_number\":\"254712345678\", \"sender_id\":\"Statum\", \"message\":\"Hello from Statum!\"}");

        Request request = new Request.Builder()
            .url("https://api.statum.co.ke/api/v2/sms")
            .post(body)
            .addHeader("Authorization", "Basic " + credentials)
            .addHeader("Content-Type", "application/json")
            .addHeader("Accept", "application/json")
            .build();

        Response response = client.newCall(request).execute();
        System.out.println(response.body().string());
    }
}

Troubleshooting Authentication Failures

If your mandatory authentication header is missing, incorrect, or malformed, the gateway rejects the request. Common states include:

401 Unauthorized

Invalid Credentials or Base64 String

The credentials could not be validated. Check for:

  • Spaces or newline characters in your Base64 encoded string.
  • Mismatched Consumer Key or Secret.
  • Omission of the Basic prefix in the header.
403 Forbidden

Service Restricted

The credentials are valid, but authorization is denied:

  • Your account balance has been locked or suspended.
  • IP address restriction is active and your server IP is not whitelisted.
  • The requested service (e.g. SMS or Airtime) is disabled on your dashboard profile.

Security Best Practices