Skip to main content
Jupiter provides three core liquidity APIs that work together to power complete trading experiences. This guide shows you how to combine them to build a swap widget.
Using AI tools or building with LLMs? Use our llms.txt index for a structured map of the docs, and see AI Workflow for how to leverage Jupiter docs in AI-assisted workflows.

Why These APIs

No RPC Required

Our APIs handle all blockchain interactions for you.

No API Key Required

Start building immediately. API keys are optional (for higher rate limits via Portal).

No Upfront Payments

Use via our free and public endpoints.

The Three APIs

APIBase URLPurpose
Ultra Swaphttps://lite-api.jup.ag/ultra/v1Swap execution - get quotes and execute transactions using your wallet
Tokens V2https://lite-api.jup.ag/tokens/v2Token discovery - search and get token metadata
Price V3https://lite-api.jup.ag/price/v3Pricing - get USD prices for any token

Common Token Addresses

TokenMint AddressDecimals
SOLSo111111111111111111111111111111111111111129
USDCEPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v6

Dependencies

For signing and executing swap transactions, install @solana/web3.js version 1.x:
npm install @solana/web3.js@1 bs58
This guide uses @solana/web3.js v1. Version 2 has a different API for transaction handling.
Building a frontend? Use Jupiter Wallet Kit for easy wallet connectivity across 20+ Solana wallets.

1. Token Discovery

Search for tokens by symbol, name, or mint address using the Tokens V2 API.
GET https://lite-api.jup.ag/tokens/v2/search?query={searchTerm}
async function searchTokens(query) {
  const response = await fetch(
    `https://lite-api.jup.ag/tokens/v2/search?query=${encodeURIComponent(query)}`
  );
  return response.json();
}

// Example
const tokens = await searchTokens('usdc');
console.log(tokens[0]); // { id, name, symbol, icon, decimals, usdPrice, ... }
Other useful endpoints:
  • GET /tag?query=verified - Get all verified tokens
  • GET /toptrending/1h - Get trending tokens
  • GET /recent - Get recently listed tokens
See Tokens V2 API Reference for full response schema and all endpoints.

2. Price Fetching

Get USD prices for tokens using the Price V3 API.
GET https://lite-api.jup.ag/price/v3?ids={mint1,mint2,...}
async function getPrices(mints) {
  const ids = mints.join(',');
  const response = await fetch(`https://lite-api.jup.ag/price/v3?ids=${ids}`);
  return response.json();
}

// Example
const SOL = 'So11111111111111111111111111111111111111112';
const USDC = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';
const prices = await getPrices([SOL, USDC]);
console.log(prices[SOL]?.usdPrice);
console.log(prices[USDC]?.usdPrice);
See Price V3 API Reference for full response schema.

3. Swap Execution

Execute swaps using the Ultra Swap API with a simple flow:
  1. Get order
  2. Sign
  3. Execute

Get a Quote (No Wallet Needed)

GET https://lite-api.jup.ag/ultra/v1/order?inputMint={}&outputMint={}&amount={}
async function getQuote(inputMint, outputMint, amount) {
  const params = new URLSearchParams({ inputMint, outputMint, amount: amount.toString() });
  const response = await fetch(`https://lite-api.jup.ag/ultra/v1/order?${params}`);
  return response.json();
}

// Example: Quote for 0.01 SOL -> USDC
const quote = await getQuote(
  'So11111111111111111111111111111111111111112',
  'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
  0.01 * 1_000_000_000 // Amount to swap: 0.01 SOL (expressed in lamports, where 1 SOL = 1,000,000,000 lamports)
);
console.log(`${quote.inAmount} -> ${quote.outAmount}`);

Execute a Swap (Wallet Required)

Add the taker parameter to get a signable transaction, then sign and submit it.
import { VersionedTransaction, Keypair } from '@solana/web3.js';
import bs58 from 'bs58';

