Skip to content

Latest commit

 

History

31 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Statum Java SDK (SMS, Airtime, & Accounts)

Java CI Maven Central License: MIT

Official Java SDK for Statum APIs. Built for secure, production-grade enterprise usage with strict typing, immutable DTO records, and built-in HTTP client connection pooling. Easily send SMS alerts, automate airtime disbursements, and query real-time account balances.


Table of Contents


Features

  • JDK 17+ Records: Uses modern Java Records and sealed types for absolute DTO immutability.
  • Zero Heavy Dependencies: Uses the native java.net.http.HttpClient under the hood (only requires Jackson for lightweight JSON binding).
  • Thread-Safe: Designed to be instantiated once and shared across multiple application threads.
  • Service-Oriented: Logical division between Airtime, SMS, and Account Management APIs.
  • Extensive Exceptions: Maps standard HTTP status code failures (401, 403, 422, 5xx) to concrete Java exception classes.

Getting Started

  1. Sign up for a Statum account: app.statum.co.ke
  2. Get your API credentials: Retrieve your Consumer Key and Consumer Secret from the Statum Dashboard.
  3. Read the full API documentation: docs.statum.co.ke
  4. Install the SDK: Follow the Installation guidelines below.

Installation

Maven

Add the dependency to your pom.xml:

<dependency>
    <groupId>ke.co.statum</groupId>
    <artifactId>statum-java-sdk</artifactId>
    <version>1.0.3</version>
</dependency>

Gradle

Add the dependency to your build.gradle:

implementation 'ke.co.statum:statum-java-sdk:1.0.3'

Quick Start

1. Plain Java Setup

Ensure your credentials are saved in your system environment variables:

export STATUM_CONSUMER_KEY="your-consumer-key"
export STATUM_CONSUMER_SECRET="your-consumer-secret"

Instantiate and reuse the thread-safe client:

import ke.co.statum.sdk.StatumClient;
import ke.co.statum.sdk.config.StatumConfig;

StatumConfig config = new StatumConfig(
    System.getenv("STATUM_CONSUMER_KEY"),
    System.getenv("STATUM_CONSUMER_SECRET")
);
StatumClient client = new StatumClient(config);

2. Spring Boot Setup

Add the properties to your application.properties:

statum.consumer-key=${STATUM_CONSUMER_KEY}
statum.consumer-secret=${STATUM_CONSUMER_SECRET}
statum.base-url=https://api.statum.co.ke/api/v2
statum.timeout-seconds=30

Create a configuration class to register the StatumClient bean:

import ke.co.statum.sdk.StatumClient;
import ke.co.statum.sdk.config.StatumConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.time.Duration;

@Configuration
public class StatumConfiguration {

    @Bean
    public StatumClient statumClient(
            @Value("${statum.consumer-key}") String consumerKey,
            @Value("${statum.consumer-secret}") String consumerSecret,
            @Value("${statum.base-url:https://api.statum.co.ke/api/v2}") String baseUrl,
            @Value("${statum.timeout-seconds:30}") int timeoutSeconds) {

        StatumConfig config = new StatumConfig(
            consumerKey,
            consumerSecret,
            baseUrl,
            Duration.ofSeconds(timeoutSeconds)
        );
        return new StatumClient(config);
    }
}

Now, inject the client into any @Service or @RestController:

import ke.co.statum.sdk.StatumClient;
import ke.co.statum.sdk.model.ApiResponse;
import org.springframework.stereotype.Service;

@Service
public class NotificationService {

    private final StatumClient statumClient;

    public NotificationService(StatumClient statumClient) {
        this.statumClient = statumClient;
    }

    public void alertUser(String phoneNumber, String message) {
        ApiResponse response = statumClient.getSmsService()
                .sendSms(phoneNumber, "STATUM", message);
                
        System.out.println("Alert sent. ID: " + response.requestId());
    }
}

Core Integration Examples

Account Details

Fetch organization profile, available balances, and service configuration:

import ke.co.statum.sdk.model.AccountDetailsResponse;

AccountDetailsResponse response = client.getAccountService().getAccountDetails();

System.out.println("Status Code: " + response.statusCode());
System.out.println("Organization: " + response.organization().name());
System.out.println("Available Balance: KES " + response.organization().details().availableBalance());

// List registered services and account codes
response.organization().accounts().forEach(account -> {
    System.out.println("Service: " + account.serviceName() + " | Code: " + account.account());
});

Sending SMS

Send transactional or promotional SMS alerts to a Kenyan phone number:

import ke.co.statum.sdk.model.ApiResponse;

