Skip to content

Callbacks

Payments are asynchronous, so NeraSika tells you the result by sending a POST request with a JSON body to a URL you provide. This is your callback URL (often called a webhook).

You set callback URLs per request:

Request Field Receives
Collection merchantCallbackURL Payment result
Disbursement merchantCallbackURL Payment result
Reversal merchantReversalCallbackURL Reversal result
Create mandate merchantCreateDDMCallbackURL Mandate approval result
Create mandate merchantPayDDMCallbackURL Direct debit payment result for scheduled charges
Charge mandate now merchantCallbackURL Direct debit payment result
Cancel mandate merchantCancelCallbackURL Mandate cancellation result
  • Reply with any 2xx status as soon as you receive the callback. Do slow work, like sending emails, after replying.
  • Any other status, or no response, counts as a failed delivery.

Failed deliveries are retried with exponential backoff, starting 10 seconds after the first attempt and doubling each time:

Result Attempts Retry window
Successful transaction 10 About 1 hour 25 minutes
Failed transaction 5 About 2.5 minutes

If a callback is delayed, you can check the status with the transactionId at any time.

You may receive more than one callback for the same transaction. For example, a status check that finds a newer result also sends a callback. Make your handler idempotent: look up the transaction by transactionId, and if you’ve already recorded a final status, reply 200 and do nothing else.

  • Use an HTTPS callback URL.
  • Use a URL that is hard to guess, such as one that includes a random path segment.
  • Check that transactionId and merchantRef match a transaction you created.

Sent for collections and disbursements.

{
"transactionId": "6718a2c4e5f0a1b2c3d4e5f6",
"merchantRef": "order-1042",
"transactionType": "collection",
"amount": 10.5,
"isoCode": "000",
"code": "111",
"status": "successful",
"statusReason": "successful",
"externalId": "8473920112"
}
Field Description
transactionId NeraSika’s transaction ID.
merchantRef Your reference from the request.
transactionType collection, disbursement-b2c or disbursement-b2b.
amount Transaction amount in GHS.
isoCode ISO 8583 result code: 000 successful, 100 failed. Use this one.
code Deprecated. Legacy result code: 111 successful, 000 failed. See Result codes.
status successful or failed.
statusReason Reason from the network, where available.
externalId The network’s reference. Present on some results only.

Payment and direct debit payment results carry two result codes. Read isoCode.

status isoCode code (deprecated)
successful 000 (approved) 111
failed 100 (declined) 000

isoCode follows ISO 8583, where 000 means approved. The legacy code uses 000 for a failed payment, so don’t mix the two up. code stays in every payload for existing integrations, but new integrations should use isoCode or status.

{
"transactionId": "6718a2c4e5f0a1b2c3d4e5f6",
"merchantRef": "order-1042",
"transactionType": "collection",
"transactinoType": "collection",
"newPaymentAmount": 5.5,
"reversalAmount": 5,
"reversed": true,
"message": "..."
}
Field Description
reversed true if the money was returned.
reversalAmount Amount returned.
newPaymentAmount The transaction’s amount after the reversal.
transactionType The original transaction’s type.
transactinoType Deprecated. Misspelled copy of transactionType with the same value, still sent for existing integrations. Use transactionType.
{
"mandateId": "6718a2c4e5f0a1b2c3d4e5f7",
"merchantRef": "member-883",
"active": true,
"description": "successful"
}

active: true means the customer approved. false means they declined or it failed, and description gives the reason.

{
"mandateId": "6718a2c4e5f0a1b2c3d4e5f7",
"transactionId": "6718a2c4e5f0a1b2c3d4e5f9",
"merchantRef": "member-883",
"amount": 50,
"isoCode": "000",
"code": "111",
"status": "successful",
"description": "successful",
"externalId": "8473920113",
"nextPaymentDate": "2026-12-01T00:00:00.000Z"
}
{
"mandateId": "6718a2c4e5f0a1b2c3d4e5f7",
"merchantRef": "member-883",
"active": false,
"message": "Canceled"
}

active: false means the mandate is cancelled.