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.
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.
Tuma ombi la malipo kwa simu ya mteja kupitia USSD push.
| Parameter | Type | Required | Description |
|---|---|---|---|
phone | string | Yes | Namba ya simu (mfano: 0712345678 au 255712345678) |
amount | number | Yes | Kiasi cha TZS (min: 100) |
description | string | No | Maelezo mafupi ya malipo (mfano: "Bidhaa") |
webhook_url | string | No | URL 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
}
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"
}
}
{
"success": true,
"wallet_balance": 94100,
"float_balance": 0
}
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"
}
<?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'];
}
?>
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);
});
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)
BumiPesa inakata ada kulingana na aina ya akaunti yako:
| Kiasi | Ada Personal (5.9%) | Unapata | Ada Biashara (2.9%) | Unapata |
|---|---|---|---|---|
| TZS 10,000 | TZS 590 | TZS 9,410 | TZS 290 | TZS 9,710 |
| TZS 50,000 | TZS 2,950 | TZS 47,050 | TZS 1,450 | TZS 48,550 |
| TZS 100,000 | TZS 5,900 | TZS 94,100 | TZS 2,900 | TZS 97,100 |
Kama una maswali au unahitaji msaada, wasiliana nasi kupitia barua pepe: support@bumipesa.com
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.
| Sandbox | Live (existing) | |
|---|---|---|
| API root | https://pay.asportshd.com/api/sandbox/v1 | https://pay.asportshd.com/api/v1 |
| Key prefix | bp_test_ | bp_live_ |
| Money | Test wallet tu | Pesa 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_scenario | Initial result | Outcome |
|---|---|---|
success (default) | inprogress, auto_push sent | completed + test credit |
failed | inprogress, auto_push sent | failed, no credit |
pending | inprogress, auto_push sent | Inasubiri manual simulation |
timeout | inprogress, delivery/auto_push uncertain | completed 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.
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.
Existing live keys, routes, order history na response fields zinaendelea kufanya kazi. Hakuna account mpya inayohitajika na live keys hazibadilishwi kuwa test keys.
/payments, /payments/{id}/push, /withdrawals juu ya API root hiyo. Kama code ina hard-coded /api/v1, ibadilishe iwe configurable; usiongeze prefix mara mbili.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.
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.