Refunds
A refund sends the full amount of a succeeded payment back to the customer’s wallet. There are no partial refunds.
curl -s -X POST http://localhost:4000/v1/payments/$PAYMENT_ID/refunds \ -H "Authorization: Bearer $XAALIS_KEY" \ -H "Idempotency-Key: refund:order_1042"{ "id": "re_…", "object": "refund", "payment_id": "pay_…", "amount": 15000, "currency": "XOF", "status": "succeeded", "fee_refunded": 0, "created_at": "…" }Idempotency-Keyis required. Repeating the request returns the same refund — a payment can never be refunded twice, however many times you retry.- Only succeeded Wave payments can be refunded (test mode simulates Wave).
GET /v1/payments/{id}/refundsreturns the refund (a list of zero or one) — use it to check an outcome without retrying.
Who pays the fee
Section titled “Who pays the fee”The customer always gets the gross amount back. By default Xaalis keeps its fee, so your available balance
must cover the gross amount:
| Payment | Your fee | Refund debits your balance | Customer receives |
|---|---|---|---|
| 15 000 | 225 | 15 000 | 15 000 |
fee_refunded shows the fee Xaalis returned (0 under the default policy). If your balance can’t cover it, the request
fails with 422 insufficient_funds and nothing happens; retry once funds arrive.
Statuses
Section titled “Statuses”status |
Meaning | You do |
|---|---|---|
succeeded |
the money is back with the customer; the payment is now refunded |
nothing — you also get payment.refunded |
pending |
the provider’s answer isn’t known yet (the API may have returned 503) |
wait for payment.refunded, or retry with the same key |
needs_review |
the provider refused; the amount stays reserved from your balance | contact Xaalis — an operator reconciles it with the provider |
A refunded subscription invoice stays paid; refunding doesn’t restart its billing cycle.