Build an EVM swap
The unsigned transactions that execute a quote for userPublicKey: the approvals it needs
(setupTransactions), then the swap (swapTransaction), simulated together. Send the quote
back unchanged as quoteResponse, as to the Solana router or to Jupiter.
Which quote is built, in this order:
quoteResponse: the stored quote itsquoteIdnames. The router builds only quotes it made and still holds, until theirexpiresAt, as many times as you like; the route, the amounts, the spender and the calldata come from the stored quote, never from the body. Achain,inputMint,outputMint,inAmount,outAmount,otherAmountThresholdorslippageBpsinquoteResponsethat differs from the stored quote is400 quote_mismatch(a new slippage goes in the top-levelslippageBps), and so is a top-levelchain,inputMint,outputMintoramountthat differs. AquoteResponsewithoutquoteIdis400 bad_request.quoteIdat the top level: the same, without sending the quote.- Otherwise the quote parameters at the top level (
chain,inputMint,outputMint,amountand the rest ofPOST /evm/quote): quoted now and built in the same call.
slippageBps moves the floor for this build only, from the quote’s outAmount (10000
leaves a zero floor: 422 declined amount_too_small); a wrap or an unwrap keeps its 1:1
floor.
At the build. At a fresh block the router prices the quoted route again and reads the
sender’s balance and allowance. If the route now gives less than otherAmountThreshold,
the answer is 409 declined quote_stale with what it gives now (outAmount, null when
it no longer executes): the floor is never lowered, quote again. Otherwise:
setupTransactions, to send first and in order:approve(spender, inAmount)on the input token, exact, to the venue’s router (spender). A smaller allowance already in place gets anapprove(spender, 0)first, for tokens like USDT that refuse a change from one non-zero allowance to another. Empty with a native input, for a wrap or an unwrap, and when the allowance already coversinAmount.swapTransaction: the floor is in its calldata (amountOutMin,amountOutMinimum, andunwrapWETH9(minimum, recipient)when the output is native) withdeadline, in Unix seconds (60 seconds after the build; 180 oneth).valueisinAmountwhen the input is native, otherwise"0". A V3 swap with native input ends withrefundETH(): whatever a pool does not take goes back to the sender in the same transaction.simulation: the approvals and the swap executed in order at the build’s block (eth_simulateV1), between reads of the sender’s input balance and the recipient’s output balance.passedneeds exactlyinAmountconsumed and at leastotherAmountThresholdarrived. It does not check nonces, nor that the sender can pay for gas.gason each transaction only when the simulation passed: the gas it used × the chain’s headroom (120%; 130% onrobinhood).maxFeePerGasandmaxPriorityFeePerGason each when the router could read the chain’s fees.costsadds them up.
Approvals and swap are separate transactions, not atomic. Sign them with the key of
userPublicKey and send them in order (each after the previous one is mined, or with
consecutive nonces) before deadline. Wrap and unwrap credit the sender: there
destinationTokenAccount must equal userPublicKey (422 declined recipient_unsupported).
Fee-on-transfer, rebasing and honeypot tokens are not supported: their builds fail in
simulation (output_below_minimum, partial_fill, swap_reverted).
Differences from the Solana POST /swap: transactions instead of instructions, always
returned (no serialize); only a quote this router holds is built, and quoteResponse must
match it; destinationTokenAccount is the address that receives the output; no platform
fee (feeBps above 0 is 400); priority-fee and tip fields are ignored (the fees are in
swapTransaction); extra fields simulation, costs (in wei), spender, deadline,
chain, chainId, blockHash, expiresAt; errors carry no quoteId.
Authorizations
Body
The wallet that signs and sends every transaction and pays the input: the from of each. Alias wallet
^0[xX][0-9a-fA-F]{40}$A quote of this router, sent back unchanged: its quoteId is what is built. Its chain, inputMint, outputMint, inAmount, outAmount, otherAmountThreshold and slippageBps, when present, must be the stored quote's (400 quote_mismatch): a new slippage goes in the top-level slippageBps
Instead of quoteResponse: the id of the quote to build
The address that receives the output. Default userPublicKey; must equal it for a wrap or an unwrap (422 declined recipient_unsupported). Alias recipient
^0[xX][0-9a-fA-F]{40}$With a quote: a new floor for this build only, outAmount × (10000 − slippageBps) / 10000 from the quote's outAmount (above 10000 counts as 10000; no effect on a wrap or an unwrap). Pair mode: the quote's slippage, default 50
Pair mode: as in POST /evm/quote. With a quote, if present, must be its chain
Pair mode: the token you spend. With a quote, if present, must be its input
"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
Pair mode: the token you receive. With a quote, if present, must be its output
"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
Pair mode: as in POST /evm/quote. With a quote, if present, must be its inAmount
Pair mode only
ExactIn, exactIn Pair mode only
Pair mode only
Pair mode only. Alias includeDex
Pair mode only. Alias excludeDex
Only 0: no platform fee on EVM (above 0 is 400; so is platformFeeBps)
Response
The unsigned transactions and their simulation (live answers of the public router; 0x…dEaD is a burn address that happens to hold ETH and USDC on Base, used so the simulations could pass)
The approvals, to send first and in order: none, approve(inAmount), or approve(0) then approve(inAmount)
The swap, to send after the approvals and before deadline
The quote built (in pair mode, the quote made for this call)
The quote's outAmount. What arrives at the build's block is simulation.outAmount
The floor in the swap's calldata: the quote's, or moved by this build's slippageBps
"ExactIn"The slippage of this build's floor
The approvals and the swap, executed in order at the build's block before you send anything
- passed
- failed
- requires_approval
- not_simulated
What the transactions cost besides the input, in wei as decimal strings; null where unknown
The venue's router the approvals are for, when the input is an ERC-20 swapped through a pool; null for a native input, a wrap or an unwrap
Unix seconds: the swap reverts if mined later. The chain's deadlineSecs after the build (60 s; 180 s on eth)
eth (chain id 1), bsc (56), base (8453), robinhood (4663)
eth, bsc, base, robinhood The block number the build was read and simulated at
That block's hash
The quote's expiry: until then it can be built again