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.
The Trigger Order API V2 uses a challenge-response flow to authenticate users. Your wallet signs a challenge, and the server issues a JWT token valid for 24 hours.
Authentication Flow
1. Request challenge → POST /v2/auth/challenge
2. Sign with wallet → (client-side)
3. Submit signature → POST /v2/auth/verify → JWT token
4. Use JWT → Authorization: Bearer <token>
Prerequisites
Signing challenges and transactions requires @solana/web3.js and bs58:
npm install @solana/web3.js bs58
Step 1: Request a Challenge
Request a challenge for your wallet. Choose message for standard wallets or transaction for hardware wallets that only support transaction signing.
const challengeResponse = await fetch('https://api.jup.ag/trigger/v2/auth/challenge', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': 'your-api-key',
},
body: JSON.stringify({
walletPubkey: walletAddress,
type: 'message', // or 'transaction' for hardware wallets
}),
});
const challenge = await challengeResponse.json();
Message challenge response:
{
"type": "message",
"challenge": "Sign this message to authenticate with Jupiter Trigger Order API..."
}
Transaction challenge response:
{
"type": "transaction",
"transaction": "Base64EncodedTransactionWithMemoInstruction..."
}
Challenges expire after 5 minutes. Request a new one if your challenge expires.
Step 2: Sign and Verify
Sign the challenge with your wallet, then submit the signature to receive a JWT token.
For message signing:
import bs58 from 'bs58';
// Sign the challenge message with your wallet
const encodedMessage = new TextEncoder().encode(challenge.challenge);
const signature = await wallet.signMessage(encodedMessage);
const verifyResponse = await fetch('https://api.jup.ag/trigger/v2/auth/verify', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': 'your-api-key',
},
body: JSON.stringify({
type: 'message',
walletPubkey: walletAddress,
signature: bs58.encode(signature),
}),
});
const { token } = await verifyResponse.json();
// Use this token in Authorization: Bearer <token> for all authenticated requests
For transaction signing (hardware wallets):
import { VersionedTransaction } from '@solana/web3.js';
const signedTx = await wallet.signTransaction(
VersionedTransaction.deserialize(Buffer.from(challenge.transaction, 'base64'))
);
const verifyResponse = await fetch('https://api.jup.ag/trigger/v2/auth/verify', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': 'your-api-key',
},
body: JSON.stringify({
type: 'transaction',
walletPubkey: walletAddress,
signedTransaction: Buffer.from(signedTx.serialize()).toString('base64'),
}),
});
const { token } = await verifyResponse.json();
Using the JWT
Include the JWT in all authenticated requests:
const response = await fetch('https://api.jup.ag/trigger/v2/vault', {
headers: {
'x-api-key': 'your-api-key',
'Authorization': `Bearer ${token}`,
},
});
Token Lifecycle
| Property | Value |
|---|
| Challenge TTL | 5 minutes |
| JWT TTL | 24 hours |
When a token expires, repeat the challenge-response flow to obtain a new one. There is no refresh endpoint.
Security Notes
For integrators building user-facing applications:
- Never store JWT tokens in local storage. Use secure, httpOnly cookies or in-memory storage
- Always verify the challenge content before signing. Do not blindly sign arbitrary messages
- Implement token refresh logic to handle expiration gracefully
- The JWT is tied to the wallet public key. Do not reuse tokens across wallets
What Happens if a JWT is Leaked
The JWT grants limited access. An attacker with a leaked token can:
- Cancel orders: This transitions the order from
open to ready_to_cancel, but does not withdraw funds. Withdrawal requires signing a transaction with the wallet private key.
- Edit order parameters: Updating trigger prices or slippage does not require transaction signing.
An attacker cannot:
- Withdraw funds: All withdrawal operations require the wallet owner to sign a transaction. The vault’s funds remain secure.
- Create new orders: Depositing tokens requires signing a deposit transaction with the wallet.
All operations involving funds (deposits, withdrawals) require the wallet owner to sign a transaction. A leaked JWT alone cannot result in loss of funds. However, if the wallet private key is also compromised, an attacker could sign transactions and withdraw funds from the vault.