Send multiple transactions as an atomic bundle through Lunar Lander. All transactions in a bundle are executed sequentially and atomically — they all land or none are committed.
What this does
This document describes Lunar Lander's /sendBundle endpoint for atomic bundle submission. The endpoint supports the following use case:
- You submit multiple signed transactions as a single atomic bundle via JSON-RPC
- All transactions in the bundle are executed sequentially — they all land or none are committed
- Lunar Lander fans out the bundle to multiple block-engine relays for best landing probability
Endpoints
POST /sendBundle
Available at all regional endpoints by using the /sendBundle endpoint
Requires Content-Type: application/json.
Note: This method is not enabled by default for all API keys. Contact us to activate bundle sending on your key.
Request Format
Use the sendBundle JSON-RPC method. The first parameter is an array of base64-encoded signed transactions.
{
"jsonrpc": "2.0",
"id": 1,
"method": "sendBundle",
"params": [
[
"<base64_encoded_signed_tx_1>",
"<base64_encoded_signed_tx_2>"
],
{
"encoding": "base64"
}
]
}params[0]— array of signed, serialized transactions encoded in base64params[1].encoding— transaction encoding (usebase64)
Validation And Limits
- Maximum transactions per bundle:
4 - Each transaction must be fully signed before submission
- At least one transaction must include a tip to a Lunar Lander tip account
- Tip minimum:
1,000,000lamports (0.001 SOL) - All transactions must pass simulation — if any fails, the entire bundle will not land on chain
Response Contract
A successful response confirms the bundle was received, validated, and relay submission was started locally. It does not guarantee relay acceptance or on-chain landing.
{
"jsonrpc": "2.0",
"result": [
"38GSYbRqgStBi1t7EnCuxhcWK5gqoRDvMzqouZUz7HuXvCn2zZGeA94qrnCUkoqfqdYGmrXhEouQNNfPMUdiXWBm",
"65YXFi1ytULbugsBhc9PLE13hsFU24KuvS3NAbxZyt5tS6ossQz3QoYbhdCa2nSaTYNpTyLRjnbVmgZvbEU9ZsX"
],
"id": 1
}result is the ordered list of base58 transaction signatures from the customer-supplied bundle payloads.
Status codes:
200 OK— bundle validated and accepted for asynchronous relay submission400 Bad Request— malformed transactions, missing tip, bundle too large, or other invalid request data403 Forbidden— API key does not havesendBundlescope enabled429 Too Many Requests— rate limited503 Service Unavailable— no eligible bundle relay is configured for the request, or the endpoint is shutting down
How /sendBundle differs from other send methods
/sendBundle differs from other send methods/send | /sendBatch | /sendBundle | |
|---|---|---|---|
| Transactions per request | 1 | Up to 16 | Up to 4 |
| Execution | Individual | Individual (no atomicity) | Sequential and atomic |
| Wire format | JSON-RPC or binary | Binary (length-prefixed frames) | JSON-RPC |
| Tip required in | The transaction | The transaction | At least one transaction in the bundle |
For details on /sendBatch, see the Batch Send API page.
Example
import requests
import base64
# Assume tx1 and tx2 are already signed Transaction objects
tx1_bytes = bytes(tx1.serialize())
tx2_bytes = bytes(tx2.serialize())
payload = {
"jsonrpc": "2.0",
"id": 1,
"method": "sendBundle",
"params": [
[
base64.b64encode(tx1_bytes).decode("utf-8"),
base64.b64encode(tx2_bytes).decode("utf-8"),
],
{"encoding": "base64"}
]
}
response = requests.post(
"http://fra.lunar-lander.hellomoon.io/sendBundle?api-key=YOUR_KEY",
json=payload,
)
print(response.json())const tx1Base64 = Buffer.from(tx1.serialize()).toString("base64");
const tx2Base64 = Buffer.from(tx2.serialize()).toString("base64");
const response = await fetch(
"http://fra.lunar-lander.hellomoon.io/sendBundle?api-key=YOUR_KEY",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "sendBundle",
params: [[tx1Base64, tx2Base64], { encoding: "base64" }],
}),
}
);
const result = await response.json();
console.log(result);Frequently Asked Questions
Do I pay if my bundle doesn't land?
No. Tips are paid via transfer instructions within the bundle transactions. If the bundle doesn't land, no transactions execute and you pay nothing.
Can I check the status of my bundle?
Bundle status tracking is not currently available through Lunar Lander. We recommend confirming your transactions landed by checking the signatures on-chain via your preferred RPC endpoint.
What happens if one transaction in my bundle fails simulation?
The entire bundle is rejected. All transactions must pass simulation for the bundle to be submitted.