Skip to main content
When you need to return money to a cardholder — a cancelled order, a duplicate charge, a dispute resolved in the customer’s favour — the refund is an operation on your account: the processor returns the money to the card and we debit that same value from your balance, with its own ledger entry on your statement, its verifiable receipt and its webhook. It is the mirror image of a payin: a payin credits, a refund debits.

What can be refunded

QR, announced transfer, dedicated deposit account and collect payins cannot be refunded through this path (refund_not_supported): those rails have no refund capability at the processor. POS charges are refunded through the crypto rail with POST /v1/pos/charges/{id}/refunds.
Fees and the FX margin are not refundable. We debit the value the payin brought in (gross), not the net that was credited: if you charged 100.00 USD and we credited 97.10 USDT after a 2.90 fee, refunding the full amount debits 100.000000 USDT. You cover the difference, just like with any card processor.

Lifecycle

A 202 pending is not an error: the refund may already be done. If you retry with a different idempotency_key, the payer receives the money twice. Always retry with the same key (we return the original object) or wait for the webhook.

Request a refund

1

Refund the full payin

Omit amount to refund everything that is left to refund:
The response is 201 when the processor approves right away, 202 when it is still in flight and 422 when it declines.
2

Or refund part of it

Send amount in the payin currency (not in USDT). The debit is computed proportionally to the value that payin brought in:
You can request several partials on the same payin. When the sum exceeds what is left to refund, we answer 422 refund_exceeds_payin without touching your balance.
3

Void instead of refunding (same day)

If the payin has not settled at the processor yet, kind: "void" voids it instead of creating a refund. The effect on your balance is the same; for the cardholder, a void usually shows up on their statement sooner.
If the payin can no longer be voided, the processor declines it and you can request a regular refund.
4

Check the status

And the history of one payin:

Second factor

POST /v1/payins/{payinID}/refunds takes money out of your account, so it requires a second factor when a person originates it with their session (action payin_refund). If your organization has it enabled, the first call answers 403 otp_required with a challenge_id: verify the code and repeat the request with the challenge token. API keys are exempt by design, same as everywhere else on the platform: your backend integrates without friction.

History and filters

Filters: status (pending, completed, failed), kind (refund, void, chargeback), payin_id, from/to and pagination.

How much of each payin is refunded

Every payin exposes its refund progress, and you can filter the payin list by it:
The payin does not change status: it stays credited. Your financial history is never rewritten; the refund is a new movement.

Chargebacks

When the card issuer imposes a chargeback, the money is already gone: it is neither your decision nor ours. In that case:
  • We debit the amount from your balance automatically, with kind: "chargeback".
  • The debit is applied even if you have no balance: the account can go negative and that debt is netted against your next credits.
  • You receive the payin_refunded webhook with kind: "chargeback" and, if the balance went negative, the balance_after field.
A chargeback cannot be requested through the API: it arrives from the issuer. All you can do is see it on your statement, your history and its receipt.
What we debit across refunds and chargebacks on the same payin never exceeds what that payin brought in. If a chargeback arrives after you already refunded, the debit is capped to whatever was left — or lands at zero with the reason recorded — so we never charge you the same money twice.

The payin_refunded webhook

Emitted on every final state (completed or failed) and on chargebacks. pending refunds do not emit: wait for the final state.
A decline also carries failure_reason; a chargeback that leaves the account negative carries balance_after.

Receipt

Every refund has its PDF receipt with your organization’s branding and a public verification code:
Anyone can validate that code on the public verification page, without credentials and without seeing personal data. Details in Receipts.

Errors

Full catalogue in Errors.

FAQ

No. The fee and the FX margin of the original payin are not refundable: we debit the gross value the payin brought in and the house keeps what it charged. This is the standard behaviour of the card industry.
Not with another key. A 202 means the refund may already have been executed and we do not have confirmation yet. Retrying with a new key would be a second real refund. Repeat the request with the same idempotency_key (we return the same object) or wait for the payin_refunded webhook.
Always USDT, the currency the payin was credited in, even if your account has a different default settlement asset for payins. We never convert on your behalf: if you do not have enough USDT, we answer insufficient_funds.
As long as the payin is credited and has refundable value left, yes on our side. The real limit comes from the processor and the card scheme rules (usually 180 days); past that window the refund is declined with failed and the reserved amount returns to your balance untouched.
The account is allowed to go negative for this reason only. The debt is settled automatically against your next credits; meanwhile, operations that move money out still require available balance.
Yes. The admin panel can originate the refund on any account of the organization; it is audited with the admin who executed it and shows up in your history with requested_by: "admin".
Last modified on July 25, 2026