Skip to main content
Every swap is two calls: a quote, then a build for that quote. You sign and send what the build returns.
1

Quote

GET /quote?inputMint=…&outputMint=…&amount=…&slippageBps=50 answers the route, the amounts and otherAmountThreshold. Every quote is checked to be buildable before it is served.
2

Build

POST /swap-instructions with userPublicKey and the quote (quoteResponse) answers the instructions; add "serialize": true for an unsigned transaction.
3

Sign and send

Sign the v1 transaction with the user’s key and send it before its blockhash expires (about a minute).

Three ways to name the route at build time

The build takes the route in one of three forms, in this order of precedence: With a quote or a ticket, any inputMint, outputMint (and with a ticket, amount) you also send must match it, or the build answers 400 quote_mismatch / route_ticket_mismatch. If a pinned route crosses a venue the router has since stopped serving, the build answers 409 venue_red: quote again.
routeTicket is not authentication. It is the quote, readable by anyone, with an HMAC so it cannot be altered. A router without ROUTER_TICKET_SECRET puts no ticket on its quotes and answers 400 invalid_route_ticket to one.

ExactIn and ExactOut

swapMode is ExactIn (default) or ExactOut. How an ExactOut is executed depends on the route:
  • One hop on a venue with an exact-output instruction (onchainExactOut in /venues): the output is pinned and the input is at most otherAmountThreshold.
  • Anything else (several hops, or a venue without that instruction): the route is built as an exact-in that spends the slippage cap (otherAmountThreshold) with a minimum output equal to the requested amount. The user pays the cap, not inAmount, and any output above the requested amount stays with the user.
The build tells you which with shape (exact_out or token_exact_in) and gives the bounds as minReturn and maxAmountIn.

Slippage

  • slippageBps defaults to 50 (0.5%) and cannot exceed 10000.
  • A slippageBps in the build body replaces the quote’s (or the ticket’s). Send it only on purpose.
  • Your deploy’s admin can cap slippage per venue on chain. A lower cap makes a route revert beyond it, even inside the slippage you asked for.

Choosing venues

Lists are comma-separated in the query string, or JSON arrays in a POST /quote body. Venues the router’s price checks currently hold out are removed from every quote automatically; GET /ready lists them in red_pass.

Split routes

allowSplit=true lets the router split an ExactIn across two routes in one transaction, when the split beats the best single route by at least 1 bps and still fits the transaction. In the quote, routePlan lists route A’s steps then route B’s; the first step of each carries its share in percent (rounded) and bps (exact).
A split build has two swap instructions, in swapInstructions; swapInstruction is only the first. A client that assembles the transaction from swapInstruction alone swaps a fraction of the input. Ask for splits only if you use swapInstructions or serialize: true.
Splits are not served for ExactOut or with a platform fee.

Wrapping SOL

wrapAndUnwrapSol (alias unwrapSol) defaults to true:
  • SOL in: the build moves the lamports into the user’s wrapped-SOL account (creating it) and closes it after the swap.
  • SOL out: the build unwraps by closing the user’s wrapped-SOL account, except when the output goes to another wallet (destinationTokenAccount), which receives wrapped SOL.
With false, the swap spends from and pays into the user’s wrapped-SOL token account and nothing is wrapped or closed.

Sending the output elsewhere

destinationTokenAccount (alias recipient) is the wallet that receives the output, not a token account: the output lands in that wallet’s associated token account, created if missing. A token account there is refused with 400 bad_recipient (it would have received into a nested account the owner cannot see).