# Fees and pricing

## In one minute

- **Deposits are free.** What the customer sends is what is credited.
- **A payout costs the network's real price plus one flat platform fee**, charged on top of
  the amount. Quote it with `GET /v1/withdrawal-fee-quote` and show `total_fee`.
- **A swap costs a percentage of the amount, with a dollar minimum, plus its own network cost**, taken out of the sold amount.
- **A card has an issue fee, a load fee and a close fee**, paid by the cardholder. A load
  carries the network price of its send and a flat platform part beside the percentage; a
  close is paid out of the balance the card returns, never from the wallet: our flat part, the
  network price of the on-chain send, your own fee and what the card rail charges to release
  the balance all come off it, and the holder receives the rest — quoted live per card as
  `refund_quote` on the close quote. There
  is no partial unload: the close is the only way value leaves a card.
- **Every card movement is real coins, on-chain.** A load leaves the holder's own address
  and only goes when the coins are there; a close's balance comes back to that address after
  the card network's settlement period (the typical and longest times are in the card table
  below). A close is always accepted — read `close_refund.state` on the card for where the
  money is. The ledger never says one thing and the chain another.
- **Your own fee, if you set one, goes on top** and lands in your balance; your affiliate
  share of ours is paid on every payout, swap, card issue, load and close.
- **Never type a number from this page into your code.** Every figure is priced when you
  ask and the response says whether it is live. The tables below read the live sheet.
- **Want a number for a given amount?** The [fee calculator](fee-calculator) applies this
  minute's sheet to any amount, your own fee included.

This is the complete list. There is no monthly fee, no setup fee, no minimum volume and
no per-API-call charge — the platform earns on movement, and only where a rate is stated
below.

Every number here is also readable from the API, and **the API is the authority**. Rates can
be set per merchant, so if your account has been given a different rate, `GET /v1/fees`
returns yours, not the ones on this page. Read it at runtime rather than hard-coding.

## Which balance pays

Two different balances pay for things on this platform, and mixing them up is the single
most common source of "where did that money go". Every fee below names the one it comes
from.

| Balance | What it is | What comes out of it |
| --- | --- | --- |
| **Customer balance** | One of your end-users' balances | Withdrawal fee, swap and exchange fees — and **every card cost**: issue, each load, close. Deposits are free |
| **Card balance** | Money sitting on a card | The issuer's charges when the card is used |

**Every card cost comes out of the cardholder's own balance.** Issue, every load and the
close are charged to the customer who holds the card, and to nobody else.

**Loads are sent on-chain.** When a customer loads a card, cryptoinfra sends what the rail
needs to the rail's wallet in real time and funds the card once that send is confirmed and
credited. That is why a load passes through a `funding` stage and takes minutes rather than
seconds, and why a load carries its own **gas** line — the network's live price for that
send, on top of the amount.

### You can hold more than one programme

A **programme** is a rail and its prices — the BIN a card is issued on and the fees that
BIN carries. Your first card with a `core_id` opens that programme for you (or open it
from the dashboard first), and you may hold several — Core-1, Core-2 — each with its own
rail, its own BIN and its own prices.

**A programme holds no money.** It decides the rail a card is on and the BIN that prices
it; the card carries that programme for life. Every card cost is charged to the
cardholder, and everything a card returns goes back to the cardholder.

That is why every card carries `core_id`, and why calls that could mean either programme
ask rather than guess:

- `POST /v1/cards` takes `core_id`. Send it — with one programme open it is optional, and
  the day you open a second, an omitted `core_id` is refused with `card_core_required`
  rather than priced off a programme you did not mean.
- `GET /v1/cards/products?core_id=…` is the shelf for one programme, priced for it.
- Every card reads back the `core_id` it belongs to, and the `bin` it carries. An order
  names its `card_id`; the programme that priced it is that card's.

## At a glance

