KabiPay|Docs
Get API key
DocsGetting startedIntroduction

KabiPay API

The KabiPay API allows you to accept payments, manage settlements, and build financial products for East Africa. Our REST API uses standard HTTP verbs, returns JSON, and uses API keys for authentication.

Base URL

HTTPShttps://api.kabipay.co.tz/v1

Authentication

All API requests must include your secret API key in the Authorization header as a Bearer token. You can find your API keys in the Dashboard → Settings → API Keys.

bash
1curl https://api.kabipay.co.tz/v1/payments \
2 -H class="text-[#f1fa8c]">"Authorization: Bearer sk_live_kabi_xK9aB3cD7eF2gH5iJ8" \
3 -H class="text-[#f1fa8c]">"Content-Type: application/json"
Keep your secret key private. Never expose it in client-side code, public repos, or logs. Use environment variables. Rotate it immediately if compromised.

Installation

Install the official KabiPay SDK for your language:

node
1npm install kabipay

Then initialise the client:

node
1class="text-[#ff79c6]">const KabiPay = class="text-[#ff79c6]">require(class="text-[#f1fa8c]">'kabipay');
2
3class="text-[#ff79c6]">const kabi = new KabiPay({
4 secretKey: process.env.KABIPAY_SECRET_KEY,
5});

Create a payment

Use the payments.create method to initiate a payment. The customer will receive a push prompt on their mobile device.

POST/v1/payments
node
1class="text-[#ff79c6]">const payment = class="text-[#ff79c6]">await kabi.payments.create({
2 amount: 50000, // TZS 50,000
3 currency: class="text-[#f1fa8c]">'TZS',
4 method: class="text-[#f1fa8c]">'mpesa',
5 phone: class="text-[#f1fa8c]">'+255712345678',
6 description: class="text-[#f1fa8c]">'Order #1042',
7 idempotency_key: class="text-[#f1fa8c]">'order-1042-v1',
8 metadata: {
9 customer_id: class="text-[#f1fa8c]">'cust_xK9aB3',
10 order_id: class="text-[#f1fa8c]">'1042',
11 },
12});
13
14console.log(payment.id); // txn_2Xk9aB...
15console.log(payment.status); // pending
Always include an idempotency_key — a unique string per payment attempt. This prevents duplicate charges if the request is retried due to a network timeout.

Response

json
1{
2 class="text-[#f1fa8c]">"id": class="text-[#f1fa8c]">"txn_2Xk9aB3cD7eF",
3 class="text-[#f1fa8c]">"object": class="text-[#f1fa8c]">"payment",
4 class="text-[#f1fa8c]">"amount": 50000,
5 class="text-[#f1fa8c]">"currency": class="text-[#f1fa8c]">"TZS",
6 class="text-[#f1fa8c]">"status": class="text-[#f1fa8c]">"pending",
7 class="text-[#f1fa8c]">"method": class="text-[#f1fa8c]">"mpesa",
8 class="text-[#f1fa8c]">"phone": class="text-[#f1fa8c]">"+255712345678",
9 class="text-[#f1fa8c]">"description": class="text-[#f1fa8c]">"Order #1042",
10 class="text-[#f1fa8c]">"idempotency_key": class="text-[#f1fa8c]">"order-1042-v1",
11 class="text-[#f1fa8c]">"created_at": class="text-[#f1fa8c]">"2025-01-20T10:32:00Z",
12 class="text-[#f1fa8c]">"updated_at": class="text-[#f1fa8c]">"2025-01-20T10:32:01Z",
13 class="text-[#f1fa8c]">"metadata": {
14 class="text-[#f1fa8c]">"customer_id": class="text-[#f1fa8c]">"cust_xK9aB3",
15 class="text-[#f1fa8c]">"order_id": class="text-[#f1fa8c]">"1042"
16 },
17 class="text-[#f1fa8c]">"webhook_url": class="text-[#f1fa8c]">"https://yoursite.com/webhook",
18 class="text-[#f1fa8c]">"livemode": true
19}

Payment statuses

StatusDescriptionFinal?
pendingPayment initiated, awaiting customer actionNo
successPayment confirmed and funds receivedYes
failedCustomer cancelled, timed out, or insufficient fundsYes
refundedPayment was reversed and funds returnedYes

Webhooks

KabiPay sends webhook events to notify your server of payment state changes. Configure your endpoint URL in the Dashboard → Settings → Webhooks.

Webhook event types

payment.success
payment.failed
payment.pending
payout.initiated
payout.complete
payout.failed
refund.created
refund.complete

Handle webhook events

node
1class="text-[#ff79c6]">const express = class="text-[#ff79c6]">require(class="text-[#f1fa8c]">'express');
2class="text-[#ff79c6]">const app = express();
3
4app.post(class="text-[#f1fa8c]">'/webhook', express.raw({ type: class="text-[#f1fa8c]">'application/json' }), (req, res) => {
5 class="text-[#ff79c6]">const sig = req.headers[class="text-[#f1fa8c]">'kabipay-signature'];
6
7 class="text-[#ff79c6]">let event;
8 class="text-[#ff79c6]">try {
9 event = kabi.webhooks.constructEvent(
10 req.body,
11 sig,
12 process.env.WEBHOOK_SECRET,
13 );
14 } class="text-[#ff79c6]">catch (err) {
15 class="text-[#ff79c6]">return res.status(400).send(class="text-[#f1fa8c]">`Webhook error: ${err.message}`);
16 }
17
18 class="text-[#ff79c6]">switch (event.type) {
19 class="text-[#ff79c6]">case class="text-[#f1fa8c]">'payment.success':
20 fulfillOrder(event.data.metadata.order_id);
21 class="text-[#ff79c6]">break;
22 class="text-[#ff79c6]">case class="text-[#f1fa8c]">'payment.failed':
23 notifyCustomer(event.data.phone);
24 class="text-[#ff79c6]">break;
25 }
26
27 res.json({ received: true });
28});
Always verify the signature. KabiPay signs every webhook with an HMAC-SHA256 signature. Verify it using the kabipay-signature header and your webhook secret to prevent spoofed requests.

Rate limits

PlanRequests / secondBurst
Starter50200
Business5002,000
EnterpriseCustomCustom

Official SDKs

🟢
Node.js
JavaScript/TypeScript
v2.4.1
🐍
Python
Python 3.8+
v1.9.0
🐘
PHP
PHP 7.4+
v3.1.2
📱
Android
Kotlin/Java
v1.2.0

Ready to build?

Get your API keys and start accepting payments in minutes.