Comprehensive guidance for integrating Jupiter APIs (Swap, Lend, Perps, Trigger, Recurring, Tokens, Price, Portfolio, Prediction Markets, Send, Studio, Lock, Routing). Use for endpoint selection, integration flows, error handling, and production hardening.
Questions
How do I install integrating-jupiter?
Download vendored/jupiter/integrating-jupiter/SKILL.md from the publisher, or copy the path and open the repository. PlugMCP lists the skill and does not host the file.
Where does integrating-jupiter live?
The publisher keeps it at https://github.com/internet-court/internet-court-skill.
Which agents can use integrating-jupiter?
Claude, Cursor, and Codex can read a SKILL.md you add from the publisher's repository.
Comprehensive guidance for integrating Jupiter APIs (Swap, Lend, Perps, Trigger, Recurring, Tokens, Price, Portfolio, Prediction Markets, Send, Studio, Lock, Routing). Use for endpoint selection, integration flows, error handling, and production hardening.
name: integrating-jupiter
description: Comprehensive guidance for integrating Jupiter APIs (Swap, Lend, Perps, Trigger, Recurring, Tokens, Price, Portfolio, Prediction Markets, Send, Studio, Lock, Routing). Use for endpoint selection, integration flows, error handling, and production hardening.
license: MIT
metadata:
author: jup-ag
version: "1.2.0"
tags:
jupiter
jup-ag
solana
defi
swap-v2
token-swap
dex-aggregator
gasless
limit-order
dca
jupiter-lend
jupiter-perps
jupiter-trigger
jupiter-recurring
jupiter-portfolio
jupiter-prediction
jupiter-send
jupiter-studio
jupiter-lock
jupiter-routing
jupiterz-rfq
metis
jupiter-price-api
jupiter-tokens-api
jupiter-portal
jlp
Jupiter API Integration
Single skill for all Jupiter APIs, optimized for fast routing and deterministic execution.
Base URL: https://api.jup.agAuth: x-api-key from developers.jup.ag (required for Jupiter REST endpoints)
Use/Do Not Use
Use when:
The task requires choosing or calling Jupiter endpoints.
The task involves swap, lending, perps, orders, pricing, portfolio, send, studio, lock, or routing.
The user needs debugging help for Jupiter API calls.
Do not use when:
The task is generic Solana setup with no Jupiter API usage.
The task is UI-only with no API behavior decisions.
The agent context is not DeFi/crypto (generic triggers like buy, sell, trade assume a DeFi domain).
import { Connection, Keypair, VersionedTransaction } from '@solana/web3.js';
const API_KEY = process.env.JUPITER_API_KEY!; // from developers.jup.ag
if (!API_KEY) throw new Error('Missing JUPITER_API_KEY');
const BASE = 'https://api.jup.ag';
const headers = { 'x-api-key': API_KEY };
async function jupiterFetch<T>(path: string, init?: RequestInit): Promise<T> {
const res = await fetch(`${BASE}${path}`, {
...init,
headers: { ...headers, ...init?.headers },
});
if (res.status === 429) throw { code: 'RATE_LIMITED', retryAfter: Number(res.headers.get('Retry-After')) || 10 };
if (!res.ok) {
const raw = await res.text();
let body: any = { message: raw || `HTTP_${res.status}` };
try {
body = raw ? JSON.parse(raw) : body;
} catch {
// keep text fallback body
}
throw { status: res.status, ...body };
}
return res.json();
}
// Sign and send any Jupiter transaction
async function signAndSend(
txBase64: string,
wallet: Keypair,
connection: Connection,
additionalSigners: Keypair[] = []
): Promise<string> {
const tx = VersionedTransaction.deserialize(Buffer.from(txBase64, 'base64'));
tx.sign([wallet, ...additionalSigners]);
const sig = await connection.sendRawTransaction(tx.serialize(), {
maxRetries: 0,
skipPreflight: true,
});
return sig;
}
Token Amounts & Decimals
Every Jupiter amount field is in the token's smallest unit (raw integer) — never a human/UI value.
Common decimals: SOL & wSOL = 9, USDC & USDT = 6. Canonical mints: SOL So11111111111111111111111111111111111111112, USDC EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v.
Convert human → raw: raw = Math.round(human * 10 ** decimals). Examples: 1 SOL → 1_000_000_000, 100 USDC → 100_000_000. slippageBps is basis points: 0.5% = 50, 1% = 100.
Read decimals per-mint on-chain with getMint(connection, mintPubkey) from @solana/spl-token — never hardcode (decimals vary by token), and do not call the Price API just to discover decimals.
Rate Limit: 50 req/10s base, scales with 24h execute volume (see Rate Limits)
Endpoints: /order (GET), /execute (POST), /build (GET, Metis-only raw instructions)
Quote vs. execute: For a read-only quote/price preview, call GET /order and omit taker — the response transaction is null and you read outAmount, routePlan[].swapInfo.label, and price-impact fields. Pass taker (then sign + POST /execute) only when you actually intend to swap. There is no separate quote endpoint — /swap/v1/quote is deprecated; use /swap/v2/order for quotes too.
Routing: 4 routers compete — Metis (metis), JupiterZ (jupiterz), Dflow (dflow), OKX (okx). The router response field returns one of these values. swapType is aggregator (Metis, Dflow, or OKX) or rfq (JupiterZ). Response mode field: "ultra" (all routers, default params) or "manual" (restricted by optional params). /build uses Metis only.
Gasless: Three paths — automatic (Jupiter-covered), JupiterZ (MM-covered), integrator-payer (payer param, Metis-only routing). Eligibility varies by balance, trade size, and parameters used. See Gasless docs for current thresholds and disqualifying params.
Gotchas:
Signed payloads have ~2 min TTL. Transactions are immutable after receipt.
Split order/execute in code and logging. Re-quote before execution when conditions may have changed.
Routing impact of optional params: referralAccount + referralFee disable JupiterZ only (Metis/Dflow/OKX remain); payer (integrator gasless) restricts routing to Metis only (disables JupiterZ, Dflow, and OKX); receiver does NOT restrict routing, but must differ from taker (receiver=taker returns 400 "Receiver cannot be same as taker").
/build transactions cannot use /execute — self-manage via RPC.
Migrating from an older integration? Use the jupiter-swap-migration skill.
Fees are documented inline on the Order & Execute and Build pages; router competition and the parameter routing-impact matrix are on the Overview and Order & Execute pages.
Common error codes returned by /swap/v2/execute with recommended actions:
Code
Category
Meaning
Retryable
Action
0
Success
Transaction confirmed
—
—
-1
Execute
Missing/expired cached order
Yes
Re-quote and retry
-2
Execute
Invalid signed transaction
No
Fix transaction signing
-3
Execute
Invalid message bytes
No
Fix serialization
-1000
Aggregator
Failed landing attempt
Yes
Re-quote with adjusted params
-1001
Aggregator
Unknown error
Yes
Retry with backoff
-1002
Aggregator
Invalid transaction
No
Fix transaction construction
-1003
Aggregator
Transaction not fully signed
No
Ensure all required signers
-1004
Aggregator
Invalid block height
Yes
Re-quote (stale blockhash)
-2000
RFQ
Failed landing
Yes
Re-quote and retry
-2001
RFQ
Unknown error
Yes
Retry with backoff
-2002
RFQ
Invalid payload
No
Fix request payload
-2003
RFQ
Quote expired
Yes
Re-quote and retry
-2004
RFQ
Swap rejected
Yes
Re-quote, possibly different route
429
Rate limit
Rate limited
Yes
Exponential backoff, wait 10s window
On success, /execute returns { status: "Success", code: 0, signature, inputAmountResult, outputAmountResult, slot, totalInputAmount, totalOutputAmount }. On failure it returns status: "Failed" with a non-zero code and an error string. inputAmountResult/outputAmountResult are the actual on-chain amounts; reconcile against your quote.
Gotchas: Recompute account state before each state-changing action. Encode risk checks (health factors, liquidation boundaries) as preconditions. All deposit/withdraw/mint/redeem return base64 unsigned VersionedTransaction.
For SDK-level integration with @jup-ag/lend and @jup-ag/lend-read, use the jupiter-lend skill.
Gotchas: Max 9 simultaneous positions: 3 long (SOL, wETH, wBTC) + 6 short (3 tokens x 2 collateral USDC/USDT). Validate margin/leverage against account model.
Auth: Dual-auth — x-api-key (all requests) + Authorization: Bearer <jwt> (order mutations). JWT obtained via challenge-response: POST /auth/challenge → sign challenge with wallet → POST /auth/verify → receive token. JWT expiry does NOT affect open orders — they continue executing.
Order types: single (one directional trigger), oco (take-profit + stop-loss pair), otoco (entry trigger + OCO). triggerCondition: "above" or "below".
Architecture: Off-chain custodial vault (Privy) per wallet. Orders invisible on-chain until execution — MEV-resistant. Triggers on USD price (not pool rate ratios). Partial fills supported.
Gotchas:
Order creation is 3 steps — GET /vault/register (register if new; returns 409 "Vault already registered" if it exists, which is fine), POST /deposit/craft (returns transaction + requestId; the body MUST include orderType: "price" and orderSubType (single/oco/otoco)), sign deposit tx, then POST /orders/price with depositRequestId + depositSignedTx.
Cancellation is two-step — POST /cancel/{orderId} returns transaction + requestId; sign, then POST /confirm-cancel/{orderId} with signedTransaction + cancelRequestId.
Create response field is id (not orderId); order history objects use orderState/rawState (no status field).
Use mint address as primary identity; treat symbol/name as convenience.
Primary trust signal is top-level isVerified (boolean) plus organicScore (0-100) and organicScoreLabel (high/medium/low).
Secondary risk flag: audit.isSus — a boolean present ONLY when true (a safe token has no isSus key at all), so check it defensively as token.audit?.isSus === true, never read it directly. Verified live on flagged tokens (dev holds ~100% of supply); those also carry isVerified: null and organicScoreLabel: "low". Absence of isSus is NOT proof of safety — not all risky tokens carry the flag.
Other conditional audit fields the live API returns: mintAuthorityDisabled, freezeAuthorityDisabled, topHoldersPercentage, devBalancePercentage, devMigrations, devMints (all nullable, any may be absent; devMigrations is returned but missing from the current OpenAPI schema).
Response: keyed by mint, each value has usdPrice, blockId, decimals, priceChange24h, liquidity, createdAt (some tokens add conditional fields like launchpad, stockData, scaledUiConfig). Price API V3 has NO confidenceLevel field (that was V2).
Gotchas: Tokens with unreliable pricing are omitted from the response entirely (not an error, no null placeholder). Fail closed when a requested mint is missing from the response for safety-sensitive actions. Use blockId to check price recency.
Gotchas: Dual-sign requirement — sender + recipient keypair (derived from invite code). Claims only via Jupiter Mobile (no API claiming). Never expose invite codes.
Flow: create-tx -> upload image to presigned URL -> upload metadata to presigned URL -> sign -> submit via /dbc-pool/submit
Gotchas: Must submit via /dbc-pool/submit (not externally) for token to get a Studio page on jup.ag. Error codes: 403 = not authorized for pool, 404 = proxy account not found.
Market Listing: Instant routing for tokens < 30 days old. Normal routing (checked every 30 min) requires < 30% loss on $500 round-trip OR < 20% price impact comparing $1k vs $500.
Download vendored/jupiter/integrating-jupiter/SKILL.md from the publisher, or copy the path and open the repository. PlugMCP lists the skill and does not host the file.
Where does integrating-jupiter live?
The publisher keeps it at https://github.com/internet-court/internet-court-skill.
Which agents can use integrating-jupiter?
Claude, Cursor, and Codex can read a SKILL.md you add from the publisher's repository.