Ready-to-use code examples for integrating GrandPay M-Pesa payments into your application.
Initiate an M-Pesa STK push payment request to a customer's phone.
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => 'https://grandpay.co.ke/api/v1/stk-push',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer YOUR_API_KEY',
'Content-Type: application/json',
'Accept: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'phone' => '254712345678',
'amount' => 500,
'reference' => 'ORDER-001',
'callback' => 'https://yoursite.com/callback',
]),
]);
$response = curl_exec($curl);
curl_close($curl);
echo $response;
const response = await fetch('https://grandpay.co.ke/api/v1/stk-push', {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
phone: '254712345678',
amount: 500,
reference: 'ORDER-001',
callback: 'https://yoursite.com/callback',
}),
});
const data = await response.json();
console.log(data);
{
"success": true,
"message": "STK push sent successfully",
"data": {
"transaction_id": "GP-TXN-000123",
"checkout_request_id": "ws_CO_12022026...",
"status": "pending"
}
}
All API requests require a Bearer token. Get your API key from the Account Settings page.
// Include this header in every API request
Authorization: Bearer your_api_key_here
// Example with cURL
curl -X GET https://grandpay.co.ke/api/v1/balance \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"
Query the status of a previously initiated transaction.
// PHP - Check transaction status
$response = Http::withToken('YOUR_API_KEY')
->get('https://grandpay.co.ke/api/v1/transaction/GP-TXN-000123');
$transaction = $response->json();
if ($transaction['data']['status'] === 'Completed') {
// Payment successful - fulfill order
} else {
// Payment pending or failed
}
Receive real-time payment notifications via webhooks. Set your webhook URL in Account Settings.
// routes/api.php
Route::post('/grandpay/webhook', [WebhookController::class, 'handle']);
// app/Http/Controllers/WebhookController.php
public function handle(Request $request)
{
$payload = $request->all();
switch ($payload['event']) {
case 'payment.completed':
// Update order status
Order::where('reference', $payload['reference'])
->update(['status' => 'paid']);
break;
case 'payment.failed':
// Handle failed payment
Log::warning('Payment failed', $payload);
break;
}
return response()->json(['status' => 'ok']);
}
{
"event": "payment.completed",
"transaction_id": "GP-TXN-000123",
"reference": "ORDER-001",
"amount": 500,
"phone": "254712345678",
"status": "Completed",
"mpesa_receipt": "SHK7ABCDEF",
"timestamp": "2026-02-16T15:30:00Z"
}
Check your wallet balance and initiate withdrawals programmatically.
// Check wallet balance
const balance = await fetch('https://grandpay.co.ke/api/v1/wallet/balance', {
headers: { 'Authorization': `Bearer ${apiKey}` }
});
// Response
{
"success": true,
"data": {
"balance": 15000.00,
"currency": "KES",
"pending_withdrawals": 0
}
}
// Initiate withdrawal
const withdrawal = await fetch('https://grandpay.co.ke/api/v1/wallet/withdraw', {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
amount: 5000,
phone: '254712345678',
}),
});
GrandPay uses standard HTTP status codes. Here are common error responses:
// Error response format
{
"success": false,
"message": "Insufficient wallet balance",
"errors": {
"amount": ["The amount exceeds your available balance"]
}
}
Create your GrandPay account and start accepting M-Pesa payments in minutes.
Get Started Free