Fetch Quotes & Routes

Before executing a swap, fetch a quote to see the expected output amount, price impact, exchange rate, and the exact route your swap will take. The route information tells you which pools will be used, helping you avoid unwanted multi-hop swaps and verify pool liquidity meets your criteria.

Why Fetch Quotes & Routes?

The quote endpoint does more than just return a price. It provides full route transparency:

  • Expected output: Exact amount the user will receive
  • Route details: Which protocol and pool will be used
  • Single vs multi-hop: See if your swap requires multiple hops
  • Pool verification: Check if the pool meets your liquidity criteria
  • Price impact: Alert users when trades are too large
  • Validation: Ensure a route exists before building the transaction

Route Transparency Matters

Without route information, you're swapping blind. With Vybe's quote response, you can:

CheckWhy It Matters
Pool addressVerify it's a legitimate, liquid pool
ProtocolKnow which DEX will execute your trade
Hop countAvoid multi-hop routes with higher slippage
Liquidity depthEnsure pool can handle your trade size

Endpoint

GET /trading/swap-quote

Request Parameters

ParameterTypeRequiredDescription
amountnumberAmount of input token in UI units (e.g., 0.1 for 0.1 SOL)
inputMintstringMint address of the token you're selling
outputMintstringMint address of the token you're buying
walletstringWallet address (enables personalized routing)
slippagenumberSlippage tolerance as percentage (default: 0.5)

Token Amount Format

The amount parameter uses UI units (human-readable), not base units:

  • 0.1 = 0.1 SOL (not 100,000,000 lamports)
  • 100 = 100 USDC (not 100,000,000 base units)

The API handles decimal conversion automatically.


Example Request

curl -X GET "https://api.vybenetwork.com/trading/swap-quote" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 1,
    "inputMint": "So11111111111111111111111111111111111111112",
    "outputMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
    "slippage": 0.5
  }'

Example Response

{
  "inAmount": "1000000000",
  "outAmount": "185234567",
  "otherAmountThreshold": "184308394",
  "outAmountUI": 185.234567,
  "otherAmountThresholdUI": 184.31,
  "swapRate": 185.234567,
  "priceImpactPct": 0.01,
  "routePlan": [
    {
      "protocol": "RAYDIUM_CLMM",
      "poolAddress": "8sLbNZoA1cfnvMJLPfp98ZLAnFSYCFApfJKMbiXNLwxj",
      "inputMint": "So11111111111111111111111111111111111111112",
      "outputMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
      "inAmount": "1000000000",
      "outAmount": "185234567"
    }
  ]
}

Response Fields Explained

Quote Fields

FieldTypeDescription
inAmountstringInput amount in base units (lamports for SOL)
outAmountstringExpected output in base units
otherAmountThresholdstringMinimum output considering slippage (base units)
outAmountUInumberExpected output in UI units (human-readable)
otherAmountThresholdUInumberMinimum output in UI units
swapRatenumberExchange rate (output tokens per 1 input token)
priceImpactPctnumberPrice impact as percentage (0.01 = 0.01%)

Route Plan Fields

The routePlan array contains each hop in the swap route:

FieldTypeDescription
protocolstringDEX protocol (e.g., RAYDIUM_CLMM, PUMPFUN)
poolAddressstringThe specific pool that will execute this hop
inputMintstringToken being sold in this hop
outputMintstringToken being received in this hop
inAmountstringInput amount for this hop (base units)
outAmountstringOutput amount for this hop (base units)

Understanding the Route

Single-Hop Routes (Best)

A single-hop route means your swap executes in one pool:

{
  "routePlan": [
    {
      "protocol": "RAYDIUM_CLMM",
      "poolAddress": "8sLbNZoA1cfnvMJLPfp98ZLAnFSYCFApfJKMbiXNLwxj",
      "inputMint": "SOL",
      "outputMint": "USDC"
    }
  ]
}

Benefits:

  • Lower slippage
  • Smaller transaction
  • Fewer failure points

Multi-Hop Routes (When Necessary)

Some swaps require multiple hops (e.g., Token A → SOL → Token B):

{
  "routePlan": [
    {
      "protocol": "PUMPSWAP",
      "poolAddress": "Pool1...",
      "inputMint": "TokenA",
      "outputMint": "SOL"
    },
    {
      "protocol": "RAYDIUM_CLMM",
      "poolAddress": "Pool2...",
      "inputMint": "SOL",
      "outputMint": "TokenB"
    }
  ]
}

Considerations:

  • Higher cumulative slippage
  • Larger transaction size
  • More potential failure points

Checking Route Quality

function analyzeRoute(quote) {
  const { routePlan, priceImpactPct } = quote;
  
  return {
    hops: routePlan.length,
    isSingleHop: routePlan.length === 1,
    protocol: routePlan[0].protocol,
    poolAddress: routePlan[0].poolAddress,
    priceImpact: priceImpactPct,
    recommendation: getRecommendation(routePlan.length, priceImpactPct)
  };
}