**One rule for every fee: our live network cost, plus a flat platform fee.** The network
part is what the send actually costs us on-chain, priced at the moment you ask; the flat
part is ours. Quote before you promise — `GET /v1/withdrawal-fee-quote` returns the exact
deduction for the amount, the recipient and the sender.

**No price on this page is typed in.** Every table below is read from the public
[`GET /v1/pricing`](reference) when the page loads — no key needed — so what you see is
the price of this minute, and the same sheet an operator changes. Build against the
endpoint, never against a number you copied from here.

## Every figure says whether it is live

A network figure is never a constant. It is priced when you ask, from the energy market
and the TRX price of that moment, and it moves. Two small fields travel with it, the same
two everywhere, and that is all you need to read:

| Field | Meaning |
| --- | --- |
| `dynamic` | `true` — priced live now. `false` — the live price could not be read and a conservative fallback applies. Label the figure "live" or "approx" |
| `quoted_at` on a quote, `priced_at` on `GET /v1/fees`, `as_of` on the price sheet, `gas_priced_at` on the card tariff | when the figure was computed — for this response, never stored |

Show the total, label it, and re-read it before you show it again. A quote's
`dynamic: false` is not an error: the send still goes, at the fallback.
The order you create afterwards carries the figure actually charged (`fee` on a
withdrawal, `gas` on a card order and its webhook) — reconcile against that, not against
the quote.

<div class="live-pricing" data-pricing="at-a-glance" data-pricing-src="https://api.cryptoinfra.build/v1/pricing"><p class="live-pricing-fallback">Live prices: <code>GET https://api.cryptoinfra.build/v1/pricing</code> (no key needed) — this table fills in from it.</p></div>

The network figures move with the market, in both directions; the quote is the price.

## Two ways to earn

Everything above is what **we** charge. You earn on top of it in two ways, together or
alone, and both land in **your own balance the moment your customer pays** — nothing to
settle, nothing to claim; pay it out from Payouts like any of your own money.

### 1. Affiliate commission — a share of our fee, nothing to set

On every payout, swap and card your customers make, a share of **our platform fee** is
yours. It is paid to your balance in the same moment our fee settles, automatically. Your
share is `affiliate.share_percent` on [`GET /v1/fees`](reference) (the platform's figure is
on the public price sheet above); the operator sets it and can give your account its own.

The share is of our fee, never of a cost: a payout's network bill, the network figure
inside a swap fee, what the card rail takes, the issuer's cancellation on a close and
the network part of a close carry no commission — on a close your share is of our own flat
part alone. Deposits are free, so they carry none either.

### 2. Your own fee — a price above ours

Charge **your own fee** on every operation — a percentage, a flat amount, or both, with no
ceiling. It is charged to your customer on top of ours and credited to your balance in the
same movement. Set it in the dashboard under **Profit → Your fees**, or with
`PUT /v1/merchant/fees/{deposit|withdrawal|swap}`; cards have their own settings.

| Where | How it is taken | Where you see it |
| --- | --- | --- |
| Deposit | skimmed from the credited amount after ours | `merchant_fee` on the deposit and the `deposit.credited` webhook; `amount_credited` is after both |
| Withdrawal | held on top of the amount with ours | `merchant_fee` on `GET /v1/withdrawal-fee-quote` and the withdrawal; `total_fee` includes it |
| Swap / exchange | from the sell side with ours | `merchant_fee` on the quote and the order |
| Card issue / load / close | on top, charged to the cardholder | `merchant_fee` on the card quotes |

Your fee is never charged on your own balance's operations or on a card programme pot. `GET /v1/fees` shows your fee beside ours under
`merchant_fee` for each operation, and your commission share under `affiliate`.

### Withdrawing your profit

**Profit → Withdraw profit** sends what you have earned — commission and your own fees, less
what you already withdrew — to any address. Our ordinary withdrawal fee is charged on top,
so the amount plus that fee may not exceed the profit available (the API answers
`409 profit_insufficient` past it). It needs your authenticator code, like every dashboard send.

