Skip to main content
A quote prices a move before you create it. Send an asset pair and an amount to POST /v2/quotes and you get back one or more priced options — no resource ids, no recipient, and no margin of your own. It answers “what would this cost” so you can show a customer a price before they commit. A quote carries no margin of your own — Conduit’s rate and fees only. Apply your own margin when you create the order, not on the quote: see Redeem the option for which margin field a redemption accepts.
Test this flow in sandbox. Drive a conversion end-to-end with simulated money first — start with the sandbox quickstart, then conversion simulation — then apply the same request shape to a quote.

Prerequisites

  • Your API key.
  • A source and destination asset pair Conduit prices — an unpriceable pair returns 422 UNSUPPORTED_PAIR. Withdrawal mode prices a rail fee only and needs no pair.
  • An amount large enough that neither side rounds to zero. When you lock the destination, Conduit divides by the rate to derive what you send. If that result rounds to zero at the source asset’s precision, the quote returns 422 AMOUNT_OUT_OF_RANGE (details.reason: source_rounds_to_zero), with details.amount echoing the amount you sent. Branch on details.reason rather than the message text to tell this apart from the other causes of that error.

Step 1 — Price it

Send source, destination, lockSide, and amount. Two more things decide what you get back: whether source and destination name the same asset, and whether you include destinationCountry — the payout recipient’s domicile. There’s no separate mode field — these two signals discriminate three modes.

Conversion only

Different assets, no destinationCountry. One option, with rail: null — there’s no payout leg to route.

Conversion and payout

Different assets plus a destinationCountry. One option per rail actually available: the domestic US rails (fedwire, rtp, fednow) are evaluated for a USA recipient regardless of what country you send, so they appear whenever the corridor otherwise supports them; swift is the one rail actually routed to the destinationCountry you send. Two different fiat currencies plus a destinationCountry return 400 VALIDATION_ERROR: no order can redeem a payout leg chained off a fiat-to-fiat conversion. Price that move in two steps — quote and create the conversion with no destinationCountry, then send from the destination virtual account with a standalone payout.
A rail eligible for the route but not for a payout to that corridor (or the reverse) is left out — it’s never defaulted in. A corridor with no eligible rail at all still returns 201 with options: [], not an error.

Withdrawal only

The same asset on both sides, plus a destinationCountry. One option per available rail, and rate: null on each — there’s no FX leg to price, only a rail fee:
The same asset with no destinationCountry returns 400 VALIDATION_ERROR — there’s nothing to price.

The envelope around options[]

sourceAssetRef and destinationAssetRef echo the pair you asked for. They name an asset — a code, plus a chain when the asset is on-chain — and never carry an amount. They’re deliberately not called sourceAsset / destinationAsset: an order response uses those two names for money, amount included, and one client type can’t mean both. amount is the amount the quote locked, in the asset of the side lockSide names. It’s money-shaped like every other amount in a /v2 response, so you never infer its asset from lockSide yourself.

Step 2 — Read an option

Each entry in options[] prices one path. A conversion-only or payout-mode option is redeemable in Step 3; a withdrawal-mode option (rate: null) is preview-only — it prices a rail’s fee for a standalone payout, and redeeming it as an order returns 422 INVALID_ORDER_COMBO.

Step 3 — Redeem the option

Create the order with quoteOptionId instead of amount / lockSide — the order inherits both from the option, so sending either alongside quoteOptionId returns 400 VALIDATION_ERROR. A redemption also always names an explicit source (wallet or virtual account); sourceAsset (deposit funding) is refused alongside quoteOptionId, since there’s no funding window to check against the option’s locked rate. markupBps isn’t available on a redemption — it’s refused alongside quoteOptionId, since redemption never recomputes the option’s locked rate to fold a percentage into. For a percentage margin, create the order directly with amount / lockSide instead. markupAmount is available, but behaves differently here than on a fresh order: the option’s sourceAmount and destinationAmount are already locked and never recomputed, so markupAmount always adds to totalDebit — on both lock sides — rather than reducing the principal the way it would on a source-locked order created directly. A payout-mode option needs autoPayout naming the recipient (quotes carry no recipient), and it’s subject to the same documentation and whitelist policy as a standalone payout — most purposes need at least one documents id:
The order executes at the option’s locked rate and fees — nothing is re-priced. Keep in mind:
  • The option is single-use and short-lived. expiresAt is about 5 minutes out.
  • A payout-mode option’s autoPayout must match what the option priced. Its rail must equal the option’s own, and — for a fiat payout — its recipient.postalAddress.country must equal the destinationCountry you quoted. Every payout-mode option has an on-chain source, because a fiat-to-fiat pair is never quoted with a destinationCountry.
  • A withdrawal-mode option (rate: null) can’t be redeemed as an order — it only informs a standalone payout.
  • Recipient-type pricing is rare, but possible. If a pricing rule scoped to this payout’s recipient type would have priced the option differently, redemption is refused rather than collecting the wrong amount. Create the order directly with amount / lockSide instead — pricing will resolve against the real recipient.

End-to-end

  1. POST /v2/quotes — get back options[].
  2. Show the customer a price from the option you want (its endUserRate, recipientAmount, totalDebit).
  3. POST /v2/orders with that option’s quoteOptionId (plus autoPayout for a payout-mode option).
  4. The order is created already priced at the quote’s locked rate — proceed exactly as you would for any other order: POST /v2/orders/{orderId}/execute, or autoExecute: true on create. See Convert crypto and Send a payout for what happens next.

See also

  • Convert crypto — creating a conversion order directly, without a quote.
  • Send a payout — the standalone payout endpoint a withdrawal-mode option informs, and the documentation/whitelist policy an autoPayout redemption shares.
  • Errors — the full QUOTE_* error reference.