$npx -y skills add jup-ag/agent-skills --skill integrating-jupiterComprehensive 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.
| 1 | # Jupiter API Integration |
| 2 | |
| 3 | Single skill for all Jupiter APIs, optimized for fast routing and deterministic execution. |
| 4 | |
| 5 | **Base URL**: `https://api.jup.ag` |
| 6 | **Auth**: `x-api-key` from [developers.jup.ag](https://developers.jup.ag/) (**required for Jupiter REST endpoints**) |
| 7 | |
| 8 | ## Use/Do Not Use |
| 9 | |
| 10 | Use when: |
| 11 | - The task requires choosing or calling Jupiter endpoints. |
| 12 | - The task involves swap, lending, perps, orders, pricing, portfolio, send, studio, lock, or routing. |
| 13 | - The user needs debugging help for Jupiter API calls. |
| 14 | |
| 15 | Do not use when: |
| 16 | - The task is generic Solana setup with no Jupiter API usage. |
| 17 | - The task is UI-only with no API behavior decisions. |
| 18 | - The agent context is not DeFi/crypto (generic triggers like `buy`, `sell`, `trade` assume a DeFi domain). |
| 19 | |
| 20 | **Triggers**: `swap`, `quote`, `gasless`, `best route`, `buy`, `sell`, `trade`, `convert`, `token exchange`, `jupiter api`, `jup.ag`, `ultra`, `metis`, `ultra swap`, `ultra api`, `ultra-api.jup.ag`, `lend`, `borrow`, `earn`, `yield`, `apy`, `deposit`, `liquidation`, `perps`, `leverage`, `long`, `short`, `position`, `futures`, `margin trading`, `limit order`, `trigger`, `price condition`, `dca`, `recurring`, `scheduled swaps`, `token metadata`, `token search`, `verification`, `shield`, `price`, `valuation`, `price feed`, `portfolio`, `positions`, `holdings`, `prediction markets`, `market odds`, `event market`, `invite transfer`, `send`, `clawback`, `create token`, `studio`, `claim fee`, `vesting`, `distribution lock`, `unlock schedule`, `dex integration`, `rfq integration`, `routing engine`, `status page`, `health check`, `service health`, `accumulate`, `auto-buy` |
| 21 | |
| 22 | ## Developer Quickstart |
| 23 | |
| 24 | ```typescript |
| 25 | import { Connection, Keypair, VersionedTransaction } from '@solana/web3.js'; |
| 26 | |
| 27 | const API_KEY = process.env.JUPITER_API_KEY!; // from developers.jup.ag |
| 28 | if (!API_KEY) throw new Error('Missing JUPITER_API_KEY'); |
| 29 | const BASE = 'https://api.jup.ag'; |
| 30 | const headers = { 'x-api-key': API_KEY }; |
| 31 | |
| 32 | async function jupiterFetch<T>(path: string, init?: RequestInit): Promise<T> { |
| 33 | const res = await fetch(`${BASE}${path}`, { |
| 34 | ...init, |
| 35 | headers: { ...headers, ...init?.headers }, |
| 36 | }); |
| 37 | if (res.status === 429) throw { code: 'RATE_LIMITED', retryAfter: Number(res.headers.get('Retry-After')) || 10 }; |
| 38 | if (!res.ok) { |
| 39 | const raw = await res.text(); |
| 40 | let body: any = { message: raw || `HTTP_${res.status}` }; |
| 41 | try { |
| 42 | body = raw ? JSON.parse(raw) : body; |
| 43 | } catch { |
| 44 | // keep text fallback body |
| 45 | } |
| 46 | throw { status: res.status, ...body }; |
| 47 | } |
| 48 | return res.json(); |
| 49 | } |
| 50 | |
| 51 | // Sign and send any Jupiter transaction |
| 52 | async function signAndSend( |
| 53 | txBase64: string, |
| 54 | wallet: Keypair, |
| 55 | connection: Connection, |
| 56 | additionalSigners: Keypair[] = [] |
| 57 | ): Promise<string> { |
| 58 | const tx = VersionedTransaction.deserialize(Buffer.from(txBase64, 'base64')); |
| 59 | tx.sign([wallet, ...additionalSigners]); |
| 60 | const sig = await connection.sendRawTransaction(tx.serialize(), { |
| 61 | maxRetries: 0, |
| 62 | skipPreflight: true, |
| 63 | }); |
| 64 | return sig; |
| 65 | } |
| 66 | ``` |
| 67 | |
| 68 | ## Token Amounts & Decimals |
| 69 | |
| 70 | Every Jupiter `amount` field is in the token's **smallest unit (raw integer)** — never a human/UI value. |
| 71 | |
| 72 | - Common decimals: **SOL & wSOL = 9**, **USDC & USDT = 6**. Canonical mints: SOL `So11111111111111111111111111111111111111112`, USDC `EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v`. |
| 73 | - 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`. |
| 74 | - **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. |
| 75 | |
| 76 | ## Intent Router (first step) |
| 77 | |
| 78 | | User intent | API family | First action | |
| 79 | |---|---|---| |
| 80 | | Swap/quote | [Swap](#swap) | `GET /swap/v2/order` -> sign -> `POST /swap/v2/execute` | |
| 81 | | Lend/borrow/yield | [Lend](#lend) | `POST /lend/v1/earn/deposit` or `/withdraw` | |
| 82 | | Leverage/perps | [Perps](#perps) | On-chain via Anchor IDL (no REST API yet) | |
| 83 | | Limit orders | [Trigger](#trigger-limit-orders) | JWT auth -> `POST /trigger/v2/orders/price` | |
| 84 | | DCA/recurring buys | [Recurring](#recurring-dca) |