> For the complete documentation index, see [llms.txt](https://docs.yifi.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.yifi.io/api-reference/quote.md).

# Quote

Live rates across CEX, DEX and private routes (`GET /v1/quote`)

## Get swap quote

> Returns live quotes for a token pair and amount.\
> \
> \*\*Response shape\*\*\
> \
> \- \`bestQuote\` — array with \*\*one\*\* item (the winner) or \`\[]\` when nothing is available.\
> \- \`allQuotes\` — remaining quotes. When \`sort\` is not \`fastest\`, private v1/v2 winners that were not the global best are placed first; the rest stay in source order after ranking.\
> \
> \*\*\`type\` (engine filter)\*\* — comma-separated, case-insensitive. Default \*\*\`cex\`\*\*.\
> \
> \- \`cex\` — CEX / off-chain providers (\`getRatesForPairWorkflow\` on the CEX queue)\
> \- \`dex\` — DEX aggregators (started only when the DEX task queue is configured)\
> \- \`private\` — two-rail private routes (\`getPrivateQuoteWorkflow\`; intermediary token is not disclosed)\
> \- \`all\` — CEX + DEX + private\
> \- combinations such as \`cex,dex\` or \`cex,dex,private\`\
> \
> \*\*Ranking (\`sort\`)\*\*\
> \
> \- \`best\` \*(default)\* — highest \`rate\`; \`bestQuote\[0].label\` is \`"best price"\`\
> \- \`fastest\` — lowest parsed \`estimatedTime\`; label is \`"fastest"\`\
> \- \`noKyc\` — CEX/DEX quotes with \`kycLevel === 0\` only, then ranked by rate. Aliases: \`nokyc\`, \`no-kyc\`, \`no\_kyc\`\
> \
> \*\*Other filters\*\*\
> \
> \- \`xmrOnly=true\` — keep only private \`version=v1\` (XMR hop). Ignored when \`type\` does not include private.\
> \- \`excludeProviders\` — comma-separated slugs; CEX/DEX will not request those providers.\
> \- \`slippage\` — percent \`0.1–1\`, default \`0.5\` when omitted (applied on the server before workflows).\
> \- \`addressFrom\` / \`addressTo\` — forwarded to CEX/DEX quote workflows for providers that need them.\
> \
> Each quote gets a fresh \`rateId\` (UUID) stored in Redis for \*\*5 minutes\*\*. Pass it as \`rateId\` on \`POST /v1/swap\`. The HTTP response itself is cached for \*\*30 seconds\*\*; \`rateId\` values are still regenerated on every call.\
> \
> Unknown tickers/networks → \`404\` \`COIN\_NOT\_FOUND\`. No successful quotes after filtering → \`404\` \`NO\_QUOTES\_AVAILABLE\`. If every source times out with no quotes, the handler returns \`{ bestQuote: \[], allQuotes: \[] }\` (\`200\`) instead of \`408\`.

```json
{"openapi":"3.0.0","info":{"title":"YiFi Swap Public API","version":"1.0"},"tags":[{"name":"Quote","description":"Live rates across CEX, DEX and private routes (`GET /v1/quote`)"}],"servers":[{"url":"https://api.yifi.io","description":"Production"},{"url":"https://api-dev.yifi.io","description":"Development / Staging"}],"paths":{"/v1/quote":{"get":{"description":"Returns live quotes for a token pair and amount.\n\n**Response shape**\n\n- `bestQuote` — array with **one** item (the winner) or `[]` when nothing is available.\n- `allQuotes` — remaining quotes. When `sort` is not `fastest`, private v1/v2 winners that were not the global best are placed first; the rest stay in source order after ranking.\n\n**`type` (engine filter)** — comma-separated, case-insensitive. Default **`cex`**.\n\n- `cex` — CEX / off-chain providers (`getRatesForPairWorkflow` on the CEX queue)\n- `dex` — DEX aggregators (started only when the DEX task queue is configured)\n- `private` — two-rail private routes (`getPrivateQuoteWorkflow`; intermediary token is not disclosed)\n- `all` — CEX + DEX + private\n- combinations such as `cex,dex` or `cex,dex,private`\n\n**Ranking (`sort`)**\n\n- `best` *(default)* — highest `rate`; `bestQuote[0].label` is `\"best price\"`\n- `fastest` — lowest parsed `estimatedTime`; label is `\"fastest\"`\n- `noKyc` — CEX/DEX quotes with `kycLevel === 0` only, then ranked by rate. Aliases: `nokyc`, `no-kyc`, `no_kyc`\n\n**Other filters**\n\n- `xmrOnly=true` — keep only private `version=v1` (XMR hop). Ignored when `type` does not include private.\n- `excludeProviders` — comma-separated slugs; CEX/DEX will not request those providers.\n- `slippage` — percent `0.1–1`, default `0.5` when omitted (applied on the server before workflows).\n- `addressFrom` / `addressTo` — forwarded to CEX/DEX quote workflows for providers that need them.\n\nEach quote gets a fresh `rateId` (UUID) stored in Redis for **5 minutes**. Pass it as `rateId` on `POST /v1/swap`. The HTTP response itself is cached for **30 seconds**; `rateId` values are still regenerated on every call.\n\nUnknown tickers/networks → `404` `COIN_NOT_FOUND`. No successful quotes after filtering → `404` `NO_QUOTES_AVAILABLE`. If every source times out with no quotes, the handler returns `{ bestQuote: [], allQuotes: [] }` (`200`) instead of `408`.","operationId":"getQuote","parameters":[{"name":"tickerFrom","required":true,"in":"query","description":"Source token ticker","schema":{"type":"string"}},{"name":"networkFrom","required":true,"in":"query","description":"Source chain **`id`** — must match `/v1/chains[].id` (canonical slug, case-insensitive). Required.","schema":{"type":"string"}},{"name":"tickerTo","required":true,"in":"query","description":"Target token ticker","schema":{"type":"string"}},{"name":"networkTo","required":true,"in":"query","description":"Target chain **`id`** — must match `/v1/chains[].id` (canonical slug, case-insensitive). Required.","schema":{"type":"string"}},{"name":"amount","required":true,"in":"query","description":"Amount to exchange in source token units. Minimum `0.00000001`.","schema":{"minimum":1e-8,"type":"number"}},{"name":"type","required":false,"in":"query","description":"Engine filter. Default `cex`. Values: `cex`, `dex`, `private`, `all`, or comma-separated combinations (`cex,dex`). Case-insensitive.","schema":{"type":"string"}},{"name":"slippage","required":false,"in":"query","description":"Slippage tolerance in percent. Range `0.1–1`. Default `0.5`.","schema":{"default":0.5,"type":"number"}},{"name":"addressFrom","required":false,"in":"query","description":"Sender wallet address for providers that require it in quote requests.","schema":{"type":"string"}},{"name":"addressTo","required":false,"in":"query","description":"Recipient wallet address for providers that require it in quote requests.","schema":{"type":"string"}},{"name":"xmrOnly","required":false,"in":"query","description":"If true, only private v1 (XMR hop) quotes are returned. Ignored when `type` does not include private.","schema":{"default":false,"type":"boolean"}},{"name":"sort","required":false,"in":"query","description":"Quote ranking: `best` (highest rate), `fastest` (lowest estimated time), `noKyc` (kycLevel 0 only, then by rate). Default `best`.","schema":{"default":"best","type":"string","enum":["best","fastest","noKyc"]}},{"name":"excludeProviders","required":false,"in":"query","description":"Comma-separated provider slugs to skip. CEX/DEX will not request rates from these providers.","schema":{"type":"array","items":{"type":"string"}}}],"responses":{"200":{"description":"Best quote (0–1 items) and remaining provider quotes. Empty arrays when no source returned a quote (including global timeout).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteResponseDto"}}}},"400":{"description":"`INVALID_PARAMS` / `INVALID_AMOUNT` or class-validator errors (missing tickers/networks, amount ≤ 0, slippage out of range, unknown query fields)","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"error":{"type":"object","properties":{"code":{"type":"string","description":"Machine-readable code (`COIN_NOT_FOUND`, `RATE_EXPIRED`, `INVALID_API_KEY`, `HTTP_EXCEPTION` for class-validator, …)"},"message":{"description":"Human-readable message. Class-validator 400s may return a string **array** of constraint texts.","oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"requestId":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"details":{"description":"Present for some validation (4xx) errors when thrown with `details`.","oneOf":[{"type":"object","additionalProperties":true},{"type":"array"}]}},"required":["code","message","requestId","timestamp"]}}}}}},"404":{"description":"`COIN_NOT_FOUND`, `NO_SOURCES_AVAILABLE`, or `NO_QUOTES_AVAILABLE`","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"error":{"type":"object","properties":{"code":{"type":"string","description":"Machine-readable code (`COIN_NOT_FOUND`, `RATE_EXPIRED`, `INVALID_API_KEY`, `HTTP_EXCEPTION` for class-validator, …)"},"message":{"description":"Human-readable message. Class-validator 400s may return a string **array** of constraint texts.","oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"requestId":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"details":{"description":"Present for some validation (4xx) errors when thrown with `details`.","oneOf":[{"type":"object","additionalProperties":true},{"type":"array"}]}},"required":["code","message","requestId","timestamp"]}}}}}},"500":{"description":"`WORKFLOW_EXECUTION_ERROR` when sources fail with errors","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"error":{"type":"object","properties":{"code":{"type":"string","description":"Machine-readable code (`COIN_NOT_FOUND`, `RATE_EXPIRED`, `INVALID_API_KEY`, `HTTP_EXCEPTION` for class-validator, …)"},"message":{"description":"Human-readable message. Class-validator 400s may return a string **array** of constraint texts.","oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"requestId":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"details":{"description":"Present for some validation (4xx) errors when thrown with `details`.","oneOf":[{"type":"object","additionalProperties":true},{"type":"array"}]}},"required":["code","message","requestId","timestamp"]}}}}}}},"summary":"Get swap quote","tags":["Aggregator","Quote"]}}},"components":{"schemas":{"QuoteResponseDto":{"type":"object","properties":{"bestQuote":{"description":"Best quote across all sources – array with a single element (or empty if no quotes are available).","type":"array","items":{"$ref":"#/components/schemas/QuoteItemDto"}},"allQuotes":{"description":"Remaining quotes. Private best v1 and v2 (when present and not picked as the global best) are placed first, then other quotes sorted by `rate` descending.","type":"array","items":{"$ref":"#/components/schemas/QuoteItemDto"}}},"required":["bestQuote","allQuotes"]},"QuoteItemDto":{"type":"object","properties":{"rateId":{"type":"string","description":"Internal rate ID. Pass this in `rateId` to `/v1/swap` to record exactly which quote the user saw. Snapshot is kept in cache for 5 minutes."},"engine":{"type":"string","description":"Swap engine used for this quote","enum":["on-chain","off-chain","private"]},"provider":{"type":"string","description":"Provider slug – use this value in the `provider` field when calling `/v1/swap`"},"exchangerName":{"type":"string","description":"Display name of the provider"},"logoUrl":{"type":"string","description":"Provider logo URL. May be absent for some providers."},"rate":{"type":"string","description":"Exchange rate expressed as output per 1 unit of input token"},"estimatedOutput":{"type":"string","description":"Estimated amount the recipient will receive after all fees"},"inUsdValue":{"type":"number","description":"USD equivalent of the IN amount. Rate is taken from the etalon provider to USDT (TRON, then ETH, then BSC), with a fallback to a quote provider if the etalon is unavailable. `null` when the rate cannot be fetched.","nullable":true},"inUsdRateError":{"type":"string","description":"Set to `\"Can't fetch USD-rate\"` when the IN USD rate cannot be fetched. The quote itself is still returned.","nullable":true},"outUsdValue":{"type":"number","description":"USD equivalent of `estimatedOutput`. Rate is taken from this quote’s provider to USDT (TRON, then ETH, then BSC). `null` when unavailable (including private routes).","nullable":true},"outUsdDeviationPercent":{"type":"number","description":"Percent deviation of `outUsdValue` from `inUsdValue`. Negative means the user receives fewer USD than they sent.","nullable":true},"fromTokenUsdtRate":{"type":"number","description":"Raw USDT rate of 1 IN token. Taken from the etalon provider (USDT TRON → ETH → BSC), with a fallback to a quote provider if the etalon is unavailable. `null` when the IN USD rate cannot be fetched.","nullable":true},"toTokenUsdtRate":{"type":"number","description":"Raw USDT rate of 1 OUT token via this quote’s provider (USDT TRON → ETH → BSC). `null` when unavailable (including private routes).","nullable":true},"rateReversed":{"type":"number","description":"Inverse of `rate`: 1 OUT coin = Y IN coin"},"quoteId":{"type":"string","description":"Quote ID from the provider. Pass this in `quoteId` when calling `/v1/swap` to lock in the rate. `null` for providers that do not support rate locking."},"gasEstimated":{"type":"string","description":"Estimated gas cost in native token units. Present for DEX routes only. `null` for CEX and private routes."},"protocolFee":{"type":"string","description":"Protocol-level fee amount. Present for some DEX routes only."},"providerFee":{"type":"string","description":"Provider-level fee on top of the protocol fee. Present for some DEX routes only."},"slippageTolerance":{"type":"string","description":"Slippage tolerance applied to this quote in percent. Present for DEX routes only."},"estimatedTime":{"type":"string","description":"Expected time to complete the swap via this provider"},"kycLevel":{"type":"number","description":"KYC level inherited from the provider: 0 = No KYC, 1 = Rare KYC, 2 = Regular KYC","enum":[0,1,2]},"kycLevelName":{"type":"string","description":"KYC level display name inherited from the provider"},"legal":{"description":"Provider legal documents (Terms of Use, etc.) inherited from the provider","type":"array","items":{"$ref":"#/components/schemas/ProviderLegalDocumentDto"}},"label":{"type":"string","description":"Label assigned to the best quote (e.g. `\"best price\"`). `null` for all other quotes in `allQuotes`."},"dataForSign":{"type":"object","description":"EIP-712 typed data for client-side signing. Present only for CoW Swap DEX routes."},"schemeSign":{"type":"string","description":"Signing scheme identifier. Present only for CoW Swap routes. Always `\"eip712\"`."},"version":{"type":"string","description":"Private route version: v1 — Monero intermediate hop; v2 — stablecoin / non-XMR. Only when engine=private.","enum":["v1","v2"]},"routeKind":{"type":"string","description":"Private route shape: `direct` is one Quickex private swap; `two_leg` is the deposit+withdraw hop. Only when engine=private. `version` stays v1 or v2.","enum":["direct","two_leg"]}},"required":["rateId","engine","provider","exchangerName","rate","estimatedOutput","inUsdValue","inUsdRateError","outUsdValue","outUsdDeviationPercent","fromTokenUsdtRate","toTokenUsdtRate","rateReversed","estimatedTime"]},"ProviderLegalDocumentDto":{"type":"object","properties":{"docName":{"type":"string","description":"Document title"},"docLink":{"type":"string","description":"Official document URL"}},"required":["docName","docLink"]}}}}
```
