Intégration API Jupiter
Compétence unique pour toutes les APIs Jupiter, optimisée pour un routage rapide et une exécution déterministe.
URL de base : https://api.jup.ag
Authentification : x-api-key depuis portal.jup.ag (obligatoire pour les endpoints REST Jupiter)
Utiliser / Ne pas utiliser
À utiliser quand :
- La tâche demande de choisir ou d'appeler des endpoints Jupiter.
- La tâche implique swap, lending, perps, orders, pricing, portfolio, send, studio, lock, ou routing.
- L'utilisateur a besoin d'aide pour déboguer des appels à l'API Jupiter.
À ne pas utiliser quand :
- La tâche est une configuration Solana générique sans utilisation de l'API Jupiter.
- La tâche est UI-only sans décisions comportementales d'API.
Déclencheurs : swap, quote, gasless, best route, lend, borrow, earn, liquidation, perps, leverage, long, short, position, 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
Démarrage rapide développeur
import { Connection, Keypair, VersionedTransaction } from '@solana/web3.js';
const API_KEY = process.env.JUPITER_API_KEY!; // depuis portal.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: 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 {
// conserver fallback texte body
}
throw { status: res.status, ...body };
}
return res.json();
}
// Signer et envoyer toute transaction Jupiter
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;
}
Intent Router (première étape)
| Intention utilisateur | Famille API | Première action |
|---|---|---|
| Swap/quote | Ultra Swap | GET /ultra/v1/order -> signer -> POST /ultra/v1/execute |
| Lend/borrow/yield | Lend | POST /lend/v1/earn/deposit ou /withdraw |
| Leverage/perps | Perps | On-chain via Anchor IDL (pas d'API REST encore) |
| Limit orders | Trigger | POST /trigger/v1/createOrder -> signer -> POST /trigger/v1/execute |
| DCA/recurring buys | Recurring | POST /recurring/v1/createOrder -> signer -> POST /recurring/v1/execute |
| Token search/verification | Tokens | GET /tokens/v2/search?query={mint} |
| Price lookup | Price | GET /price/v3?ids={mints} |
| Portfolio/positions | Portfolio | GET /portfolio/v1/positions/{address} |
| Prediction market integration | Prediction Markets | GET /prediction/v1/events -> POST /prediction/v1/orders |
| Invite send/clawback | Send | POST /send/v1/craft-send -> signer -> envoyer à RPC |
| Token creation/fees | Studio | POST /studio/v1/dbc-pool/create-tx -> upload -> submit |
| Vesting/distribution | Lock | Program on-chain LocpQgucEQHbqNABEYvBvwoxCPsSbG91A1QaQhQQqjn |
| DEX/RFQ integration | Routing | Choisir chemin DEX (trait AMM) vs RFQ (webhook) |
Playbooks API
Utilisez chaque bloc comme un contrat d'exécution minimal. Récupérez les références liées pour les formes complètes de requête/réponse, interfaces TypeScript, et détails des paramètres.
Ultra Swap
- URL de base :
https://api.jup.ag/ultra/v1 - Déclencheurs :
swap,quote,gasless,best route - Frais : 5-10 bps (standard) ou 20% des frais d'intégrateur avec frais personnalisés configurés
- Rate Limit : 50 req/10s base, évolue avec le volume d'exécution 24h (voir Rate Limits)
- Endpoints :
/order(GET),/execute(POST),/holdings/{account}(GET),/shield(GET),/search(GET),/routers(GET) - Pièges : Les payloads signés ont une TTL de ~2 min. Les transactions sont immuables après réception. Séparer order/execute dans le code et logging. Re-quoter avant exécution si les conditions peuvent avoir changé.
- Refs : Overview | Order | Execute | Responses | OpenAPI
Lend
- URL de base :
https://api.jup.ag/lend/v1 - Déclencheurs :
lend,borrow,earn,liquidation - Programs : Earn
jup3YeL8QhtSx1e253b2FDvsMNC87fDrgQZivbrndc9, Borrowjupr81YtYssSyPt8jbnGuiWon5f6x9TcDEFxYe3Bdzi - SDK :
@jup-ag/lend(TypeScript) - Endpoints :
/earn/deposit(POST),/earn/withdraw(POST),/earn/mint(POST),/earn/redeem(POST),/earn/deposit-instructions(POST),/earn/withdraw-instructions(POST),/earn/tokens(GET),/earn/positions(GET),/earn/earnings(GET) - Pièges : Recalculer l'état du compte avant chaque action qui change l'état. Encoder les vérifications de risques (health factors, limites de liquidation) comme préconditions. Tous deposit/withdraw/mint/redeem retournent une
VersionedTransactionbase64 non signée. - Refs : Overview | Earn | SDK | OpenAPI
Perps
- Statut : L'API est en cours de développement. Pas d'endpoints REST encore. Interagir on-chain via Anchor IDL.
- Déclencheurs :
perps,leverage,long,short,position - Community SDK : github.com/julianfssen/jupiter-perps-anchor-idl-parsing
- Pièges : Max 9 positions simultanées : 3 long (SOL, wETH, wBTC) + 6 short (3 tokens x 2 collateral USDC/USDT). Valider margin/leverage contre le modèle de compte.
- Refs : Overview | Position account | Position request
Trigger (Limit Orders)
- URL de base :
https://api.jup.ag/trigger/v1 - Déclencheurs :
limit order,trigger,price condition - Frais : 0,1% (non-stablecoin), 0,03% (paires stables)
- Pagination : 10 orders par page
- Endpoints :
/createOrder(POST),/cancelOrder(POST),/cancelOrders(POST, max 5 par tx),/execute(POST),/getTriggerOrders(GET) - Pièges : Frontend applique un min de 5 USD ; on-chain n'a pas de minimum. Program ne valide PAS si les taux sont favorables — valider le prix cible avant create. Token-2022 désactivé. Slippage zéro par défaut ("Exact" mode) ; définir
slippageBpspour "Ultra" mode avec taux de remplissage plus élevé. - Refs : Overview | Create | Get orders | Best Practices | OpenAPI
Recurring (DCA)
- URL de base :
https://api.jup.ag/recurring/v1 - Déclencheurs :
dca,recurring,scheduled swaps - Frais : 0,1% sur tous les orders récurrents
- Contraintes : Min 100 USD total, min 2 orders, min 50 USD par order
- Pagination : 10 orders par page
- Endpoints :
/createOrder(POST),/cancelOrder(POST),/execute(POST),/getRecurringOrders(GET) - Pièges : Token-2022 non supporté. Les orders récurrents basés sur le prix sont dépréciés — utiliser
params.timeuniquement. - Refs : Overview | Create | Get orders | Best Practices | OpenAPI
Tokens
- URL de base :
https://api.jup.ag/tokens/v2 - Déclencheurs :
token metadata,token search,verification,shield - Endpoints :
/search?query={q}(GET, séparer les mints par virgule, max 100),/tag?query={tag}(GET,verifiedoulst),/{category}/{interval}(GET, catégories :toporganicscore,toptraded,toptrending; intervalles :5m,1h,6h,24h),/recent(GET) - Pièges : Utiliser l'adresse mint comme identité primaire ; traiter symbol/name comme commodité. Afficher
audit.isSusetorganicScoredans l'UX. - Refs : Overview | Token info v2 | OpenAPI
Price
- URL de base :
https://api.jup.ag/price/v3 - Déclencheurs :
price,valuation,price feed - Limite : Max 50 mint IDs par requête
- Endpoints :
/price/v3?ids={mints}(GET, séparés par virgule) - Pièges : Les tokens avec tarification peu fiable retournent
nullou sont omis (pas une erreur). Échouer fermé sur données manquantes/faible confiance pour actions sensibles à la sécurité. Utiliser le champconfidenceLevel. - Refs : Overview | Price v3 | OpenAPI
Portfolio
- URL de base :
https://api.jup.ag/portfolio/v1 - Statut : Beta — plateformes Jupiter uniquement
- Déclencheurs :
portfolio,positions,holdings - Endpoints :
/positions/{address}(GET),/positions/{address}?platforms={ids}(GET),/platforms(GET),/staked-jup/{address}(GET) - Pièges : Traiter les positions vides comme état valide. La réponse est beta — normaliser dans un schéma interne stable. Types d'éléments :
multiple,liquidity,trade,leverage,borrowlend. - Refs : Overview | Jupiter positions | OpenAPI
Prediction Markets
- URL de base :
https://api.jup.ag/prediction/v1 - Statut : Beta (breaking changes possibles)
- Géo-restreint : IPs USA et Corée du Sud bloquées
- Convention de prix : 1 000 000 unités natives = $1,00 USD
- Déclencheurs :
prediction markets,market odds,event market - Dépôt mints : JupUSD (
JuprjznTrTSp2UFa3ZBUFgwdAmtZCq4MQCwysN55USD), USDC - Endpoints :
/events(GET),/events/search(GET),/markets/{marketId}(GET),/orderbook/{marketId}(GET),/orders(POST),/orders/status/{pubkey}(GET),/positions(GET),/positions/{pubkey}(DELETE),/positions/{pubkey}/claim(POST),/history(GET),/leaderboards(GET) - Pièges : Vérifier
position.claimableavant de réclamer. Les gagnants reçoivent $1/contrat. - Refs : Overview | Events | Positions | OpenAPI
Send
- URL de base :
https://api.jup.ag/send/v1 - Statut : Beta
- Déclencheurs :
invite transfer,send,clawback - Tokens supportés : SOL, USDC, memecoins
- Endpoints :
/craft-send(POST),/craft-clawback(POST),/pending-invites(GET),/invite-history(GET) - Pièges : Exigence double signature — keypair du sender + recipient (dérivé du code invite). Les réclamations uniquement via Jupiter Mobile (pas de réclamation API). Ne jamais exposer les codes invite.
- Refs : Overview | Invite code | Craft send | OpenAPI
Studio
- URL de base :
https://api.jup.ag/studio/v1 - Statut : Beta
- Déclencheurs :
create token,studio,claim fee - Endpoints :
/dbc-pool/create-tx(POST),/dbc-pool/submit(POST, multipart/form-data),/dbc-pool/addresses/{mint}(GET),/dbc/fee(POST),/dbc/fee/create-tx(POST) - Flux : create-tx -> upload image vers URL présignée -> upload metadata vers URL présignée -> signer -> submit via
/dbc-pool/submit - Pièges : Doit être soumis via
/dbc-pool/submit(pas externalement) pour que le token reçoive une page Studio sur jup.ag. Codes d'erreur :403= non autorisé pour pool,404= proxy account non trouvé. - Refs : Overview | Create token | Claim fee | OpenAPI
Lock
- Program ID :
LocpQgucEQHbqNABEYvBvwoxCPsSbG91A1QaQhQQqjn - Déclencheurs :
vesting,distribution lock,unlock schedule - Intégration : Program on-chain uniquement (pas d'API REST)
- Source : github.com/jup-ag/jup-lock
- UI : lock.jup.ag
- Sécurité : Audité par OtterSec et Sec3
- Pièges : Pas d'API REST. Utiliser les scripts d'instruction du répertoire
cli/src/bin/instructions. - Refs : Lock overview
Routing
- Déclencheurs :
dex integration,rfq integration,routing engine - Engines : Juno (meta-aggregator), Iris (multi-hop DEX routing, alimente Ultra), JupiterZ (RFQ market maker quotes)
- DEX Integration (vers Iris) : Gratuit, pas de frais. Prérequis : health du code, audit de sécurité, traction commerciale. Implémenter le crate
jupiter-amm-interface. Critique : Pas d'appels réseau dans l'implémentation (les accounts sont pré-batched et en cache). Ref impl : github.com/jup-ag/rust-amm-implementation - RFQ Integration (JupiterZ) : Les market makers hébergent webhook à
/jupiter/rfq/quote(POST, 250ms),/jupiter/rfq/swap(POST),/jupiter/rfq/tokens(GET). Requis : taux de remplissage 95%, réponse 250ms, expiration 55s. SDK : github.com/jup-ag/rfq-webhook-toolkit - Market Listing : Routage instantané pour tokens < 30 jours. Routage normal (vérifié tous les 30 min) demande < 30% de perte sur round-trip $500 OU < 20% d'impact de prix comparant $1k vs $500.
- Refs : Overview | DEX integration | RFQ integration | Market listing
Rate Limits
Ultra Swap (dynamique, basé sur le volume) :
| Volume d'exécution 24h | Requêtes par fenêtre 10s |
|---|---|
| $0 | 50 |
| $10 000 | 51 |
| $100 000 | 61 |
| $1 000 000 | 165 |
Les quotas se recalculent tous les 10 minutes. Le plan Pro n'augmente PAS les limites Ultra.
Autres APIs : Gérées au niveau du portal. Voir rate limits du portal.
Sur HTTP 429 : Backoff exponentiel avec jitter : delay = min(baseDelay * 2^attempt + random(0, jitter), maxDelay). Attendre la rafraîchissement de la fenêtre glissante 10s. Ne PAS burst agressivement.
Durcissement production
- Auth : Échouer rapidement si
x-api-keyest manquant ou invalide. - Timeouts : 5s pour les quotes, 30s pour les exécutions, plus timeout d'opération total.
- Retries : Uniquement les défaillances transientes/réseau/rate-limit avec backoff exponentiel + jitter.
- Idempotence : Ultra
/executeaccepte la mêmesignedTransaction+requestIdpendant 2 min sans exécution dupliquée. - Validation : Valider les adresses mint, la précision des montants, et la propriété du wallet avant les appels.
- Safety : Appliquer des guardrails slippage et max-amount depuis la config app.
- Observabilité : Logger
requestId, API family, endpoint, latency, status, et error code. - UX résilience : Retourner des états exploitables (
retry,adjust params,insufficient balance,rate limited). - Cohérence : Réconcilier les états asynchrones (submitted vs confirmed vs failed) avant succès utilisateur final.
- Fraîcheur : Re-récupérer les docs référencées quand le comportement diffère du flux attendu.
Bonnes pratiques d'intégration
- Commencer par l'overview spécifique à l'API avant coder les appels endpoint.
- Appliquer l'auth comme précondition stricte pour toute requête. Ref : Portal setup
- Concevoir la logique de retry autour du comportement de rate-limit documenté, pas d'hypothèses fixes. Ref : Rate limits
- Mapper toutes les réponses non-succès vers des erreurs app typées en utilisant la sémantique de réponse documentée. Ref : API responses
- Pour les produits basés sur les orders (Ultra/Trigger/Recurring), séparer les phases create/execute/retrieve dans le code et les logs.
- Traiter la santé réseau/service comme part du comportement runtime (dégrader gracieusement). Ref : Status page
Pattern d'erreur transversal
interface JupiterResult<T> {
ok: boolean;
result?: T;
error?: { code: string | number; message: string; retryable: boolean };
}
async function jupiterAction<T>(action: () => Promise<T>): Promise<JupiterResult<T>> {
try {
const result = await action();
return { ok: true, result };
} catch (error: any) {
const code = error?.code ?? error?.status ?? 'UNKNOWN';
// Rate limit — retry avec backoff
if (code === 429 || code === 'RATE_LIMITED') {
return { ok: false, error: { code: 'RATE_LIMITED', message: 'Rate limited', retryable: true } };
}
// Erreurs Ultra execute (codes négatifs)
if (typeof code === 'number' && code < 0) {
const retryable = [-1, -1000, -1001, -1005, -1006, -2000, -2003, -2005].includes(code);
return { ok: false, error: { code, message: error?.error ?? 'Execute failed', retryable } };
}
// Erreurs program (codes positifs comme 6001 = slippage)
if (typeof code === 'number' && code > 0) {
return { ok: false, error: { code, message: error?.error ?? 'Program error', retryable: false } };
}
return { ok: false, error: { code, message: error?.message ?? 'UNKNOWN_ERROR', retryable: false } };
}
}
Politique de contexte frais
Toujours récupérer le contexte le plus frais depuis les docs/specs référencés avant d'exécuter un playbook.
- Résoudre l'intention avec
Intent Router. - Avant de coder, récupérer les refs liées du playbook (overview + docs spécifiques à l'API).
- Si nécessaire pour validation ou ambiguïté, récupérer la spec OpenAPI.
- Traiter les docs récupérés comme source de vérité sur mémoire cachée.
- Si les docs récupérés entrent en conflit avec ce fichier, suivre les docs récupérés et noter le désaccord.
- Si les docs ne peuvent pas être récupérés, déclarer que le contexte est obsolète/non vérifié et continuer avec la meilleure guidance connue.
- Conserver l'invariant auth :
x-api-keyest requis pour les endpoints REST Jupiter (pas pour les flux on-chain-only comme Perps/Lock).
Vérifier
- Un vrai appel RPC/SDK a été émis (mainnet, devnet, ou validateur local) et le payload de réponse est capturé dans la transcription, pas seulement paraphrasé
- Chaque transaction a été simulée (
simulateTransactionou équivalent) avant toute étape de signature/envoi ; les logs de simulation sont attachés - Pour toute transaction signée/envoyée, la signature résultante est enregistrée et confirmée on-chain (statut retourné par
getSignatureStatusesou une URL explorer) - Slippage, priority-fee, et compute-unit limits ont été définis explicitement avec valeurs numériques concrètes, pas laissés aux defaults de la librairie
- Les adresses de compte, mints, et program IDs utilisés dans la run correspondent aux adresses jupyter-defi documentées pour le cluster cible (pas de mix mainnet/devnet)
- Le chemin d'erreur a été exercé au moins une fois (solde insuffisant, oracle obsolète, blockhash expiré, etc.) et la gestion d'erreur de l'agent a produit un message lisible
Références opérationnelles
- Portal setup — Configuration de clé API
- Rate limits — Politique de rate limit globale
- Ultra rate limits — Limites dynamiques basées sur le volume
- API responses — Standards de format de réponse
- Ultra responses — Codes d'erreur détaillés
- Status page — Santé du service
- Documentation sitemap — Index complet des docs
- Tool Kits — Plugin, Wallet Kit, Referral Program