M-PESA Gateway API v1 β Partner Integration Guide
This guide is strictly focused on how partners interact with the gateway and the callback payloads the gateway will forward to the partnerβs endpoint. All examples are server-side (recommended).
Overview
Partners call the gateway to request STK Push payments. The gateway processes the request and will forward a summarized result to the partner's callback_url. For the gateway to accept a request, callback_url is required. Requests without it will be rejected.
π Base URL
https://payments.kodawaritechnologies.com/api/v1
π Authentication
Include your partner API key in the header X-API-KEY. Keep it secret and server-side.
| Header | Purpose | Required |
|---|---|---|
X-API-KEY | Partner API key (secret) | Yes |
Content-Type | application/json | Yes |
X-Idempotency-Key | Prevent duplicate requests | Recommended |
π³ Initiate Payment β STK Push
Endpoint: POST https://payments.kodawaritechnologies.com/api/v1/mpesa/stk_push
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
| phone | string | Yes | 2547XXXXXXXX (international format) |
| amount | number | Yes | Amount in KES |
| reference | string | No | Partner reference (optional) |
| callback_url | string | Yes β required | URL the gateway will POST the summarized result to (required) |
curl -X POST "https://payments.kodawaritechnologies.com/api/v1/mpesa/stk_push" \
-H "Content-Type: application/json" \
-H "X-API-KEY: YOUR_CLIENT_API_KEY" \
-H "X-Idempotency-Key: $(uuidgen)" \
-d '{
"phone":"254712345678",
"amount":150,
"reference":"INV-2025-001",
"callback_url":"https://yourapp.example.com/payment_callback"
}'
Accepted / success response
{
"status": "success",
"transaction_id": 102,
"message": "STK Push accepted for processing"
}
Rejected request (missing callback_url)
HTTP 400 Bad Request
{
"status": "error",
"message": "callback_url is required"
}
Idempotent duplicate response
{
"status": "duplicate",
"transaction_id": 102,
"message": "Duplicate request (idempotency)"
}
π What the gateway forwards to your callback_url
When the transaction completes (success or fail), the gateway will POST a summarized JSON payload to the callback_url you supplied. The gateway will also store the full raw payload for auditing.
{
"transaction_id": 102,
"merchant_request_id": "29115-34620561-1",
"checkout_request_id": "ws_CO_22052025084523789",
"result_code": 0,
"result_desc": "Processed successfully.",
"amount": 150,
"mpesa_receipt": "RKT7S9T2UB",
"transaction_date": "2025-05-22T08:47:05Z",
"phone": "254712345678",
"status": "successful"
}
β Recommended callback handling (partner)
Your callback endpoint must:
- Accept an HTTP POST with JSON.
- Return HTTP 200 quickly to acknowledge receipt.
- Update your internal records and perform any business logic (e.g., credit user account) when you receive a successful
status. - Validate payload authenticity if you implement HMAC or other verification (optional β we can add an HMAC option later).
# Example partner callback endpoint (pseudo)
POST /payment_callback
Content-Type: application/json
# gateway will send JSON like the 'partner-callback' example above
# MUST return 200 OK to acknowledge
π§ Client examples (server-side)
Always call the gateway from server-side code. Do not embed X-API-KEY in front-end code.
Python (requests)
import os, requests, uuid
API_KEY = os.getenv('MPESA_GATEWAY_API_KEY')
URL = "https://payments.kodawaritechnologies.com/api/v1/mpesa/stk_push"
payload = {"phone":"254712345678","amount":150,"reference":"INV-2025-001","callback_url":"https://yourapp.example.com/payment_callback"}
headers = {"Content-Type":"application/json","X-API-KEY": API_KEY,"X-Idempotency-Key": str(uuid.uuid4())}
resp = requests.post(URL, json=payload, headers=headers, timeout=30)
print(resp.status_code, resp.json())
PHP (cURL)
<?php
$apiKey = getenv('MPESA_GATEWAY_API_KEY');
$url = 'https://payments.kodawaritechnologies.com/api/v1/mpesa/stk_push';
$data = json_encode(['phone'=>'254712345678','amount'=>150,'reference'=>'INV-2025-001','callback_url'=>'https://yourapp.example.com/payment_callback']);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json','X-API-KEY: '.$apiKey,'X-Idempotency-Key: '.bin2hex(random_bytes(8))]);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch); curl_close($ch);
echo $response;
?>
π Best practices
- Every request must include
callback_url. Missingcallback_urlresults in a 400 rejection. - Use
X-Idempotency-Keyto prevent duplicate transactions. - Keep
X-API-KEYserver-side (never in browser JS). - Persist transaction IDs returned by gateway for reconciliation.
- Use HTTPS for your callback endpoint and validate incoming requests if possible.
π€ Support
Email: support@kodawaritechnologies.com
Phone: 254 768 737 559 / 254 755 977 252
Version: API v1.0 β’ Last Updated: November 7, 2025 β’ Status: Production