function getRecommendation(hops, impact) {
  if (hops === 1 && impact < 1) return "✅ Optimal route";
  if (hops === 1 && impact < 5) return "⚠️ High impact, consider smaller trade";
  if (hops > 1 && impact < 1) return "ℹ️ Multi-hop but low impact";
  if (hops > 1 && impact >= 1) return "⚠️ Multi-hop with significant impact";
  return "❌ Consider alternative";
}

Verifying Pool Liquidity

Use the pool address from the route to verify it meets your criteria:

async function verifyPoolBeforeSwap(inputMint, outputMint, amount) {
  // Get quote with route
  const quote = await getSwapQuote(inputMint, outputMint, amount);
  
  // Check route quality
  const route = quote.routePlan[0];
  
  // Verify it's using a protocol you trust
  const trustedProtocols = ['RAYDIUM_CLMM', 'RAYDIUM_CPMM', 'METEORA_DLMM'];
  if (!trustedProtocols.includes(route.protocol)) {
    console.warn(`Using ${route.protocol} - verify this is acceptable`);
  }
  
  // Check price impact
  if (quote.priceImpactPct > 2) {
    console.warn(`High price impact: ${quote.priceImpactPct}%`);
  }
  
  // Check for multi-hop
  if (quote.routePlan.length > 1) {
    console.log(`Multi-hop route with ${quote.routePlan.length} hops`);
  }
  
  return {
    quote,
    isOptimal: quote.routePlan.length === 1 && quote.priceImpactPct < 1,
    pool: route.poolAddress,
    protocol: route.protocol
  };
}

Understanding Price Impact

Price impact measures how much your trade moves the market price:

Price ImpactInterpretationRecommendation
< 0.1%NegligibleSafe to proceed
0.1% - 1%MinorNormal for most trades
1% - 5%ModerateConsider smaller trade
> 5%HighSplit into multiple trades

JavaScript Implementation

async function getSwapQuote(inputMint, outputMint, amount, slippage = 0.5) {
  const response = await fetch('https://api.vybenetwork.com/trading/swap-quote', {
    method: 'GET',
    headers: {
      'X-API-Key': API_KEY,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      amount,
      inputMint,
      outputMint,
      slippage
    })
  });
  
  if (!response.ok) {
    const error = await response.json();
    throw new Error(error.message || 'Failed to get quote');
  }
  
  return response.json();
}

// Usage with route analysis
async function displaySwapPreview() {
  const quote = await getSwapQuote(
    'So11111111111111111111111111111111111111112',  // SOL
    'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // USDC
    1  // 1 SOL
  );
  
  // Quote info
  console.log(`You'll receive: ${quote.outAmountUI} USDC`);
  console.log(`Minimum (with slippage): ${quote.otherAmountThresholdUI} USDC`);
  console.log(`Exchange rate: 1 SOL = ${quote.swapRate} USDC`);
  console.log(`Price impact: ${quote.priceImpactPct}%`);
  
  // Route info
  const route = quote.routePlan[0];
  console.log(`\nRoute: ${route.protocol}`);
  console.log(`Pool: ${route.poolAddress}`);
  console.log(`Hops: ${quote.routePlan.length}`);
}

Live Quote Updates

For swap UIs, poll quotes regularly to show live rates:

function useSwapQuote(inputMint, outputMint, amount) {
  const [quote, setQuote] = useState(null);
  const [loading, setLoading] = useState(false);
  
  useEffect(() => {
    if (!amount || amount <= 0) {
      setQuote(null);
      return;
    }
    
    // Debounce: wait 300ms after user stops typing
    const timeout = setTimeout(async () => {
      setLoading(true);
      try {
        const newQuote = await getSwapQuote(inputMint, outputMint, amount);
        setQuote(newQuote);
      } catch (e) {
        setQuote(null);
      }
      setLoading(false);
    }, 300);
    
    return () => clearTimeout(timeout);
  }, [inputMint, outputMint, amount]);
  
  // Auto-refresh every 10 seconds
  useEffect(() => {
    if (!quote) return;
    
    const interval = setInterval(async () => {
      const refreshed = await getSwapQuote(inputMint, outputMint, amount);
      setQuote(refreshed);
    }, 10000);
    
    return () => clearInterval(interval);
  }, [inputMint, outputMint, amount, quote]);
  
  return { quote, loading };
}

Error Handling

StatusErrorCauseSolution
400Missing required parametersamount, inputMint, or outputMint not providedInclude all required fields
400Invalid amountAmount is negative, zero, or not a numberUse positive number
400Invalid mint addressMint address is not a valid public keyCheck token addresses
400Failed to get quoteNo route available for the token pairToken may not have liquidity

Handling "No Route" Errors

async function getQuoteWithFallback(inputMint, outputMint, amount) {
  try {
    return await getSwapQuote(inputMint, outputMint, amount);
  } catch (error) {
    if (error.message.includes('No route') || error.message.includes('Failed to get quote')) {
      // This token pair has no liquidity
      return { 
        error: true, 
        message: 'No liquidity available for this pair' 
      };
    }
    throw error;
  }
}

Next Steps