A profit withdrawal is a request to cryptoinfra. Every fee, ours and yours, is moved on-chain
to our profit wallet as it settles, so that is where your earnings physically are; the request
is approved there and then leaves that wallet in real time. Most go on their own the moment
you ask. A few wait for a look first: a large amount, an address we have never paid you at
(it waits a fixed number of hours, then goes on its own), or a day's total past the cap. There is a small minimum, a limit on how many can be on the way at
once, and a short wait between two requests; the dialog shows the figures that apply today,
and a refused request comes back with the reason (`409 profit_below_minimum`,
`profit_too_many_open`, `profit_cooldown`). Owner and finance logins get a mail at each turn:
requested, waiting, approved, refused. Your Profit page lists every request with where it
stands and why. A refused request returns the whole hold to your profit.

An earning matures before it can be withdrawn. It lands in your balance the moment the
customer pays, but counts as profit available only after a wait: a short one for what was
earned on-chain (payouts, deposits, swaps — final once the block is), a longer one for what
was earned on cards, which can still be refunded or disputed for days. The Profit page
shows what is available and what is still pending, with the moment it becomes available;
the dialog shows the two waits that apply today. A request while nothing has matured yet
answers `409 profit_not_matured`, with the pending amount and that moment.

If an operation comes back — a swap the exchange refunds, a card load the rail refunds —
the earning on it comes back too: your own fee returns to the customer or
to us, whichever refunded them, and your share of our fee returns to us. What your balance
holds is taken at once. What it does not — you had withdrawn it already — is owed back: it is
netted from your next earnings, never from money you fund your account with, and no profit
withdrawal goes until it is settled (`409 profit_owed`). The Profit page lists every reversed
earning with the reason, and `GET /v1/merchant/profit` carries them under `reversals`, the
pending figures under `profit_pending`, and what is owed under `profit_owed`.

## Deposits

**Free.** A deposit to an address we issue is credited in full: a 100 USDT deposit credits
100.00 USDT. There is no platform fee and no network charge — the sender pays the
chain's fee to reach the address, and we take nothing when it lands. The deposit row's
`fee` is `0`.

<div class="live-pricing" data-pricing="deposit" data-pricing-src="https://api.cryptoinfra.build/v1/pricing"><p class="live-pricing-fallback">Live prices: <code>GET https://api.cryptoinfra.build/v1/pricing</code> (no key needed) — this table fills in from it.</p></div>

The only thing ever taken out of a deposit is **your own fee**, if you have set one
(`merchant_fee`; see *Your own fee* above), and then `amount_credited = amount − merchant_fee`.

**A deposit below the asset's minimum is not credited at all.** It is marked `ignored_dust`
and left alone — a dust floor, so that a balance never moves by an amount the chain cannot
economically move again. The floor is `min_deposit` in the table above and on
[`GET /v1/assets`](reference); show it wherever you show a static wallet address.

The deposit row carries both figures and they are not interchangeable: `amount` is what the
customer sent, `amount_credited` is what reached the balance (equal unless you charge a fee).

Live schedule: [`GET /v1/fees`](reference) (`deposit.total` is `0`). See
[Static Wallet Address](deposit-addresses) for how a payment becomes a balance.

## Withdrawals

**The flat platform fee + the network cost of the send, quoted live, on top of the amount.**

**Charged to: the customer's balance.** `amount` is exactly what the recipient receives; the
fee is held alongside it. A send of `amount` quoted at fee `f` holds **`amount + f`** and the
recipient gets **`amount`** — so a balance one cent short of `amount + f` cannot send it.

<div class="live-pricing" data-pricing="withdrawal" data-pricing-src="https://api.cryptoinfra.build/v1/pricing"><p class="live-pricing-fallback">Live prices: <code>GET https://api.cryptoinfra.build/v1/pricing</code> (no key needed) — this table fills in from it.</p></div>