async function executeSwap(inputMint, outputMint, amount, wallet) {
  const walletAddress = wallet.publicKey.toBase58();

  // 1. Get order with transaction
  const params = new URLSearchParams({
    inputMint,
    outputMint,
    amount: amount.toString(),
    taker: walletAddress,
  });
  const order = await fetch(`https://lite-api.jup.ag/ultra/v1/order?${params}`).then(r => r.json());

  if (order.errorCode) throw new Error(order.errorMessage);

  // 2. Sign transaction
  const tx = VersionedTransaction.deserialize(Buffer.from(order.transaction, 'base64'));
  tx.sign([wallet]);
  const signedTx = Buffer.from(tx.serialize()).toString('base64');

  // 3. Submit to execute endpoint
  const result = await fetch('https://lite-api.jup.ag/ultra/v1/execute', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ signedTransaction: signedTx, requestId: order.requestId }),
  }).then(r => r.json());

  return result;
}

// Example
const wallet = Keypair.fromSecretKey(bs58.decode(process.env.PRIVATE_KEY));
const result = await executeSwap(
  'So11111111111111111111111111111111111111112',
  'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
  10000000,
  wallet
);

if (result.status === 'Success') {
  console.log(`Swap successful: ${JSON.stringify(result, null, 2)}`);
} else {
  console.error(`Swap failed: ${JSON.stringify(result, null, 2)}`);
}
Never hardcode private keys. Use environment variables or secure key management.

Frontend: Using Wallet Adapter

For browser-based apps, use a wallet adapter (e.g., Jupiter Wallet Extension) instead of a Keypair:
import { VersionedTransaction } from '@solana/web3.js';
import { useWallet } from '@solana/wallet-adapter-react';

async function executeSwapWithWalletAdapter(inputMint, outputMint, amount, wallet) {
  // wallet comes from useWallet() hook
  const walletAddress = wallet.publicKey.toBase58();

  // 1. Get order with transaction
  const params = new URLSearchParams({
    inputMint,
    outputMint,
    amount: amount.toString(),
    taker: walletAddress,
  });
  const order = await fetch(`https://lite-api.jup.ag/ultra/v1/order?${params}`).then(r => r.json());

  if (order.errorCode) throw new Error(order.errorMessage);

  // 2. Sign transaction using wallet adapter
  const tx = VersionedTransaction.deserialize(Buffer.from(order.transaction, 'base64'));
  const signedTx = await wallet.signTransaction(tx);
  const signedTxBase64 = Buffer.from(signedTx.serialize()).toString('base64');

  // 3. Submit to execute endpoint
  const result = await fetch('https://lite-api.jup.ag/ultra/v1/execute', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ signedTransaction: signedTxBase64, requestId: order.requestId }),
  }).then(r => r.json());

  return result;
}

// Usage in a React component
function SwapButton() {
  const wallet = useWallet();

  const handleSwap = async () => {
    if (!wallet.connected) return;
    const result = await executeSwapWithWalletAdapter(
      'So11111111111111111111111111111111111111112',
      'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
      10000000,
      wallet
    );
    console.log(result);
  };

  return <button onClick={handleSwap}>Swap</button>;
}
Need to set up wallet connectivity? See Jupiter Wallet Kit for a plug-and-play solution supporting 20+ wallets.
See Ultra Swap API Reference for full response schemas, error codes, and additional parameters.

4. All Functions Together

Here are all the standalone functions you need. Each function is self-contained and can be used independently.
import { VersionedTransaction, Keypair } from '@solana/web3.js';
import bs58 from 'bs58';

// ============================================================
// CONFIGURATION
// ============================================================

const API = {
  TOKENS: 'https://lite-api.jup.ag/tokens/v2',
  PRICE: 'https://lite-api.jup.ag/price/v3',
  ULTRA: 'https://lite-api.jup.ag/ultra/v1',
};

const TOKENS = {
  SOL: 'So11111111111111111111111111111111111111112',
  USDC: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
  USDT: 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',
};

// ============================================================
// TOKEN DISCOVERY (Tokens V2 API)
// ============================================================

async function searchTokens(query) {
  const response = await fetch(`${API.TOKENS}/search?query=${encodeURIComponent(query)}`);
  return response.json();
}

