TL;DR
Metis is Jupiter’s routing engine, powering every swap on jup.ag. Get a quote, build a transaction, sign and send. Three API calls for a complete swap with full control over routing, fees, and execution. Base URL:https://api.jup.ag/swap/v1
When to use Metis
Ultra handles everything for you: routing, slippage, MEV protection, and transaction sending. No RPC node required. Metis gives you full control. Use Metis when you need:- Custom instructions in the same transaction (token transfers, program calls, memos)
- CPI from your Solana program to call Jupiter’s swap on-chain
- Your own transaction broadcasting via your RPC or Jito
- Full control over fees including priority fees, compute budget, and platform fees
- Route filtering to include or exclude specific DEXes
Prerequisites
- Get an API key at portal.jup.ag (free)
- All requests need the
x-api-keyheader - Install
@solana/web3.jsfor transaction signing and sending - Have an RPC endpoint (Helius, Triton, or similar)
Quick start
/swap to build a transaction:
swapTransaction (base64 unsigned). Deserialise, sign, send via your RPC.
API reference
Base URL:https://api.jup.ag/swap/v1
| Endpoint | Description |
|---|---|
GET /quote | Get a swap route quote from the Metis routing engine |
POST /swap | Build a serialised swap transaction from a quote |
POST /swap-instructions | Get individual swap instructions for custom transaction composition |
GET /program-id-to-label | Map program IDs to DEX labels |
The swap flow
Three steps: get a quote, build the transaction, sign and send.Step 1: Get a quote
GET /quote takes the token pair, amount, and slippage. It returns the best route across 74+ DEXes.
| Parameter | Required | Description |
|---|---|---|
inputMint | Yes | Token mint address to swap from |
outputMint | Yes | Token mint address to swap to |
amount | Yes | Raw amount in smallest units (lamports for SOL) |
slippageBps | Yes | Maximum slippage in basis points (50 = 0.5%) |
platformFeeBps | No | Basis points to charge as a platform fee. Requires feeAccount in /swap |
maxAccounts | No | Limit accounts in the swap instruction. Default: 64. Lower it when composing with custom instructions |
dexes | No | Comma-separated DEXes to route through exclusively |
excludeDexes | No | Comma-separated DEXes to exclude from routing |
instructionVersion | No | Always pass V2. Enables native SOL output, Token-2022 fees, and future features. Default: V1 |
Always pass
instructionVersion=V2. V2 instructions support nativeDestinationAccount for receiving native SOL, platform fees on Token-2022 swap pairs, and all future features. All examples in this guide use V2.| Field | What it means |
|---|---|
outAmount | Best output amount after deducting AMM fees and platform fees |
otherAmountThreshold | Minimum acceptable output, which is outAmount after applying slippageBps tolerance |
routePlan | Route breakdown: which DEXes, percentage split, amounts |
priceImpactPct | Price impact as a decimal string (0 to 1, not a percentage). Multiply by 100 to get the percentage. A value of 1 means 100% price impact (total loss). |
mostReliableAmmsQuoteReport | Markets that would have quoted for this pair. Useful for route debugging |
Step 2: Build the transaction
POST /swap takes the quote and returns a serialised transaction ready to sign.
| Parameter | Default | Description |
|---|---|---|
quoteResponse | required | The full quote response object from /quote |
userPublicKey | required | Wallet public key that will sign the transaction |
wrapAndUnwrapSol | true | Automatically wrap/unwrap SOL. Set to false if you manage wSOL yourself |
dynamicComputeUnitLimit | false | Simulates the swap to provide an accurate compute unit limit. Recommended for all normal flows |
prioritizationFeeLamports | auto | Priority fee config. See Optimise execution |
feeAccount | none | Token account for platform fees. Required if platformFeeBps was set in /quote |
Step 3: Sign and send
The response contains a base64-encoded serialised transaction. Deserialise, sign, send via your RPC.Full working example
End-to-end: swap 1 SOL to USDC, from scratch.Error handling
Errors can surface at every stage of the swap flow.During quoting
During quoting
| Error | What happened | What to do |
|---|---|---|
NO_ROUTES_FOUND / COULD_NOT_FIND_ANY_ROUTE | No liquidity path exists | Check if the token is tradeable on jup.ag. See Market Listing for the grace period criteria |
TOKEN_NOT_TRADABLE | Token mint not available for trading | Verify the token has sufficient liquidity on supported DEXes |
ROUTE_PLAN_DOES_NOT_CONSUME_ALL_THE_AMOUNT | Route cannot process the full input amount | Reduce input amount for a better output |
| Invalid parameters | Bad amount, slippageBps, or mint address | Validate inputs before calling /quote |
High priceImpactPct | Low liquidity or large trade relative to pool size | Not an error, but worth flagging. Reduce swap amount or split across multiple swaps |
During transaction building
During transaction building
| Error | What happened | What to do |
|---|---|---|
INVALID_COMPUTE_UNIT_PRICE_AND_PRIORITIZATION_FEE | Both compute unit price and prioritisation fee specified | Use one or the other, not both |
MAX_ACCOUNT_GREATER_THAN_MAX | Too many accounts in the transaction | Reduce maxAccounts in /quote |
FAILED_TO_GET_SWAP_AND_ACCOUNT_METAS | Failed to generate the swap transaction | Check the error message for details |
Invalid quoteResponse | Stale or malformed quote passed to /swap | Always pass the full, unmodified quote response. Re-quote if expired |
During transaction execution
During transaction execution
Transaction landing depends heavily on your execution pipeline: RPC quality, priority fee/tip calibration, and network conditions all play a role.
Jupiter swap program error codes come from the Anchor IDL on Solscan. For the full error reference, see Common Errors.
| Error | What happened | What to do |
|---|---|---|
| Transaction expired | Blockhash expired before landing | Re-quote and send faster. Consider blockhashSlotsToExpiry for tighter control |
SlippageToleranceExceeded (6001) | Price moved beyond slippageBps | Re-quote with fresh prices and retry |
InsufficientFunds (6024) | Not enough tokens for swap amount, transaction fees, or rent | Check balance before quoting |
InvalidTokenAccount (6025) | Token account is uninitialised or unexpected | Verify all token accounts are correctly initialised |
IncorrectTokenProgramID (6014) | Attempted platform fees on a Token2022 token without instructionVersion=V2 | Pass instructionVersion=V2 in /quote |
| DEX program errors | A CPI-ed AMM returned an error during the swap. Each AMM in the route is invoked via CPI, so errors can come from any program along the path | If the AMM’s IDL is public, decode the error code on a block explorer like Solscan. If the error is obscure, reach out on Jupiter Discord |
Execution debugging
When something fails, log the end-to-end flow: the URL and parameters used, the API responses, and the transaction signature. This makes issues reproducible.Route debugging
The quote response includesmostReliableAmmsQuoteReport: the markets that would have quoted for this pair.
outAmount to verify routing decisions. Map AMM addresses to DEX names with GET /program-id-to-label.
Optimise execution
Priority fees, compute units, slippage, and your RPC setup all affect whether transactions land. For the full deep dive, see Send Swap Transaction.Priority fees
Priority fees
Use
prioritizationFeeLamports with priorityLevelWithMaxLamports to set a fee level (medium, high, veryHigh) with a cap to prevent overpaying. Alternatively, use jitoTipLamports for Jito bundle tips (requires a Jito RPC). You cannot use both in the same /swap call.See how Jupiter estimates priority fees.Compute units
Compute units
Always pass
dynamicComputeUnitLimit: true in /swap or /swap-instructions. This simulates the swap to set an accurate compute unit limit, which directly reduces the priority fee you pay since fees are proportional to the compute budget requested.See how Jupiter estimates compute unit limit.Slippage
Slippage
slippageBps should match the volatility of the token pair. Too tight and transactions fail with SlippageToleranceExceeded; too loose and you lose value.See how Jupiter estimates slippage.RPC and broadcasting
RPC and broadcasting
A fast, well-connected RPC with stake-weighted connections will land transactions more reliably. Bad RPCs or poor fee calibration lead to delayed, expired, or dropped transactions.See how Jupiter broadcasts transactions.
Common questions
Why is there no route found for this token?
Why is there no route found for this token?
Jupiter routes through 74+ DEXes, but not every token has a routable market. New markets on supported DEXes get instant routing with a grace period based on token age (up to 30 days). After the grace period, the market must meet liquidity criteria. If no route is found, the token may not have graduated from its bonding curve, or its market doesn’t meet the requirements. See Market Listing for the full criteria.
What does priceImpactPct mean and when should I block swaps?
What does priceImpactPct mean and when should I block swaps?
priceImpactPct is a decimal from 0 to 1, not a percentage. Multiply by 100 to get the actual percentage. A value of 0.01 means 1% price impact. A value of 1 means 100% price impact, meaning the user would lose their entire input value. Always check this value before executing. If price impact exceeds your threshold (e.g. 5-10%), warn the user or block the swap entirely.Why is my transaction failing with slippage errors?
Why is my transaction failing with slippage errors?
Price moved between quote and landing. Re-quote with fresh pricing and send faster. For volatile tokens, increase
slippageBps.Can I use Metis and Ultra together?
Can I use Metis and Ultra together?
Yes. They access the same liquidity. Use Ultra for simple swaps, Metis for flows that need custom instructions, CPI, or full transaction control.
How do I filter which DEXes are used?
How do I filter which DEXes are used?
Use
dexes to restrict to specific DEXes, or excludeDexes to block them. Get the full list from GET /program-id-to-label.What's the difference between /swap and /swap-instructions?
What's the difference between /swap and /swap-instructions?
/swap returns a complete serialised transaction. /swap-instructions returns individual instructions you compose into your own transaction. Use /swap for standard swaps; /swap-instructions when you need custom instructions or CPI.Next steps
- Add Fees to Swap. Collect platform fees on swaps through your integration.
- Swap API Reference. Full endpoint schema and playground.
- Market Listing. How tokens and markets get listed in Jupiter’s routing engine.
- Ultra Swap API. Want simpler? Ultra handles everything for you.