The network part is what the send costs us: the energy we rent for **two transfers** — the
payout and our fee's own move to our wallet — the bandwidth of each, and, on a user's first
send, the TRX that creates their address on-chain. It is converted at the live TRX price
with a cushion (`cushion_pct` under `priced_from` on the sheet) and rounded up to the cent. `GET /v1/fees` shows today's figures
(`withdrawal.network_fee` for a recipient that holds the token,
`network_fee_fresh_recipient` for one that does not, `first_send_activation_fee` for the
one-time part); [`GET /v1/withdrawal-fee-quote`](withdrawals) with `to_address` and `user_id`
prices the exact send, and `network_cost` on it says what the figure was built from.
**The figure the quote returns is the one that is charged.**

Whether a recipient already holds the token is your customer's wallet, not anything you can
see — pass `to_address` to the quote and show the customer the total before they confirm.

When the live TRX price cannot be read, the send is charged the asset's static fallback —
`static_fallback` on the price sheet — and the quote says so with `dynamic: false`. When
only the energy market is unreadable, the energy part is priced at a fixed fallback rate
and the rest of the figure stays live; the quote is still `dynamic: true`. In both cases
the figure the quote returns is the one that is charged.

**A network figure is never below what a send cost us yesterday.** Live or fallback, it
is lifted to the dearest confirmed send of the last 24 hours, priced and cushioned like a
quote. Nothing for you to read or handle — it is inside the figure the quote returns.

### What you never do

- **you never hold TRX**, prepay gas, or top anything up — every network cost is inside the quote;
- guess a fee: the quote is the price, and it is rounded up, never down.

## Swaps and exchanges

**A percentage of the amount, with a dollar minimum, plus the swap's network cost** — both taken out of the
sold amount and returned together as `fee` on the quote, with the network part on its own as
`network_fee`.

**Charged to: the balance being sold from** — the customer's, not yours.

A USDT ⇄ TRX swap is traded on the TRON network itself, from the user's own address, so the
network part is that trade's real gas, priced live the way a payout is. The first USDT sale
from an address also pays, once, for approving the trade. An exchange out of USDT or TRX pays
the same percentage and minimum plus the network cost of its own send. Nothing else is added.

<div class="live-pricing" data-pricing="swap" data-pricing-src="https://api.cryptoinfra.build/v1/pricing"><p class="live-pricing-fallback">Live prices: <code>GET https://api.cryptoinfra.build/v1/pricing</code> (no key needed) — this table fills in from it.</p></div>

**USDC on TRON cannot be swapped or exchanged today** — no route carries it. It can still be
deposited and withdrawn. `GET /v1/assets` marks such assets `swappable: false`; leave them
out of your picker. A swap that names one on either side, or an exchange that sells one, is
refused with `400 invalid_pair` before anything is charged — the same answer a disabled
asset gets.

A **swap** moves between coins the platform custodies and credits the balance. An
**exchange** sells a coin you hold and pays a different one out to an address you supply —
same fee rule, but the payout is as final as a withdrawal. The route itself may also carry a
routing fee of up to 0.5%, taken inside the route; `receive_estimate` and `receive_minimum`
already reflect it, so display those rather than working the buy side out from the sell
amount yourself. Quote first in both cases: the quote is the only thing that validates a
destination address, and it rejects a bad one before anything is charged.

Live rate: [`POST /v1/swap/quote`](swaps) and [`POST /v1/exchange/quote`](exchange).

## Card fees

> **Every card cost is charged to the cardholder's own balance** — issue, each load, and the
> close. Not the card, and not a programme balance. Your customer pays; if you have set your
> own fee, your share lands in your own balance in the same movement.

**The rules, in one place** (each is a fact you can read from the API, never a number to type in):

1. **Issue** — a one-time issue fee plus a funded opening balance, priced as a load.
2. **Load** — the load rate (`load_fee_bps`, floor `load_fee_min`) plus the flat platform
   part (`load_fee_flat`) plus the live network figure (`gas`), all on top of the amount.
   Sent on-chain from the holder's own address; refused with `409 card_coins_not_on_chain`
   while the coins are not there.
