Trade
POST https://sol.shrine.trade/api/lightspeed. Lightspeed comes with Lite and Developer, and a trade goes out from one of two wallets:
- A dashboard wallet. Make one on the dashboard, or link one you made here, and send its
ls_key inx-api-key. It trades on your account's plan. - Your own wallet. Send your plan's key (
sk_…) inx-api-keyand the wallet'sprivateKeyin the body.
- JavaScript
- Python
- curl
const res = await fetch("https://sol.shrine.trade/api/lightspeed", {
method: "POST",
headers: { "content-type": "application/json", "x-api-key": "ls_…" }, // a dashboard wallet's key
body: JSON.stringify({
action: "buy", // "buy" or "sell"
mint: "<token mint>",
amount: 0.5, // SOL on a buy; tokens or "100%" on a sell
slippage: 25, // percent; snipes want room
priorityFee: 0.002, // SOL, total
tip: 0.001, // SOL, per provider copy; paid once, by the copy that lands
providers: ["shrine", "temporal"], // Developer: the lanes that race (omit for these two, ["all"] for every one); Lite: shrine only
}),
});
const r = await res.json();
console.log(r.success, r.signature, r.submissions);
import os, requests
r = requests.post(
"https://sol.shrine.trade/api/lightspeed",
headers={"x-api-key": "ls_…"}, # a dashboard wallet's key
json={
"action": "buy",
"mint": "<token mint>",
"amount": 0.5,
"slippage": 25,
"priorityFee": 0.002,
"tip": 0.001,
"providers": ["shrine", "temporal"], # Developer: the lanes that race (omit for these two, ["all"] for every one); Lite: shrine only
},
).json()
print(r["success"], r["signature"], r["submissions"])
curl -X POST https://sol.shrine.trade/api/lightspeed \
-H "content-type: application/json" -H "x-api-key: ls_…" \
-d '{ "action": "buy", "mint": "<token mint>", "amount": 0.5, "slippage": 25, "priorityFee": 0.002, "tip": 0.001, "providers": ["shrine", "temporal"] }'
Request
| Field | ||
|---|---|---|
apiKey | string | A Lightspeed wallet's ls_ key, here or in the x-api-key header. |
privateKey | string | Instead of a wallet's key: your own wallet's private key, base58, with your plan's key in x-api-key. It signs this one trade and is dropped; nothing is stored. |
action | "buy" | "sell" | |
mint | string | Token mint, base58. |
amount | number | string | SOL on a buy, also on a coin priced in USDC or a stock (the SOL is swapped into its quote in the same transaction). Tokens, or "100%" / "50%" of the balance, on a sell. |
settle | string | A coin priced in USDC, a stock or another token: "sol" (default) buys and sells it with SOL through the quote's own pool, in one transaction; "quote" pays in the quote from the wallet and is paid in it. See Quoted coins. |
slippage | number | Percent. Default 5. |
priorityFee | number | Total priority fee in SOL. Default 0.001. |
tip | number | Tip per provider copy in SOL. Default 0.001, which reaches every provider but Node1 (0.002). Only the copy that lands pays it. A provider whose minimum is above it is left out of the race. |
pool | string | Force a launchpad: pumpfun, pumpswap, bonk, raydium_cpmm, raydium_amm_v4, meteora_damm_v2, meteora_dbc. Omit to auto-route from the live cache. |
poolAddress | string | For the AMMs when the cache has no pool for the mint. |
guard | boolean | One-fill protection. Default true. With false every copy can land and the wallet trades once per provider. |
nonce | boolean | Race on the wallet's durable nonce. Default false. Only the first copy can run; the others are dropped before they execute and cost nothing, not even their priority fee. Make the wallet's nonce account once with POST /api/lightspeed/nonce (about 0.001 SOL of rent, which stays the wallet's; see Nonce account). Without one, the first nonce: true trade makes it and races the usual way meanwhile. See below under one fill. |
providers | string[] | Developer: which landing providers race this trade, by lowercase name. On Lite the trade goes out on shrine alone and this field is ignored. Omitted: the two defaults, shrine and temporal. ["all"]: every provider the region has. Any other list: exactly those, nothing added. A name that is not on GET /api/lightspeed/providers answers 400, and a list none of whose providers accepts your tip answers 400 too. |
Send your plan's key in x-api-key and privateKey in the body, and the trade is signed with your wallet. The private key is used for that one request and dropped: nothing is stored, nothing is logged. A dashboard wallet keeps the private key off the wire; this is for a bot that already holds its wallet and wants the same race.
headers: { "content-type": "application/json", "x-api-key": "sk_…" }, // your plan's key
body: JSON.stringify({ action: "buy", mint, amount: 0.5, slippage: 25, privateKey: "<base58>" }),
A Lightspeed wallet that is not on your account works the same way: your plan's key in x-api-key, the wallet's ls_ key as apiKey in the body.
A wallet whose account has no running plan, or a request without a plan's key, answers 403:
{ "error": "plan_required", "plan": "lite", "message": "Lightspeed comes with Lite and Developer: …", "upgrade": "https://shrine.trade/api/pricing/" }
Providers: which paths race
On Developer, with provider racing, a Lightspeed trade is not sent down one path. It is signed once per provider and all copies leave at the same instant; the first to reach the leader fills, the rest fail before moving funds, and only the winning copy pays its tip. Details on the SWQoS page.
Without providers a trade races Shrine (shrine, the staked RPC in the region, never tipped) and Temporal (temporal). That pair lands most trades in the next slot at one tip. Add more when you are fighting for a crowded slot, not before: every extra copy that reverts costs its priority fee.
Enable more, or different, providers per trade:
// Everything the region has
body: JSON.stringify({ action: "buy", mint, amount: 0.5, slippage: 25, tip: 0.001, providers: ["all"] })
// Exactly these, nothing added
body: JSON.stringify({ action: "buy", mint, amount: 0.5, slippage: 25, tip: 0.001, providers: ["temporal", "jito", "astralane"] })
// Only our own path, no tip at all
body: JSON.stringify({ action: "buy", mint, amount: 0.5, slippage: 25, tip: 0, providers: ["shrine"] })
GET https://sol.shrine.trade/api/lightspeed/providers lists what the region has right now, each with its minimum tip and whether it is a default:
[
{ "name": "shrine", "minTipSol": 0, "default": true },
{ "name": "temporal", "minTipSol": 0.001, "default": true },
{ "name": "jito", "minTipSol": 0.000001, "default": false },
{ "name": "astralane","minTipSol": 0.00001, "default": false }
]
A provider whose minimum is above your tip is left out of the race. The default 0.001 reaches all of them but Node1, tip: 0.002 reaches all; tip: 0 reaches only shrine. A list that leaves no provider in the race answers 400 with each one's minimum.
Response
{
"success": true,
"signature": "3nQ…",
"submissions": [
{ "provider": "temporal", "signature": "3nQ…", "accepted": true, "ms": 9.1, "sentUs": 98 },
{ "provider": "shrine", "signature": "4Rc…", "accepted": true, "ms": 11.7, "sentUs": 124 }
],
"feeLamports": 1250000,
"quoteMint": "So11111111111111111111111111111111111111112",
"tipLamports": 1000000,
"slot": 447483508,
"guard": true,
"buildMs": 0.07,
"timingsUs": {
"toHandler": 35, "outerLayers": 14, "requestLog": 8, "gate": 13,
"plan": 0, "wallet": 21, "checks": 3, "blockhash": 0, "holdings": 1,
"build": 12, "guard": 1, "firstSign": 23, "firstSend": 98, "lastSend": 124
}
}
On Lite a request that names other providers still goes out on shrine alone, and the answer carries a warning saying so.
success means at least one provider accepted the transaction. Any accepted copy may be the one that lands, so to confirm, watch every signature in submissions (or just the wallet's balance). ms is measured from the request's arrival on our server to that provider's acknowledgement. slot is the newest slot our feed had seen when the copies left; the landed transaction's slot minus it is your slots-to-land.
timingsUs is where our side spent its time, in microseconds from the request's arrival: reaching the handler, opening the wallet, building the trade, signing the first copy (firstSend is when it left, lastSend the last copy). sentUs on each submission is when that copy left for its provider.
The answer leaves on the first acceptance: the trade is on its way the moment one provider has it, and a slower acknowledgement from another does not hold it. A copy still in flight at that moment is listed in pending with its provider and signature (absent when every provider had answered). Its signature is fixed before it leaves, so watch it like the ones in submissions: any copy may be the one that lands.
One fill, never two
Every copy carries the same trade and a different tip, so each has its own signature and any of them may be the one that lands. The first to execute trades; the rest fail on chain before moving funds. A failed copy costs its priority fee and nothing else: the tip is inside the same transaction and fails with it. So the trade happens once and the tip is paid once, to the provider whose copy landed.
Set guard: false only if you mean to buy once per provider.
With nonce: true the copies share the wallet's durable nonce instead of a recent blockhash, and each opens by advancing it. The first copy to run advances the nonce; every other copy then fails the nonce check before it executes, is dropped, and costs nothing at all, so racing more providers costs nothing extra. The answer's nonce says what happened: used; preparing while the nonce account is being made (this trade raced the usual way, the next ones use the nonce; make it beforehand with POST /api/lightspeed/nonce and the first trade uses it); busy while the wallet's previous nonce trade is unresolved (this one raced the usual way rather than wait). A nonce transaction does not expire the way a blockhash one does, so when no copy has landed 8 seconds after the send, the nonce is advanced on purpose and every copy still out can no longer run.
What a reverted copy costs is its base fee (0.000005 SOL) plus its priority fee, nothing more. Copies the leader never includes cost nothing. So put the budget into tip, which only the winning copy pays, and keep priorityFee modest: at 0.00002 SOL three reverted copies cost 0.000075 SOL, at 0.001 they cost 0.003.
Fees
None: Lightspeed comes with Lite and Developer, which trade at 0%. The tip is yours to set and goes to the provider whose copy landed. On Lite the race is the Shrine lane alone; providers with more names, or ["all"], races every lane on Developer. See Plans and limits.
Speed checklist
- Keep the wallet funded so no request waits on a deposit.
- Send
mintthe moment your stream shows the launch; thecreateevent onsubscribe_streamcarries it. A pump.fun coin can be bought from its create event alone, the API needs no chain read for it. - Run your bot in the region next to it; our side adds about a millisecond.
- Add providers with
providers: ["all"]and raisetipwhen a launch is crowded; keep the defaults otherwise.
LimitsLite Shrine lane, ~100 ms · 3 req/sDeveloper 8 lanes raced, ~50 ms · 10 req/sSee plans →