Jito Bundles
Jito Bundles let you send up to 5 transactions in a single atomic package — all or nothing. Either every transaction lands, or none of them do.
Unlike Actions, the transactions inside a bundle are independent from each other on-chain. To an outside observer, they look like completely unrelated transactions — but they are guaranteed to execute together, in order, with no possibility for anyone to sandwich or front-run between them.
Why use Jito Bundles?
- Token creators: launch a token and buy it from multiple wallets in a way that looks like organic, unrelated buys — while staying 100% protected from snipers squeezing in between your transactions.
- Fast account cleanup: sell everything across multiple transactions at once.
- Massive batch operations: combine with Actions to pack multiple operations into each transaction — e.g. 4 sells per tx × 5 txs = 20 sells in one bundle. For simple transfers, you can fit ~150 transfers in a single bundle.
Endpoint
POST https://api.pumpapi.io
Basic Structure
Just send your usual requests wrapped inside a transactions array:
{
"transactions": [
{ /* tx1 */ },
{ /* tx2 */ },
{ /* tx3 */ },
{ /* tx4 */ },
{ /* tx5 */ }
]
}
Each transaction in the array follows the exact same format as a normal Trade API call. Everything we support works inside bundles — including Actions (so you can nest actions inside each transaction) and guaranteedDelivery (continuous re-sending of your transaction, perfect for sells). Just place these flags above the transactions array.
Jito Tip and Jito tip payer
You can specify jitoTip and its payer above the transactions array to set it globally for the whole bundle:
{
"jitoTip": 0.00001,
"transactions": [
{ /* tx1 */ },
{ /* tx2 */ }
]
}
- If
jitoTipis not set at the top level, the value from the last transaction in the array will be used. - If it's not specified anywhere, we fall back to the minimum Jito tip of
0.00001 SOL(the minimum Jito requires). - If
privateKey(for lightning mode) orpublicKey(for local mode) is not specified above thetransactionsblock, the payer of the last transaction covers the Jito tip.
Inside a Jito Bundle, priorityFee has no effect — bundles are routed through the Jito Block Engine, which doesn't care about Solana priority fees. Only jitoTip determines how fast your bundle lands. You can safely omit priorityFee from every transaction in the bundle.
Example: Create a Token and Buy from 4 Other Wallets
This is the classic use case — launch a token, have the dev wallet buy on creation, and then buy from 4 additional wallets in separate transactions that look unrelated to outside observers.
- Python
- JavaScript
- Rust
- Go
import requests
url = "https://api.pumpapi.io"
data = {
"jitoTip": 0.00001,
"transactions": [
{
"privateKey": "dev_wallet_private_key",
"action": "create",
"name": "PumpApi",
"symbol": "PAPI",
"description": "Fast API for Pump.fun, Raydium, Meteora",
"imageURL": "https://pumpapi.io/img/pumpapi_logo.webp",
"website": "https://pumpapi.io",
"telegram": "https://t.me/YOUR_TG",
"x": "https://x.com/realpumpapi",
"mintRef": "0", # set a temporary reference for the new token
"initialTradeAction": "buy", # dev buy
"amount": 0.5,
"denominatedInQuote": True,
"slippage": 99,
},
{
"privateKey": "wallet_2_private_key",
"action": "buy",
"mintRef": "0", # reuse the mintRef we set during create
"amount": 0.3,
"denominatedInQuote": True,
"slippage": 99,
},
{
"privateKey": "wallet_3_private_key",
"action": "buy",
"mintRef": "0", # reuse the mintRef we set during create
"amount": 0.3,
"denominatedInQuote": True,
"slippage": 99,
},
{
"privateKey": "wallet_4_private_key",
"action": "buy",
"mintRef": "0", # reuse the mintRef we set during create
"amount": 0.3,
"denominatedInQuote": True,
"slippage": 99,
},
{
"privateKey": "wallet_5_private_key",
"action": "buy",
"mintRef": "0", # reuse the mintRef we set during create
"amount": 0.3,
"denominatedInQuote": True,
"slippage": 99,
}
]
}
response = requests.post(url, json=data)
print(response.json())
import axios from 'axios';
const data = {
jitoTip: 0.0001,
transactions: [
{
privateKey: "dev_wallet_private_key",
action: "create",
name: "PumpApi",
symbol: "PAPI",
description: "Fast API for Pump.fun, Raydium, Meteora",
imageURL: "https://pumpapi.io/img/pumpapi_logo.webp",
website: "https://pumpapi.io",
telegram: "https://t.me/YOUR_TG",
x: "https://x.com/realpumpapi",
mintRef: "0", // set a temporary reference for the new token
initialTradeAction: "buy", // dev buy
amount: 0.5,
denominatedInQuote: true,
slippage: 99,
},
{
privateKey: "wallet_2_private_key",
action: "buy",
mintRef: "0", // reuse the mintRef we set during create
amount: 0.3,
denominatedInQuote: true,
slippage: 99,
},
{
privateKey: "wallet_3_private_key",
action: "buy",
mintRef: "0", // reuse the mintRef we set during create
amount: 0.3,
denominatedInQuote: true,
slippage: 99,
},
{
privateKey: "wallet_4_private_key",
action: "buy",
mintRef: "0", // reuse the mintRef we set during create
amount: 0.3,
denominatedInQuote: true,
slippage: 99,
},
{
privateKey: "wallet_5_private_key",
action: "buy",
mintRef: "0", // reuse the mintRef we set during create
amount: 0.3,
denominatedInQuote: true,
slippage: 99,
}
]
};
axios.post("https://api.pumpapi.io", data)
.then(response => console.log(response.data))
.catch(error => console.error(error));
use reqwest::Client;
use serde_json::json;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
let res = client
.post("https://api.pumpapi.io")
.json(&json!({
"jitoTip": 0.00001,
"transactions": [
{
"privateKey": "dev_wallet_private_key",
"action": "create",
"name": "PumpApi",
"symbol": "PAPI",
"description": "Fast API for Pump.fun, Raydium, Meteora",
"imageURL": "https://pumpapi.io/img/pumpapi_logo.webp",
"website": "https://pumpapi.io",
"telegram": "https://t.me/YOUR_TG",
"x": "https://x.com/realpumpapi",
"mintRef": "0", // set a temporary reference for the new token
"initialTradeAction": "buy", // dev buy
"amount": 0.5,
"denominatedInQuote": true,
"slippage": 99,
},
{
"privateKey": "wallet_2_private_key",
"action": "buy",
"mintRef": "0", // reuse the mintRef we set during create
"amount": 0.3,
"denominatedInQuote": true,
"slippage": 99,
},
{
"privateKey": "wallet_3_private_key",
"action": "buy",
"mintRef": "0", // reuse the mintRef we set during create
"amount": 0.3,
"denominatedInQuote": true,
"slippage": 99,
},
{
"privateKey": "wallet_4_private_key",
"action": "buy",
"mintRef": "0", // reuse the mintRef we set during create
"amount": 0.3,
"denominatedInQuote": true,
"slippage": 99,
},
{
"privateKey": "wallet_5_private_key",
"action": "buy",
"mintRef": "0", // reuse the mintRef we set during create
"amount": 0.3,
"denominatedInQuote": true,
"slippage": 99,
}
]
}))
.send()
.await?
.text()
.await?;
println!("{}", res);
Ok(())
}
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
)
func main() {
data := map[string]interface{}{
"jitoTip": 0.00001,
"transactions": []map[string]interface{}{
{
"privateKey": "dev_wallet_private_key",
"action": "create",
"name": "PumpApi",
"symbol": "PAPI",
"description": "Fast API for Pump.fun, Raydium, Meteora",
"imageURL": "https://pumpapi.io/img/pumpapi_logo.webp",
"website": "https://pumpapi.io",
"telegram": "https://t.me/YOUR_TG",
"x": "https://x.com/realpumpapi",
"mintRef": "0", // set a temporary reference for the new token
"initialTradeAction": "buy", // dev buy
"amount": 0.5,
"denominatedInQuote": true,
"slippage": 99,
},
{
"privateKey": "wallet_2_private_key",
"action": "buy",
"mintRef": "0", // reuse the mintRef we set during create
"amount": 0.3,
"denominatedInQuote": true,
"slippage": 99,
},
{
"privateKey": "wallet_3_private_key",
"action": "buy",
"mintRef": "0", // reuse the mintRef we set during create
"amount": 0.3,
"denominatedInQuote": true,
"slippage": 99,
},
{
"privateKey": "wallet_4_private_key",
"action": "buy",
"mintRef": "0", // reuse the mintRef we set during create
"amount": 0.3,
"denominatedInQuote": true,
"slippage": 99,
},
{
"privateKey": "wallet_5_private_key",
"action": "buy",
"mintRef": "0", // reuse the mintRef we set during create
"amount": 0.3,
"denominatedInQuote": true,
"slippage": 99,
},
},
}
jsonData, _ := json.Marshal(data)
resp, err := http.Post("https://api.pumpapi.io", "application/json", bytes.NewBuffer(jsonData))
if err != nil {
panic(err)
}
defer resp.Body.Close()
var result map[string]interface{}
json.NewDecoder(resp.Body).Decode(&result)
fmt.Println(result)
}
Response Format
{
"signatures": [
"signature1",
"signature2",
"signature3",
"signature4",
"signature5"
],
"err": ""
// "createdMints": ["created_mint_address"] ← only present if the bundle contained a "create" action
// ...other extra fields may appear depending on which actions you performed inside the bundle
}
signatures— array of transaction signatures, one per transaction in the bundle (up to 5).err—""on success, or the error message if the bundle failed.createdMints— only included when the bundle creates one or more tokens. Contains the mint addresses of the newly created tokens.- Other extra fields may appear depending on which actions you performed inside the bundle.
Actions vs. Jito Bundles
| Actions | Jito Bundles | |
|---|---|---|
| What it does | Combines multiple operations into 1 transaction | Combines multiple transactions into 1 bundle |
| Use case | Multi-step logic in one atomic tx | Atomic ordering of separate txs |
See the Actions page for details. And remember — the two can be combined: nest Actions inside each transaction of a Jito Bundle to pack even more operations into a single atomic package.
Local (Unsigned) Transactions
Local transactions are fully supported for Jito Bundles. Head over to the Trade API page for a local-transactions example and adapt it to the transactions array format shown above.
Jito Bundles can only be submitted to the Jito Block Engine, which enforces strict rate limits for unauthorized users — typically only ~1 out of every 5 transactions will be accepted for a new wallet. To raise these limits you must apply through the Jito Discord.
This is why we strongly recommend using the lightning version (the default examples shown above on this page) — it's both faster and dramatically simpler, with no rate-limit headaches.
Need help? Join our Telegram group.