Spring Lander docs
Overview
Spring Lander is a high-performance Solana transaction landing service. Construct your transaction as normal, add one tip instruction, sign, and send it to a Spring Lander endpoint — we deliver it directly to the leader over staked connections backed by 27+ million stake. Pay per transaction. If it doesn't land, you pay nothing.
How it works
Transactions are forwarded over staked QUIC connections directly to the current and upcoming leaders' TPU ports. There is no public RPC queue in the path and no middleman proxy — your signed bytes go from our edge to the leader.
Those edges run in 20 regions placed near validator concentrations, so the hop from your servers to ours is short and the hop from us to the leader is shorter. Pin the region closest to you for the lowest end-to-end latency.
Failed sends are free. Your tip is a transfer instruction inside your own transaction — it only executes if the transaction lands. No landing, no cost.
Tips
To use Spring Lander, add a standard SOL transfer instruction to one of the tip accounts below. Minimum tip: 0.001 SOL. Transactions are processed in order received and by tip amount — higher tips get priority during congestion.
SpWrza9E63MQuHeGnnfzmtLVCs3pBdjyKPXUABPo9nqSpagSJmnh8E9cGT5Y431xPPaS2c1xLREGGCWN9yDeUfPick either account — randomize your choice to avoid write-lock contention when sending at high frequency.
Endpoints
| Region | Code | Endpoint |
|---|---|---|
| North America — US | ||
| New York | nyc | nyc.springlander.xyz |
| Ashburn | ash | ash.springlander.xyz |
| Chicago | chi | chi.springlander.xyz |
| Atlanta | atl | atl.springlander.xyz |
| Miami | mia | mia.springlander.xyz |
| Dallas | dal | dal.springlander.xyz |
| Houston | hou | hou.springlander.xyz |
| Kansas City | mci | mci.springlander.xyz |
| Denver | den | den.springlander.xyz |
| Salt Lake City | slc | slc.springlander.xyz |
| Phoenix | phx | phx.springlander.xyz |
| Los Angeles | lax | lax.springlander.xyz |
| Seattle | sea | sea.springlander.xyz |
| North America — Canada | ||
| Toronto | yyz | yyz.springlander.xyz |
| Vancouver | yvr | yvr.springlander.xyz |
| Europe | ||
| Frankfurt | fra | fra.springlander.xyz |
| Amsterdam | ams | ams.springlander.xyz |
| London | lon | lon.springlander.xyz |
| Asia-Pacific | ||
| Singapore | sgp | sgp.springlander.xyz |
| Tokyo | tyo | tyo.springlander.xyz |
Global (geolocated): send.springlander.xyz — resolves to the nearest region. Region-specific endpoints are always faster; pin one if you can.
Paths on every region:
POST /send JSON-RPC sendTransaction (drop-in RPC compatible)
POST /send-bin raw serialized transaction (application/octet-stream)
POST /send-cors /send with CORS headers, for browser integrations
POST /send-bin-cors /send-bin with CORS headers
GET /ping keep-aliveAuthentication
Every request needs an API key, passed as a query parameter:
https://fra.springlander.xyz/send?api-key=<your-api-key>Get your key on Telegram.
Browser & CORS
Sending directly from the user's browser skips a round trip through your backend — the signed transaction goes straight from the wallet to Spring Lander. The -cors endpoint variants exist for exactly this:
POST /send-cors JSON-RPC sendTransaction with CORS headers
POST /send-bin-cors raw binary submission with CORS headersBoth return Access-Control-Allow-Origin: * and answer OPTIONS preflight requests. The plain /send and /send-bin endpoints do not send CORS headers and will be blocked by browsers.
- Pages served over HTTPS must call the
https://endpoints — browsers hard-block mixed content, so plainhttp://is unusable from a secure page. - Preflight: a JSON
POSTtriggers anOPTIONSpreflight on the first request; the connection is then reused, so subsequent sends skip it. Keep the connection warm with/ping. /send-bin-corswithContent-Type: application/octet-streamalso works from browsers and skips JSON encoding.- Use a browser-scoped API key: keys in front-end code are visible to users, so issue a separate key for browser traffic (domain-restricted keys available — ask on Telegram).
Full example URL:
https://fra.springlander.xyz/send-cors?api-key=<your-browser-key>A complete browser code example is in the Examples section below.
Binary submission
POST the raw serialized transaction bytes to /send-bin with Content-Type: application/octet-stream. Skips JSON parsing on both ends — the fastest submission path over HTTP. Returns HTTP 200 with the transaction signature as plain text, or HTTP 400 with an error message.
curl -X POST "https://fra.springlander.xyz/send-bin?api-key=YOUR_KEY" \
-H "Content-Type: application/octet-stream" \
--data-binary @signed-tx.binKeep-alive
GET /ping returns 200 pong. Ping every 30–45 seconds on the same TCP connection you send on — a reconnect adds a handshake to your next send. Most HTTP clients (reqwest, axios with a keep-alive agent, browser fetch to the same origin) reuse connections automatically.
// Node: force a keep-alive agent and ping on an interval
import { Agent } from "https";
const agent = new Agent({ keepAlive: true });
const BASE = "https://fra.springlander.xyz";
setInterval(() => {
fetch(`${BASE}/ping`, { agent } as any).catch(() => {});
}, 35_000);
// send transactions with the same agent so the warm connection is reusedHTTP vs HTTPS
Both schemes work on every regional endpoint. On a warm keep-alive connection, throughput is identical; plain HTTP saves one round trip on cold connects only. Browser integrations must use HTTPS. Over plain HTTP your API key travels in cleartext — use a dedicated key for HTTP traffic.
Examples
import {
Connection, Keypair, PublicKey, SystemProgram,
TransactionMessage, VersionedTransaction,
} from "@solana/web3.js";
const ENDPOINT = "https://fra.springlander.xyz/send?api-key=YOUR_KEY";
const TIP_ACCOUNTS = [
"SpWrza9E63MQuHeGnnfzmtLVCs3pBdjyKPXUABPo9nq",
"SpagSJmnh8E9cGT5Y431xPPaS2c1xLREGGCWN9yDeUf",
];
const MIN_TIP_LAMPORTS = 1_000_000; // 0.001 SOL
async function sendWithSpring(payer: Keypair, instructions: any[], rpc: Connection) {
// Spring Lander tip — required, minimum 0.001 SOL
const tip = SystemProgram.transfer({
fromPubkey: payer.publicKey,
toPubkey: new PublicKey(TIP_ACCOUNTS[Math.floor(Math.random() * TIP_ACCOUNTS.length)]),
lamports: MIN_TIP_LAMPORTS,
});
const { blockhash } = await rpc.getLatestBlockhash();
const msg = new TransactionMessage({
payerKey: payer.publicKey,
recentBlockhash: blockhash,
instructions: [...instructions, tip],
}).compileToV0Message();
const tx = new VersionedTransaction(msg);
tx.sign([payer]);
const res = await fetch(ENDPOINT, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
jsonrpc: "2.0", id: 1, method: "sendTransaction",
params: [Buffer.from(tx.serialize()).toString("base64"), { encoding: "base64" }],
}),
});
const { result: signature } = await res.json();
return signature;
}