LightBridge Documentation
Everything you need to integrate LightBridge into your Solana application. Send transactions through optimized, multi-path infrastructure and land them reliably.
Quickstart
Get up and running in minutes. Here's the minimal setup to send your first transaction through LightBridge.
1. Get your API key
Request access through our Discord server. You'll receive an API key to authenticate your requests.
2. Send a transaction
const API_KEY = "YOUR_API_KEY";
const response = await fetch("http://fra.lightbridge.vision-node.com/send?api-key=" + API_KEY, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
transaction: serializedTx,
}),
});
const { signature, status } = await response.json();
3. Check the result
The response includes a transaction signature and landing status. See the Send Transaction reference for full response details.
Authentication
All API requests require a valid API key passed as a query parameter.
http://fra.lightbridge.vision-node.com/send?api-key=YOUR_API_KEY
Append ?api-key=YOUR_API_KEY to any endpoint URL. For example:
# Send transaction (JSON)
POST /send?api-key=YOUR_API_KEY
# Send binary transaction
POST /send-bin?api-key=YOUR_API_KEY
# Batch send (binary, up to 16 transactions)
POST /sendBatch?api-key=YOUR_API_KEY
# CORS-enabled variants (for browser use)
POST /send-cors?api-key=YOUR_API_KEY
POST /send-bin-cors?api-key=YOUR_API_KEY
# Keep-alive ping
GET /ping?api-key=YOUR_API_KEY
Endpoints
Use the base URL below for all API requests. Additional regions will be added in the future.
| Region | Base URL |
|---|---|
| Frankfurt | http://fra.lightbridge.vision-node.com |
Tips
Every transaction sent through LightBridge must include a minimum tip of 0.001 SOL. This tip is a transfer instruction included in your transaction that goes to one of our designated tip wallets.
How it works
When you build your transaction, include a SOL transfer instruction to one of the tip wallets listed below. Because the tip is an instruction inside your transaction, you only pay if your transaction lands on-chain. If it doesn't land, you pay nothing.
Key points:
- The tip is a standard SOL transfer instruction — not a priority fee or compute budget change
- Include the tip as one of the instructions in your transaction before signing and serializing
- The minimum is 0.001 SOL (1,000,000 lamports) — you can tip more for higher priority
- Send the tip to any one of the tip wallets listed below
Tip wallets
Include a SOL transfer to any one of these wallets in your transaction:
vsn7B5w2z1eopfoBmwd1eDakvFUUatmmMwdMJJ37m8e
vsn7szXXVgeAu6jW7YcCB6vUvYTnWwRgUhhecS87Ynd
vsnL7iaCzAsfgjBs1RupXmUrYjkVgXzGpzK3WwzSvcr
vsnQHLdhyfnsH433UsXTwhvN51GHqWxeJa9UqbBSVii
vsnRAHFiGjQyJ7Yc3dEDXwkeys94AVmKh6zpk3vniQh
vsnZSeFgToWvR1ZJoMcMqcVYss7vE15yxHxgHnC85Tb
vsncMHAQEfRXvMkmeWaAk2thDziTVP1wqYqUAR8isqn
vsncn9qJ31kadx4JNc8mfoX5yQs7GWNf9aELBVhTRPQ
vsngK2qBBVJZfWhMxruQmDnrzBmD6UaZdiMee6vho4m
vsnqiBRqfLRviiyNjYZNVzxNB1dAE9JSzVCN3VKkdU4
Example
Here's how to include a tip instruction in your transaction:
import { SystemProgram, PublicKey, Transaction } from "@solana/web3.js";
// Choose any one of the tip wallets
const TIP_WALLET = new PublicKey("vsn7B5w2z1eopfoBmwd1eDakvFUUatmmMwdMJJ37m8e");
const TIP_AMOUNT = 1_000_000; // 0.001 SOL in lamports
// Create the tip instruction
const tipInstruction = SystemProgram.transfer({
fromPubkey: payer.publicKey,
toPubkey: TIP_WALLET,
lamports: TIP_AMOUNT,
});
// Add the tip to your transaction alongside your other instructions
const transaction = new Transaction().add(
tipInstruction,
yourInstruction, // your swap, mint, transfer, etc.
);
// Sign, serialize, and send via LightBridge as usual
Send Transaction
Submit a serialized Solana transaction for landing via LightBridge. The request body can contain just the transaction as shown in the Quickstart example, or a full JSON-RPC payload if you wish to be compatible with the standard Solana sendTransaction RPC method.
/send
skipPreflight: true when sending transactions — it's handled automatically.Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
transaction |
string |
Yes | Base64-encoded serialized transaction |
Response
| Status | Body | Description |
|---|---|---|
200 |
Transaction signature (string) | Transaction was accepted for landing |
400 |
Error message (string) | An error message describing what went wrong |
Send Binary
Submit a raw serialized transaction in binary format. This may be faster than the JSON endpoint since there is less processing overhead.
/send-bin
Headers
| Header | Value | Required | Description |
|---|---|---|---|
Content-Type |
application/octet-stream |
Yes | Indicates the body contains raw binary data |
Request Body
The body should be the raw serialized transaction bytes — not base64-encoded, not JSON-wrapped. Send the binary data directly.
// Serialize your transaction to raw bytes
const serialized = transaction.serialize();
const API_KEY = "YOUR_API_KEY";
const response = await fetch("http://fra.lightbridge.vision-node.com/send-bin?api-key=" + API_KEY, {
method: "POST",
headers: {
"Content-Type": "application/octet-stream",
},
body: serialized,
});
const signature = await response.text();
import requests
API_KEY = "YOUR_API_KEY"
serialized = transaction.serialize()
response = requests.post(
f"http://fra.lightbridge.vision-node.com/send-bin?api-key={API_KEY}",
headers={"Content-Type": "application/octet-stream"},
data=bytes(serialized),
)
Response
| Status | Body | Description |
|---|---|---|
200 |
Transaction signature (string) | Transaction was accepted for landing |
400 |
Error message (string) | An error message describing what went wrong |
Send Batch
Submit multiple transactions in a single request with lower client and network overhead. Transactions are streamed and processed as bytes arrive — the server doesn't wait for the full request body before it starts working.
/sendBatch
Headers
| Header | Value | Required | Description |
|---|---|---|---|
Content-Type |
application/octet-stream |
Yes | Indicates the body contains raw binary data |
Wire Format
The request body uses length-prefixed frames. Each transaction is preceded by a 2-byte big-endian unsigned integer indicating the length of the transaction bytes that follow.
// Each frame: 2-byte big-endian length prefix + raw transaction bytes
[u16_be_length][raw_tx_bytes][u16_be_length][raw_tx_bytes]...
// Example with 3 transactions:
[len1_be][tx1][len2_be][tx2][len3_be][tx3]
const API_KEY = "YOUR_API_KEY";
const transactions = [tx1, tx2, tx3]; // Array of signed Transaction objects
// Build the length-prefixed binary payload
const frames: Uint8Array[] = [];
for (const tx of transactions) {
const serialized = tx.serialize();
const lenBuf = new Uint8Array(2);
new DataView(lenBuf.buffer).setUint16(0, serialized.length);
frames.push(lenBuf, serialized);
}
const body = new Uint8Array(
frames.reduce((acc, f) => { acc.push(...f); return acc; }, [] as number[])
);
const response = await fetch(
"http://fra.lightbridge.vision-node.com/sendBatch?api-key=" + API_KEY,
{
method: "POST",
headers: { "Content-Type": "application/octet-stream" },
body: body,
}
);
const result = await response.json();
// { attempted: 3, accepted: 3, rejected: 0, parse_error: null }
Limits
| Constraint | Value |
|---|---|
| Max transactions per request | 16 |
| Min payload size per transaction | 66 bytes |
| Max payload size per transaction | 1,232 bytes |
Response
{
"attempted": 3, // Total transactions parsed and processed
"accepted": 3, // Transactions that passed ingress validation
"rejected": 0, // Transactions that failed validation
"parse_error": null // Framing/stream errors, or null if none
}
| Status | Condition |
|---|---|
200 |
No rejections and no parse errors |
400 |
One or more rejections or parse errors present |
Parse Error Types
If the server encounters a framing issue, the parse_error field will contain the error type and a 1-based at_tx_index indicating where in the batch the problem occurred.
| Error | Description |
|---|---|
empty_body |
Request body was empty |
incomplete_length_prefix |
Not enough bytes for the 2-byte length prefix |
incomplete_payload |
Fewer bytes than the length prefix indicated |
max_batch_exceeded |
More than 16 transactions in a single request |
body_read_error |
Error reading the request stream |
rate_limited |
Request was rate-limited |
CORS Endpoints
If you're sending transactions from a browser environment, use the CORS-enabled variants of the standard endpoints. These return the Access-Control-Allow-Origin: * header and handle OPTIONS preflight requests automatically.
| Standard Endpoint | CORS Endpoint | Description |
|---|---|---|
/send |
/send-cors |
JSON transaction with CORS headers |
/send-bin |
/send-bin-cors |
Binary transaction with CORS headers |
// Use /send-cors instead of /send for browser-based applications
const response = await fetch(
"http://fra.lightbridge.vision-node.com/send-cors?api-key=" + API_KEY,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ transaction: serializedTx }),
}
);
Keep-Alive
Use the ping endpoint to maintain persistent connections and prevent idle timeout closures across network hops. This is especially useful for long-lived connections where you want to avoid the overhead of re-establishing TCP connections between transaction sends.
/ping
Response
Returns HTTP 200 with a plain text body of pong.
const API_KEY = "YOUR_API_KEY";
// Ping every 30–45 seconds to keep the connection alive
setInterval(async () => {
await fetch(
"http://fra.lightbridge.vision-node.com/ping?api-key=" + API_KEY
);
}, 30_000);
Rate Limits
Every API key starts with a default rate limit of 5 transactions per second (TPS). If you need a higher limit, reach out to us on Discord and we'll work with you to increase it.
Error Handling
LightBridge uses standard HTTP status codes and returns structured error responses.
Support
Need help? Reach out through any of these channels.
- Discord — Fastest way to get help from the team
- X / Twitter — Follow for updates and announcements
- Vision Node — Parent company website