3. **No partial unload** — `POST /v1/cards/{id}/withdraw` is retired (`410`); the close is
   the only way value leaves a card.
4. **Close** — our flat close fee (`close_fee`) plus the live network figure for the on-chain
   send, the issuer's cancellation kept on the card and the rail's release charge, all taken
   from the balance being returned; the rest reaches the holder's own address. A close is
   **never refused for money reasons**: read `close_refund.state` for where the money is.
5. **Your share** — your affiliate commission on our part of every one of these, and your
   own fee on top if you set one.

### What a load costs, and where the money goes

Loading a card is an on-chain send, and **the fees are charged on top of the amount**. Ask
to load `amount` and the card holds `amount`; the cardholder's balance is debited more:

| | Amount | |
| --- | ---: | --- |
| Lands on the card | **`amount`** | exactly what you asked for — sent on-chain to the card rail, plus the rail's own small fee so our balance there nets to zero |
| Our fee | **+ `load_fee_bps` of `amount` + `load_fee_flat`** | the product's load rate on the price sheet (with its floor, `load_fee_min`) plus the flat platform part |
| Gas | **+ `gas`** | the network's live price for that send — the load and our fee's own transfer, priced for an address that holds none of the token, so it is its own figure, not a withdrawal's |
| Your fee | **+ `merchant_fee`** | unless you set none (below) |
| **Charged to the cardholder** | **the sum** | `total` on the quote |

The number the cardholder chose is the number that reaches the card, and every fee is a
visible line of its own — the way every card product they have ever used behaves.

`GET /v1/cards/topup-quote?amount=100&card_id=…&user_id=…` returns exactly these lines —
`fee`, `gas`, `merchant_fee`, `credited`, `total` — priced for that card. `credited` is
what reaches the card (the amount itself) and **`total` is what the balance is debited**.
Show `total` wherever you tell someone what a load will cost, and check it against the
balance first: a load the balance cannot cover is refused before anything is charged.

**A load below the product's minimum is refused** with `400`, and the error names the
minimum.

**It takes minutes.** The order is `funding` while the coins travel, `requested` once the
chain confirms them, `sent` once the rail is asked, `confirmed` once the card is funded. A
`card.topup` webhook tells you at the end; treat everything before it as pending. If the
rail refuses, everything — including gas — is refunded to the cardholder.

**A card's price belongs to its programme and BIN together, not to the platform.** Two BINs
can be open at once, priced completely differently, and the same BIN number under a
different programme is a different card with different prices.

So the pair is the key. Read `core_id` **and** `card_bin` out of a response before comparing
prices — a BIN number on its own does not identify a card's terms, and code that treats it
as if it does will price one programme's card off another's sheet.

`GET /v1/cards/products` is the per-programme version of the table below and the one to
build against with your key; add `?core_id=…` to see one programme's shelf priced for that
programme. Its `issue_total` is everything the cardholder pays to issue that card at the
minimum opening balance, your own fee included. The table here is the public sheet, live:

<div class="live-pricing" data-pricing="cards" data-pricing-src="https://api.cryptoinfra.build/v1/pricing"><p class="live-pricing-fallback">Live prices: <code>GET https://api.cryptoinfra.build/v1/pricing</code> (no key needed) — this table fills in from it.</p></div>

Take the virtual product as the worked example; the same shape applies to any row.

**Issue fee — one time, from the cardholder.** Charged when `POST /v1/cards` is accepted.
Flat, not a percentage of the opening load, and it is the whole price of the card itself:
nothing else is charged for issuing.

**Minimum opening load — required, from the cardholder.** A card is issued *funded, never
empty*: `initial_amount` on `POST /v1/cards` must be at least `min_opening_balance`. It is
priced exactly like a load — the load rate + gas on top, so the card opens holding the full
amount — and it goes on-chain with the issue, so a new card takes a few minutes to arrive.
Issuing at the minimum charges the cardholder
**issue fee + minimum opening load + its load fee + gas** — `issue_total_at_minimum` on the
sheet above, `issue_total` on the products shelf (yours included) — and
`GET /v1/cards/issue-quote` prices any other opening balance. An issue for a holder whose
balance is short is refused with `409 insufficient_balance` before anything is charged.

