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.

/submit sends your signed transactions through Jupiter’s proprietary transaction landing infrastructure. This is the same infrastructure that powers Jupiter’s own swap products, now open to any integrator. It accepts any valid signed Solana transaction with a SOL tip, costs zero API credits, and works on all plans including keyless access.

Why /submit is competitive

Jupiter’s transaction landing stack is purpose-built for high throughput and low latency:
  • SWQoS via high-stake validator. Jupiter operates one of the highest-staked validators on Solana. Solana’s Stake-Weighted Quality of Service (SWQoS) reserves ~80% of a leader’s TPU capacity for staked validators proportional to their stake. Higher stake means more reserved bandwidth when forwarding transactions to the current leader.
  • Beam (custom TPU forwarder). Jupiter’s own TPU client bypasses standard RPC nodes and sends transactions directly to leaders via staked QUIC connections. This removes intermediaries that could be malicious actors and eliminates RPC processing overhead.
  • DoubleZero. Dedicated fiber network for validator communication, with FPGA-based spam filtering and transaction deduplication at the network edge. Cleaner transaction set, faster propagation between validators.
  • Ultra-low-latency fiber. Private fiber links from Tokyo to Frankfurt reduce physical propagation time between Jupiter’s infrastructure and leader validators globally.
  • High-performance, scalable infrastructure. Built to handle the volume of Jupiter’s own products, where millions of swaps land daily.

How it works

  1. Build your transaction (using /build, or assemble your own)
  2. Include a SOL tip transfer instruction (minimum 0.001 SOL) to one of 16 tip receiver accounts
  3. Sign the transaction
  4. POST the base64-encoded signed transaction to https://api.jup.ag/tx/v1/submit
For /build transactions, use the tipAmount parameter to have the tip instruction included automatically. For non-Jupiter transactions, add a standard SOL transfer instruction to one of the tip receiver accounts.

Requirements

RequirementDetails
Valid signed transactionMust be a valid Solana transaction with all required signatures
SOL tipMinimum 1,000,000 lamports (0.001 SOL) transferred to one of the 16 tip receiver accounts
Transaction sizeMust not exceed the Solana transaction size limit (1232 bytes)
API accessWorks with any API key or keyless access
/submit has its own dedicated rate limit bucket (Keyless 20, Free 50, Paid 100 RPS), separate from your general API limit. See Rate Limits.

Code example

Using /build

Use /build with the tipAmount parameter to automatically include a tip instruction in the response.
import {
  AddressLookupTableAccount,
  ComputeBudgetProgram,
  Connection,
  Keypair,
  PublicKey,
  TransactionInstruction,
  TransactionMessage,
  VersionedTransaction,
} from "@solana/web3.js";
import bs58 from "bs58";

// ── Types matching the /build response ───────────────────────────────────────

type ApiAccount = { pubkey: string; isSigner: boolean; isWritable: boolean };

type ApiInstruction = {
  programId: string;
  accounts: ApiAccount[];
  data: string; // base64
};

type BuildResponse = {
  computeBudgetInstructions: ApiInstruction[];
  setupInstructions: ApiInstruction[];
  swapInstruction: ApiInstruction;
  cleanupInstruction: ApiInstruction | null;
  otherInstructions: ApiInstruction[];
  tipInstruction: ApiInstruction;
  addressesByLookupTableAddress: Record<string, string[]> | null;
  blockhashWithMetadata: {
    blockhash: number[];
    lastValidBlockHeight: number;
  };
};

// ── Helpers ──────────────────────────────────────────────────────────────────

const CU_LIMIT_MAX = 1_400_000;

function toInstruction(ix: ApiInstruction): TransactionInstruction {
  return new TransactionInstruction({
    programId: new PublicKey(ix.programId),
    keys: ix.accounts.map((acc) => ({
      pubkey: new PublicKey(acc.pubkey),
      isSigner: acc.isSigner,
      isWritable: acc.isWritable,
    })),
    data: Buffer.from(ix.data, "base64"),
  });
}

