When a full payment is made a JSON request is sent to the merchant’s callback url.
We send out IPNs on the callback_url provided on the checkout payload. The payment notifications are in the form of HTTP requests from our platform.
We send a HTTP POST request to the merchant's callback URL
Webhook Request
| Parameter Name | Type | Description |
|---|---|---|
| checkout_request_id | Double | A unique identifier on Cellulant’s end. |
| merchant_transaction_id | String | Unique ID the merchant raised for the request |
| request_amount | Double | The converted amount for the request raised by the merchant |
| original_request_amount | Double | The original request amount raised by the merchant in the invoice currency |
| request_currency_code | String | Converted currency for the request the customer made the payment in |
| original_request_currency_code | String | ISO Code of the currency code the merchant raised the request in |
| amount_paid_in_original_currency | Double | Total amount paid in Original Currency. (Sum of amount_paid_in_original_currency in payments array) |
conversion_rate | Double | Conversion rate used to convert from original currency to payment currency |
| account_number | Double | Merchant reference the customer was paying for |
| currency_code | String | ISO Currency code of the payment made |
| amount_paid | Double | Amount the customer paid for the request |
| service_charge_amount | Double | Charges added to the service for the request initiated |
| request_date | Date | Date when the request was raised in |
| service_code | String | Unique service code identifying the service the payment request was raised for. |
| request_status_code | String | Overall request code indicating the status of the service 177 - partially paid requests 178 - indicating the request was fully paid for 179 - indicating the request was partially paid for but expired 129 - Request expired without payments 102 - Insufficient funds 101 - Invalid pin/canceled 99 - Generic Failed Payment Status |
| request_status_description | String | Description of the status given back on the webhook request |
| MSISDN | String | The mobile number the person came with from the merchant site |
| payments | JSON Array | An array of successful payments made to the request |
| failed_payments | JSON Array | An array of any payments initiated but not successfully authorized |
| extra_data | String | metadata |
| country_abbrv | String | Abbreviation of the country |
Payments array for both failed and successful payments array.
| Parameter Name | Type | Description |
|---|---|---|
| customer_name | string | Customer name of the person who made the payment |
| account_number | string | Merchant reference the customer was paying for. |
| cpg_transaction_id | String | Unique Cellulant identity |
| currency_code | string | ISO Currency code of the payment made |
| payer_client_code | string | Payment option customer paid with e.g. Airtel |
| payer_client_name | String | Payment option customer name |
| amount_paid | double | Amount customer paid for |
| amount_paid_in_original_currency | double | Amount received from the customer in the original currency |
| original_request_currency_code | String | ISO Code of the currency code the merchant raised the request in |
| service_code | String | Code of service paid to |
| date_payment_received | Date | When the payment was made and received |
| MSISDN | string | The mobile number the customer is paying for |
| payer_transaction_id | string | Unique ID the MNO or bank generated for the transaction |
| hub_overall_status | string | The overall status of the payment made is described in the status code table below 138 - Payment request initiated but failed 139 - Payment pending acknowledgment from the merchant 140 - Payment accepted by the merchant 141 - Payment rejected by merchant system 144 - Payment delivered to the merchant but not yet acknowledged as successful 219 - Payment escalated |
| payment_status | String | This has the specific standard code on why the payment failed from the MNO. |
| payer_narration | String | MNO, bank, or card acquirer given payment description. |
Here is a sample JSON request body that you'll receive in the IPN:
{
"request_status_code": 178,
"account_number": "11800",
"merchant_transaction_id": "56679792",
"amount_paid": 10,
"service_charge_amount": 0,
"request_amount": "10",
"payments": [
{
"account_number": "11800",
"payer_client_name": "Mula Checkout",
"amount_paid": 5,
"amount_paid_in_original_currency":5,
"original_request_currency_code":"KES",
"payer_narration": "The service request is processed successfully.",
"date_payment_received": "2021-11-26 14:47:45.0",
"currency_code": "KES",
"payer_transaction_id": "PKQ082LB08",
"cpg_transaction_id": "1195072932",
"payer_client_code": "MULACHECKOUT_KEN",
"hub_overall_status": 139,
"payment_status":"SUCCESS",
"service_code": "MULACHECKOUTONLINE",
"customer_name": "Customer",
"msisdn": 254700000000
},
{
"account_number": "11800",
"payer_client_name": "Mula Checkout",
"amount_paid": 5,
"amount_paid_in_original_currency":5,
"original_request_currency_code":"KES",
"payer_narration": "The service request is processed successfully.",
"date_payment_received": "2021-11-26 14:47:45.0",
"currency_code": "KES",
"payer_transaction_id": "PKQ082LB08",
"cpg_transaction_id": "1195072932",
"payer_client_code": "MULACHECKOUT_KEN",
"hub_overall_status": 139,
"payment_status":"SUCCESS",
"service_code": "MULACHECKOUTONLINE",
"customer_name": "Customer",
"msisdn": 254700000000
}
],
"original_request_amount": 10,
"checkout_request_id": 6,
"currency_code": "KES",
"failed_payments": [],
"request_currency_code": "KES",
"request_date": "Fri Nov 26 11:47:04 GMT 2021",
"service_code": "MULACHECKOUTONLINE",
"request_status_description": "Success payment",
"amount_paid_in_original_currency":10,
"conversion_rate":1.0,
"original_request_currency_code": "KES",
"msisdn": "254700000000",
"extra_data": "abcd",
"country_abbrv": "KEN"
}{
"request_status_code":99,
"account_number":"2252523565",
"merchant_transaction_id":"1152468646",
"amount_paid":0,
"service_charge_amount":10,
"request_amount":"10",
"original_request_amount":10,
"checkout_request_id":5098938,
"currency_code":"KES",
"failed_payments":[
{
"account_number":"2252523565",
"payer_client_name":"Mula Checkout",
"amount_paid":10,
"payer_narration":"{\"statusDescription\":\"PAN is invalid. retry with correct card PAN\",\"statusCode\":213}",
"date_payment_received":"2024-04-11 14:44:03",
"currency_code":"KES",
"payer_transaction_id":"3613032_410214093703_1561460982605433261",
"cpg_transaction_id":"341644746",
"payer_client_code":"MULACHECKOUT_KEN",
"hub_overall_status":138,
"payment_status":"FAILED",
"service_code":"MULACHECKOUTONLINE",
"customer_name":"Joan Munene",
"msisdn":254700000000
},
{
"account_number":"2252523565",
"payer_client_name":"Mula Checkout",
"amount_paid":10,
"payer_narration":"{\"statusDescription\":\"PAN is invalid. retry with correct card PAN\",\"statusCode\":213}",
"date_payment_received":"2024-04-11 14:44:03",
"currency_code":"KES",
"payer_transaction_id":"3613032_410214093703_1561460982605433261",
"cpg_transaction_id":"341644746",
"payer_client_code":"MULACHECKOUT_KEN",
"hub_overall_status":138,
"payment_status":"FAILED",
"service_code":"MULACHECKOUTONLINE",
"customer_name":"Joan Munene",
"msisdn":254700000000
}
],
"extra_data":"",
"request_currency_code":"KES",
"request_date":"Thu Apr 11 14:38:28 GMT 2024",
"service_code":"MULACHECKOUTONLINE",
"request_status_description":"Failed payment notification received",
"original_request_currency_code":"KES",
"msisdn":"254700000000",
"country_abbrv":"KE"
}After receiving the HTTP POST request on the callback_url specified on the checkout payload, you have to respond with the following JSON payloads to either accept or reject the payment according to your business processes.
Failed Payment Status (Work in Progress)
Kindly note on callback under the failed_payments array we will send the field payment_status with the exact status code of why the request failed on the MNO's end. Here overall_status for the request will be 99 or 101 or 102 however the individual failed payment will have the correct status code with the reason for failure. Note the new field showing the actual failure reason will be under failed_payments[].payment_status
| Status Code | Description |
|---|---|
| FAILED | Generic failure reason given by the payment provider. |
| TIMEOUT | There was a timeout when MNO was sending request to end users handset or customer did not enter their pin in time. |
| INVALID_PIN | Customer entered incorrect pin. |
| BLOCKED | Customers mobile number was blocked by the MNO. |
| INSUFFICIENT_BALANCE | This indicates customer does not have enough money in their wallet to complete these transactions. |
| CANCELLED | Request was cancelled by the customer. |
| LIMIT_EXCEEDED | Declined due to limit rule: would exceed or fall below the transfer limits |
| SUCCESS | Payment was debited successfully. |
| ERROR | Internal error / network timeout when trying to reach the MNO / Authentication error when sending the request to the MNO |
| NOT_ALLOWED | Customer is not allowed to make such a transaction either due to decimals or their account is on hold or it is a suspected fraudulent transaction |
| ENGAGED | Handset has a similar request they are processing hence cannot proceed. |
| INVALID | For the request sent one of the parameters are not correct and has a problem. |
| ACCOUNT_NOT_FOUND | MSISDN or wallet is not available on the acquirers end. |
Webhook Response
| Parameter Name | Type | Description |
|---|---|---|
| checkout_request_id | String | The unique Cellulant ID on the database |
| merchant_transaction_id | String | Unique ID the merchant raised for the request |
| status_code | String | Indicate if a request is received successfully, failed, or accepted 183 - Successful 180 - Payment rejected 188 - Payment received and will be acknowledged later |
| status_description | String | A narration of the status code meaning |
| receipt_number | String | Unique identifier of the acknowledgment response given back |
Sample Response for processed payments
{
"status_code": "183",
"checkout_request_id": 4826296,
"receipt_number": "r77az121236884",
"merchant_transaction_id": "abcd-efg-hijklm",
"status_description": "Successfully"
}{
"status_code": "180",
"checkout_request_id": 4826296,
"receipt_number": "r77az121236884",
"merchant_transaction_id": "abcd-efg-hijklm",
"status_description": "Payment rejected"
}