async function getVerifiedTokens() {
  const response = await fetch(`${API.TOKENS}/tag?query=verified`);
  return response.json();
}

async function getTrendingTokens(interval = '1h') {
  const response = await fetch(`${API.TOKENS}/toptrending/${interval}`);
  return response.json();
}

// ============================================================
// PRICE FETCHING (Price V3 API)
// ============================================================

async function getPrices(mints) {
  const ids = Array.isArray(mints) ? mints.join(',') : mints;
  const response = await fetch(`${API.PRICE}?ids=${ids}`);
  return response.json();
}

// ============================================================
// SWAP EXECUTION (Ultra API)
// ============================================================

async function getQuote(inputMint, outputMint, amount) {
  const params = new URLSearchParams({ inputMint, outputMint, amount: amount.toString() });
  const response = await fetch(`${API.ULTRA}/order?${params}`);
  return response.json();
}

async function executeSwap(inputMint, outputMint, amount, wallet) {
  const params = new URLSearchParams({
    inputMint,
    outputMint,
    amount: amount.toString(),
    taker: wallet.publicKey.toBase58(),
  });

  // Get order
  const order = await fetch(`${API.ULTRA}/order?${params}`).then(r => r.json());
  if (order.errorCode) throw new Error(order.errorMessage);

  // Sign
  const tx = VersionedTransaction.deserialize(Buffer.from(order.transaction, 'base64'));
  tx.sign([wallet]);
  const signedTx = Buffer.from(tx.serialize()).toString('base64');

  // Execute
  const result = await fetch(`${API.ULTRA}/execute`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ signedTransaction: signedTx, requestId: order.requestId }),
  }).then(r => r.json());

  return {
    success: result.status === 'Success',
    signature: result.signature,
    explorerUrl: result.signature ? `https://solscan.io/tx/${result.signature}` : null,
    error: result.error,
  };
}

// ============================================================
// USER DATA (Ultra API)
// ============================================================

async function getHoldings(walletAddress) {
  const response = await fetch(`${API.ULTRA}/holdings/${walletAddress}`);
  return response.json();
}

async function getTokenWarnings(mints) {
  const mintList = Array.isArray(mints) ? mints.join(',') : mints;
  const response = await fetch(`${API.ULTRA}/shield?mints=${mintList}`);
  return response.json();
}

// ============================================================
// USAGE
// ============================================================

// Search tokens
const tokens = await searchTokens('bonk');

// Get prices
const prices = await getPrices([TOKENS.SOL, TOKENS.USDC]);

// Get quote (no wallet)
const quote = await getQuote(TOKENS.SOL, TOKENS.USDC, 10000000);

// Execute swap (with wallet)
const wallet = Keypair.fromSecretKey(bs58.decode(process.env.PRIVATE_KEY));
const result = await executeSwap(TOKENS.SOL, TOKENS.USDC, 10000000, wallet);
console.log(result.success ? result.explorerUrl : result.error);

Function Reference

FunctionAPIDescription
searchTokens(query)Tokens V2Search tokens by name, symbol, or mint
getVerifiedTokens()Tokens V2Get all verified tokens
getTrendingTokens(interval)Tokens V2Get trending tokens
getPrices(mints)Price V3Get USD prices for tokens
getQuote(input, output, amount)UltraGet swap quote (no wallet needed)
executeSwap(input, output, amount, wallet)UltraExecute a swap
getHoldings(walletAddress)UltraGet wallet token balances
getTokenWarnings(mints)UltraGet security warnings for tokens

Test with curl

# Search tokens
curl "https://lite-api.jup.ag/tokens/v2/search?query=SOL" | jq '.[0].symbol'

# Get price
curl "https://lite-api.jup.ag/price/v3?ids=So11111111111111111111111111111111111111112" | jq

# Get quote
curl "https://lite-api.jup.ag/ultra/v1/order?inputMint=So11111111111111111111111111111111111111112&outputMint=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v&amount=10000000" | jq '{inAmount, outAmount}'

Next Steps