UnifiWallet Payments

Refunds

We never held the money, so a refund is a transfer you make and we verify — with a deadline, and one transfer per refund.

This is the one place where not holding your money costs you work rather than saving it. We never received the payment, so we cannot send it back. You do, and we verify it.

A refund is a transfer you make.

There is no balance of yours here to debit. A refund is recorded as an obligation with a deadline; you pay it from your own wallet, and we confirm the transfer on chain before marking it complete. Nobody can mark a refund done without a transaction that actually reached the buyer.

The flow

Each step as an expandable operation is on the API reference.

// 1. Record what is owed. This does not move money.
const refund = await call('POST', '/v1/refunds', {
  payment_id: 'pay_3nQ8xK2mLp4R',
  amount: '20.00',          // omit for the full amount
  reason: 'Customer returned one ticket',
});

// 2. Build the transaction. We hand back exactly what to send.
const prepared = await call('POST', `/v1/refunds/${refund.id}/prepare`, {});

// 3. Send it from your own wallet. We are not in this step.
const sent = await wallet.sendTransaction(prepared.transaction);

// 4. Tell us, and we verify it on chain before marking it done.
await call('POST', `/v1/refunds/${refund.id}/submit`, { tx_hash: sent.hash });

Where it goes

The buyer's stated refund address wins over the address they paid from, because a paying address is frequently an exchange withdrawal that cannot receive an arbitrary token — sending there loses the money.

A buyer sets that address at checkout by signing for it with the paying wallet, and it freezes once their transaction is out. You can override the destination on the refund if the buyer asks you to in writing.

One transfer, one refund

A refund claims the exact transfer that paid it — chain, transaction and log. Two refunds of the same size to the same address cannot both point at one transfer, so a single payment cannot close two obligations.

When you can refund

Once the payment is completed. A payment that is only settled can still be taken back by a chain reorganisation, and a refund you had already sent would not come back with it. Asking earlier returns payment_not_final.

The transfer you submit must be newer than the payment, and one transfer completes one refund. The payment becomes refunded once refunds add up to what you received — the net after the fee, which is also the most you can refund.

Deadlines

Each refund carries an sla_due_at. Passing it emits refund.sla_breached and emails every owner, then again once a day until the refund is sent. Nothing is automatically deducted — there is nothing to deduct from — but an account with a pattern of breaches is one we will ask about.

Partial refunds and tax

A partial refund reverses tax pro rata at the rate that applied when the payment was taken, not today's. It also reverses any discount proportionally, so a buyer cannot refund their way into a better price on what they keep.

States

StateMeaning
requestedRecorded and owed. Nothing has been sent.
fulfilment_pendingYou submitted a transaction; we are verifying it.
completedVerified on chain. The buyer has their money.
requested again, with failure_reasonThe transaction you submitted reverted, did not reach the destination, predates the payment, or never mined within a day. Still owed; send a new one. refund.fulfilment_failed tells you.
cancelledWithdrawn before it was paid.

Refunds you do not have to fund

Two cheaper paths exist, and both avoid a transfer entirely:

  • Before settlement. Cancel the payment. Nothing has moved, so there is nothing to send back.
  • Overpayment from a wallet. Anything above the required amount is returned to the buyer inside the original transaction, automatically. You never see it and never owe it. A deposit address is different: it forwards everything it received, and payment.overpaid names the excess for you to return.