ApiResponse response = client.getSmsService().sendSms(
    "254721553678",           // Phone number in international format
    "STATUM",                 // Your approved Sender ID
    "Hello from the Statum Java SDK!" // Message content
);

System.out.println("Status Code: " + response.statusCode());
System.out.println("Description: " + response.description());
System.out.println("Request ID: " + response.requestId());

Disbursing Airtime

Disburse airtime rewards or incentives (supports amounts from KES 5 to KES 10,000):

import ke.co.statum.sdk.model.ApiResponse;

ApiResponse response = client.getAirtimeService().sendAirtime(
    "254721553678",           // Phone number in international format
    "100"                     // Amount must be passed as a String representation
);

System.out.println("Status Code: " + response.statusCode());
System.out.println("Description: " + response.description());
System.out.println("Request ID: " + response.requestId());

Error & Exception Handling

The SDK maps standard HTTP responses to concrete exception classes that inherit from ke.co.statum.sdk.exceptions.ApiException.

import ke.co.statum.sdk.exceptions.*;
import ke.co.statum.sdk.model.ApiResponse;

try {
    ApiResponse response = client.getSmsService().sendSms("2547XXXXXXXX", "STATUM", "Message");
} catch (AuthenticationException e) {
    // Credentials failed validation (HTTP 401)
    System.err.println("Auth Failure: Check Consumer Key and Secret.");
} catch (AuthorizationException e) {
    // Access denied or forbidden resource (HTTP 403)
    System.err.println("Access Denied: " + e.getMessage());
} catch (ValidationException e) {
    // API-side validation parameters failed (HTTP 422)
    System.err.println("Validation failed. Body: " + e.getResponseBody());
    e.getValidationErrors().forEach((field, errors) -> {
        System.err.println("Field: " + field + " | Errors: " + String.join(", ", errors));
    });
} catch (NetworkException e) {
    // DNS, connection timeouts, or socket failures
    System.err.println("Connection error: " + e.getMessage());
} catch (ApiException e) {
    // General API errors (e.g. 402 Insufficient Funds, 500 Server Error)
    System.err.println("HTTP Status Code: " + e.getStatusCode());
    System.err.println("Error Body: " + e.getResponseBody());
}

API JSON Payload Specifications

Here are the wire-level JSON schemas transmitted and returned by the APIs under the hood:

1. SMS API

  • Endpoint: POST /sms
  • Headers: Authorization: Basic <base64(key:secret)>
JSON Request
{
  "phone_number": "254721553678",
  "sender_id": "STATUM",
  "message": "Hello from Statum SDK!"
}
JSON Response (Success - 200)
{
  "status_code": 200,
  "description": "Operation successful.",
  "request_id": "d173a8b3-0f3a-463f-8a03-29826b9a2d78"
}

2. Airtime API

  • Endpoint: POST /airtime
JSON Request
{
  "phone_number": "254721553678",
  "amount": "100"
}
JSON Response (Success - 200)
{
  "status_code": 200,
  "description": "Operation successful.",
  "request_id": "6e0213d5-6df9-47bf-ba2d-9b9470d96854"
}

3. Account Details API

  • Endpoint: GET /account-details
JSON Response (Success - 200)
{
  "status_code": 200,
  "description": "Operation successful.",
  "request_id": "5a45bc7b-bf99-49ae-b089-9daf5f4adbb0",
  "organization": {
    "name": "Statum Test",
    "details": {
      "available_balance": 695.15,
      "location": "Nairobi - Westlands",
      "website": "www.statum.co.ke",
      "office_email": "admin@statum.co.ke",
      "office_mobile": "+254722199199",
      "mpesa_account_top_up_code": "B9E573"
    },
    "accounts": [
      { "account": "Statum", "service_name": "sms" },
      { "account": "CONNECT", "service_name": "sms" }
    ]
  }
}

Integration Guidelines & Gotchas

  1. Sender ID Approval: SMS requests will throw an HTTP 422 ValidationException if the senderId is not registered and approved under your Statum account profile.
  2. Phone Number Formatting: Ensure phone numbers are passed in the international format (with or without + prefix), e.g. 254721553678 or +254721553678.
  3. Airtime Limits: Airtime amounts must be passed as strings (e.g. '100') and must fall strictly within the KES 5 to KES 10,000 range per transaction.
  4. Jackson Deserialization Dependency: If running outside of Spring Boot (which manages Jackson dependencies automatically), ensure that jackson-databind is present on your classpath.

License

This project is licensed under the MIT License. See LICENSE for details.

About

The official Java SDK for the Statum API. This library provides a simple, thread-safe, and strictly typed interface for interacting with Statum services including Airtime, SMS, and Account Management.

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages