Webhooks
When you provide a callback_url on a payment request, SwiftWallet POSTs the transaction result to that URL after M-Pesa processes it. The payload structure varies by transaction type as shown below.
Callback Types
Stk callback
Sent when an STK Push payment is completed or fails. Includes M-Pesa result data and optional channel info.
{
"success": true,
"transaction_id": 789,
"external_reference": "INV-12345",
"checkout_request_id": "ws_CO_12345...",
"merchant_request_id": "12345-67890",
"status": "completed",
"timestamp": "2024-12-31T12:30:05+03:00",
"service_fee": 5,
"result": {
"ResultCode": 0,
"ResultDesc": "Success",
"Amount": 100,
"MpesaReceiptNumber": "ABC123XYZ",
"Phone": "254712345678",
"TransactionDate": "20241231123000"
},
"channel_info": {
"channel_type": "paybill",
"channel_name": "Main Paybill",
"routing_description": "Paybill 174379, Account: ACC001"
}
}
B2c callback
Sent when a B2C payment is completed or fails. Internal M-Pesa balance snapshots (Utility/Working/ChargesPaid account balances) are never included — use the Wallet API to check your own balance.
{
"success": true,
"transaction_id": 790,
"external_reference": "SALARY-DEC-001",
"originatorConversationID": "12345-67890-1",
"conversationID": "AG_20241231_...",
"transactionID": "NLJ41HAY6Q",
"status": "completed",
"timestamp": "2024-12-31T12:35:00+03:00",
"service_fee": 15,
"withdrawal_fee": 15,
"result": {
"ResultCode": 0,
"ResultDesc": "The service request is processed successfully.",
"TransactionAmount": 1000,
"TransactionReceipt": "NLJ41HAY6Q",
"RecipientIsRegistered": "Y",
"TransactionCompletedDateTime": "31.12.2024 12:35:00",
"ReceiverPublicName": "254712345678 - John Doe"
},
"transaction_info": {
"phone_number": "254712345678",
"amount": 1000,
"currency": "KES",
"transaction_type": "B2C"
},
"payer_name": "Jane Merchant"
}
B2pochi callback
Sent when a B2Pochi payment is completed or fails. Same structure as B2C callback with transaction_type set to B2Pochi. Internal M-Pesa balance snapshots are excluded.
{
"success": true,
"transaction_id": 795,
"external_reference": "POCHI-PAY-001",
"originatorConversationID": "12345-67890-1",
"conversationID": "AG_20241231_...",
"transactionID": "SG632NMUAB",
"status": "completed",
"timestamp": "2024-12-31T12:30:00+03:00",
"service_fee": 15,
"withdrawal_fee": 15,
"result": {
"ResultCode": 0,
"ResultDesc": "The service request is processed successfully.",
"TransactionAmount": 1000,
"TransactionReceipt": "SG632NMUAB",
"RecipientIsRegistered": "Y",
"TransactionCompletedDateTime": "31.12.2024 12:30:00",
"ReceiverPublicName": "254705912645 - JOHN DOE"
},
"transaction_info": {
"phone_number": "254705912645",
"amount": 1000,
"currency": "KES",
"transaction_type": "B2Pochi"
}
}
Reversal callback
Sent when a Reversal is completed or fails. On success, the original transaction is marked as reversed and funds are credited back to your payments wallet.
{
"success": true,
"reversal_transaction_id": 801,
"original_transaction_id": 790,
"external_reference": "SALARY-DEC-001",
"originatorConversationID": "34567-12345-1",
"conversationID": "AG_20241231_...",
"transactionID": "RL78HG3X9P",
"status": "reversed",
"timestamp": "2024-12-31T13:05:00+03:00",
"result": {
"ResultCode": 0,
"ResultDesc": "The service request is processed successfully.",
"TransactionAmount": 1000,
"TransactionReceipt": "RL78HG3X9P",
"TransactionCompletedDateTime": "31.12.2024 13:05:00"
},
"reversal_info": {
"amount": 1000,
"currency": "KES",
"original_product": "b2c",
"transaction_type": "reversal"
}
}
Retry Policy
| Max Retries | 4 |
| Retry Intervals | 5 minutes (fixed interval) |
| Timeout | 30 seconds per attempt |
| Expected Response | HTTP 2xx |
Security Recommendations
Always verify transaction via Transactions API before processing