API Documentation - BumiPesa
← Rudi Mipangilio  |  Nyumbani

BumiPesa API

Unganisha mfumo wako wa malipo na BumiPesa. Pokea malipo ya USSD push moja kwa moja kwenye app au website yako bila usumbufu.

Domain mpya

Website na API sasa zinatumia https://pay.asportshd.com. Kama tayari ume-integrate, badili hostname ya API kwenye backend yako tu. Account, API credentials, order IDs na balances zako hazijabadilika.

Endpoint paths na headers zibaki kama zilivyo. Usitume upya payment/USSD iliyopo kwa ajili ya kujaribu domain mpya; tumia status, balance au sandbox. Utahitaji ku-login tena kwenye domain mpya.

Authentication

Kila ombi lazima liwe na API key yako kwenye header:

X-API-Key: bpk_your_api_key_here

Unaweza kupata API key yako kwenye Mipangilio.

Endpoints

1. Kukusanya Malipo

POST https://pay.asportshd.com/api/v1/collect

Tuma ombi la malipo kwa simu ya mteja kupitia USSD push.

ParameterTypeRequiredDescription
phonestringYesNamba ya simu (mfano: 0712345678 au 255712345678)
amountnumberYesKiasi cha TZS (min: 100)
descriptionstringNoMaelezo mafupi ya malipo (mfano: "Bidhaa")
webhook_urlstringNoURL ya kupokea taarifa (POST) pale status itakapokuwa "completed" au "failed"

Response (Success):

{
  "success": true,
  "message": "USSD push sent to phone",
  "order_id": "BP1706123456789",
  "amount": 10000,
  "net_amount": 9410,
  "fee": 590
}

2. Angalia Hali ya Malipo

GET https://pay.asportshd.com/api/v1/status/{order_id}

Angalia hali ya malipo kwa kutumia order_id.

{
  "success": true,
  "payment": {
    "order_id": "BP1706123456789",
    "status": "completed",
    "amount": 10000,
    "net_amount": 9410,
    "fee_amount": 590,
    "created_at": "2026-09-09T12:00:00Z",
    "completed_at": "2026-09-09T12:01:30Z"
  }
}

3. Angalia Salio

GET https://pay.asportshd.com/api/v1/balance
{
  "success": true,
  "wallet_balance": 94100,
  "float_balance": 0
}

Webhook Notifications

Ikiwa ulikuwa umeongeza webhook_url kwenye ombi la /api/v1/collect, BumiPesa itatuma POST mara moja (kila inapotokea) inapopokea matokeo ya completed au failed:

{
  "order_id": "BP1706123456789",
  "status": "completed",
  "amount": 10000,
  "net_amount": 9410,
  "fee_amount": 590,
  "created_at": "2026-09-09T12:00:00Z",
  "completed_at": "2026-09-09T12:01:30Z"
}

Mfano wa PHP

<?php
// BumiPesa PHP Integration Example

class BumiPesa {
    private $apiKey;
    private $baseUrl = 'https://pay.asportshd.com';

    public function __construct($apiKey) {
        $this->apiKey = $apiKey;
    }

    public function collectPayment($phone, $amount, $description = '', $webhookUrl = '') {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $this->baseUrl . '/api/v1/collect');
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json',
            'X-API-Key: ' . $this->apiKey
        ]);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
            'phone' => $phone,
            'amount' => $amount,
            'description' => $description,
            'webhook_url' => $webhookUrl
        ]));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $response = curl_exec($ch);
        curl_close($ch);
        return json_decode($response, true);
    }

    public function checkStatus($orderId) {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $this->baseUrl . '/api/v1/status/' . $orderId);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'X-API-Key: ' . $this->apiKey
        ]);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $response = curl_exec($ch);
        curl_close($ch);
        return json_decode($response, true);
    }

    public function getBalance() {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $this->baseUrl . '/api/v1/balance');
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'X-API-Key: ' . $this->apiKey
        ]);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $response = curl_exec($ch);
        curl_close($ch);
        return json_decode($response, true);
    }
}

// Jinsi ya Kutumia:
$bumi = new BumiPesa('bpk_your_api_key_here');

// Tuma ombi la malipo
$result = $bumi->collectPayment('0712345678', 10000, 'Bidhaa Yangu');
if (!empty($result['success'])) {
    echo 'Order ID: ' . $result['order_id'];
}
?>

Mfano wa JavaScript (Node.js)

const axios = require('axios');

const API_KEY = 'bpk_your_api_key_here';
const BASE_URL = 'https://pay.asportshd.com';

async function collectPayment(phone, amount, description) {
    const response = await axios.post(`${BASE_URL}/api/v1/collect`, {
        phone, amount, description
    }, {
        headers: { 'X-API-Key': API_KEY }
    });
    return response.data;
}

async function checkStatus(orderId) {
    const response = await axios.get(`${BASE_URL}/api/v1/status/${orderId}`, {
        headers: { 'X-API-Key': API_KEY }
    });
    return response.data;
}

// Mfano wa matumizi
collectPayment('0712345678', 10000, 'Bidhaa').then(result => {
    console.log('Order ID:', result.order_id);
});

