Jupiter API Guide: Free Solana Price Data for Your Apps
What You’ll Need
- n8n Cloud or self-hosted n8n
- Hetzner VPS or Contabo VPS for self-hosting
- DigitalOcean as an alternative hosting option
- A Jupiter API key (free tier available)
- Node.js 16+ or Python 3.8+ for local testing
- Basic understanding of REST APIs and webhooks
Table of Contents
- Understanding Jupiter API and Why It Matters
- Getting Your Free Jupiter API Key
- Building Your First Price Data Query
- Real-Time Solana Price Monitoring with n8n
- Storing Price Data in Google Sheets
- Advanced: Historical Data Analysis
- Getting Started
Understanding Jupiter API and Why It Matters
I’ve been working with Solana ecosystem APIs for about three years now, and I can tell you that Jupiter API is one of the best-kept secrets for developers who need reliable, free Solana price data. Jupiter is the largest DEX aggregator on Solana, and their API exposes real-time pricing information that powers some of the most sophisticated trading bots and analytics platforms in the space.
What makes Jupiter different from other price APIs? Speed, accuracy, and zero rate limits for reasonable usage. You’re not dealing with a centralized price feed—you’re tapping directly into on-chain liquidity data from Solana’s most liquid markets. This means you get true price discovery rather than some aggregated guess.
The use cases are endless: build portfolio dashboards, create alert systems when tokens hit certain prices, automate trading decisions, or feed price data into machine learning models. I’ve personally used Jupiter API to power everything from Discord bots that alert traders to automated portfolio rebalancers.
Getting Your Free Jupiter API Key
First, head to the Jupiter API documentation. They don’t require traditional API keys—the API is public and free to use. This is one of the beauties of the Solana ecosystem. However, you’ll want to understand rate limiting and best practices.
Here’s the base endpoint you’ll be working with:
https://price.jup.ag/v4/price
No authentication needed. Let me show you the anatomy of a real request:
curl -X GET "https://price.jup.ag/v4/price?ids=So11111111111111111111111111111111111111112&vsToken=EPjFWaJgt46ggsuKpQSetg69YXiGBkSstw2HYPi81md"
Breaking this down:
ids= the token mint address you want price data for (SOL in this case)vsToken= what you’re pricing against (USDC in this example)
The response looks like this:
{
"data": {
"So11111111111111111111111111111111111111112": {
"id": "So11111111111111111111111111111111111111112",
"type": "derivedPrice",
"price": "175.50",
"decimals": 2,
"time": 1704067200000
}
},
"timeTaken": 0.0001
}
Clean, fast, and immediately actionable. You get the price, decimal precision, and timestamp.
Building Your First Price Data Query
Let me walk you through a practical example. I’m going to show you how to query multiple tokens at once and parse the response in Node.js:
const https = require('https');
const tokenMints = {
SOL: 'So11111111111111111111111111111111111111112',
USDC: 'EPjFWaJgt46ggsuKpQSetg69YXiGBkSstw2HYPi81md',
USDT: 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenYes',
RAY: '4k3Dyjzvzp8eMZWUXbBCjEvwSvsrH3xn5ZH3KD2Zcco',
JUP: 'JUPyiwrYJFskUPiHa7hkeR8NqtwybKHLo3xKc4CMycJ'
};
const vsToken = 'EPjFWaJgt46ggsuKpQSetg69YXiGBkSstw2HYPi81md';
async function getPrices() {
const mintIds = Object.values(tokenMints).join(',');
const url = `https://price.jup.ag/v4/price?ids=${mintIds}&vsToken=${vsToken}`;
return new Promise((resolve, reject) => {
https.get(url, (res) => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
try {
const parsed = JSON.parse(data);
resolve(parsed);
} catch (e) {
reject(e);
}
});
}).on('error', (e) => {
reject(e);
});
});
}
async function displayPrices() {
try {
const prices = await getPrices();
const tokenNames = Object.keys(tokenMints);
tokenNames.forEach((name, index) => {
const mint = Object.values(tokenMints)[index];
const priceData = prices.data[mint];
if (priceData) {
console.log(`${name}: $${priceData.price}`);
}
});
} catch (error) {
console.error('Error fetching prices:', error);
}
}
displayPrices();
Save this as get-prices.js and run it:
node get-prices.js
You’ll get output like:
SOL: $175.50
USDC: $1.00
USDT: $0.99
RAY: $1.25
JUP: $0.45
The beauty here is that you’re making one request to get multiple token prices. This is efficient and respects Jupiter’s infrastructure.
Real-Time Solana Price Monitoring with n8n
Now let’s automate this. I’m going to show you how to build a workflow in n8n Cloud that queries Jupiter API every minute and stores results.
💡 Fast-Track Your Project: Don’t want to configure this yourself? I build custom n8n pipelines and bots. Message me with code SYS3-HUGO.
Here’s your n8n workflow configuration (exportable JSON):
{
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"intervalValue": 1,
"intervalUnit": "minutes"
}
]
}
},
"id": "fd5a4d6c-8c2e-4bbb-9f3e-2a1b3c4d5e6f",
"name": "Trigger",
"type": "n8n-nodes-base.cron",
"typeVersion": 1,
"position": [
250,
300
]
},
{
"parameters": {
"url": "https://price.jup.ag/v4/price",
"options": {},
"specialParameters": {
"queryParameters": {
"ids": "So11111111111111111111111111111111111111112,EPjFWaJgt46ggsuKpQSetg69YXiGBkSstw2HYPi81md,Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenYes",
"vsToken": "EPjFWaJgt46ggsuKpQSetg69YXiGBkSstw2HYPi81md"
}
}
},
"id": "a1b2c3d4-e5f6-4g7h-8i9j-0k1l2m3n4o5p",
"name": "Fetch Jupiter Prices",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.4,
"position": [
500,
300
]
},
{
"parameters": {
"functionCode": "const data = $input.first().json.data;\nconst prices = {};\n\nconst tokenMap = {\n 'So11111111111111111111111111111111111111112': 'SOL',\n 'EPjFWaJgt46ggsuKpQSetg69YXiGBkSstw2HYPi81md': 'USDC',\n 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenYes': 'USDT'\n};\n\nObject.keys(data).forEach(mint => {\n const tokenName = tokenMap[mint];\n if (tokenName) {\n prices[tokenName] = {\n price: data[mint].price,\n timestamp: new Date(data[mint].time).toISOString()\n };\n }\n});\n\nreturn { prices, timestamp: new Date().toISOString() };"
},
"id": "b2c3d4e5-f6g7-4h8i-9j0k-1l2m3n4o5p6q",
"name": "Transform Prices",
"type": "n8n-nodes-base.function",
"typeVersion": 1,
"position": [
750,
300
]
}
],
"connections": {
"Trigger": {
"main": [
[
{
"node": "Fetch Jupiter Prices",
"type": "main",
"index": 0
}
]
]
},
"Fetch Jupiter Prices": {
"main": [
[
{
"node": "Transform Prices",
"type": "main",
"index": 0
}
]
]
}
}
}
After you create this workflow in n8n, you can extend it by adding a webhook that triggers alerts when prices move by more than 5%. Here’s the alert logic you’d add to the Transform Prices function:
const data = $input.first().json.data;
const prices = {};
const tokenMap = {
'So11111111111111111111111111111111111111112': 'SOL',
'EPjFWaJgt46ggsuKpQSetg69YXiGBkSstw2HYPi81md': 'USDC',
'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenYes': 'USDT'
};
const previousPrices = {
SOL: 175.00,
USDC: 1.00,
USDT: 0.99
};
Object.keys(data).forEach(mint => {
const tokenName = tokenMap[mint];
if (tokenName) {
const currentPrice = parseFloat(data[mint].price);
const previousPrice = previousPrices[tokenName];
const changePercent = ((currentPrice - previousPrice) / previousPrice) * 100;
prices[tokenName] = {
price: currentPrice,
changePercent: changePercent.toFixed(2),
alertTriggered: Math.abs(changePercent) >= 5,
timestamp: new Date(data[mint].time).toISOString()
};
}
});
return { prices, timestamp: new Date().toISOString() };
This code compares incoming ticks against baseline values to flag significant percentage shifts. You can route the output directly into a Discord or Slack notification node inside n8n whenever alertTriggered evaluates to true.
Storing Price Data in Google Sheets
Once your workflow runs automatically, logging those price ticks into a persistent data store is the next step. Google Sheets provides a simple, low-maintenance database for tracking price history without setting up SQL servers.
In n8n, add a Google Sheets node directly after the Transform Prices node. Set the action to “Append Row” and format your JSON payload so each token price gets its own row:
const input = $input.first().json.prices;
const rows = [];
Object.keys(input).forEach(token => {
rows.push({
json: {
Token: token,
Price: input[token].price,
ChangePercent: input[token].changePercent || 0,
Timestamp: input[token].timestamp
}
});
});
return rows;
This returns an array of standardized items that the Google Sheets node processes in a single execution batch. Every time your cron trigger fires, new rows append seamlessly to your spreadsheet.
Advanced: Historical Data Analysis
While Jupiter’s core price endpoint serves immediate snapshot data, building historical trends requires sampling snapshot data regularly over time.
Here is a complete Python script that queries the Jupiter API continuously, computes a moving average locally, and logs the calculated indicators:
import time
import urllib.request
import json
MINT_IDS = "So11111111111111111111111111111111111111112"
VS_TOKEN = "EPjFWaJgt46ggsuKpQSetg69YXiGBkSstw2HYPi81md"
URL = f"https://price.jup.ag/v4/price?ids={MINT_IDS}&vsToken={VS_TOKEN}"
price_history = []
EMA_PERIOD = 5
def fetch_price():
req = urllib.request.Request(URL, headers={'User-Agent': 'Mozilla/5.0'})
with urllib.request.urlopen(req) as response:
data = json.loads(response.read().decode('utf-8'))
return float(data['data'][MINT_IDS]['price'])
def calculate_ema(prices, period):
if len(prices) < period:
return sum(prices) / len(prices)
multiplier = 2 / (period + 1)
ema = sum(prices[:period]) / period
for price in prices[period:]:
ema = (price - ema) * multiplier + ema
return ema
print("Starting continuous price monitoring...")
for iteration in range(1, 11):
try:
current_price = fetch_price()
price_history.append(current_price)
current_ema = calculate_ema(price_history, EMA_PERIOD)
print(f"Sample #{iteration}: Price = ${current_price:.2f} | 5-Period EMA = ${current_ema:.2f}")
except Exception as err:
print(f"Error fetching price: {err}")
time.sleep(2)
Running this script gives you real-time streaming calculation over Jupiter’s aggregated DEX liquidity without relying on expensive paid data feeds.
Getting Started
Ready to launch your own automated price pipeline? Here is your step-by-step launch checklist:
- Deploy your hosting environment: Sign up for n8n Cloud for a fully managed setup, or configure a self-hosted server on a Hetzner VPS or Contabo VPS . DigitalOcean is another great option for fast cloud droplets.
- Setup custom routing: Register a domain via Namecheap if you plan on pointing webhooks or SSL certificates to your instance.
- Import the workflow: Paste the n8n JSON pipeline into your editor and activate the cron trigger.
- Connect alerts: Attach Google Sheets or notification nodes to store data and get notified when markets move.
Outsource Your Automation
Don’t have time? I build production n8n workflows, WhatsApp bots, and fully automated YouTube Shorts pipelines. Hire me on Fiverr — mention SYS3-HUGO for priority. Or DM at chasebot.online .
Want to automate this yourself?
Start with n8n Cloud (free tier available) or self-host on a Hetzner VPS for full control.
Want this engine running on your own VPS?
This blog publishes itself — daily, unattended, on free API tiers. The full engine, Hugo theme, and setup guide are available as System 3.
Get System 3