Selcom Business API Gateway
The Selcom Business API Gateway provides a secure, REST-based interface that allows your applications to programmatically initiate payments, check account balances, and track transaction statuses — all from a single integration point.
Secure by Design
Every request is authenticated using an HMAC-based digest signature combining your API key, secret, and a time-bounded timestamp.
Real-time Processing
Transactions are processed in real time via the Selcom infrastructure, with instant status tracking through a dedicated status endpoint.
Multi-channel Support
Send money to bank accounts, mobile wallets, or other Selcom Business accounts — all through a unified API interface.
https://sandbox.selcom.business
— All endpoints listed in this documentation are relative to this base URL.
https://api.selcom.business/v1
— All endpoints listed in this documentation are relative to this base URL.
Getting Started
-
Obtain API Credentials
Log in to Selcom Business and navigate to My Account → API Credentials to generate your Signing Keys.
-
Build Request Headers
Compute the digest. See Authorization and Signature Generation for the formulas.
-
Make Your First API Call
Try the Balance API to verify your credentials and Bearer token are working correctly.
Client Packages
Following are links to the client library code repositories on GitHub and ways to install using package managers. For more information and source code visit the GitHub pages.
PHP
Installation
composer require selcom/selcom-apigw-client
GitHub Link
JAVA
Installation
io.github.selcompaytechltd/apigwClient
or search for io.github.selcompaytechltd/apigwClient using your package manager.
GitHub Link
C#
Installation
dotnet add package selcom-apigw-client
GitHub Link
Python
Installation
pip install selcom_apigw_client
GitHub Link
Node.js
Installation
npm i selcom-apigw-client
GitHub Link
Request Headers
Every request to the API Gateway must include the following HTTP headers.
Missing or malformed headers will result in a 400 Bad Request response.
| Header | Required | Format / Example | Description |
|---|---|---|---|
api-key |
Required | a1b2c3d4e5... |
Your unique API key obtained from the credentials panel. |
timestamp |
Required | 2026-05-27T06:01:03.273Z |
Current UTC time in ISO 8601 format with milliseconds. Must be identical to the value used in the signing string. |
digest |
Required | Base64 encoded string |
RSA-SHA256 signature of the signing string, Base64-encoded. See Authorization for the formula. |
signed-fields |
Required | transId,amount,msisdn |
Comma-separated list of request field names (POST body or GET query params)
in the exact same order as the signing string.
Do not include timestamp.
|
Content-Type |
Required for POST | application/json |
Must be application/json for all POST endpoints. |
Accept |
Optional | application/json |
Recommended. All responses are returned as JSON. |
Signing String Generation
The digest is an RSA-SHA256 signature over a canonical signing string
built from the timestamp and the request fields listed in signed-fields.
Signing String & Digest Format
signing_string = "timestamp=" + timestamp + "&" + field1 + "=" + value1 + "&" + ...
digest = Base64( RSA_SHA256(signing_string, PrivateKey) )
timestampis always first, even though it is not listed insigned-fields.- Fields follow in the exact order listed in the
signed-fieldsheader. - Values must match the request payload exactly — no extra spaces or type conversions.
- For GET requests, use query parameter names and values.
- For POST requests, use JSON body field names and values.
Implementation Examples
$apiKey = 'YOUR_API_KEY';
$privateKey = file_get_contents('/path/to/private_key.pem');
$timestamp = (new DateTime('now', new DateTimeZone('UTC')))->format('Y-m-d\TH:i:s.v\Z');
$fields = [
'transId' => '1234567899',
'recipientFiCode' => 'SELCOM',
'recipientAccount' => '255711410410',
'recipientName' => 'John Doe',
'amount' => 100,
'purpose' => 'FT',
];
$signedFields = implode(',', array_keys($fields));
$signingString = 'timestamp=' . $timestamp;
foreach ($fields as $key => $value) {
$signingString .= '&' . $key . '=' . $value;
}
openssl_sign($signingString, $signature, $privateKey, OPENSSL_ALGO_SHA256);
$digest = base64_encode($signature);
$headers = [
'api-key: ' . $apiKey,
'timestamp: ' . $timestamp,
'digest: ' . $digest,
'signed-fields: ' . $signedFields,
'content-type: application/json',
];
import base64
from datetime import datetime, timezone
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
api_key = 'YOUR_API_KEY'
now = datetime.now(timezone.utc)
timestamp = now.strftime('%Y-%m-%dT%H:%M:%S.') + f"{now.microsecond // 1000:03d}Z"
with open('/path/to/private_key.pem', 'rb') as f:
private_key = serialization.load_pem_private_key(f.read(), password=None)
fields = {
'transId': '1234567899',
'recipientFiCode': 'SELCOM',
'recipientAccount': '255711410410',
'recipientName': 'John Doe',
'amount': 100,
'purpose': 'FT',
}
signed_fields = ','.join(fields.keys())
signing_string = 'timestamp=' + timestamp + '&' + \
'&'.join(f"{k}={v}" for k, v in fields.items())
signature = private_key.sign(signing_string.encode(), padding.PKCS1v15(), hashes.SHA256())
digest = base64.b64encode(signature).decode()
headers = {
'api-key': api_key,
'timestamp': timestamp,
'digest': digest,
'signed-fields': signed_fields,
'content-type': 'application/json',
}
const crypto = require('crypto');
const fs = require('fs');
const apiKey = 'YOUR_API_KEY';
const privateKey = fs.readFileSync('/path/to/private_key.pem', 'utf8');
const timestamp = new Date().toISOString(); // e.g. 2026-05-27T06:01:03.273Z
const fields = {
transId: '1234567899',
recipientFiCode: 'SELCOM',
recipientAccount: '255711410410',
recipientName: 'John Doe',
amount: 100,
purpose: 'FT',
};
const signedFields = Object.keys(fields).join(',');
const signingString = 'timestamp=' + timestamp + '&' +
Object.entries(fields).map(([k, v]) => `${k}=${v}`).join('&');
const sign = crypto.createSign('RSA-SHA256');
sign.update(signingString, 'utf8');
const digest = sign.sign(privateKey, 'base64');
const headers = {
'api-key': apiKey,
'timestamp': timestamp,
'digest': digest,
'signed-fields': signedFields,
'content-type': 'application/json',
};
Sample Raw Request (Protected Endpoint)
POST /v1/transaction/process HTTP/1.1
Host: api.selcom.business
api-key: a1b2c3d4e5f6g7h8i9j0
timestamp: 2026-05-27T06:01:03.273Z
digest: Base64EncodedRSASignature==
signed-fields: transId,recipientFiCode,recipientAccount,recipientName,amount,purpose,remarks
content-type: application/json
Accept: application/json
{
"transId": "1234567899",
"recipientFiCode": "SELCOM",
"recipientAccount": "255711410410",
"recipientName": "John Doe",
"amount": 100,
"purpose": "FT",
"remarks": "Test transfer"
}
Error Responses for Header Failures
| HTTP Status | error_code | Cause |
|---|---|---|
| 400 | 612 |
One or more required headers are missing. |
| 401 | 613 |
API key not found or inactive. |
| 401 | 631 |
digest does not match — invalid RSA signature. |
| 403 | 611 |
Client IP is not whitelisted for this credential. |
| 503 | 613 |
Authentication service is temporarily unavailable — retry the request after a short delay. |
Purpose Codes
Every transaction request requires a purpose field. Use the
Code value from the table below. Only active purposes are listed.
| # | Purpose Name | Code |
|---|---|---|
| 1 | Payment |
PAYMENT
|
| 2 | Airfare |
AIRFARE
|
| 3 | Airtime |
AIRTIME
|
| 4 | Betting and gaming |
BETTING
|
| 5 | Business expense |
BUSINESSEXPENSES
|
| 6 | Car repair |
CARREPAIR
|
| 7 | Cash |
CASH
|
| 8 | Contribution |
CONTRIBUTE
|
| 9 | Contributions |
CONTRIBUTES
|
| 10 | Dining |
DINING
|
| 11 | Donation |
DONATION
|
| 12 | Dry cleaning |
DRYCLEANING
|
| 13 | Education |
EDUCATION
|
| 14 | Entertainment |
ENTERTAINMENT
|
| 15 | Fitness |
FITNESS
|
| 16 | Fuel |
FUEL
|
| 17 | Funds transfer |
FT
|
| 18 | General repairs |
GENERALREPAIRS
|
| 19 | General/uncategorized |
GENERAL
|
| 20 | Gift |
GIFT
|
| 21 | Gift Cards |
GIFTCARD
|
| 22 | Government payment |
GOV
|
| 23 | Groceries and essentials |
GROCERIES
|
| 24 | Health and fitness |
HEALTH
|
| 25 | House repair |
HOUSEREPAIR
|
| 26 | Insurance |
INSURANCE
|
| 27 | Internet and broadband |
INTERNET
|
| 28 | Investments |
INVEST
|
| 29 | Legal fees |
LEGALFEES
|
| 30 | Loan repayment |
LOAN
|
| 31 | Logistics & Shipment |
SHIPMENT
|
| 32 | Lottery |
LOTTERY
|
| 33 | Medical Bills |
MEDICALBILLS
|
| 34 | Office/business expense |
OFFICEEXPENSE
|
| 35 | Personal care |
PERSONALCARE
|
| 36 | Renewable energy |
RENERGY
|
| 37 | Salary and other income |
INCOME
|
| 38 | Salary or wages |
SALARYOFWAGES
|
| 39 | Savings |
SAVINGS
|
| 40 | Shopping |
SHOPPING
|
| 41 | Social contribution |
SOCIALCONTRIBUSTION
|
| 42 | Stocks & Securities |
STOCKS
|
| 43 | Taxes and fines |
TAX
|
| 44 | Transport |
TRANSPORT
|
| 45 | Travel |
TRAVEL
|
| 46 | TV subscription |
TV
|
| 47 | Utility payment |
UTILITY
|
purpose field of your transaction request.
Invalid codes will result in a validation error (error_code: 651).
Balance API
Retrieve the current available balance for a linked organization account.
/v1/balance
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
account_number |
string | Required | The account number associated with your API credentials. Must be an active B2C account registered under your organization. |
Response Fields
| Field | Type | Description |
|---|---|---|
success |
boolean | true on success, false on failure. |
error_code |
integer | 1 on success; negative value on error (see Error Codes). |
message |
string | Human-readable status message. |
data.account_number |
string | The queried account number. |
data.currency |
string | Account currency (e.g., TZS). |
data.available_balance |
float | Current available balance in the account. |
data.active |
boolean | true if the account is currently active; false otherwise. |
result |
string | Transaction result based on actual status. See API Response — Result column. |
resultcode |
string | Result code based on actual transaction status. See API Response — Errorcode column. |
Example
{
"account_number": "0123456789"
}
{
"success": true,
"error_code": 1,
"message": "Balance fetched successfully.",
"result": "SUCCESS",
"resultcode": "000",
"data": {
"account_number": "000011636",
"currency": "TZS",
"available_balance": 100000000,
"active": true
}
}
{
"success": false,
"error_code": 641,
"message": "Invalid or unauthorized account number.",
"result": "FAIL",
"resultcode": "641",
"data": []
}
Webhook (Callback)
Selcom sends a POST request to your registered callback URL when an API-initiated transaction completes successfully. Only the parameters you select will be included in the payload. For TIPS / TISS transactions, the callback fires after final network confirmation is received.
Callback URL *
A publicly reachable HTTPS endpoint on your server. Selcom will POST the transaction payload to this URL on every successful transaction.
Configuration Fields
| Field | Type | Required | Description |
|---|---|---|---|
callback_url |
string | Required | The HTTPS URL that will receive the POST callback. Maximum 500 characters. |
callback_parameters |
array | Required | The payload fields to include in the callback. At least one parameter must be selected. |
Callback Payload
Every callback always includes reference_id and
status. All other fields are included only if selected
in the callback configuration.
Payload Fields
| Field | Type | Description |
|---|---|---|
reference_id |
string | Your unique transaction reference ID from the original API request. Always included. |
status |
string | Always SUCCESS. Callbacks are only sent for successful transactions. Always included. |
sender_account_name |
string | Name of the sending (debit) account. |
sender_account_number |
string | Account number of the sender. |
recipient_name |
string | Name of the transaction recipient. |
recipient_account_number |
string | Destination account number or phone number of the recipient. |
amount |
numeric | Principal transaction amount excluding charges. |
charges |
numeric | Transaction charges applied. May be 0 if no charges apply. |
selcom_receipt |
string | Selcom-issued receipt number for the transaction. |
Example
{
"reference_id": "2024061500123",
"status": "SUCCESS",
"sender_account_name": "Acme Limited",
"sender_account_number": "0000123456",
"recipient_name": "John Doe",
"recipient_account_number": "255712345678",
"amount": 50000,
"charges": 500,
"selcom_receipt": "202406150001"
}
Transaction API
Initiate a fund transfer, look up a recipient account before transferring, or query the status of a previously submitted transaction. The debit account is automatically resolved from your API credentials.
Transaction Process
/v1/transaction/process
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
transId |
string | Required | Your unique transaction reference ID. Must be unique across all transactions. Used for idempotency and status tracking. |
recipientFiCode |
string | Required | Destination institution code (bank, wallet, or SELCOM for internal transfers). See destination codes below. |
recipientAccount |
string | Required | Recipient account number or phone number depending on the recipientFiCode. |
recipientName |
string | Required | Recipient full name (max 100 characters). |
amount |
numeric | Required | Transaction amount. Must be at least 1. |
purpose |
string | Required | Transaction purpose code. See Purpose Codes. |
remarks |
string | Optional | Free-text remark (max 140 characters). Appears on statements. |
Response Fields
| Field | Type | Description |
|---|---|---|
success |
boolean | true on success. |
error_code |
integer | 1 on success; negative on error. |
message |
string | Human-readable status message. |
data.trans_id |
string | Your unique transId for status tracking. |
data.selcom_receipt |
string | Selcom internal transaction identifier. |
data.status |
string | Initial status: ACCEPTED (async) or COMPLETED (sync). See Transaction Status Values. |
data.amount |
float | Transaction amount. |
data.currency |
string | Transaction currency. |
result |
string | Transaction result based on actual status. See API Response — Result column. |
resultcode |
string | Result code based on actual transaction status. See API Response — Errorcode column. |
Account Lookup
/v1/account/lookup
Look up a recipient account before initiating a transfer. Returns the account holder name, applicable charges, and operator details.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
bank |
string | Required | Destination institution code (bank, wallet, or SELCOM). See destination codes below. |
account |
string | Required | Recipient account number or phone number to look up. |
transId |
string | Required | Unique reference ID for this lookup request. |
amount |
numeric | Optional | Transfer amount. When provided, the response includes charge calculations for that amount. |
Response Fields
| Field | Type | Description |
|---|---|---|
success |
boolean | true on success. |
error_code |
integer | 1 on success; negative on error. |
message |
string | Human-readable status message. |
transId |
string | The reference ID you sent in the request. |
resultcode |
string | 000 on success. |
data.bank |
string | Institution code used in the lookup. |
data.account |
string | Recipient account number used in the lookup. |
data.accountName |
string | Recipient account holder name. |
data.operator |
string | Institution or operator name. |
data.charges |
array | Breakdown of applicable transaction charges. |
data.totalCharges |
float | Total of all applicable charges. |
data.categoryCode |
string | Category code returned by the bridge. |
result |
string | Transaction result based on actual status. See API Response — Result column. |
resultcode |
string | Result code based on actual transaction status. See API Response — Errorcode column. |
Transaction Status
/v1/transaction/query
Query the status and details of a previously submitted transaction using your transId.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
transId |
string | Required | The unique transaction reference ID submitted in the process request. |
Response Fields
| Field | Type | Description |
|---|---|---|
success |
boolean | true on success. |
error_code |
integer | 1 on success; negative on error. |
message |
string | Human-readable status message. |
data.transId |
string | Your transaction reference ID. |
data.status |
string | ACCEPTED, COMPLETED, or FAILED. |
data.amount |
float | Transaction amount. |
data.currency |
string | Transaction currency. |
data.selcomReceipt |
string | Selcom internal transaction identifier. |
data.transDatetime |
string | Transaction datetime (Y-m-d H:i:s). |
data.senderAccount |
string | Sender account number (resolved from your API credentials). |
data.senderName |
string | Sender account name (resolved from your API credentials). |
result |
string | Transaction result based on actual status. See API Response — Result column. |
resultcode |
string | Result code based on actual transaction status. See API Response — Errorcode column. |
Destination Shortcodes
| Destination Name | Destination Shortcode | Reference Type | Lookup |
|---|---|---|---|
| Selcom Bank/Selcom Pesa/Selcom Business | SELCOM |
NUMERIC | Enabled |
| Absa Bank | ABSA |
NUMERIC | Enabled |
| Access Bank | BANCABC |
NUMERIC | Enabled |
| Akiba Bank | ACB |
NUMERIC | Enabled |
| Amana Bank | AMANA |
NUMERIC | Enabled |
| Azania Bank | AZANIA |
NUMERIC | Enabled |
| Bank of Africa | BOA |
NUMERIC | Enabled |
| Bank of Baroda | BOBTZ |
NUMERIC | Enabled |
| Bank of India | BOI |
NUMERIC | Enabled |
| Bank of Tanzania | BOT |
NUMERIC | No |
| Canara Bank | CANARA |
NUMERIC | Enabled |
| Citi Bank | CITI |
NUMERIC | Enabled |
| CRDB Bank | CRDB |
ALPHANUMERIC | Enabled |
| DCB Commercial Bank | DCB |
NUMERIC | Enabled |
| Diamond Trust Bank | DTB |
NUMERIC | Enabled |
| Ecobank | ECOBANK |
NUMERIC | Enabled |
| Equity Bank | EQUITY |
NUMERIC | Enabled |
| Exim Bank | EXIM |
NUMERIC | Enabled |
| Finca Microfinance Bank | FINCA |
NUMERIC | Enabled |
| Guaranty Trust Bank | GTBANK |
NUMERIC | Enabled |
| Habib African Bank | HABIB |
NUMERIC | Enabled |
| I&M Bank | IMBANK |
NUMERIC | Enabled |
| International Commercial Bank | ICB |
NUMERIC | Enabled |
| KCB Bank | KCB |
NUMERIC | Enabled |
| Letshego Bank | LETSHEGO |
NUMERIC | Enabled |
| Maendeleo Bank | MAENDELEO |
NUMERIC | Enabled |
| Mkombozi Commercial Bank | MKOMBOZI |
NUMERIC | Enabled |
| MUCOBA Bank | MUCOBA |
NUMERIC | Enabled |
| Mwalimu Commercial Bank | MWALIMU |
NUMERIC | Enabled |
| Mwanga Hakika Bank | MWANGA |
NUMERIC | Enabled |
| National Bank of Commerce | NBC |
NUMERIC | Enabled |
| NCBA Bank | NCBA |
NUMERIC | Enabled |
| NMB Bank | NMB |
NUMERIC | Enabled |
| People's Bank of Zanzibar | PBZ |
NUMERIC | Enabled |
| Stanbic Bank | STANBIC |
NUMERIC | Enabled |
| Standard Chartered Bank | SCB |
NUMERIC | Enabled |
| Tanzania Commercial Bank | TCB |
NUMERIC | Enabled |
| Uchumi Commercial Bank | UCHUMI |
NUMERIC | Enabled |
| United Bank for Africa | UBA |
NUMERIC | Enabled |
| Airtel Money | AIRTELMONEY |
NUMERIC | Enabled |
| Halo Pesa | HALOPESA |
NUMERIC | Enabled |
| Mixx by Yas | MIXXBYYAS |
NUMERIC | Enabled |
| TTCL Pesa | TTCLPESA |
NUMERIC | Enabled |
| Vodacom M-pesa | MPESA |
NUMERIC | Enabled |
Sample Response
Examples
{
"transId": "TXN20250715093045ABC",
"recipientFiCode": "CRDB",
"recipientAccount": "01234567890",
"recipientName": "John Doe",
"amount": 50000,
"purpose": "SALARY",
"remarks": "Monthly salary payment"
}
{
"success": true,
"error_code": 1,
"message": "Transaction processed successfully.",
"result": "INPROGRESS",
"resultcode": "111",
"data": {
"trans_id": "TXN20250715093045ABC",
"selcom_receipt": "SLK-987654321",
"status": "ACCEPTED",
"amount": 50000,
"currency": "TZS"
}
}
{
"transId": "TXN20250715093210XYZ",
"recipientFiCode": "MPESA",
"recipientAccount": "255712345678",
"recipientName": "Jane Smith",
"amount": 10000,
"purpose": "VENDOR",
"remarks": "Payment for services"
}
{
"success": true,
"error_code": 1,
"message": "Transaction processed successfully.",
"result": "INPROGRESS",
"resultcode": "111",
"data": {
"trans_id": "TXN20250715093210XYZ",
"selcom_receipt": "SLK-112233445",
"status": "ACCEPTED",
"amount": 10000,
"currency": "TZS"
}
}
{
"transId": "TXN20250715095900INT",
"recipientFiCode": "SELCOM",
"recipientAccount": "9876543210",
"recipientName": "Alex Mwangi",
"amount": 100000,
"purpose": "BUSINESS",
"remarks": "Inter-account settlement"
}
{
"success": true,
"error_code": 1,
"message": "Transaction processed successfully.",
"result": "SUCCESS",
"resultcode": "000",
"data": {
"trans_id": "TXN20250715095900INT",
"selcom_receipt": "SLK-998877665",
"status": "COMPLETED",
"amount": 100000,
"currency": "TZS"
}
}
Common Error Responses
{
"success": false,
"error_code": 651,
"message": "Validation failed.",
"result": "FAIL",
"resultcode": "651",
"data": {
"purpose": ["The selected purpose is invalid."]
}
}
{
"success": false,
"error_code": 643,
"message": "Duplicate transaction detected.",
"result": "FAIL",
"resultcode": "643",
"data": []
}
Statement API
Retrieve a paginated transaction statement for a linked organization account,
or export it as PDF, XLSX, CSV, or JSON. Date ranges can be specified via a preset
label or explicit from_date / to_date values.
/v1/statements
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
account_number |
string | Required | The account number associated with your API credentials. Must be an active account registered under your organization. |
preset |
string | Optional |
Preset date range shortcut. When provided, from_date and
to_date are computed automatically server-side.Allowed values: Today, Last 7 Days, This Month,
Last Month, Last 10 Transactions.
|
from_date |
string | Optional |
Start date in Y-m-d format (e.g., 2025-01-01).
Required when to_date is provided and no preset is given.
|
to_date |
string | Optional |
End date in Y-m-d format. Must be on or after from_date.
Required when from_date is provided and no preset is given.
|
per_page |
integer | Optional |
Number of transactions per page. Min: 1, Max: 500.
Defaults to 10.
|
order |
string | Optional |
Sort order of transactions. Allowed values: ASC, DESC.
Defaults to DESC.
|
export_type |
string | Optional |
Controls the response format. Allowed values: pdf, xlsx, csv, json.File types ( pdf, xlsx, csv) return a downloadable file URL instead of paginated data.json returns the same paginated JSON response as omitting this field entirely.
|
preset or a
from_date + to_date pair. If neither is provided the statement
returns an empty result set. The two approaches are mutually exclusive — preset values
auto-compute their own dates server-side.
Response Fields — Listing
| Field | Type | Description |
|---|---|---|
success |
boolean | true on success, false on failure. |
error_code |
integer | 1 on success; negative value on error (see Error Codes). |
message |
string | Human-readable status message. |
data.filters_applied |
object | Echo of the resolved filters used for the query (account_number, preset, from_date, to_date, per_page, order). |
data.account.account_name |
string | Registered organization name. |
data.account.account_number |
string | Formatted account number. |
data.account.sub_account_name |
string | Sub-account / business label for the queried account. |
data.currency |
string | Account currency (e.g., TZS). |
data.opening_balance |
float | Balance at the start of the requested date range. |
data.closing_balance |
float | Balance at the end of the requested date range. |
data.pagination.total |
integer | Total number of matching transactions. |
data.pagination.per_page |
integer | Records returned per page. |
data.pagination.current_page |
integer | Current page number. |
data.pagination.last_page |
integer | Last page number. |
data.transactions |
array | Array of transaction objects for the current page. |
result |
string | Transaction result based on actual status. See API Response — Result column. |
resultcode |
string | Result code based on actual transaction status. See API Response — Errorcode column. |
Response Fields — Export (pdf / xlsx / csv)
When export_type is pdf, xlsx, or csv, the listing fields are replaced by:
| Field | Type | Description |
|---|---|---|
data.export_type |
string | The requested export format (pdf, xlsx, or csv). |
data.file_url |
string | Temporary public URL to download the generated file. |
data.expires_at |
string | ISO 8601 timestamp indicating when the download link expires (1 hour from generation). |
data.filters_applied |
object | Echo of the resolved filters used for the export. |
result |
string | Transaction result based on actual status. See API Response — Result column. |
resultcode |
string | Result code based on actual transaction status. See API Response — Errorcode column. |
Example — Listing (Preset)
{
"account_number": "0123456789",
"preset": "This Month",
"per_page": 10,
"order": "DESC"
}
{
"success": true,
"error_code": 1,
"message": "Statement fetched successfully.",
"result": "SUCCESS",
"resultcode": "000",
"data": {
"filters_applied": {
"account_number": "0123456789",
"preset": "This Month",
"from_date": "2025-07-01",
"to_date": "2025-07-31",
"per_page": 10,
"order": "DESC"
},
"account": {
"account_name": "Acme Ltd",
"account_number": "01234 56789",
"sub_account_name": "Main Account"
},
"currency": "TZS",
"opening_balance": 500000,
"closing_balance": 450000,
"pagination": {
"total": 42,
"per_page": 10,
"current_page": 1,
"last_page": 5,
"from": 1,
"to": 10
},
"transactions": [...]
}
}
Example — Export
{
"account_number": "0123456789",
"from_date": "2025-07-01",
"to_date": "2025-07-31",
"export_type": "pdf"
}
{
"success": true,
"error_code": 1,
"message": "Statement exported successfully.",
"result": "SUCCESS",
"resultcode": "000",
"data": {
"export_type": "pdf",
"file_url": "https://your-domain.com/storage/exports/statement-1234.pdf",
"expires_at": "2025-07-15T10:30:00+00:00",
"filters_applied": {
"account_number": "0123456789",
"preset": "",
"from_date": "2025-07-01",
"to_date": "2025-07-31",
"per_page": 10,
"order": "ASC"
}
}
}
Example — Export (JSON)
Passing "export_type": "json" returns the same paginated JSON listing as omitting the field.
{
"account_number": "0123456789",
"from_date": "2025-07-01",
"to_date": "2025-07-31",
"export_type": "json",
"per_page": 10,
"order": "DESC"
}
{
"success": true,
"error_code": 1,
"message": "Statement fetched successfully.",
"result": "SUCCESS",
"resultcode": "000",
"data": {
"filters_applied": {
"account_number": "0123456789",
"preset": "",
"from_date": "2025-07-01",
"to_date": "2025-07-31",
"per_page": 10,
"order": "DESC"
},
"account": {
"account_name": "Acme Ltd",
"account_number": "01234 56789",
"sub_account_name": "Main Account"
},
"currency": "TZS",
"opening_balance": 500000,
"closing_balance": 450000,
"pagination": {
"total": 42,
"per_page": 10,
"current_page": 1,
"last_page": 5,
"from": 1,
"to": 10
},
"transactions": [...]
}
}
{
"success": false,
"error_code": 641,
"message": "Account number not found or not authorized.",
"result": "FAIL",
"resultcode": "641",
"data": []
}
API Response
The table below describes the possible transaction results returned in the API response, along with their associated error codes and meanings.
| Result | Errorcode | Description |
|---|---|---|
| SUCCESS | 000 |
Transaction successful. |
| INPROGRESS |
111
927
|
Transaction in progress — please query to know the exact status of the transaction. |
| AMBIGUOUS | 999 |
Transaction status unknown — wait for reconciliation. |
| FAIL | All others | Transaction failed. |
Error Codes
All error responses share a consistent structure. Use the error_code
integer to programmatically handle specific failure scenarios.
Error Response Structure
{
"success": false,
"error_code": 613,
"message": "Invalid or inactive API key.",
"result": "FAIL",
"resultcode": "613",
"data": []
}
Complete Error Code Reference
| error_code | HTTP Status | Category | Description |
|---|---|---|---|
000 |
200 | Success | Request completed successfully. |
611 |
403 | Authentication | Requesting IP address is not whitelisted. |
612 |
400 | Authentication | One or more required headers are missing (api-key, request-timestamp, digest). |
613 |
401 | Authentication | API key is invalid or has been deactivated. |
621 |
400/404 | General | Generic server-side error or resource not found. |
631 |
401 | Authentication | digest signature does not match. Check your formula or secret key. |
632 |
400 | Authentication | Request timestamp is stale (outside ±5 minute window) or format is invalid. Ensure your server clock is synchronized with UTC. |
641 |
400 | Balance | Account not found, not authorized, or account type not permitted for balance fetch. |
642 |
400 | Transaction | Transaction processing failed at the bank or wallet level. |
643 |
422 | Transaction | Duplicate transaction detected. A transaction with the same parameters was recently processed. |
646 |
403 | Transaction | Transaction exists but was not initiated by this API key (ownership violation). |
651 |
422 | Validation | Request body failed field validation. Check the data object for field-level error details. |