conversions:execute API-key scope, or the conversions:manage team permission plus a fresh MFA factor from the dashboard.
Two execution modes, one API
The platform resolves the mode at quote and execute time — you can’t choose it, and a pair the external route can’t handle silently falls back to internal mode. The quote tells you which one you got viaexecutionMode.
Internal mode (executionMode absent or "internal") — an instant ledger swap against platform inventory. The debit, the credit and the completion commit atomically: either all of it happened or none of it did. The 201 body already carries status: "completed".
External mode (executionMode: "external") — the swap runs asynchronously over an external liquidity route:
- The full source amount is debited immediately and the conversion is persisted as
status: "processing". This is what the201returns. No credit exists yet. - The swap executes over the external route.
- A background monitor drives the conversion to a terminal state: on a verified fill it credits
creditAmountStroftoCurrencyand moves the row tocompleted; if the swap could not complete, it credits the full source amount back (commission included) and moves the row tofailed. The credit is normally at least the quoted minimum (toAmountStr), but in rare shortfall cases — a late deposit that the route filled at a worse rate — the conversion still completes crediting the amount that actually arrived on-chain, which can be below the quoted minimum. Always reconcile on the finalcreditAmountStr, never on the quote. - Positive slippage passes through to you. When the fill lands above the quoted minimum, the extra is credited to you up to the route’s expected (mid) output — the credited figure is what
creditAmountStrreads after completion, and the extra is reported separately asbonusToMerchantStr. You carry the downside band of the quote, so the symmetric upside within it is yours; only the excess above the expected output is platform margin. - Crediting is proven on-chain before it happens, and success and refund credits are mutually exclusive by construction — a double credit is impossible.
201 does not mean finished. In external mode, poll Get a conversion until status is completed or failed.
Status lifecycle
Rows that stall in
initializing/pending are automatically rolled back; they are never left dangling.
How the commission is computed
The commission is the maximum of several independent floors:- Configured rate — the platform’s configured commission rate, floored at 40 bps (0.4 %).
- Base floor (always applied) —
0.4 % × fromAmount + \$0.10. The two parts are additive: the percentage prices risk and volume, the flat $0.10 prices per-conversion handling. - Execution-cost floor — the base floor plus the real cost of physically moving the funds on-chain for that route. The fee reflects measured execution cost, and it only gets cheaper as the platform measures reality on your source currency.
Conversion temporarily unavailable — please try again shortly rather than quoting an unpriced conversion.
Rounding is asymmetric on purpose: commission rounds up, net and credited amounts round down. A conversion whose commission would swallow the whole amount is refused with a concrete suggested minimum (see below).
Fee breakdown (feeBreakdown)
When the effective fee lands above the 0.4 % base, the quote carries a display decomposition:
feeBreakdown
liddieFeePct— always0.4, the platform’s own margin, in percent.providerFeePct— the excess over that base, covering the execution cost of actually moving the funds.
liddieFeePct + providerFeePct reconstructs commissionRate × 100.
Minimums, maximums, and the learned minimum behaviour
A pair has a real minimum order size that moves with network fees and liquidity. The platform doesn’t hardcode one — it continuously re-learns each pair’s boundary, and a transient refusal can never raise a pair’s floor forever. What that means for you:- An amount below the floor is refused up front with a concrete suggestion, e.g.
Conversion amount too small — the minimum for USDT_TRC20 is about 25.4 USDT_TRC20. - When the commission floors exceed the whole amount you get
Conversion amount too small to cover execution costs — the minimum for X is about N X. - Routes also have a ceiling:
Conversion amount too large — the maximum convertible right now is about N X, orInsufficient liquidity for this conversion pair right now. - If your ledger balance exceeds what is physically convertible right now, the quote refuses with
Insufficient funds available to convert — the maximum amount convertible right now is about N X.
Do not cache minimums. Re-quote; the numbers move.
Error responses
Most conversion errors use the standard envelope:Error envelope
CONVERSIONS_DISABLEDon Get a quote and Execute a conversion →{ "error": "CONVERSIONS_DISABLED", "message": "…" }(on/best-routeand/cheaper-targetsthe same condition uses the envelope).409 RATE_DRIFT→{ "error", "message", "driftPct", "newQuote" }— see Execute a conversion.- A failed MFA factor →
{ "error": "…" }with the verification status code (including429when the account is locked out).
All error codes
All error codes
Idempotency conflicts
Reuse anidempotencyKey (your unique retry token) and you get a 409 in the standard envelope — never a bare 400. The code tells you which case you’re in:
The status code is the reliable signal: 409 = your key collided, nothing new was executed by this request. A
400 CONVERSION_FAILED is a genuine domain failure.
Message passthrough
The only failure text you should ever render ismerchantMessage on the conversion record: every message is filtered so internal details can never reach your users, and anything that isn’t safe collapses to a generic fallback ("Quote failed" / "Conversion failed"). Compliance refusals (This conversion cannot be processed for compliance reasons — contact support) do pass through, because contacting support is the actionable answer.
Integration checklist
- Get a quote → show
toAmountStr,commissionRateand, when present,feeBreakdown. - Optionally call Get best route (or Get cheaper targets) first and offer the cheaper option.
- Execute echoing
fromAmountStr,quotedRate,quotedToAmountand your ownidempotencyKey. On a409 CONVERSION_IN_PROGRESS, retry the same key after a backoff; on a409 IDEMPOTENCY_KEY_CONSUMED, stop — funds already moved. - Handle
409 RATE_DRIFTby re-presentingnewQuote(with a fresh passkey assertion if you used one). - If the
201body hasstatus: "processing", poll Get a conversion untilcompletedorfailed. Reconcile oncreditAmountStr, and rendermerchantMessageon failure. - Never persist minimums, and never rely on fields that aren’t documented on the conversion record — provider details are not returned.
See also
- Get a quote: price a conversion without moving funds.
- Execute a conversion: the endpoint this page prepares you for.
- Get a conversion: the status source of truth for external mode.
- Get balances: the ledger the conversion debits and credits.