**Load fee — the load rate + gas, on top of the amount, on every load after that.** Loading
`amount` puts exactly `amount` on the card and charges `amount + fee + gas`. A load pays
its own way **on-chain from the holder's own address**: the coins have to be there. A
balance the ledger shows but the chain does not yet — a close refund or a deposit still on
its way — answers `409 card_coins_not_on_chain`; nothing is charged, load again once it has
arrived.

**Close fee — flat plus the live network figure, taken from the balance the card returns.**
The flat part is ours; the network part pays for returning the card's balance to the
holder's own address on-chain. Two more things come off that balance before it arrives, and
neither is ours:

- **the issuer's cancellation charge**, kept on the card (a card holding less simply keeps
  what it has — a close is never refused for it);
- **the card network's release charge** — a percentage of the balance with a minimum, capped
  below a threshold — shown per card as `close_refund` on the price sheet.

The refund then reaches the holder's address after the settlement period — usually quickly,
never later than the longest time on the price sheet. `GET /v1/cards/{id}/close-quote` does
the whole sum for one card as `refund_quote`; show its `refund` before your user confirms.

There is no partial unload of a card, and there is no monthly or dormancy fee on any BIN
today; a future row would say so explicitly if that
changed. The issuer may net its own unload tariff out of what it releases, so the balance
is credited what actually came off the card — `amount_credited` on the order, which can be
less than `amount`.

### Your own fee, on top of ours

Ours is the floor and is always charged. On top of it you may add a percentage of the
amount, a flat amount, or both — separately for issuing, loading and closing — over the
API:

```
GET    /v1/merchant/card-fees                 ours, yours, and what the cardholder pays
PUT    /v1/merchant/card-fees/load            { "percent_bps": 50, "flat": "0.25" }
PUT    /v1/merchant/card-fees/issue           { "flat": "2" }
DELETE /v1/merchant/card-fees/close
```

`percent_bps` is basis points: 100 = 1%, at most 1000 (10%). Your fee is charged to the
cardholder with everything else and credited to **your own balance in the same movement** —
there is nothing to collect. Every quote (`topup-quote`, `issue-quote`, `close-quote`,
`issue_total`) and every `card.*` webhook shows it as `merchant_fee`.

Your account needs a balance of its own for the fee to land in; setting a fee without one is
refused with `409 no_own_account`.

### Adding a card to a phone wallet

BIN 493 provisions into **Apple Pay, Google Pay and Samsung Pay**. Wallet support is a
property of the BIN, not of the platform: do not assume a future BIN carries it.

**BIN 493 prints no cardholder name.** The issuer has no such field, so nothing is
embossed on the card itself. `name_on_card` is still worth sending: we store it against
the card and return it on every read, so your dashboard and ours can tell one cardholder
from another — `last4` cannot.

Provisioning asks the cardholder to verify the card, and that verification code comes from
us rather than from the wallet. It appears live on the card's page in your dashboard the
moment it arrives; over the API, read it with [`GET /v1/cards/{id}/otp`](cards) and show it
to the cardholder. The code is short-lived and read once per channel — once with your API
key, once in the dashboard, so your server fetching it never hides it from the dashboard —
so fetch it when they are looking at the screen, not in advance. Without one of the two the
customer waits for an SMS that is never coming.

### Closing a card

**Everything below is per programme and BIN.** A card's close fee, the issuer's cancellation
charge, the rail's release charge and the settlement period are properties of the rail and BIN
that card sits on — not of cryptoinfra, and not of your account. Two of your programmes can
answer differently on the same day. The close quote prices the card you name; treat it as the
only source.

