Skip to main content
LitePart of the Lite plan; Developer includes it too. See plans · Get your key

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 in x-api-key. It trades on your account's plan.
  • Your own wallet. Send your plan's key (sk_…) in x-api-key and the wallet's privateKey in the body.
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);

Request​

Field
apiKeystringA Lightspeed wallet's ls_ key, here or in the x-api-key header.
privateKeystringInstead 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"
mintstringToken mint, base58.
amountnumber | stringSOL 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.
settlestringA 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.
slippagenumberPercent. Default 5.
priorityFeenumberTotal priority fee in SOL. Default 0.001.
tipnumberTip 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.
poolstringForce a launchpad: pumpfun, pumpswap, bonk, raydium_cpmm, raydium_amm_v4, meteora_damm_v2, meteora_dbc. Omit to auto-route from the live cache.
poolAddressstringFor the AMMs when the cache has no pool for the mint.
guardbooleanOne-fill protection. Default true. With false every copy can land and the wallet trades once per provider.
noncebooleanRace 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.
providersstring[]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.
Your own wallet

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.

Without a plan

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.

Two providers by default

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 }
]
The tip must clear every provider you name

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 mint the moment your stream shows the launch; the create event on subscribe_stream carries 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 raise tip when 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 →