Mfano wa Python

import requests

API_KEY = 'bpk_your_api_key_here'
BASE_URL = 'https://pay.asportshd.com'

def collect_payment(phone, amount, description=''):
    r = requests.post(
        f'{BASE_URL}/api/v1/collect',
        json={'phone': phone, 'amount': amount, 'description': description},
        headers={'X-API-Key': API_KEY}
    )
    return r.json()

def check_status(order_id):
    r = requests.get(
        f'{BASE_URL}/api/v1/status/{order_id}',
        headers={'X-API-Key': API_KEY}
    )
    return r.json()

# Mfano wa matumizi
res = collect_payment('0712345678', 10000, 'Bidhaa')
print('Result:', res)

Ada za Malipo

BumiPesa inakata ada kulingana na aina ya akaunti yako:

KiasiAda Personal (5.9%)UnapataAda Biashara (2.9%)Unapata
TZS 10,000TZS 590TZS 9,410TZS 290TZS 9,710
TZS 50,000TZS 2,950TZS 47,050TZS 1,450TZS 48,550
TZS 100,000TZS 5,900TZS 94,100TZS 2,900TZS 97,100

Msaada

Kama una maswali au unahitaji msaada, wasiliana nasi kupitia barua pepe: support@bumipesa.com

TEST
Integration testing

Sandbox · bila pesa halisi

Fungua Sandbox dashboard kwa account yako ileile na chagua Create TEST key. Copy key na secret mara moja. Email lazima iwe verified. Sandbox ni simulator ya BumiPesa; haiwasiliani na payment network wala kutuma USSD/SMS.

SandboxLive (existing)
API roothttps://pay.asportshd.com/api/sandbox/v1https://pay.asportshd.com/api/v1
Key prefixbp_test_bp_live_
MoneyTest wallet tuPesa halisi

Headers zote mbili bado zinahitajika: X-API-Key na X-API-Secret. Key ya environment tofauti inarudisha 403. Test responses zina "environment":"test", "livemode":false. Request fields na core response fields zinafanana na live.

POST /api/sandbox/v1/payments
X-API-Key: bp_test_...
X-API-Secret: your-test-secret
Content-Type: application/json

{
  "order_id": "DEV-ORDER-001",
  "buyer_name": "Test Customer",
  "buyer_email": "customer@example.com",
  "buyer_phone": "255700000001",
  "amount": 1000,
  "test_scenario": "success"
}

Namba yoyote yenye valid Tanzania mobile format inakubalika; haitapokea prompt. amount ni integer TZS 100–100,000,000. Test balance inaanza zero; successful test payments ndizo zinaiongeza. Sandbox create limit ni 240/hour kwa merchant; API limit pia ni 120 requests/minute kwa IP + key. Ukifikia limit utapata 429.

test_scenarioInitial resultOutcome
success (default)inprogress, auto_push sentcompleted + test credit
failedinprogress, auto_push sentfailed, no credit
pendinginprogress, auto_push sentInasubiri manual simulation
timeoutinprogress, delivery/auto_push uncertaincompleted baada ya refresh/worker

Simulator worker inakamilisha success, failed na timeout ndani ya takriban dakika moja (inaweza kuchelewa worker ikiwa busy). GET /payments/{order_id}?refresh=1 inakamilisha immediately. GET bila refresh inasoma stored status. Timeout ni simulated ambiguous provider response; HTTP connection yako haikatwi.

GET /api/sandbox/v1/payments/DEV-ORDER-001?refresh=1
GET /api/sandbox/v1/payments?status=completed&limit=50
GET /api/sandbox/v1/wallet

POST /api/sandbox/v1/payments/DEV-ORDER-001/simulate
{"status":"completed"}

Manual outcomes: completed, failed, cancelled, usercancelled, rejected. Terminal status haiwezi kubadilishwa; ukirudia outcome ileile credit na callback event haviongezwi tena.

Duplicate testing: create order ileile tena inarudisha 409. Hii ni sawa na live duplicate contract, si automatic successful replay. Baada ya lost response tumia existing order ID kucheck status. Repeated push kwa order ambayo tayari imepushiwa inarudisha 409.

Create only: "auto_push":false huacha created. Tumia POST /api/sandbox/v1/payments/{order_id}/push na {"phone":"255700000001"} kuanza. DELETE /api/sandbox/v1/payments/{order_id} inaweza cancel create-only order. Order IDs zinaweza kurudiwa kati ya test na live, lakini zitenganishe pia kwenye database ya app yako.

Test withdrawals

POST /api/sandbox/v1/withdrawals
{"amount":500,"phone":"255700000001"}

GET /api/sandbox/v1/withdrawals?limit=50
GET /api/sandbox/v1/withdrawals/123
POST /api/sandbox/v1/withdrawals/123/simulate
{"status":"paid"}

Tumia withdrawal_id iliyorudishwa na create. Request inareserve test balance na kubaki pending; simulate paid kumaliza au rejected kurudisha test balance. Insufficient balance ni 422. Live withdrawals bado zinafuata admin settlement; sandbox haiwezi kutoa pesa halisi.

Kwa walio-integrate tayari