**Our close fee has two parts.** A flat part (`close_fee` on the sheet — our own charge, and
nothing else) and the live network figure (`gas` on the close quote, with `dynamic`) for
returning the card's balance to the holder's own address on-chain. Separately the issuer
keeps its own cancellation charge on the card, which is also the least the card must hold
(`cancellation` under the cardholder fees on the sheet, `minimum_card_balance` on the close
quote), and the card rail charges to release the rest to us (`rail_return_fee`).

**Everything is taken from the balance the card returns**, never from the holder's wallet.
`refund_quote` on the close quote does the arithmetic live and names every line; the holder
receives `refund`.

**The balance comes back on-chain.** Cancelling a card opens the issuer's settlement period,
which the issuer says can run to **45 days** (`refund_eta_max_days` on the close quote) —
though it has settled within 24–48 hours in practice. Once released, the balance reaches the
holder's own address within `refund_eta_working_days` working days, paid from a wallet
cryptoinfra funds by hand. The close itself is never refused while that is arranged: read
`close_refund.state` on `GET /v1/cards/{id}` for where the money is (`waiting` → `approved` →
`sending` → `paid`). Until the refund lands the holder cannot load another card with that
balance (a load needs the coins at their address, rule 2 above).

| Card balance at close | What happens |
| --- | --- |
| **More than C** | The excess returns to the cardholder's balance; **C stays on the card** and the issuer takes it. |
| **Exactly C** | The issuer takes it from the card. Nothing returns. |
| **Less than C, or empty** | **Closes anyway** (20 September 2026). The issuer keeps whatever is on the card as its cancellation charge, there is nothing to return, and nobody is asked to load a card they want to be rid of. |

A card holding **B**, more than C, closes as: **B − C** released by the rail, less the rail's
own release charge and less our close fee, the network figure and yours — and what remains is
the holder's `refund`. Nothing is ever debited from their wallet balance, so an empty wallet
never blocks a close.

`GET /v1/cards/{id}/close-quote?user_id=…` shows what the close itself will debit the
cardholder — `fee` (our flat part), `gas` (the live network figure, `dynamic` says whether it
was priced now), `merchant_fee` (yours) and `total` — with `charged_to: "cardholder"` and
`refund_eta_working_days`. There is nothing for you to credit afterwards: the residual lands in your
customer's balance on its own, and if you want to charge them for closing, set your own
close fee rather than moving money by hand.

**Read the settled amount, not the card's last known balance.** The residual comes back as
a withdraw order and is credited when the rail confirms it; `amount_credited` on that order
is what actually reached the balance, and it can be less than `amount` if the issuer netted
its own unload tariff.

#### The call

`DELETE /v1/cards/{id}` (with `user_id` in the body) does the return itself — you do not
unload first:

1. The first call unloads everything above C and answers **`202 card_close_in_progress`**;
   `details.order_id` is the withdraw order and `details.card_id` the card. A `card.withdraw`
   webhook tells you when it settles.
2. Call it again once that order is confirmed; our close fee (and yours, if set) is charged
   to the balance, the card terminates and the issuer keeps C.

A card at or below C closes on the first call. Calling close again on a card whose
return is still travelling answers the same `202` with the same order; retrying a close
never double-charges, and a card already closed answers `409 card_state`.

**Anything still pending** → `409 card_state`, whatever the balance reads. It can settle
after the card is gone, so it has to clear first. A balance the rail cannot confirm right
now is `400 invalid_request` — try again, rather than closing on an unknown figure.

### Fees the issuer charges on card use

Everything above is what the **cardholder** pays us. These are the **issuer's** charges,
and they never touch a cryptoinfra balance.

**Charged to: the card balance.** They appear on the card's own transaction history, so
your customer sees them.

<div class="live-pricing" data-pricing="card-holder" data-pricing-src="https://api.cryptoinfra.build/v1/pricing"><p class="live-pricing-fallback">Live prices: <code>GET https://api.cryptoinfra.build/v1/pricing</code> (no key needed) — this table fills in from it.</p></div>

