Pump.fun Jito Bundles
Jito bundles let you execute multiple Solana transactions atomically in the same block. On Pump.fun, this means you can launch a token and have multiple wallets buy it simultaneously — no front-running, no failed partial executions, and guaranteed transaction ordering.
PumpDev supports Jito bundles across token creation, trading, and Lightning APIs:
| API Endpoint | Bundle Type | Description |
|---|---|---|
POST /api/bundle | Local-Sign Bundle | Unsigned bundle — you sign locally + send to Jito |
POST /api/bundle-lightning | Lightning Bundle | One-call server-signed bundle (buy/sell/create) — sends via Jito |
POST /api/create | Create + Dev Buy | Split create + buy into Jito bundle for faster landing |
POST /api/create-bundle | Multi-Buyer Launch | Creator + up to 3 additional buyers atomically |
POST /api/trade-bundle | Multi-Wallet Trade | Multiple wallets buy or sell in one bundle |
/api/bundle— returns unsigned txs. You sign locally and send to Jito (usespublicKey). Full control over signing and submission./api/bundle-lightning— server signs AND sends via Jito. One call, fully managed (usesapiKey).
Why Use Jito Bundles on Pump.fun?
Without Bundles (Standard RPC)
When you send transactions individually via standard RPC:
- Transactions land in different blocks (or never land)
- Other bots can front-run your buy after seeing the token creation
- No guarantee of execution order — buyer 2 might execute before buyer 1
- If one transaction fails, others may still execute (partial state)
With Jito Bundles
All transactions in a bundle execute atomically in one block:
- Atomic Execution — All transactions succeed or all fail together
- No Front-Running — Creator + buyers land in the same block, in order
- Guaranteed Ordering — Transaction 1 always executes before transaction 2
- Faster Landing — Jito validators prioritize bundles with tips
- Up to 5 Transactions — Enough for creator + 3 buyers + tip
How Jito Bundles Work
┌──────────────────────────────────────────────────────┐
│ Jito Bundle │
│ │
│ TX 1: Create Token (signed: creator + mint) │
│ TX 2: Creator Buy (signed: creator) │
│ TX 3: Buyer 1 Buy (signed: buyer1) │
│ TX 4: Buyer 2 Buy (signed: buyer2) │
│ │
│ All execute atomically in ONE Solana block │
└──────────────────────────────────────────────────────┘
- PumpDev API builds all transactions with a shared blockhash
- You sign each transaction with the appropriate keypair(s)
- You send all signed transactions to a Jito block engine endpoint
- Jito validators execute them atomically in sequence
Local-Sign Bundle: POST /api/bundle
POST /api/bundle builds a Jito bundle and returns unsigned transactions for client-side signing. Same flexible request format as /api/bundle-lightning (buy, sell, create — up to 5 transactions), but you sign with your own private keys and send to Jito yourself.
Use this when you keep your private keys local and want full control over signing and bundle submission.
Request
Same structure as bundle-lightning, but uses publicKey instead of apiKey per account:
{
"accounts": [
{ "publicKey": "WalletPublicKey", "type": "buy", "amount": 0.1, "denominatedInSol": "true" }
],
"mint": "TokenMintAddress",
"jitoTip": 0.01
}
All top-level parameters and account entry types from Lightning Bundle apply — just swap apiKey for publicKey.
Response
{
"transactions": [
{
"transaction": "base58_unsigned_tx",
"signers": ["WalletPublicKey"],
"type": "buy",
"publicKey": "WalletPublicKey",
"error": null
}
],
"mint": "TokenMintAddress"
}
For create bundles, the response also includes mintSecretKey and the create transaction lists both the creator and mint public keys in signers:
{
"transactions": [
{
"transaction": "base58_unsigned_tx",
"signers": ["CreatorPublicKey", "MintPublicKey"],
"type": "create",
"publicKey": "CreatorPublicKey",
"mint": "MintPublicKey",
"metadataUri": "https://..."
},
{
"transaction": "base58_unsigned_tx",
"signers": ["CreatorPublicKey"],
"type": "buy",
"publicKey": "CreatorPublicKey"
}
],
"mint": "MintPublicKey",
"mintSecretKey": "base58_mint_secret_key"
}
Example: Build, Sign, and Send to Jito
import { VersionedTransaction, Keypair } from '@solana/web3.js';
import bs58 from 'bs58';
const API_URL = 'https://pumpdev.io';
const JITO_URL = 'https://mainnet.block-engine.jito.wtf';
const wallet1 = Keypair.fromSecretKey(bs58.decode('WALLET1_PRIVATE_KEY'));
const wallet2 = Keypair.fromSecretKey(bs58.decode('WALLET2_PRIVATE_KEY'));
const wallet3 = Keypair.fromSecretKey(bs58.decode('WALLET3_PRIVATE_KEY'));
const wallet4 = Keypair.fromSecretKey(bs58.decode('WALLET4_PRIVATE_KEY'));
const walletMap = {
[wallet1.publicKey.toBase58()]: wallet1,
[wallet2.publicKey.toBase58()]: wallet2,
[wallet3.publicKey.toBase58()]: wallet3,
[wallet4.publicKey.toBase58()]: wallet4,
};
// 1. Build unsigned bundle via PumpDev
const res = await fetch(`${API_URL}/api/bundle`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
accounts: [
{ publicKey: wallet1.publicKey.toBase58(), type: 'buy', amount: 0.1, denominatedInSol: 'true' },
{ publicKey: wallet2.publicKey.toBase58(), type: 'buy', amount: 0.1, denominatedInSol: 'true' },
{ publicKey: wallet3.publicKey.toBase58(), type: 'buy', amount: 0.1, denominatedInSol: 'true' },
{ publicKey: wallet4.publicKey.toBase58(), type: 'buy', amount: 0.1, denominatedInSol: 'true' },
],
mint: 'TokenMintAddress',
jitoTip: 0.01
})
});
const data = await res.json();
// 2. Sign each transaction with the correct wallet
const signedTxs = data.transactions.map((entry) => {
const tx = VersionedTransaction.deserialize(bs58.decode(entry.transaction));
const signer = walletMap[entry.publicKey];
tx.sign([signer]);
return bs58.encode(tx.serialize());
});
// 3. Send to Jito yourself
const bundleRes = await fetch(`${JITO_URL}/api/v1/bundles`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0', id: 1,
method: 'sendBundle',
params: [signedTxs]
})
});
const bundleResult = await bundleRes.json();
console.log('Bundle ID:', bundleResult.result);
For create transactions, sign with both your wallet keypair and the mint keypair (from mintSecretKey):
const mintKeypair = Keypair.fromSecretKey(bs58.decode(data.mintSecretKey));
// For create tx:
tx.sign([wallet, mintKeypair]);
// For buy tx:
tx.sign([wallet]);
Token Creation Bundles
Create + Dev Buy via Jito
When you add jitoTip to the /api/create endpoint, the API returns separate transactions for create and buy that you send as a Jito bundle:
import { VersionedTransaction, Keypair } from '@solana/web3.js';
import bs58 from 'bs58';
const API_URL = 'https://pumpdev.io';
const JITO_URL = 'https://mainnet.block-engine.jito.wtf';
async function createWithJitoBundle(metadataUri) {
const creator = Keypair.fromSecretKey(bs58.decode('CREATOR_PRIVATE_KEY'));
// 1. Request bundle-format transactions from API
const response = await fetch(`${API_URL}/api/create`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
publicKey: creator.publicKey.toBase58(),
name: 'My Token',
symbol: 'MTK',
uri: metadataUri,
buyAmountSol: 0.5,
slippage: 90,
jitoTip: 0.01 // Triggers bundle format response
})
});
const result = await response.json();
const mintKeypair = Keypair.fromSecretKey(bs58.decode(result.mintSecretKey));
// 2. Sign each transaction
const signedTxs = result.transactions.map((txInfo) => {
const tx = VersionedTransaction.deserialize(bs58.decode(txInfo.transaction));
const signers = txInfo.signers.includes('mint')
? [creator, mintKeypair]
: [creator];
tx.sign(signers);
return bs58.encode(tx.serialize());
});
// 3. Send as Jito bundle
const bundleRes = await fetch(`${JITO_URL}/api/v1/bundles`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0', id: 1,
method: 'sendBundle',
params: [signedTxs]
})
});
const bundleResult = await bundleRes.json();
console.log('Bundle ID:', bundleResult.result);
console.log(`Token: https://pump.fun/${result.mint}`);
}
Only add jitoTip to /api/create if you plan to send via Jito. Without jitoTip, the API merges create + buy into a single transaction that you can send via any standard RPC — no bundle needed. See Token Creation for the single-transaction approach.
Multi-Buyer Bundle Launch
Use /api/create-bundle to launch a token with multiple wallets buying atomically — creator + up to 3 additional buyers, all in the same block.
async function multiBuyerLaunch(metadataUri) {
const creator = Keypair.fromSecretKey(bs58.decode('CREATOR_KEY'));
const buyer1 = Keypair.fromSecretKey(bs58.decode('BUYER1_KEY'));
const buyer2 = Keypair.fromSecretKey(bs58.decode('BUYER2_KEY'));
const buyer3 = Keypair.fromSecretKey(bs58.decode('BUYER3_KEY'));
const wallets = { creator, buyer1, buyer2, buyer3 };
// 1. Request bundle from API
const response = await fetch(`${API_URL}/api/create-bundle`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
publicKey: creator.publicKey.toBase58(),
name: 'Bundled Token',
symbol: 'BUND',
uri: metadataUri,
buyAmountSol: 1.0, // Creator buys 1 SOL
slippage: 90,
jitoTip: 0.03, // Tip split across transactions
additionalBuyers: [
{ publicKey: buyer1.publicKey.toBase58(), amountSol: 2.0 },
{ publicKey: buyer2.publicKey.toBase58(), amountSol: 1.5 },
{ publicKey: buyer3.publicKey.toBase58(), amountSol: 0.5 }
]
})
});
const result = await response.json();
const mintKeypair = Keypair.fromSecretKey(bs58.decode(result.mintSecretKey));
console.log('Mint:', result.mint);
console.log('Transactions:', result.transactions.length);
// 2. Sign each transaction with the correct signer
const signedTxs = result.transactions.map((txInfo) => {
const tx = VersionedTransaction.deserialize(bs58.decode(txInfo.transaction));
const signers = txInfo.signers
.map(s => s === 'mint' ? mintKeypair : wallets[s])
.filter(Boolean);
tx.sign(signers);
return bs58.encode(tx.serialize());
});
// 3. Send as Jito bundle
const bundleRes = await fetch(`${JITO_URL}/api/v1/bundles`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0', id: 1,
method: 'sendBundle',
params: [signedTxs]
})
});
const bundleResult = await bundleRes.json();
console.log('Bundle sent:', bundleResult.result);
console.log(`Token: https://pump.fun/${result.mint}`);
}
Bundle Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
publicKey | string | Yes | Creator wallet public key |
name | string | Yes | Token name (max 32 chars) |
symbol | string | Yes | Token symbol (max 10 chars) |
uri | string | Yes | Metadata URI from Pinata or another IPFS/metadata host |
buyAmountSol | number | No | Creator's buy amount for native-SOL pairs |
buyAmountQuote | number | No | Creator's buy amount in quote-token units for non-SOL pairs |
quoteMint | string | No | Quote mint for the new coin. Omit for native SOL/WSOL pairs |
slippage | number | No | Slippage % (default: 90) |
jitoTip | number | No | Jito tip in SOL, split across transactions (default: 0.03). Increase it when you want to pay more for bundle priority |
priorityFee | number | No | Priority fee in SOL (default: 0.0005) |
mintKeypair | string | No | Base58 mint secret key (auto-generated if omitted) |
additionalBuyers | array | No | Up to 3 additional buyers |
cashbackEnabled | boolean | No | Deprecated by pump.fun: new cashback coins can no longer be created, so true returns 400. Use holderReward |
holderReward | boolean | No | Create a pump.fun Holder Rewards coin: the creator fee of every trade goes to the coin's holders instead of the creator wallet, so there is nothing for the creator to claim. Permanent. Works on any quote and together with creatorFeeBps |
creatorFeeBps | number | No | Creator fee for custom pairs, in basis points: 1–300 (0.01–3%). Applies only when quoteMint is a custom pair (not SOL or USDC); SOL and USDC coins always use pump.fun's standard fee schedule, so it is ignored there. Fixed at launch |
Provide one creator buy field:
buyAmountSolfor native-SOL pairs, orbuyAmountQuotetogether withquoteMintfor non-SOL quote pairs.
Additional Buyer Object
{ "publicKey": "BuyerWalletPublicKey", "amountSol": 0.5 }
For non-SOL quote pairs, use amountQuote instead:
{ "publicKey": "BuyerWalletPublicKey", "amountQuote": 25 }
Bundle Transaction Structure
| TX # | Description | Signers |
|---|---|---|
| 1 | Create token | creator, mint |
| 2 | Creator buy | creator |
| 3 | Buyer 1 buy | buyer1 |
| 4 | Buyer 2 buy | buyer2 |
| 5 | Buyer 3 buy | buyer3 |
All transactions execute atomically in the same Solana block.
A 5-transaction launch bundle competes with every other pump.fun launch in the
same slot. Below the market tip Jito still returns a bundle id and then
drops the bundle without any error — it simply never lands. Measured on
2026-08-24: 0.02 SOL never landed, 0.03 SOL landed on the first slot every
time. Verify against the chain (does the mint account exist?) rather than
trusting the sendBundle response.
Trade Bundles — Multi-Wallet Buy/Sell
Use POST /api/trade-bundle to build multiple buy or sell transactions in a single API call. Each wallet gets its own transaction, and the last transaction receives the Jito tip.
async function tradeBundleBuy(mint) {
const creator = Keypair.fromSecretKey(bs58.decode('CREATOR_KEY'));
const wallet1 = Keypair.fromSecretKey(bs58.decode('WALLET1_KEY'));
const wallet2 = Keypair.fromSecretKey(bs58.decode('WALLET2_KEY'));
const accounts = [
{ publicKey: creator.publicKey.toBase58(), name: 'creator' },
{ publicKey: wallet1.publicKey.toBase58(), name: 'wallet1' },
{ publicKey: wallet2.publicKey.toBase58(), name: 'wallet2' }
];
const walletMap = { creator, wallet1, wallet2 };
// 1. Build all transactions in one API call
const response = await fetch(`${API_URL}/api/trade-bundle`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
accounts,
action: 'buy',
mint,
amount: 0.5,
denominatedInSol: 'true',
slippage: 15,
jitoTip: 0.01 // Applied to last transaction only
})
});
const result = await response.json();
// 2. Sign each transaction with its wallet
const signedTxs = result.transactions
.filter(tx => tx.transaction !== null)
.map(tx => {
const decoded = VersionedTransaction.deserialize(bs58.decode(tx.transaction));
decoded.sign([walletMap[tx.name]]);
return bs58.encode(decoded.serialize());
});
// 3. Send as Jito bundle
await fetch(`${JITO_URL}/api/v1/bundles`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0', id: 1,
method: 'sendBundle',
params: [signedTxs]
})
});
}
Trade Bundle Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
accounts | array | Yes | Array of { publicKey, name } objects |
action | string | Yes | "buy" or "sell" |
mint | string | Yes | Token mint address |
amount | number/string | Yes | Trade amount (SOL for buy, "100%" or tokens for sell) |
denominatedInSol | string | No | Legacy field name. Set "true" when a buy amount is in the pair's quote asset: SOL for SOL pairs, USDC for USDC pairs |
slippage | number | No | Slippage % (default: 90) |
priorityFee | number | No | Priority fee in SOL (default: 0.00005) |
jitoTip | number | No | Jito tip applied to last transaction (default: 0) |
creator | string | No | Creator public key — skip bonding curve lookup for speed |
closeTokenAccount | boolean | No | Close token ATA after selling to reclaim ~0.002 SOL rent. Auto-enabled on "100%" sells. Set false to disable |
Quote mint handling:
trade-bundleresolves quote mint from the token on-chain. You do not passquoteMintfor ordinary buy/sell bundles. If a token is USDC-quoted, a buy withdenominatedInSol: "true"expects theamountin USDC units.
Trade Bundle Response
{
"transactions": [
{ "name": "creator", "transaction": "base58...", "error": null },
{ "name": "wallet1", "transaction": "base58...", "error": null },
{ "name": "wallet2", "transaction": "base58...", "error": null }
],
"stats": {
"total": 3,
"success": 3,
"failed": 0,
"durationMs": 45
}
}
Each account in the accounts array must use a unique wallet. Identical wallets produce identical transaction hashes, which Jito rejects with "Duplicate transaction message hash".
Jito Block Engine Endpoints
Send your bundles to any Jito block engine. Send to multiple endpoints simultaneously for better landing rates:
const JITO_ENDPOINTS = [
'https://mainnet.block-engine.jito.wtf',
'https://amsterdam.mainnet.block-engine.jito.wtf',
'https://frankfurt.mainnet.block-engine.jito.wtf',
'https://ny.mainnet.block-engine.jito.wtf',
'https://tokyo.mainnet.block-engine.jito.wtf'
];
// Send to all endpoints for maximum landing rate
async function sendBundleToAll(signedTxs) {
const payload = JSON.stringify({
jsonrpc: '2.0', id: 1,
method: 'sendBundle',
params: [signedTxs]
});
const results = await Promise.allSettled(
JITO_ENDPOINTS.map(endpoint =>
fetch(`${endpoint}/api/v1/bundles`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: payload
}).then(r => r.json())
)
);
const bundleId = results.find(r => r.status === 'fulfilled')?.value?.result;
console.log('Bundle ID:', bundleId);
return bundleId;
}
Jito Tip Recommendations
The Jito tip incentivizes validators to include your bundle. Higher tips = faster landing.
| Scenario | Recommended Tip | Notes |
|---|---|---|
| Token creation + dev buy | 0.01 SOL | Standard priority |
| Multi-buyer launch | 0.02 - 0.05 SOL | Higher tip for larger bundles |
| Trade bundle (2-3 wallets) | 0.01 SOL | Standard priority |
| High-priority sniper | 0.05+ SOL | Competitive landing |
| Low urgency | 0.005 SOL | Minimum viable tip |
For /api/create-bundle, the Jito tip is automatically split across transactions to stay within Solana's per-transaction limits. For /api/trade-bundle, the tip is applied only to the last transaction in the bundle.
Bundle Pricing
| Operation | Fee |
|---|---|
| Token creation (in bundle) | FREE |
| Buy transactions (in bundle) | 0.25% of buy amount |
| Jito tip | Passed directly to validators |
The Jito tip is separate from PumpDev fees. You pay the standard 0.25% commission on buy/sell amounts plus whatever Jito tip you choose.
Error Handling
API Errors
| HTTP Status | Cause |
|---|---|
400 | Missing required fields, invalid parameters, duplicate wallets |
402 | Insufficient SOL balance for transaction + fees |
500 | Transaction build failed (invalid metadata URI, network issues) |
Jito Bundle Errors
| Error | Cause | Solution |
|---|---|---|
Duplicate transaction message hash | Same wallet used twice | Use unique wallets per transaction |
| Bundle accepted but no on-chain txs | Bundle landed in failed slot | Retry with new blockhash |
Bundle simulation failed | Insufficient funds or invalid state | Check wallet balances and parameters |
After sending a bundle, check its status using the bundle ID:
const statusRes = await fetch(`${JITO_URL}/api/v1/bundles`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0', id: 1,
method: 'getBundleStatuses',
params: [[bundleId]]
})
});
Best Practices
- Fund all wallets first — Every wallet in the bundle needs enough SOL for its transaction + fees
- Use unique wallets — Duplicate wallets produce duplicate tx hashes that Jito rejects
- Send to multiple Jito endpoints — Increases landing probability
- Set reasonable slippage — server defaults first; override slippage only when your strategy requires it
- Choose appropriate tips — Higher tips during congestion, lower during calm periods
- Check bundle status — Use
getBundleStatusesto verify execution - Test on devnet first — Validate your signing and bundle flow before mainnet
Frequently Asked Questions
What is the maximum number of transactions in a Jito bundle?
Jito supports up to 5 transactions per bundle. PumpDev's /api/create-bundle uses up to 5 (1 create + 1 creator buy + 3 additional buyers).
Can I mix buy and sell transactions in one bundle?
The /api/trade-bundle endpoint processes either all buys or all sells in a single request, not mixed. For mixed operations, submit separate bundles.
What happens if one transaction in the bundle fails?
The entire bundle fails. This is by design — atomic execution means all-or-nothing. No partial state changes occur.
Do I need a Jito staking account?
No. You just need to pay a Jito tip in your transactions. The tip goes to the Jito validator that processes your bundle.
Can I use Jito bundles with the Lightning API?
Yes! Two options:
/api/bundle-lightning— server signs AND sends. One call, fully managed:
const response = await fetch('https://pumpdev.io/api/bundle-lightning', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
accounts: [
{ apiKey: 'YOUR_KEY', type: 'buy', amount: 0.1, denominatedInSol: 'true' }
],
mint: 'TokenMintAddress',
jitoTip: 0.01
})
});
/api/bundle— returns unsigned txs. You sign locally and send to Jito. See the Local-Sign Bundle section above for full details and examples.
Next Steps
- Lightning Bundle — One-call Jito trades and launches (server-signed)
- Token Creation — Create tokens with optional dev buy (single tx or Jito bundle)
- Trade API — Client-side buy and sell single transactions
- Lightning Create — One-call token launch (no Jito needed)
- Lightning Trade — One-call instant trading
- WebSocket Data — Real-time pump.fun trades for sniper bots
- Pricing — Commission and fee details