Buy & sell
Quote and route a crypto purchase or sale across every connected provider — one best executable route, with the fee breakdown shown up front, not discovered at checkout.
Concept
A quote prices a side (buy or sell), an asset pair and an amount across every connected provider and returns the best executable route. An order is what you get when a quote is turned into an actual attempt to transact with that provider.
Resources
| Object | What it is |
|---|---|
quotes | rate, final_out, final_in, total_fees, expires_at, plus the winning offer_id, every priced offers[] route, and terminal per-provider outcomes (quoted, no_offer, paused, error) from the same quote call. |
orders | The attempt itself — status is the public lifecycle; money_state (never_authorized / hold_placed / captured) is the actual money truth, never inferred from status alone. Published only once a row has been classified — absent otherwise, and absence is never never_authorized or any other value. |
Lifecycle
Quotes are ready or indicative and always carry an expires_at — re-quote rather than reuse a stale one. An order's public status is the one lifecycle field on the wire (draft/quote_ready/etc. is not a separate enum — the hand-off to a provider's own checkout is read from whether provider_url is present); money_state, when classified, is reconciled with it on the same object, never a second, disagreeing status field.
checkout_readiness carries provider-specific handoff and freshness facts. ready means the quote passed those checks; it does not guarantee the final provider price, verification eligibility or settlement. An indicative quote retains its actual indicative_as_of; re-quote live before acting.
providers contains one row per provider observed in the existing call, ordered by provider ID. A usable offer wins over a failure on another payment method for the same provider. Each quoted row includes its selectable offer.offer_id. A route with no usable offer returns 409 capability_unavailable, with safe terminal outcomes in error.details.providers when available. Raw diagnostics and provider payloads are private.
offers[] contains every fully priced route from that fan-out, including sibling payment methods. Each entry binds the
canonical payment_method when known and opaque offer_id to its provider, readiness, expiry, resolved limits and
non-PII execution_context (assets, amount side, and supplied route selectors). Use entries with a known method when
presenting or selecting a method; unknown methods remain visible but are never inferred. Capabilities are not substituted
for missing quotes.
rate — on the winner, every offers[] entry and every providers[].offer echo — is each offer's own final_in
decimal value ÷ final_out decimal value, computed BEFORE either is rounded into the published Money fields, one
basis (from_asset per to_asset) computed the same way for every offer regardless of provider or side. Because
the derivation runs pre-rounding, rate × the published final_out amount can differ from the published final_in
amount in the last digit(s) when an asset's published decimals are coarser than the server's own internal
precision — treat that cross-check as approximate, not exact. It is informational only: never rank or compare offers by rate. For a
from_amount request, compare by final_out instead — every offer targets a different final_out for the same pay
amount, so the largest wins. For a to_amount request, compare by final_in only among offers whose final_out
equals the requested amount — the lowest pay amount among those wins. An offer whose final_out differs from the
requested amount is not comparable this way: not every provider honors an exact-output target.
The winner and each provider offer may include payment_method, the canonical method priced
for that specific offer_id. Preserve both when presenting or selecting an offer. A different
offer from the same provider can use another method; missing payment_method means unknown,
so do not copy it from the request or winning offer. The field describes the priced payment
intent and does not establish customer eligibility or guarantee the eventual settlement rail.
For Transak offers, specify the crypto network (to_network when buying, from_network
when selling). An unspecified network cannot authorize its checkout. Other usable provider
offers remain available; when none remain, 409 capability_unavailable includes
QUOTE_NETWORK_REQUIRED and the network field to provide.
Anonymous quoting stays on the existing public widget transport. Test-mode /v1/quotes requests currently return 503 temporarily_unavailable before any provider request; sandbox dispatch remains pending.
When sent, country must be an uppercase ISO 3166-1 alpha-2 code; a comprehensively-sanctioned or unsupported one is refused with 409 capability_unavailable before pricing runs, even when country is omitted and only inferred from a forwarded geo header.
Minimal flow
-
Authenticate with a business key or bearer holding
orders.write, then callPOST /v1/quotes— or the MCP toolget_quote— with side, assets, amount,to_network(required later to create a Bridge-native order from this quote) and (when known) country and payment method. -
Present the route and its fees to the person; quotes expire, so don't hold one past its
expires_at. A quote or selectableoffer_idalone never authorizes execution — the person must see the route and its fees first (see What an agent can and cannot do here below). -
Create the order:
POST /v1/orderswithquote_id, the chosenoffer_id, andwallet_address— required for a Bridge-native buy. A test-mode (sk_test_) key cannot create an order —orders.createanswers503 temporarily_unavailable("Test-mode orders are not available yet") before any other check, and releases the idempotency reservation; see Test mode. Step 3 is a live-key call that moves real money. It completes in place, landing directly on an activestatus, with no separate hand-off page. This release only a Bridge-native BUY offer creates this way: check the offer's owncheckout_readiness.handoff_modebefore calling create — onlybackend_nativeis live here today. Every other selectable offer is a typed, non-retryable refusal, not a bug:- A quote priced without
to_networkcannot become a Bridge-native order: answers409 capability_unavailable(param: quote_id), "This quote has no to_network — request a new quote with to_network set before creating a Bridge-native order". Re-quote withto_networkset and retry. - A Bridge-native SELL offer (same
handoff_mode,side: sell) answers409 capability_unavailable(codecapability_unavailable), "Bridge-native sell orders are not created through this endpoint yet" — a Sell's payout destination has no field onOrderCreateRequestyet. Never retry as-is. - Any hosted-provider offer —
checkout_readiness.handoff_modeother thanbackend_native— answers409 capability_unavailable(codecapability_unavailable), "<Provider>checkout is not available through this endpoint yet". Never retry as-is; a future release returns aprovider_urlto open instead. - A Paybis offer answers
409 capability_unavailable(codeprovider_paused) — Paybis's checkout path is frozen pending a product/security review, defense-in-depth on top ofPOST /v1/quotesalready excluding Paybis from every response. Never retry as-is.
The
wallet_addressitself can also be refused by destination screening:403 permission_error(codedestination_blocked) on a flagged address — never retry as-is — or503 temporarily_unavailable(codedestination_check_unavailable) when screening is itself unavailable and the fail-closed policy blocks the create — retry after the response'sRetry-After.Two more answers are conflicts, not bugs, and worth telling apart from an actual defect: a stale offer — past its own
expires_atorcheckout_readiness.checkout_fresh_until— answers409 conflict(coderequote_required); request a fresh quote and create the order from the newoffer_id. A create that reconciled onto an already-existing order — made by a prior attempt under a differentIdempotency-Key, recovered through Bridge's own provider-side idempotency key, rather than creating a second one — still answers201, but carriesIdempotent-Replayed: true; read that header before booking this call as having made a new order. See Errors for the full code reference. - A quote priced without
-
GET /v1/orders/{id}— readmoney_state, when present, before ever telling a user money moved.
Never conclude money moved from the status label alone — or from money_state's absence
get_order_status and get_payment both say this explicitly: a classified order can read completed while
money_state reads never_authorized. money_state itself is published only once a row is classified — most
rows never get one, so an ABSENT money_state means "never classified," not "not charged." Read the field's
presence and value together; never the display status, and never treat absence as a value.
What an agent can and cannot do here
get_quote prices a route; nothing about pricing a quote authorizes spending. An order is created from a quote, never chained straight from a quote response without the person seeing the route and its fees first — the same human-in-the-loop rule every money-preparation tool follows (see Agents & MCP).
Next: the reference for the full quote and order schemas · Providers & coverage for which providers and countries are actually live.