// ── Main ─────────────────────────────────────────────────────────────────────

const API_KEY = process.env.JUPITER_API_KEY!;
const connection = new Connection(process.env.RPC_URL!);
const signer = Keypair.fromSecretKey(
  bs58.decode(process.env.BS58_PRIVATE_KEY!),
);

// 1. Call /build with your swap parameters
const buildRes = await fetch(
  "https://api.jup.ag/swap/v2/build?" +
    new URLSearchParams({
      inputMint: "So11111111111111111111111111111111111111112",
      outputMint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
      amount: "100000000",
      taker: signer.publicKey.toString(),
      tipAmount: "1000000",
    }),
  { headers: { "x-api-key": API_KEY } },
);
const build: BuildResponse = await buildRes.json();

// 2. Collect instructions (excluding compute budget — we handle CU limit ourselves)
const instructions = [
  ...build.setupInstructions.map(toInstruction),
  toInstruction(build.swapInstruction),
  ...(build.cleanupInstruction
    ? [toInstruction(build.cleanupInstruction)]
    : []),
  ...build.otherInstructions.map(toInstruction),
  toInstruction(build.tipInstruction),
];

// 3. Prepare blockhash and address lookup tables
const addressLookupTableAccounts: AddressLookupTableAccount[] = [];
for (const addr of Object.keys(build.addressesByLookupTableAddress ?? {})) {
  const result = await connection.getAddressLookupTable(new PublicKey(addr));
  if (result.value) addressLookupTableAccounts.push(result.value);
}

const recentBlockhash = bs58.encode(
  Buffer.from(build.blockhashWithMetadata.blockhash),
);
const { lastValidBlockHeight } = build.blockhashWithMetadata;

// 4. Simulate to estimate CU usage, then apply 1.2x buffer
const simMessage = new TransactionMessage({
  payerKey: signer.publicKey,
  recentBlockhash,
  instructions: [
    ComputeBudgetProgram.setComputeUnitLimit({ units: CU_LIMIT_MAX }),
    ...instructions,
  ],
}).compileToV0Message(addressLookupTableAccounts);

const sim = await connection.simulateTransaction(
  new VersionedTransaction(simMessage),
  { sigVerify: false, replaceRecentBlockhash: true },
);

if (sim.value.err) {
  console.error("Simulation failed:", sim.value.err);
  process.exit(1);
}

const estimatedCUL = sim.value.unitsConsumed
  ? Math.min(Math.ceil(sim.value.unitsConsumed * 1.2), CU_LIMIT_MAX)
  : CU_LIMIT_MAX;

// 5. Build final transaction with estimated CU limit + CU price from response
const messageV0 = new TransactionMessage({
  payerKey: signer.publicKey,
  recentBlockhash,
  instructions: [
    ComputeBudgetProgram.setComputeUnitLimit({ units: estimatedCUL }),
    ...build.computeBudgetInstructions.map(toInstruction),
    ...instructions,
  ],
}).compileToV0Message(addressLookupTableAccounts);

const transaction = new VersionedTransaction(messageV0);
transaction.sign([signer]);

// 6. Sign and submit via /submit (or use your own RPC / transaction pipeline)
const submitRes = await fetch("https://api.jup.ag/tx/v1/submit", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "x-api-key": API_KEY,
  },
  body: JSON.stringify({
    signedTransaction: Buffer.from(transaction.serialize()).toString("base64"),
  }),
});

const { signature } = await submitRes.json();
console.log("Submitted:", `https://solscan.io/tx/${signature}`);

// 7. Confirm the transaction landed
const confirmation = await connection.confirmTransaction(
  { signature, blockhash: recentBlockhash, lastValidBlockHeight },
  "confirmed",
);

if (confirmation.value.err) {
  console.error("Transaction failed:", confirmation.value.err);
  process.exit(1);
}

console.log("Confirmed:", signature);

Adding tip instruction manually

