Refunds
SaySwitch refunds let merchants return all or part of a successful card payment to a customer. Refunds are asynchronous: an accepted request reserves the required funds, then moves through funding and processing before it is complete.
Current Availability
- Refunds currently support successful USD card transactions.
- Full and partial refunds are supported.
- Each accepted refund includes a processing fee based on the merchant’s agreement with SaySwitch. The USD
1.00fee used below is only an example. - The processing fee becomes non-refundable after the refund completes successfully.
- Automatic virtual-account and payment-difference refunds use a separate workflow.
How Refund Funding Works
SaySwitch determines the funding split automatically. Merchants do not choose whether available or pending balance is used.
- Available wallet balance is reserved first.
- Any remaining requirement is held from eligible pending balance.
- The refund fee is included in the total amount that must be reserved.
For a USD card refund:
total_reserved = refund amount + USD refund feeFunding Example
| Item | Amount |
|---|---|
| Refund amount | USD 100.00 |
| Refund fee (example) | USD 1.00 |
| Total required | USD 101.00 |
| Available balance | USD 40.00 |
| Eligible pending balance | USD 100.00 |
SaySwitch reserves USD 40.00 from available balance and holds USD 61.00 from eligible pending balance. The refund is accepted with the awaiting_settlement status.
The gross pending balance is not reduced immediately. Instead, the held amount is excluded from pending_available, which represents pending funds that remain spendable.
If available balance plus eligible pending balance cannot cover the refund amount and fee, the request is rejected with HTTP 422. No funds are deducted or reserved.
Settlement Lifecycle
- The merchant requests a refund.
- SaySwitch reserves available balance first.
- Any remaining requirement is held from eligible pending balance.
- The refund returns
awaiting_settlementwhen pending funding is needed. - As settlements occur, settled money funds the refund hold before any remainder is added to available balance.
- Once completely funded, the refund automatically changes to
pending. - The refund then proceeds through normal processing.
- SaySwitch sends webhook notifications as the status changes.
Merchants do not need to resubmit a refund after settlement and cannot manually change its status.
Refund Statuses
awaiting_settlement -> pending -> processing -> success
pending -> processing -> successAlternative paths include:
awaiting_settlement -> rejected
pending -> rejected
processing -> failed
failed -> processing
failed -> rejected| Status | Meaning |
|---|---|
awaiting_settlement | Waiting for reserved pending funds to settle. |
pending | Fully funded and waiting for processing. |
processing | Refund processing has started. |
success | Refund completed successfully. |
failed | A processing attempt failed and may be retried. |
rejected | The refund was rejected and reserved funds were released. |
Funding Status
Refund status and funding.status describe different parts of the process. Refund status tracks processing, while funding status shows whether the reserved money is ready.
| Field | Description |
|---|---|
funding.status | awaiting_settlement, funded, or released. |
funding.available_reserved | Amount reserved immediately from available balance. |
funding.pending_reserved | Amount reserved from eligible pending balance. |
funding.pending_funded_amount | Pending reservation already funded through settlement. |
funding.pending_remaining | Pending reservation still awaiting settlement. |
funding.funded_at | Time the refund became fully funded, or null while waiting. |
Wallet Balance Fields
Use GET /api/v1/wallet_balance/{currency} to review the balances involved in refund funding.
| Field | Description |
|---|---|
balance | Available wallet balance. |
pending | Gross pending settlement balance. |
pending_available | Pending balance not already reserved for refunds. |
refund_pending | Total money reserved for active refunds. |
refund_pending_unsettled | Refund reservation still waiting to be funded by settlement. |
Use pending_available, not gross pending, when showing spendable pending funds. See Get Wallet Balance for the complete response.
Integration Flow
- Check the USD wallet balance and use
pending_availablewhen showing spendable pending funds. - Initiate the refund with a unique
Idempotency-Key. - Store the returned
refund_reference, refund status, and funding status. - If the refund is
awaiting_settlement, wait for status updates instead of submitting it again. - Verify refund webhook signatures and process each event idempotently.
- Verify the refund status before treating it as complete.
Only success is final confirmation that the refund completed. HTTP 202, awaiting_settlement, pending, processing, and failed do not mean that money has been returned successfully.
Safety Rules
- Wallet balances cannot become negative because of a refund request.
- No funds change when combined eligible funds are insufficient.
- Existing pending refund holds cannot fund another refund.
- An
awaiting_settlementrefund is accepted but is not ready for processing. - Rejected refunds release their reserved funds.
- Refund fees are included in required wallet funding.
- Idempotency prevents retries from reserving the wallet twice.
API Reference
| Task | Endpoint | Documentation |
|---|---|---|
| Initiate a refund | POST /api/v1/refund | Initiate a Refund |
| List refunds | GET /api/v1/refund | Get Refunds |
| Verify a refund | GET /api/v1/refund/status/{refund_reference} | Get Refund Details |
| Check wallet balance | GET /api/v1/wallet_balance/{currency} | Get Wallet Balance |
| Receive status updates | Configured webhook URL | Refund Webhooks |
Refund API requests use secret-key authentication and must be made from a secure server. Keep secret keys out of frontend code.