Rudia testing bila kubadilisha production

Existing live keys, routes, order history na response fields zinaendelea kufanya kazi. Hakuna account mpya inayohitajika na live keys hazibadilishwi kuwa test keys.

  1. Tengeneza TEST key kwenye merchant account yako.
  2. Kwenye development/staging backend, weka API root, test key na test secret kama configuration moja.
  3. Tumia paths zilezile /payments, /payments/{id}/push, /withdrawals juu ya API root hiyo. Kama code ina hard-coded /api/v1, ibadilishe iwe configurable; usiongeze prefix mara mbili.
  4. Tenganisha development database, callbacks na fulfillment ili test payment isifungue huduma ya production. Thibitisha expected environment kwenye kila response.
  5. Jaribu success, failure, pending, timeout, duplicate create/push, status refresh, withdrawal reject/paid na callback retry.
  6. Ukienda production, tumia live root + original live key/secret na ondoa test_scenario, callback_url pamoja na simulation calls. Fanya live verification chache za kiasi kidogo kabla ya launch.
# Development backend .env
BUMIPESA_API_ROOT=https://pay.asportshd.com/api/sandbox/v1
BUMIPESA_API_KEY=bp_test_...
BUMIPESA_API_SECRET=your-test-secret

# Production backend .env (existing live credentials)
BUMIPESA_API_ROOT=https://pay.asportshd.com/api/v1
BUMIPESA_API_KEY=bp_live_...
BUMIPESA_API_SECRET=your-live-secret

Fail closed: ikiwa request imerudisha 403 kwa key/root mismatch, rekebisha configuration. Usifanye fallback automatically kwenda live. Sandbox fields zikitumwa kwenye live create zinakataliwa kabla ya payment kuanza.

Sandbox inathibitisha integration logic. Haitoi proof ya mobile network uptime, real USSD, fees, settlement timing au provider payout activation. Live polling/reconciliation flow iliyopo ibaki.

Sandbox only

Signed test callbacks

Optional: ongeza "callback_url":"https://dev.example.com/webhooks/bumipesa-test" kwenye create ya sandbox. Terminal payment itaweka callback kwenye queue; errors za callback hazibadilishi payment status. Tumia public HTTPS hostname, port 443. Local/private IPs, credentials kwenye URL, na redirects haziruhusiwi.

Hii ni sandbox callback facility. Existing live API bado hutumia status polling; callback_url haijaongezwa kwenye live collection API. Usibadilishe live fulfillment iwe callback-only.

GET /api/sandbox/v1/webhook-secret
GET /api/sandbox/v1/events
POST /api/sandbox/v1/events/bptest_evt_.../replay

Secret ni ya test callbacks kwa merchant account yako; ihifadhi backend. Endpoint ya secret inahitaji test API key + secret. Replay inaruhusiwa kwa delivered/failed event tu, max 10/hour; inatumia event ID na payload ileile ili ujaribu duplicate handling.

X-BumiPesa-Environment: test
X-BumiPesa-Event: bptest_evt_...
X-BumiPesa-Timestamp: unix-seconds
X-BumiPesa-Signature: sha256=hex-hmac

{
  "id": "bptest_evt_...",
  "type": "payment.completed",
  "environment": "test",
  "livemode": false,
  "data": {"payment": {"order_id":"DEV-ORDER-001","status":"completed", "amount_minor":1000}}
}

Payload example imefupishwa; actual data.payment ina fields zote za status response. Verify HMAC-SHA256 ya timestamp + "." + rawBody kwa test webhook secret, tumia constant-time comparison na timestamp tolerance ya dakika 5.

<?php
$raw = file_get_contents('php://input');
$timestamp = $_SERVER['HTTP_X_BUMIPESA_TIMESTAMP'] ?? '';
$signature = $_SERVER['HTTP_X_BUMIPESA_SIGNATURE'] ?? '';
$secret = getenv('BUMIPESA_TEST_WEBHOOK_SECRET');
if (!$secret || !ctype_digit($timestamp) || abs(time() - (int)$timestamp) > 300) {
    http_response_code(401); exit;
}
$expected = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $raw, $secret);
if (!hash_equals($expected, $signature)) { http_response_code(401); exit; }
$event = json_decode($raw, true);
if (!is_array($event) || ($event['environment'] ?? '') !== 'test'
    || ($event['livemode'] ?? true) !== false) { http_response_code(400); exit; }
// In your DEVELOPMENT database transaction:
// 1. Deduplicate event['id'] with a unique constraint.
// 2. Match order_id, amount_minor and currency to your test order.
// 3. Persist the payment state and any test fulfillment atomically.
// Return 2xx only after durable processing; duplicate events may return 2xx.
http_response_code(204);

Maximum 5 delivery attempts: initial + retry baada ya ~1m, 5m, 15m na 1h (worker huongeza scheduling delay). Kila delivery ina timestamp/signature mpya; event ID na body vinabaki vilevile. Endpoint yako irudishe 2xx haraka. Timeout/non-2xx inaretry; hakuna redirect follow. Check /events au Sandbox dashboard kuona attempts na HTTP result. Withdrawals hazina callbacks kwenye toleo hili.