Documentation Index Fetch the complete documentation index at: https://dev.jup.ag/docs/llms.txt
Use this file to discover all available pages before exploring further.
TL;DR
Jupiter’s Prediction API lets you add prediction market trading to your Solana app. Users can trade on real-world event outcomes (sports, crypto, politics) with liquidity aggregated from Polymarket and Kalshi. The API handles order matching, position tracking, and settlement.
Base URL: https://api.jup.ag/prediction/v1
Prerequisites
Get an API key at Portal
All requests require the x-api-key header
Users need JupUSD (or USDC) to trade
BETA The Prediction Market API is currently in beta and subject to breaking changes. If you have feedback, reach out in Discord .
Quick start
# Get available prediction events
curl -X GET "https://api.jup.ag/prediction/v1/events?category=crypto" \
-H "x-api-key: YOUR_API_KEY"
When you need this
You’re building an app where users can:
Trade on event outcomes. “Will BTC hit $100k by end of 2026?”
Bet on sports, politics, or crypto. Binary YES/NO markets.
Build a prediction market frontend. Custom UI for trading.
Add speculation features. Let users put money on their predictions.
Track trading performance. Leaderboards, P&L history, profiles.
Common searches that lead here:
“prediction market api solana”
“binary options solana”
“bet on events solana api”
“polymarket on solana”
Why Jupiter
Building prediction markets from scratch requires:
Liquidity sourcing and market making
Order matching infrastructure
Settlement and payout systems
Real-world event data feeds
Jupiter handles all of this:
Aggregates liquidity from Polymarket and Kalshi.
Keeper network matches and fills orders.
On-chain settlement with guaranteed payouts.
No payout fees. Winners receive the full $1 per contract.
You get prediction market functionality without building the infrastructure.
How prediction markets work
Binary outcomes : Every market is YES or NO. “Will X happen?” → YES or NO.
Contract pricing : Prices range from 0.01 t o 0.01 to 0.01 t o 0.99. Price = implied probability.
70¢ YES price = market thinks 70% chance of YES
If you buy YES at 70¢ and YES wins, you profit 30¢ per contract
Losing contracts expire worthless
Settlement : When the event resolves, winning contracts pay out $1 each. No fees on payouts.
API reference
Base URL: https://api.jup.ag/prediction/v1
Endpoint Description GET /eventsList prediction events with filters GET /events/search?query={term}Search events by keyword GET /events/{eventId}Get event details GET /markets/{marketId}Get market pricing and status POST /ordersCreate order (returns unsigned tx) GET /orders?ownerPubkey={pubkey}Get user’s orders GET /orders/status/{orderPubkey}Get order fill status GET /positions?ownerPubkey={pubkey}Get user’s positions DELETE /positions/{positionPubkey}Close a position (sell all contracts) DELETE /positionsClose all positions POST /positions/{positionPubkey}/claimClaim winnings (returns unsigned tx)
Code examples
Browse available events
curl -X GET "https://api.jup.ag/prediction/v1/events?category=crypto&includeMarkets=true" \
-H "x-api-key: YOUR_API_KEY"
Filter options:
category: all, crypto, sports, politics, esports, culture, economics, tech
filter: new (last 24h), live (in progress), trending
provider: polymarket (default), kalshi
Search for specific events
const response = await fetch (
'https://api.jup.ag/prediction/v1/events/search?query=bitcoin&limit=10' ,
{
headers: { 'x-api-key' : 'YOUR_API_KEY' }
}
);
const { data : events } = await response . json ();
Create a buy order
curl -X POST "https://api.jup.ag/prediction/v1/orders" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"ownerPubkey": "USER_WALLET_PUBKEY",
"marketId": "MARKET_ID",
"isYes": true,
"isBuy": true,
"depositAmount": "2000000",
"depositMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
}'
Amount format : All USD values use native token units where 1,000,000 = $1.00.
depositAmount: '2000000' = $2.00
depositMint accepts USDC (EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v) or JupUSD (JuprjznTrTSp2UFa3ZBUFgwdAmtZCq4MQCwysN55USD)
Get user positions
const response = await fetch (
`https://api.jup.ag/prediction/v1/positions?ownerPubkey= ${ userPubkey } ` ,
{
headers: { 'x-api-key' : 'YOUR_API_KEY' }
}
);
const { data : positions } = await response . json ();
positions . forEach ( pos => {
const side = pos . isYes ? 'YES' : 'NO' ;
const pnl = pos . pnlUsd ? ( parseInt ( pos . pnlUsd ) / 1_000_000 ). toFixed ( 2 ) : 'N/A' ;
console . log ( ` ${ pos . marketMetadata . title } : ${ pos . contracts } ${ side } contracts, P&L: $ ${ pnl } ` );
});
Claim winnings from a settled position
// Check if position is claimable
if ( position . claimable ) {
const response = await fetch (
`https://api.jup.ag/prediction/v1/positions/ ${ position . pubkey } /claim` ,
{
method: 'POST' ,
headers: {
'x-api-key' : 'YOUR_API_KEY' ,
'Content-Type' : 'application/json'
},
body: JSON . stringify ({
ownerPubkey: userPubkey
})
}
);
const claimResponse = await response . json ();
// Deserialize, sign, and send
const transaction = VersionedTransaction . deserialize (
Buffer . from ( claimResponse . transaction , 'base64' )
);
transaction . sign ([ userWallet ]);
const signature = await connection . sendRawTransaction ( transaction . serialize (), {
skipPreflight: true ,
});
}
Event
interface Event {
eventId : string ;
isActive : boolean ; // Whether the event is listed
isLive : boolean ; // Whether the event is currently live
category : 'crypto' | 'sports' | 'politics' | 'esports' | 'culture' | 'economics' | 'tech' ;
subcategory : string ; // Subcategory within the category
tags : string []; // Tags associated with the event
metadata : {
eventId : string ;
title : string ;
subtitle : string ;
slug : string ; // URL-friendly identifier
series : string ; // Groups related events (e.g., "NFL Week 1")
closeTime : string ; // ISO 8601 formatted close time
imageUrl : string ;
isLive : boolean ;
};
markets : Market [];
volumeUsd : string ; // Total volume (micro USD)
closeCondition : string ;
beginAt : string | null ; // When the event begins
rulesPdf : string ; // URL to full rules document
}
Market
interface Market {
marketId : string ;
status : 'open' | 'closed' | 'cancelled' ;
result : null | 'yes' | 'no' ;
openTime : number ; // Unix timestamp
closeTime : number ; // Unix timestamp
resolveAt : number | null ; // Unix timestamp when market resolved
marketResultPubkey : string | null ; // Market result account public key
imageUrl : string ; // Market image URL
metadata : {
title : string ;
status : string ;
openTime : number ;
closeTime : number ;
isTeamMarket : boolean ; // Whether this is a team market
rulesPrimary : string ;
rulesSecondary : string ;
};
pricing : {
buyYesPriceUsd : number | null ; // Price to buy YES (micro USD)
buyNoPriceUsd : number | null ; // Price to buy NO (micro USD)
sellYesPriceUsd : number | null ; // Price to sell YES (micro USD)
sellNoPriceUsd : number | null ; // Price to sell NO (micro USD)
volume : number ; // Trading volume for this market
};
}
Position
interface Position {
pubkey : string ; // Position account
ownerPubkey : string ; // User's wallet
marketId : string ;
isYes : boolean ; // YES or NO side
contracts : string ; // Contracts held (u64 as string)
avgPriceUsd : string ; // Average entry price (micro USD)
totalCostUsd : string ; // Cost basis (micro USD)
sizeUsd : string ; // Alias of totalCostUsd (micro USD)
valueUsd : string | null ; // Mark-to-market value (null if market closed)
markPriceUsd : string | null ; // Current mark price (null if market closed)
sellPriceUsd : string | null ; // Best exit price (null if unavailable)
pnlUsd : string | null ; // Unrealized P&L (micro USD)
pnlUsdPercent : number | null ;
pnlUsdAfterFees : string | null ; // P&L after fees (micro USD)
pnlUsdAfterFeesPercent : number | null ;
realizedPnlUsd : number ; // Realized P&L (micro USD)
feesPaidUsd : string ; // Total fees paid (micro USD)
payoutUsd : string ; // Payout if position wins (contracts x $1)
claimable : boolean ; // Can claim payout?
claimed : boolean ; // Has payout been claimed?
claimedUsd : string ; // Amount claimed (micro USD)
openOrders : number ; // Number of open orders
openedAt : number ; // Unix timestamp when position opened
updatedAt : number ; // Unix timestamp of last update
claimableAt : number | null ; // When position becomes claimable
settlementDate : number | null ; // When market settles
eventMetadata : EventMetadata ;
marketMetadata : MarketMetadata ;
}
Create order response
interface CreateOrderResponse {
transaction : string ; // Base64 encoded unsigned transaction
txMeta : {
blockhash : string ;
lastValidBlockHeight : number ;
};
order : {
orderPubkey : string ;
positionPubkey : string ;
contracts : string ;
orderCostUsd : string ;
estimatedTotalFeeUsd : string ;
};
}
History event
interface HistoryEvent {
id : number ; // Unique event identifier
eventType : 'order_created' | 'order_filled' | 'order_failed'
| 'payout_claimed' | 'position_updated' | 'position_lost' ;
signature : string ; // Solana transaction signature
slot : string ; // Solana slot number
timestamp : number ; // Unix timestamp (seconds)
orderPubkey : string ; // Associated order account
positionPubkey : string ; // Associated position account
marketId : string ;
ownerPubkey : string ;
keeperPubkey : string ; // Keeper that processed the tx
externalOrderId : string ; // Client-provided order ID
orderId : string ; // Venue order ID
isBuy : boolean ; // Buy or sell
isYes : boolean ; // YES or NO side
contracts : string ; // Contracts in the order
filledContracts : string ; // Contracts filled
contractsSettled : string ; // Contracts settled
avgFillPriceUsd : string ; // Average fill price (micro USD)
maxFillPriceUsd : string ; // Max fill price (micro USD)
maxBuyPriceUsd : string | null ; // Buyer max price (micro USD)
minSellPriceUsd : string | null ; // Seller min price (micro USD)
depositAmountUsd : string ; // Deposit amount (micro USD)
totalCostUsd : string ; // Total cost (micro USD)
feeUsd : string | null ; // Fee charged (micro USD)
grossProceedsUsd : string ; // Gross proceeds (micro USD)
netProceedsUsd : string ; // Net proceeds (micro USD)
transferAmountToken : string | null ; // Token amount transferred
realizedPnl : string | null ; // Realized P&L (micro USD)
realizedPnlBeforeFees : string | null ; // Realized P&L before fees (micro USD)
payoutAmountUsd : string ; // Payout amount (micro USD)
eventId : string ;
marketMetadata : MarketMetadata ;
eventMetadata : EventMetadata ;
}
Order lifecycle
Create order : Call POST /orders → get unsigned transaction
Sign & submit : User signs, you submit to Solana
Keeper fills : Jupiter’s keeper network matches the order
Position updates : Position reflects new contracts
Market settles : When event resolves, result is recorded
Claim payout : If position won, call /claim to withdraw
Common questions
What tokens can users deposit?
JupUSD or USDC. Specify via depositMint parameter (defaults to USDC).
How do I know if a market is tradeable?
Check market.status === 'open'. A market with status open is actively trading.
What happens if my order doesn't fill?
You can close a position using DELETE /positions/{positionPubkey}, which sells all contracts. Unfilled orders that fail are closed automatically by the keeper network. Use GET /orders/status/{orderPubkey} to check if an order is pending, filled, or failed.
How do I calculate potential profit?
const contracts = 10 ;
const buyPrice = 0.70 ; // 70¢
const potentialProfit = contracts * ( 1 - buyPrice ); // $3.00 if wins
const potentialLoss = contracts * buyPrice ; // $7.00 if loses
How do I handle the micro USD format?
Which data provider should I use?
Polymarket (default) has more markets. Kalshi is US-regulated. Use the provider query param to switch.
Next steps