Core ConceptsFees & Quotes

Fees & Quotes

What a conversion costs, how to preview it, and how to price your own customers per account.

Who charges what

Two independent fee layers ride a conversion, both itemized in the conversion's fee_lines.

LineCharged byHow it is collected
onrampRastoOur conversion fee, named for the service it prices. On the standard plan it is metered to your monthly invoice, so deliveries go out whole and nothing is netted from your customer's funds
partner_feeYouWhatever you configure per virtual account. Netted in flight and credited to your balance immediately

Every rate is in basis points (bps). Your plan decides, per fee kind, whether a fee is collected monthly or realtime, and each fee line on a conversion states its own collection. GET /api/corridors always shows your effective rates.

Your fee, per virtual account

You price each customer individually by setting the fee on their account. There is deliberately no partner-wide default.

# At creation
curl -s $BASE/api/customers/cus_.../virtual_accounts \
  -H "Api-Key: $KEY" -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"currency": "usd", "destination": {...},
       "partner_fee_bps": "100", "partner_fee_flat": "0.25"}'

# Repricing later
curl -s -X PATCH $BASE/api/virtual_accounts/va_... \
  -H "Api-Key: $KEY" -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"partner_fee_bps": "150"}'
  • partner_fee_bps: 0 to 1000 bps (up to 3 decimal places), applied to the deposit amount.
  • partner_fee_flat: a fixed amount in the source currency, 0 to 1000 with up to 2 decimal places, combined with the bps component.
  • Send both as strings: a fractional JSON number returns 422 invalid_parameter.
  • Both default to 0 and are never null. Send 0 to stop charging.
  • The combined fee is capped so the delivered amount can never go negative.
  • Collected fees settle to your own balance on every conversion, visible immediately in GET /api/balances.

Previewing with quote estimates

GET /api/quotes/estimate prices a hypothetical conversion. It is non-binding, fee-itemized, and works in both directions.

"My user sends 100 USD, what lands?"

curl -s "$BASE/api/quotes/estimate?target_asset=usdc&target_chain=solana&amount=100" \
  -H "Api-Key: $KEY"
{
  "object": "quote_estimate",
  "quote_kind": "source",
  "source": {"asset": "usd", "amount": "100"},
  "target": {"asset": "usdc", "chain": "solana", "network": "mainnet"},
  "fee_lines": [{"kind": "onramp", "amount": "0.3", "asset": "usd", "collection": "monthly"}],
  "fee_total": "0.3",
  "amount_after_fees": "100",
  "estimated_delivered_amount": "100",
  "total_cost_bps": "0",
  "liquidity_available": true,
  "binding": false,
  "quoted_at": "2026-08-26T09:28:00+00:00"
}

total_cost_bps is the spread priced into the rate, a decimal string that may be fractional. Fees are itemized in fee_lines, each with its collection. A target-based estimate adds target_amount_requested.

Query paramNotes
target_asset, target_chainRequired
amountSource based. Exactly one of amount or target_amount
target_amountTarget based
source_assetDefaults to usd
partner_fee_bps, partner_fee_flatOptional. Fold your own fee into the preview, since estimates are account-agnostic

Sending both amount and target_amount, or neither, returns 422 invalid_parameter, as does a fractional JSON number (send amounts as strings; in a query string they always are). Other refusals:

  • 400 amount_out_of_range: outside the corridor's limits.
  • 400 unsupported_corridor: no enabled corridor delivers that asset on that chain.
  • 400 no_rate_available: no price for the pair right now. Retry.
  • 400 invalid_amount: target_amount is finer than the target asset's decimals.

amount_after_fees is what actually converts. On an all-monthly plan it equals the gross, because nothing was netted, and the fee lines above are what the month-end invoice will carry.

Estimates are indicative, never locked. ACH and wire deposits arrive hours later and convert at the rate current when the money lands. The binding numbers are exchange_rate, fee_lines, and delivered_amount on the conversion itself.

Wallet fees

Wallets bill by usage, monthly, in USD.

  • Per-unit usage prices on your plan, one per countable kind: wallet_creation, transaction_send, and webhook_delivery. A send's price includes the signing infrastructure: there is no separate signing fee.
  • Destination-chain gas at cost plus your plan's markup: the network fee a send actually burned, plus the recipient's token-account rent when a first-time delivery opens it. Priced at the rate noted when it executed, and never re-priced afterwards, so token price moves before month end are never your FX gain or loss.
  • Deposits into wallets are free.

Corridors

GET /api/corridors lists every enabled pair with its limits and your effective fees in its fees object. Build corridor pickers and validation from this endpoint. For the response shape and the full matrix, see Coverage.