For non-Jupiter transactions (another swap protocol, a program call, a transfer), add a standard SOL transfer to one of the 16 tip receiver accounts. Randomise which account you send to on each transaction to reduce write-lock contention.
import { SystemProgram, PublicKey } from "@solana/web3.js";

const TIP_ACCOUNTS = [
  "GGztQqQ6pCPaJQnNpXBgELr5cs3WwDakRbh1iEMzjgSJ",
  "2MFoS3MPtvyQ4Wh4M9pdfPjz6UhVoNbFbGJAskCPCj3h",
  "BQ72nSv9f3PRyRKCBnHLVrerrv37CYTHm5h3s9VSGQDV",
  "6U91aKa8pmMxkJwBCfPTmUEfZi6dHe7DcFq2ALvB2tbB",
  "4xDsmeTWPNjgSVSS1VTfzFq3iHZhp77ffPkAmkZkdu71",
  "CapuXNQoDviLvU1PxFiizLgPNQCxrsag1uMeyk6zLVps",
  "9nnLbotNTcUhvbrsA6Mdkx45Sm82G35zo28AqUvjExn8",
  "6LXutJvKUw8Q5ue2gCgKHQdAN4suWW8awzFVC6XCguFx",
  "HFqp6ErWHY6Uzhj8rFyjYuDya2mXUpYEk8VW75K9PSiY",
  "DSN3j1ykL3obAVNv7ZX49VsFCPe4LqzxHnmtLiPwY6xg",
  "69yhtoJR4JYPPABZcSNkzuqbaFbwHsCkja1sP1Q2aVT5",
  "HU23r7UoZbqTUuh3vA7emAGztFtqwTeVips789vqxxBw",
  "3LoAYHuSd7Gh8d7RTFnhvYtiTiefdZ5ByamU42vkzd76",
  "3CgvbiM3op4vjrrjH2zcrQUwsqh5veNVRjFCB9N6sRoD",
  "GP8StUXNYSZjPikyRsvkTbvRV1GBxMErb59cpeCJnDf1",
  "7iWnBRRhBCiNXXPhqiGzvvBkKrvFSWqqmxRyu9VyYBxE",
];

const tipIx = SystemProgram.transfer({
  fromPubkey: signer.publicKey,
  toPubkey: new PublicKey(
    TIP_ACCOUNTS[Math.floor(Math.random() * TIP_ACCOUNTS.length)]
  ),
  lamports: 1_000_000, // 0.001 SOL minimum
});

// Add tipIx to your transaction, sign, then submit via /submit

Best practices

  • Randomise tip accounts: there are 16 tip receiver accounts. Randomise which one you send to on each transaction to reduce write-lock contention across concurrent submissions.
  • Use tipAmount with /build: pass tipAmount as a query parameter to have the tip instruction included automatically, rather than adding it manually.
  • Set maxRetries: 0 on RPC fallback: if you run /submit in parallel with sendRawTransaction, let your application control retry logic rather than the RPC node, so you can refresh the blockhash between attempts.
  • Poll for confirmation: use confirmTransaction with the blockhash and lastValidBlockHeight from your transaction. If the blockhash expires without confirmation, rebuild with a fresh blockhash and resubmit.
  • /submit does not simulate: we send directly to the TPU for fastest possible delivery. If you require simulation, do it before making a request to /submit.
  • Colocate for lowest latency: Jupiter’s API gateway runs in six AWS regions. Deploy your servers in the nearest region to minimise round-trip time.

How /submit differs from /execute

/execute/submit
Paired with/order (meta-aggregator flow)/build or any signed transaction
Fee modelJupiter swap fees (included in the order)SOL tips (minimum 0.001 SOL)
Transaction sourceMust match the exact transaction from /orderAny valid signed Solana transaction
Credit cost0 credits0 credits
Use caseManaged swap execution for /order transactionsAny transaction: /build swaps, non-Jupiter transactions

API reference

Endpoint: POST https://api.jup.ag/tx/v1/submit See the POST /submit API reference for the full specification.