UnifiedPay API Documentation
Integrate M-Pesa payments with a few lines of code. Free forever.
🚀 Quick Start
Base URL
https://unifiedpay.co.ke
All requests must be HTTPS POST.
POST Validate Credentials
/auth/cred/{consumer_key}/{consumer_secret}/url
Check if your API credentials are valid and active.
Request
No request body required.
Response
Success (200)
{
"ResultCode": 0,
"message": "Credentials valid",
"shortcode": "4201775"
}
Error (401)
{
"ResultCode": 401,
"errorMessage": "Invalid API credentials"
}
curl -X POST https://unifiedpay.co.ke/auth/cred/YOUR_CONSUMER_KEY/YOUR_CONSUMER_SECRET/url
<?php
$url = 'https://unifiedpay.co.ke/auth/cred/YOUR_CONSUMER_KEY/YOUR_CONSUMER_SECRET/url';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);
if ($result['ResultCode'] == 0) {
echo "Credentials valid. Shortcode: " . $result['shortcode'];
} else {
echo "Error: " . $result['errorMessage'];
}
?>
import requests
url = "https://unifiedpay.co.ke/auth/cred/YOUR_CONSUMER_KEY/YOUR_CONSUMER_SECRET/url"
response = requests.post(url)
data = response.json()
if data['ResultCode'] == 0:
print(f"Valid. Shortcode: {data['shortcode']}")
else:
print(f"Error: {data['errorMessage']}")
fetch('https://unifiedpay.co.ke/auth/cred/YOUR_CONSUMER_KEY/YOUR_CONSUMER_SECRET/url', {
method: 'POST'
})
.then(res => res.json())
.then(data => {
if (data.ResultCode === 0) {
console.log('Valid. Shortcode:', data.shortcode);
} else {
console.error('Error:', data.errorMessage);
}
});
POST Send STK Push
/auth/cred/{consumer_key}/{consumer_secret}/sendstk
Initiate M-Pesa payment prompt on customer's phone.
Request Body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
| amount | integer | Yes | Amount to pay (KES, whole numbers only) |
| msisdn | string | Yes | Customer phone number (e.g., 254712345678 or 0712345678) |
| reference | string | Yes | Payment reference/description (max 20 chars) |
| account_number | string | No | Account number for Paybill (optional) |
Response
Success (200)
{
"ResponseCode": "0",
"success": true,
"message": "STK push initiated",
"transaction_request_id": "FL20240315143022123",
"MerchantRequestID": "2d5c-4e7b-8f1a-9c3d6e8f1a2b",
"CheckoutRequestID": "ws_CO_1234567890"
}
Error (400/500)
{
"ResultCode": 400,
"errorMessage": "Missing required fields"
}
curl -X POST https://unifiedpay.co.ke/auth/cred/YOUR_KEY/YOUR_SECRET/sendstk \
-H "Content-Type: application/json" \
-d '{
"amount": "1",
"msisdn": "254712345678",
"reference": "Test Payment",
"account_number": "INV001"
}'
<?php
$url = 'https://unifiedpay.co.ke/auth/cred/YOUR_KEY/YOUR_SECRET/sendstk';
$data = [
'amount' => 1,
'msisdn' => '254712345678',
'reference' => 'Test Payment',
'account_number' => 'INV001'
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);
if ($result['ResponseCode'] == '0') {
echo "STK sent. Transaction ID: " . $result['transaction_request_id'];
} else {
echo "Error: " . ($result['errorMessage'] ?? 'Unknown error');
}
?>
import requests
import json
url = "https://unifiedpay.co.ke/auth/cred/YOUR_KEY/YOUR_SECRET/sendstk"
payload = {
"amount": 1,
"msisdn": "254712345678",
"reference": "Test Payment",
"account_number": "INV001"
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
data = response.json()
if data.get('ResponseCode') == '0':
print(f"STK sent. Transaction ID: {data['transaction_request_id']}")
else:
print(f"Error: {data.get('errorMessage')}")
fetch('https://unifiedpay.co.ke/auth/cred/YOUR_KEY/YOUR_SECRET/sendstk', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
amount: 1,
msisdn: '254712345678',
reference: 'Test Payment',
account_number: 'INV001'
})
})
.then(res => res.json())
.then(data => {
if (data.ResponseCode === '0') {
console.log('STK sent. ID:', data.transaction_request_id);
} else {
console.error('Error:', data.errorMessage);
}
});
POST Transaction Status
/auth/cred/{consumer_key}/{consumer_secret}/sendstatus
Query the status of a previously initiated STK push transaction.
Request Body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
| transaction_request_id | string | Yes | The ID returned from the /sendstk endpoint |
Response
Success (200)
{
"ResultCode": "200",
"ResultDesc": "Success",
"CheckoutRequestID": "ws_CO_1234567890",
"MerchantRequestID": "2d5c-4e7b-8f1a-9c3d6e8f1a2b",
"TransactionStatus": "Completed",
"TransactionCode": "0",
"TransactionReceipt": "QKJ8H7G9L2",
"TransactionAmount": "1",
"Msisdn": "254712345678",
"TransactionDate": "20240315143022",
"TransactionReference": "Test Payment"
}
Pending
{
"ResultCode": "200",
"ResultDesc": "Transaction is pending",
"TransactionStatus": "Pending",
...
}
curl -X POST https://unifiedpay.co.ke/auth/cred/YOUR_KEY/YOUR_SECRET/sendstatus \
-H "Content-Type: application/json" \
-d '{"transaction_request_id": "FL20240315143022123"}'
<?php
$url = 'https://unifiedpay.co.ke/auth/cred/YOUR_KEY/YOUR_SECRET/sendstatus';
$data = ['transaction_request_id' => 'FL20240315143022123'];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);
echo "Status: " . $result['TransactionStatus'];
if ($result['TransactionStatus'] == 'Completed') {
echo " Receipt: " . $result['TransactionReceipt'];
}
?>
import requests
url = "https://unifiedpay.co.ke/auth/cred/YOUR_KEY/YOUR_SECRET/sendstatus"
payload = {"transaction_request_id": "FL20240315143022123"}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
data = response.json()
print(f"Status: {data['TransactionStatus']}")
if data['TransactionStatus'] == 'Completed':
print(f"Receipt: {data['TransactionReceipt']}")
fetch('https://unifiedpay.co.ke/auth/cred/YOUR_KEY/YOUR_SECRET/sendstatus', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ transaction_request_id: 'FL20240315143022123' })
})
.then(res => res.json())
.then(data => {
console.log('Status:', data.TransactionStatus);
if (data.TransactionStatus === 'Completed') {
console.log('Receipt:', data.TransactionReceipt);
}
});
Error Codes Reference
0 - Success
1 - Insufficient balance
1032 - Cancelled by user
1037 - Timeout (user unreachable)
2001 - Invalid initiator info
1019 - Invalid receiving organization
401 - Invalid API credentials
400 - Missing required fields
404 - Transaction not found
500 - Server error
💡 Note: The callback URL is automatically handled by UnifiedPay. You can optionally set a webhook URL in your dashboard to receive real-time payment notifications.