Skip to main content

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

PropertyValue
Challenge TTL5 minutes
JWT TTL24 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.