Core API
Webhooks
Receive real-time payment notifications. Configure endpoints, verify signatures, and handle events.
Overview
Webhooks let your server receive instant HTTP notifications when payments succeed, fail, or change status. No polling required.
Register a Webhook
bash
curl -X POST "https://paynexus.co.ke/api/webhooks/register" \
-H "X-API-Key: sk_your_secret_key_here" \
-H "Content-Type: application/json" \
-d '{
"name": "My Payment Webhook",
"url": "https://your-domain.com/webhook/mpesa",
"events": ["payment.completed", "payment.failed"]
}'
Webhook Payload
Successful Payment
json
{
"event": "payment.completed",
"timestamp": "2026-01-27T10:17:18+03:00",
"data": {
"payment_id": 123,
"merchant_id": 456,
"reference": "PNXABC123DEF",
"amount": "100.00",
"currency": "KES",
"phone": "254746990866",
"status": "completed",
"account_reference": "ORDER_123",
"checkout_request_id": "ws_CO_27012026101718139746990866",
"transaction_id": "OEI2AK4Q16",
"provider_transaction_id": "OEI2AK4Q16",
"provider_reference": "Success",
"payer_name": "M-Pesa 254746990866"
}
}
Failed Payment
json
{
"event": "payment.failed",
"timestamp": "2026-01-27T10:17:18+03:00",
"data": {
"payment_id": 123,
"reference": "PNXABC123DEF",
"amount": "100.00",
"status": "failed",
"failure_reason": "Insufficient funds",
"user_message": "The request was cancelled by the user",
"retry_possible": false
}
}
Signature Verification
All webhooks include an HMAC signature in the X-PayNexus-Signature header. Verify it to confirm authenticity:
php
function verifyWebhookSignature(string $payload, string $signature, string $secret): bool
{
$expectedSignature = hash_hmac('sha256', $payload, $secret);
return hash_equals($expectedSignature, $signature);
}
$signature = $_SERVER['HTTP_X_PAYNEXUS_SIGNATURE'] ?? '';
$payload = file_get_contents('php://input');
if (!verifyWebhookSignature($payload, $signature, $_ENV['PAYNEXUS_WEBHOOK_SECRET'])) {
http_response_code(401);
exit;
}
echo json_encode(['ResultCode' => 0, 'ResultDesc' => 'Received']);
Available Events
| Event | Description |
|---|---|
payment.completed | Payment successful |
payment.failed | Payment failed |
payment.initiated | Payment initiated |
invoice.created | Invoice created |
invoice.paid | Invoice paid |
invoice.overdue | Invoice overdue |
subscription.created | Subscription created |
subscription.canceled | Subscription canceled |
Best Practices
Return 200 quickly
Process webhooks asynchronously. Return a 200 response immediately to prevent retries.
Verify signatures
Always verify the X-PayNexus-Signature header before processing.
Handle duplicates
Webhooks may be delivered more than once. Use the reference or payment_id to deduplicate.