Every one of these follows the same rule: **taken from the card when it happens.** When the
card cannot cover it — a dispute landing on a spent-down card is the usual case — the
issuer bills the difference to us, not to you and not to your customer's balance.

**The fee is inside the transaction, not added to it.** A purchase shown as $3.86 with a
$0.25 fee takes $3.86 from the card in total — the merchant received $3.61 and the issuer
kept $0.25. Card loads read the same way: a $50.35 movement puts $50.00 on the card.

**3-D Secure is charged per authentication, not per purchase.** A checkout that challenges
the cardholder costs the 3-D Secure fee in the table above whether or not the purchase
completes, so a customer who abandons at the 3DS step still generates one. It is small, but
it is the only fee here that can fire without a sale behind it.

### Spending limits on the card

Every BIN carries the issuer's own ceilings: how much one purchase can be, how much the card
can spend in a day and in a month, how much cash it can draw at an ATM, and how long it is
valid. They are the same for every merchant on that BIN, and nothing on our side raises them.

<div class="live-pricing" data-pricing="card-limits" data-pricing-src="https://api.cryptoinfra.build/v1/pricing"><p class="live-pricing-fallback">Live prices: <code>GET https://api.cryptoinfra.build/v1/pricing</code> (no key needed) — this table fills in from it.</p></div>

**A purchase over a limit is declined**, whatever the card holds. Show these before a
customer loads a card for one large payment.
The same figures are on every product as `limits` on `GET /v1/cards/products`; read them
there for the BIN in front of you rather than copying one from this page. A BIN marked *not
published yet* has limits of its own; they are not on the sheet yet.

## Gas, on TRON

**Nothing to do.** Where the gas shows up depends on the movement:

- **A payout** — inside the withdrawal fee, nothing extra. See [Withdrawals](#withdrawals)
  for what that covers.
- **A card load or issue** — its own line, `gas`, on top of the amount. See
  [What a load costs](#what-a-load-costs-and-where-the-money-goes).

Both are priced live; [Every figure says whether it is live](#every-figure-says-whether-it-is-live)
explains how to read the figure you are shown.

You never hold TRX, never top up a gas balance and never switch anything on.

Sweeps between our own addresses never cost you gas at all — those are ours.

## What is never charged

- **The API itself.** No monthly plan, no per-call fee, no tiers. Rate limits, not bills,
  are what keep usage sane.
- **Creating users or addresses.** Unlimited, free, permanent.
- **Receiving a deposit.** Nothing is taken when money lands.
- **Webhooks, retries, the dashboard, or the documentation MCP server.**

## Reading rates from the API

| Call | Returns |
| --- | --- |
| [`GET /v1/fees`](reference) | The withdrawal fee per asset — `network_fee` plus any rate on your account — and `deposit.total` (`0`), with `dynamic` and `priced_at`. Swap and card prices are on their quote endpoints |
| [`GET /v1/withdrawal-fee-quote`](withdrawals) | The exact fee for a specific withdrawal — `total_fee` is the number to show — with `dynamic` and `quoted_at` |
| [`GET /v1/cards/products`](cards) | Card issue fee, load rate, close fee and minimum opening balance per BIN, with `issue_total`; the `gas` inside it, `gas_dynamic` and `gas_priced_at` |
| [`GET /v1/cards/issue-quote`](cards) | An issue priced end to end for a chosen opening balance — `total` is the number to show — with `dynamic` |
| [`GET /v1/cards/topup-quote`](cards) | A load priced end to end — fee, gas, your fee, `total` — with `dynamic` |
| [`GET /v1/cards/{id}/close-quote`](cards) | What closing a card debits the cardholder |
| [`POST /v1/swap/quote`](swaps) | A swap priced end to end, fee included |
| [`POST /v1/exchange/quote`](exchange) | An exchange priced end to end, fee included |

Quote endpoints return the number that will actually be charged. If a quote and this page
ever disagree, the quote is right and the page is a bug — please report it. Every quote
also says when it was priced and whether the figure is live; carry that to your own
customers rather than printing a number as a fixed charge.
