/v3/quote - Request a swap quote
Obtain a quote before performing a swap.
Method: POST
URL: https://api.swapkit.dev/v3/quote
The first step towards performing a swap is requesting a quote, which will compare the price offered by the different swap providers.
Quotes are cached for 5 minutes, and can be used to obtain swap transaction details.
Request Schema
Here's a detailed description of the different parameters:
sellAsset
string
Yes
The asset being sold (e.g. "ETH.ETH").
buyAsset
string
Yes
The asset being bought (e.g. "BTC.BTC").
sellAmount
string
Yes
Amount in basic units (decimals separated with a dot).
sourceAddress
string
No
Blockchain address to send the asset from. Must be a valid address for the sell asset's chain
Note - This is optional. By providing here we can screen the address against our index of bad addresses. Full screen is done in the /v3/swap endpoint
Refunds go here — there's no separate refundAddress. Must be an address the user controls and can receive at, not an exchange deposit address.
destinationAddress
string
No
Recipient blockchain address to send the asset to. Must be a valid address for the buy asset's chain
Note - This is optional. By providing here we can screen the address against our index of bad addresses. Full screen is done in the /v3/swap endpoint
providers
array
No
Limits the possible liquidity providers. If omitted, all available providers are used.
slippage
number
No
Max slippage in percentage (5 = 5%).
affiliateFee
number
No
Affiliate fee override in basis points (0-1000, max 10%). Must be a positive integer. If it is not provided, the API key configured fee tiers are applied.
cfBoost
boolean
No
Enables Chainflip boost for better rates.
maxExecutionTime
number
No
Maximum execution time in seconds. Routes exceeding this time are filtered out.
quoteType
string
No
"EXACT_INPUT" (default) or "FLEX_INPUT". Controls how the provider treats the input amount. See Flex input quotes below.
usePrivacyMode
boolean
No
Set to true to request a privacy-preserving swap, where the trade details aren't exposed publicly while the swap executes. Acts as a filter. See Privacy mode. Default: false.
enableSweep
boolean
No
Set to true to enable sweeping wallet funds when the transaction would otherwise leave unspendable dust in the address. Default: false
gasCheck
boolean
No
Set to true to check the wallet's native gas balance and warn when it can't cover the network fee. Opt-in, and applies to token sells only. The check runs at /v3/swap, which inherits this value unless it sets its own — no insufficientGas warning appears in the /v3/quote response. Default: false.
txHints
array
No
Only return routes your wallet can sign: simpleTransfer (transfer to a deposit address), transferWithMemo (transfer carrying a memo or OP_RETURN), or contractCall (calldata submitted to a contract). No match returns 404 noRoutesFound.
Note: Asset names for sellAsset and buyAsset should follow the following nomenclature:
Chain.Asset (e.g.,
"BTC.BTC"or"ARB.ETH")Chain.Asset-ContractAddress (e.g.,
"ETH.USDC-0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48")
This is the identifier as provided in the /tokens or /swapTo endpoints.
Flex input quotes
The optional quoteType parameter controls how the amount you send is treated by the swap provider.
EXACT_INPUT (default)
The exact sellAmount is swapped. This is the standard behaviour and applies when quoteType is omitted.
FLEX_INPUT
Swaps whatever is actually deposited instead of requiring the exact sellAmount. Set it when your deposit amount isn't fixed at quote time.
By default a quote assumes you'll deposit the exact input amount you asked for. Flexible input relaxes that: the amount that actually arrives may differ from the quote, and the route settles on whatever it receives.
It applies in three cases:
Sending a full balance. When the wallet sweeps its whole balance (when
enableSweepis set), the exact amount isn't known until send time, so flexible input is applied automatically.Manual sends. If the user signs and sends the transaction themselves and might deposit a slightly different amount than quoted, pass
quoteType: FLEX_INPUTso the first leg tolerates the difference.Multi-provider routes. On any leg after the first, the input is the previous leg's output, which isn't known exactly ahead of time — so flexible input is turned on automatically for those legs.
When you pass FLEX_INPUT, only routes where every provider supports flexible input are returned — any route containing a provider that doesn't is dropped.
Flexible input is decided entirely at quote time. Both the behaviour and the route filtering happen at /v3/quote; it can't be set at /swap, which only executes the route you've already picked.
The providers that support FLEX_INPUT are:
THORCHAIN_STREAMINGMAYACHAIN_STREAMINGCHAINFLIPCHAINFLIP_STREAMINGNEARFLASHNET
Privacy mode
The optional usePrivacyMode parameter requests a privacy-preserving swap, where the trade details aren't exposed publicly while it executes. Off unless you ask for it. Today it's fulfilled through NEAR Intents' Confidential Intents, though the parameter describes the capability rather than any one provider's implementation.
It's a filter, not a preference: only routes where every provider supports a privacy mode are returned. A route whose second hop is public exposes the trade just as thoroughly as a fully public one, so partial privacy is treated as no privacy. NEAR is the only privacy-capable provider today, so requesting privacy narrows you to the pairs NEAR Intents covers.
Because it filters rather than falls back, usePrivacyMode: true can leave you with nothing on a pair that quotes fine without it — either 404 noRoutesFound, or 200 with an empty routes array and a populated providerErrors. Decide up front whether you retry as a public quote or tell the user the pair isn't available privately; silently returning a public route is the wrong answer, since the user wouldn't know they hadn't got privacy.
Privacy mode is decided entirely at quote time. You can't set it at /v3/swap, which inherits the mode from the quote it executes. The flag isn't echoed in the response, so track it against routeId on your side.
Tracking is unaffected: /track resolves these swaps normally, including by depositAddress, because it reads the provider's status API rather than the public explorer.
Example request
A simple request to trade ETH.ETH to BTC.BTC may omit the providers array if you can manage them in the response, but should include the amount and slippage settings.
A quote expires after 5 minutes. Once it does, you can request a new one, or one will be requested automatically if a swap is initiated using this routeId .
Quote Response Schema
quoteId
string
UUID for this quote response
createdAt
string
ISO 8601 timestamp of when this quote response was created. Top level — a sibling of quoteId, not a per-route field.
routes
QuoteRoute[]
An array of routes with an individual routeId to request a swap with. QuoteRoute schema is explained below
providerErrors
QuoteError[] or undefined
Optional. Providers that were asked for a quote and declined. Present on a 200 response — it does not mean the request failed. Schema below; the codes are listed in Route availability and providers errors.
error
string or undefined
In case of a bad request, root level error is provided.
Quote Route Schema
Each route identifies a provider or a group of providers for the swap. Each item in the routes array contains the information needed to compare between them:
routeId
string
UUID of this specific swap response.
providers
array
List of providers available for this route (CHAINFLIP, THORHCAIN etc.).
sellAsset
string
The asset being sold (e.g., “ETH.ETH”).
buyAsset
string
The asset being bought (e.g., “BTC.BTC”).
sellAmount
string
Amount of the sell asset in smallest units.
expectedBuyAmount
string
Estimated amount of the buy asset to be received.
expectedBuyAmountMaxSlippage
string
Worst-case buy amount considering max slippage.
fees
array
List of fees applied to the swap (inbound, network, affiliate, service, outbound, liquidity).
estimatedTime
object
Estimated time for different phases of the swap.
totalSlippageBps
number
Expected total slippage.
legs
array
The different steps invovled in the swap.
warnings
array
Potential warnings about this swap provider.
txHint
string
(enum, optional)
How the deposit must be sent for this route — one of simpleTransfer (plain value transfer), transferWithMemo (transfer that must include the memo), or contractCall (submit as a smart-contract / EVM transaction). Returned at quote time so you can filter routes against your wallet's signing capabilities before calling /v3/swap, and guaranteed to match what /v3/swap builds for the same routeId. Absent on route patterns SwapKit hasn't classified — treat missing as unknown.
meta
object
Other information about the transaction and the assets involved.
meta.tags
array
"FASTEST", "RECOMMENDED" or "CHEAPEST" tag help sort the available routes.
nextActions
object
Data needed for the next request in the flow. { method: string; url: string; payload: object }
Quote Error Schema
provider
string
Specific ProviderName value
errorCode
string
One of the possible error codes listed below.
message
string
Message relating to thrown error.
minAmount
string or undefined
The provider's minimum sell amount in human units, when the provider reported one. Present on most sellAssetAmountTooSmall entries — retry at or above it.
Quote Error Codes and messages
noRoutesFound
No routes found for swap from {sellAsset} to {buyAsset}
404
No valid swap path exists between the requested token pair.
blackListAsset
Asset {asset} is blacklisted
400
The sell or buy asset is identified as a scam token in our blacklist.
apiKeyInvalid or unauthorized
"Invalid API key" / "Unauthorized”
401
Missing, expired, or invalid API key in x-api-key header.
invalidRequest
"Request body is required and must be a valid JSON object”.
400
Request body is missing, null, or malformed JSON.
solanaOutputBelowRentExemptMinimum
Guaranteed output of {minimumOutput} lamports is below the {minimum} lamport rent-exempt minimum needed to fund destination {address}. Increase the swap amount or send to an existing account.
400
Same-chain Jupiter swap buying native SOL for a destinationAddress other than the sender, where the post-slippage minimum output is under Solana's 890,880-lamport (0.00089088 SOL) rent-exempt floor. No on-chain existence check, so an already-funded destination is rejected too. Raise the sell amount, or deliver to sourceAddress.
solanaTokenProgramUnavailable
Could not resolve the Solana token program for mint {tokenAddress}. Please retry.
502
Transient. SwapKit could not determine whether an SPL mint is Token or Token-2022 while preparing a same-chain Solana destination. Safe to retry.
The invalidRequest error may include additional details depending on the missing parameters. Make sure to check the JSON formatting in the request.
Fees breakdown
Fees are categorized into different types based on their role in the swap process.
Inbound
Cost of getting the sell asset to the provider: estimated gas for the deposit, plus any provider ingress fee. Two entries when they're in different assets.
Network
Blockchain transaction fee for processing the swap.
Affiliate
Fee paid to the specified affiliate.
Service
SwapKit's service fee.
Outbound
Fee for transferring the buy asset to the destination address.
Liquidity
Fee applied by the liquidity provider to facilitate the swap.
Fees other than inbound are already reflected in expectedBuyAmount, whether taken from the input or the output — don't subtract them again. inbound is the only fee your wallet funds on top of sellAmount, and it isn't reflected in expectedBuyAmount.
Chainflip is the exception. Its inbound combines your gas with Chainflip's ingress fee, and only the gas is paid on top of sellAmount — the ingress is already reflected in expectedBuyAmount. Token deposits return the two separately (ingress in the deposited asset, gas in the chain's gas asset); native deposits sum them into one entry, so budget the full amount as an upper bound.
Estimated time
The estimated time in seconds for the swap is divided into the following phases:
Inbound: Time taken to receive the sell asset.
Swap: Time taken for the swap process.
Outbound: Time taken to transfer the bought asset to the destination. This includes the provider outbound time, not only the transaction time.
Total: The sum of all time estimates.
Example estimated time:
Route metadata
The meta section provides additional information about the swap.
assets
Details of the involved assets, including price and image links.
tags
["FASTEST", "RECOMMENDED", "CHEAPEST"]
approvalAddress
Token-approval spender address. Present only for EVM ERC-20 sells that require an approval.
/v3/swap returns a larger meta than this. Fields that only exist once a transaction is built — allowance, and the deposit-channel fields providerDepositChannelId / depositChannelExpiration — are documented on that page. /v3/quote never opens a deposit channel, so they never appear here.
Example meta Object:
The "tags" help identify what SwapKit considers the best routes by filtering through the ["FASTEST", "RECOMMENDED", "CHEAPEST"] labels.
RECOMMENDED
Best overall route based on output and speed.
CHEAPEST
The route with the maximum output.
FASTEST
The route with the shortest total estimated time.
To determine the RECOMMENDED route when multiple options are available, each route gets two normalized scores:
Output score (0-100): Compare the route's output to the maximum output of the available routes, multiplied by 100 for weight.
(routeOutput / maxOutput) * 100Time score (0-50): Compare the route's expected confirmation time to the minimum confirmation time of the available routes, subtracting from 50 to give it a dynamic weight. The fastest route will obtain 50 points here.
50 - abs(routeTime - minTime) / (maxTime - minTime)
Output and time are weighted dynamically, depending on the difference between the fastest route and the one being analyzed.
≤ 60 seconds
100 %
0 %
60s - 5 min
95 %
5 %
5 - 15 min
90 %
10 %
> 15 min
80 %
20 %
The weights are then multiplied to the score, and the route with the highest total is tagged as RECOMMENDED . It is simply outputScore * outputWeight + timeScore * timeWeight .
Next Actions
The nextActions object includes information about the request to make next. Generally it will point to the /swap endpoint which will return a transaction object, but for ERC-20 tokens the /swap endpoint may first return an approvalTx for spending approval, requiring a second /swap call to get the transaction.
For example, it could look like the following, which includes the method, url and payload to use. The "soureAddress" and "destinationAddress" need to be filled in:
Last updated

