Skip to main content
A refund returns money to the person who paid you. In Kwugwo a refund is attached to a single activity, the specific charge attempt that collected the money, rather than to the ugwo as a whole. An ugwo can have several activities (an abandoned bank transfer, then a successful USSD charge), and only the one that succeeded holds funds to return. Refund IDs look like rfd.XXXX.YYYYYYYYYYYYYYYYYYYYYYYY.

At a glance

Lifecycle

Creating a refund records it and submits it to the provider in the same request, so the response is normally processing rather than pending. You do not need to poll. Kwugwo follows the refund with the provider and sends a webhook as soon as it resolves. If a refund is still processing after a couple of weeks, contact support with its uid.

What a refund does to the payment

A refund is counted against the activity as soon as it is created, before the provider confirms it, so that a second request cannot over-refund a payment while the first is still in flight:
  • On create, the activity’s refunded_amount rises and the activity becomes partially_refunded, or refunded once the full amount is covered.
  • If the refund fails, refunded_amount is given back and the activity returns to partially_refunded or successful.
The ugwo mirrors its activity: partially_refunded while some of the money is still yours, refunded once all of it has gone back. See the ugwo status table.
Treat refunded_amount as committed, not settled. For accounting, reconcile on the refund.successful webhook.

How much you can refund

Leave amount out and Kwugwo refunds everything still refundable on the activity: what the provider collected (charged_amount, falling back to the activity’s amount) less anything already refunded. Pass amount for a partial refund. It must be at least the currency minimum (20000 kobo for NGN), and it cannot take the total past what the activity collected.

Providers

A refund goes back through the same provider that took the payment. By default Kwugwo uses the connection the activity used; pass nzube_psp to use a different connection for the same provider. Not every provider supports refunds. When one does not, the refund comes back failed with an error.code of system_error. Check with support before building a flow on top of a provider you have not refunded through before.

Refunds for bank transfer and USSD payments

Some PSPs cannot send money back to the account that paid by bank transfer or USSD, because they never saw it. For these, pass the customer’s bank account as destination when you create the refund:
Without it, such refunds come back failed with an error.message like nzube.psp.paystack.error.missing_destination. Sending it for other mediums is harmless.

Refunds created outside the API

A refund can also start at the provider, for example when someone issues it from the provider’s own dashboard. Kwugwo records it and reports it exactly like any other refund, so:
  • A refund.created webhook can arrive for a refund you never requested. Do not treat unknown refund IDs as an error.
  • Its ref is null, since there was no API request to carry one.
  • Its amount can be below the currency minimum.

Idempotency

ref is unique per workspace, which makes it an idempotency key. Send one on every refund and a duplicate request is rejected with 409 instead of refunding twice. If a create call times out, retry it with the same ref. Either the first attempt never landed and you get a refund back, or it did and you get 409.

The Refund object

Every field is documented on The Refund object.

Partial refunds in practice

A customer paid ₦5,000.00 (500000 kobo) and returns two items worth ₦3,000.00.
  1. Create a refund for 200000 with "ref": "order_4719_refund_1". The activity becomes partially_refunded with refunded_amount: 200000.
  2. Create a second for 100000 with a new ref. refunded_amount becomes 300000; the activity stays partially_refunded.
  3. Each refund resolves on its own and its webhooks can arrive in any order, so match on data.uid rather than arrival order.
  4. To return the rest later, omit amount. The activity and the ugwo both become refunded.