Processing Refunds
Issue full or partial refunds for any completed payment. All refunds are on-chain and auditable.
A refund moves funds from your wallet back to the payer's wallet. You can refund partially (useful for price adjustments) or fully. There's a bounded refund window, so refunds can't be issued indefinitely after payment.
Issuing a refund
- Go to Invoices in the dashboard
- Find the paid invoice and click it
- Click Refund
- Enter the refund amount (can be less than the invoice amount for a partial refund)
- Optionally include a reason that gets recorded on-chain
- Confirm the transaction in your wallet
When the transaction confirms, the funds move from your wallet back to the customer's wallet, and the invoice's amount_refunded increases.
Refund states on the invoice
- Partial refund — if
amount_refunded < amount_paid, the invoice stays in its current status but records the partial refund. - Full refund — when
amount_refunded ≥ amount_paid, the invoice status changes to Refunded (status 5). This is terminal for the invoice.
Multiple partial refunds are supported
The refund window
Refunds can only be issued within a bounded window after the invoice's first payment. This prevents indefinite clawback and gives customers certainty that after enough time, funds are final.
The window is measured in burn blocks from the first-payment-at block. Check the contract source for the exact constant — it's currently set to a value that gives merchants a comfortable window for dispute handling but not indefinite.
Subscription payment refunds
You can refund individual subscription payments the same way you refund invoice payments. Each subscription payment is an independent on-chain event — refunding one payment doesn't affect the rest of the subscription, and doesn't automatically cancel it.
What's recorded on-chain
Every refund emits a refund-processed event with:
- The refund ID (unique per refund)
- The invoice ID being refunded
- The amount refunded
- The reason (optional string you provide)
- The burn block at which the refund was processed
This means anyone can audit the full refund history of a merchant with a block explorer — useful for transparency and dispute resolution.
Common scenarios
Customer requested a return
Issue a full refund. Customer receives the full amount back, invoice marks as Refunded.
Customer wants a price adjustment
Issue a partial refund for the difference. Invoice remains Paid, but amount_refunded reflects the partial return.
Chargeback equivalent
In crypto there's no "chargeback" — you control the refund. If a payer disputes a charge, you have full discretion to refund or not. This means you take on the dispute burden that card networks normally handle — factor that into your fraud policy.
Errors you might hit
- Refund window expired — the invoice is too old. See the Error Codes page for the exact constant.
- Insufficient balance — your wallet doesn't have enough sBTC/STX to cover the refund. Top it up before retrying.
- Already fully refunded — someone (you, or an automated process) already refunded the full amount.