Implement Webhook via Callback URL

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 NameTypeDescription
checkout_request_idDoubleA unique identifier on Cellulant’s end.
merchant_transaction_idStringUnique ID the merchant raised for the request
request_amountDoubleThe converted amount for the request raised by the merchant
original_request_amountDoubleThe original request amount raised by the merchant in the invoice currency
request_currency_codeStringConverted currency for the request the customer made the payment in
original_request_currency_codeStringISO Code of the currency code the merchant raised the request in
amount_paid_in_original_currencyDoubleTotal amount paid in Original Currency. (Sum of amount_paid_in_original_currency in payments array)
conversion_rateDoubleConversion rate used to convert from original currency to payment currency
account_numberDoubleMerchant reference the customer was paying for
currency_codeStringISO Currency code of the payment made
amount_paidDoubleAmount the customer paid for the request
service_charge_amountDoubleCharges added to the service for the request initiated
request_dateDateDate when the request was raised in
service_codeStringUnique service code identifying the service the payment request was raised for.
request_status_codeStringOverall 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_descriptionStringDescription of the status given back on the webhook request
MSISDNStringThe mobile number the person came with from the merchant site
paymentsJSON ArrayAn array of successful payments made to the request
failed_paymentsJSON ArrayAn array of any payments initiated but not successfully authorized
extra_dataStringmetadata
country_abbrvStringAbbreviation of the country

Payments array for both failed and successful payments array.

Parameter NameTypeDescription
customer_namestringCustomer name of the person who made the payment
account_numberstringMerchant reference the customer was paying for.
cpg_transaction_idStringUnique Cellulant identity
currency_codestringISO Currency code of the payment made
payer_client_codestringPayment option customer paid with e.g. Airtel
payer_client_nameStringPayment option customer name
amount_paiddoubleAmount customer paid for
amount_paid_in_original_currencydoubleAmount received from the customer in the original currency
original_request_currency_codeStringISO Code of the currency code the merchant raised the request in
service_codeStringCode of service paid to
date_payment_receivedDateWhen the payment was made and received
MSISDNstringThe mobile number the customer is paying for
payer_transaction_idstringUnique ID the MNO or bank generated for the transaction
hub_overall_statusstringThe 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_statusStringThis has the specific standard code on why the payment failed from the MNO.
payer_narrationStringMNO, 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 CodeDescription
FAILEDGeneric failure reason given by the payment provider.
TIMEOUTThere was a timeout when MNO was sending request to end users handset or customer did not enter their pin in time.
INVALID_PINCustomer entered incorrect pin.
BLOCKEDCustomers mobile number was blocked by the MNO.
INSUFFICIENT_BALANCEThis indicates customer does not have enough money in their wallet to complete these transactions.
CANCELLEDRequest was cancelled by the customer.
LIMIT_EXCEEDEDDeclined due to limit rule: would exceed or fall below the transfer limits
SUCCESSPayment was debited successfully.
ERRORInternal error / network timeout when trying to reach the MNO / Authentication error when sending the request to the MNO
NOT_ALLOWEDCustomer 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
ENGAGEDHandset has a similar request they are processing hence cannot proceed.
INVALIDFor the request sent one of the parameters are not correct and has a problem.
ACCOUNT_NOT_FOUNDMSISDN or wallet is not available on the acquirers end.


Webhook Response

Parameter NameTypeDescription
checkout_request_idStringThe unique Cellulant ID on the database
merchant_transaction_idStringUnique ID the merchant raised for the request
status_codeStringIndicate if a request is received successfully, failed, or accepted
183 - Successful
180 - Payment rejected
188 - Payment received and will be acknowledged later
status_descriptionStringA narration of the status code meaning
receipt_numberStringUnique 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"
}