pump.fun API: What Exists and What You Build Yourself

There is no official pump.fun API. What developers use instead to read bonding curve state, detect launches, and submit trades — and where each breaks.

BoltTx Team··10 min read
solanapump-funbonding-curvesniper-bottrading-bottransaction-landing

The first thing to know about the pump.fun API is that there is no official one. No documented REST endpoint, no published SDK, no support channel.

What people mean when they say "pump.fun API" is one of three different things, and the one you need depends on whether you are reading state, detecting launches, or actually trading.

The Three Things People Mean

1. Reading bonding curve state

Every pump.fun token has an on-chain account holding its curve state — virtual reserves, real reserves, whether it has completed. You read this the same way you read any Solana account: getAccountInfo against the program's PDA, then deserialize.

★No API needed. It is just chain state.★ The work is knowing the account layout and doing the math correctly.

2. Detecting new launches

You want to know a token exists before everyone else does. Options: poll for new accounts under the program, subscribe to program logs, or consume a third-party feed that does one of those and resells it.

Polling is simplest and slowest. Log subscriptions are faster and more work. Third-party feeds are fastest to integrate and add a hop you do not control.

3. Submitting trades

Building the swap instruction and getting it into a block. ★This is where the actual money is won or lost★, and it has nothing to do with pump.fun — it is a standard Solana transaction submission problem.

Already building and just need the submission half? A free BoltTx key is one line of config. The rest of this covers the parts you have to build yourself.

Reading Curve State

The bonding curve account holds four numbers that matter:

import { Connection, PublicKey } from "@solana/web3.js";

const PUMP_PROGRAM = new PublicKey(
  "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P",
);

function bondingCurvePda(mint: PublicKey): PublicKey {
  const [pda] = PublicKey.findProgramAddressSync(
    [Buffer.from("bonding-curve"), mint.toBuffer()],
    PUMP_PROGRAM,
  );
  return pda;
}

async function readCurve(connection: Connection, mint: PublicKey) {
  const info = await connection.getAccountInfo(bondingCurvePda(mint));
  if (!info) return null;

  // Layout: 8-byte discriminator, then five u64 and a bool.
  const d = info.data;
  const u64 = (off: number) => d.readBigUInt64LE(off);

  return {
    virtualTokenReserves: u64(8),
    virtualSolReserves: u64(16),
    realTokenReserves: u64(24),
    realSolReserves: u64(32),
    tokenTotalSupply: u64(40),
    complete: d[48] === 1, // true once the curve has graduated
  };
}

The price at any moment comes from the virtual reserves, using constant product:

// Cost in lamports to buy `tokensOut` tokens, before fees.
function costToBuy(
  virtualSol: bigint,
  virtualTokens: bigint,
  tokensOut: bigint,
): bigint {
  if (tokensOut >= virtualTokens) throw new Error("exceeds curve");
  const k = virtualSol * virtualTokens;
  const newTokens = virtualTokens - tokensOut;
  return k / newTokens - virtualSol + 1n; // +1 rounds in the curve's favour
}

★Two things that catch people out:★ the reserves are u64 so you need BigInt throughout, and the complete flag matters — once a curve completes, trading moves to an AMM pool and this math no longer applies.

Detecting Launches

The three approaches, with the trade-off each one makes:

Polling getProgramAccounts. Ask for all accounts under the program, diff against what you saw last time. Simple, and heavy enough that most providers rate-limit it. You will be seconds behind.

Log subscriptions. Subscribe to the program's logs over WebSocket and parse creation events as they stream. Much faster, and you own the parsing.

const sub = connection.onLogs(
  PUMP_PROGRAM,
  (logs) => {
    // Creation events appear in the log lines. Parse, then fetch
    // the account for authoritative state — logs alone are not enough.
    if (logs.logs.some((l) => l.includes("Instruction: Create"))) {
      handleNewMint(logs.signature);
    }
  },
  "processed", // "confirmed" costs you a slot or more of latency
);

Third-party feeds. Someone else runs the above and sells you the output. Fastest integration, and you inherit their latency plus a hop.

★Whichever you pick, detection is only half the race.★ Being first to know is worthless if your transaction lands three slots later than someone who knew second.

Where the Money Actually Moves

Here is the part that gets underweighted. Say you detect a launch and decide to buy. The sequence is:

detect → build instruction → sign → submit → land

Most tutorials cover the first three steps in detail and treat the last two as "call sendTransaction." But during a launch, ★the network is congested precisely because everyone else is trying the same thing★, and submission becomes the constraint.

Three things decide whether you get filled:

Priority fee derived from live conditions. A hardcoded value is either wasteful or useless, and during a launch it is usually useless.

import { ComputeBudgetProgram } from "@solana/web3.js";

// Fees are contested per account. Query with the accounts your
// transaction actually writes to, not globally.
const recent = await connection.getRecentPrioritizationFees({
  lockedWritableAccounts: [bondingCurvePda(mint), yourTokenAccount],
});
const fees = recent.map((r) => r.prioritizationFee).sort((a, b) => a - b);
const median = fees[Math.floor(fees.length / 2)] ?? 0;

instructions.unshift(
  ComputeBudgetProgram.setComputeUnitPrice({
    microLamports: Math.max(median * 3, 10_000), // launches are contested
  }),
  ComputeBudgetProgram.setComputeUnitLimit({ units: 120_000 }),
);

Continuous retry until the blockhash expires. One submission during a launch is a coin flip.

A submission path that does not get deprioritised. Validators accept forwarded transactions in proportion to the forwarding node's stake weight. During congestion, a low-stake path loses exactly when you need it not to.

Slippage on a Moving Curve

Bonding curve prices move with every buy, which means your quote is stale the moment you compute it. During an active launch it can move several percent between quote and inclusion.

Set slippage against the curve state you read, not against a fixed percentage of an already-stale price:

const curve = await readCurve(connection, mint);
const expectedCost = costToBuy(
  curve.virtualSolReserves,
  curve.virtualTokenReserves,
  tokensWanted,
);

// maxSolCost is what goes in the instruction. Too tight and you
// fail on a curve that moved; too loose and you overpay on a
// curve someone else pushed up first.
const maxSolCost = (expectedCost * 115n) / 100n;

★A failed transaction from tight slippage still costs the base fee.★ A filled transaction at a bad price costs more. Neither is free, so the tolerance is a real decision rather than a default to leave alone.

Graduation and What Changes

When a curve completes, the token migrates to an AMM pool. Everything about your integration changes at that moment:

Before graduation After
Price source Bonding curve account AMM pool reserves
Instruction pump.fun buy/sell Standard AMM swap
Slippage behaviour Moves with curve Moves with pool depth

★A bot that does not check the complete flag will keep sending curve instructions to a graduated token and get consistent failures.★ Check it before every trade, not once at startup.

What Landing Looks Like

Real transactions through our delivery nodes: median confirmation 336ms — under one slot.

During a launch that number stretches — most transactions are unaffected while a minority take noticeably longer. That minority is where submission path quality shows up, and it clusters exactly when launches happen.

Where BoltTx Fits

We handle the last step and nothing else. Not indexing, not parsed history, not launch feeds.

Submissions route through our own delivery nodes in four regions with stake-weighted routing and no public mempool exposure, so a transaction is not observable in transit before it lands. You sign locally — we never hold funds, never sign, and never modify transaction contents.

The tip travels inside the transaction, paid on chain from your own wallet. If the transaction reverts, the tip reverts with it, because that is how Solana handles atomic transactions. You pay only on transactions that reach the chain.

Get a free API key. No monthly fee:

// Pick the region closest to where your bot runs
const connection = new Connection("https://la.bolttx.io/?api-key=YOUR_KEY");

FAQ

Is there an official pump.fun API? No. There is no documented REST endpoint, published SDK, or support channel. What people call the pump.fun API is a mix of reading on-chain program accounts, subscribing to program logs, and third-party feeds built on top of those.

What is the pump.fun program ID? 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P on mainnet. You derive the bonding curve PDA from the seed bonding-curve plus the mint address under that program.

How do I read the pump.fun bonding curve? Fetch the bonding curve PDA with getAccountInfo and deserialize the account data. After an 8-byte discriminator you get five u64 values (virtual and real reserves, total supply) and a boolean marking whether the curve has completed.

How do I calculate the price of a pump.fun token? Use constant product against the virtual reserves: k = virtualSol * virtualTokens, then solve for the SOL cost of removing the tokens you want. Use BigInt throughout, since the reserves are u64 and JavaScript numbers lose precision.

How do I detect new pump.fun launches? Three options: poll getProgramAccounts and diff (simple, slow, rate-limited), subscribe to program logs over WebSocket and parse creation events (faster, more work), or consume a third-party feed (fastest to integrate, adds a hop).

Is there a pump.fun SDK? Nothing official. Several community libraries wrap the instruction building and account layouts. Read the source before depending on one, since the layouts change and an unmaintained wrapper fails silently.

Why do my pump.fun sniper transactions fail? Usually one of four: priority fee too low for launch congestion, blockhash expired between building and submitting, slippage tolerance too tight for a curve that moved, or a submission path that gets deprioritised under load.

What slippage should I set for pump.fun trades? Compute expected cost from the current curve state, then add tolerance. During an active launch the price moves between quote and inclusion, so a tight tolerance fails often. A failed transaction still costs the base fee, so the tolerance is a real trade-off.

How do I know when a pump.fun token has graduated? The complete boolean in the bonding curve account. Once it is true, trading has moved to an AMM pool and curve instructions will fail. Check it before every trade rather than once at startup.

Can I use a regular Solana RPC for a pump.fun bot? For reading state, yes. For submitting during launches, the constraint is not your RPC's read capacity but how your transaction is routed toward a block producer under congestion.

How fast do I need to be to snipe a pump.fun launch? Fast enough to land within a slot or two of detection. Detection speed matters less than most people assume, because being first to know does nothing if your transaction lands three slots behind someone else's.

What compute unit limit should a pump.fun buy use? Simulate during development to find your real consumption, then set the limit slightly above it. Leaving the default means being charged against a much higher figure, which wastes fee budget during exactly the moments fees are expensive.

Why does my bot work in testing but fail during real launches? Testing happens when the network is quiet and every submission path performs identically. Launches create congestion, and congestion is when priority fee, retry behaviour, and routing all start mattering at once.

Do I need a WebSocket connection for a pump.fun bot? For launch detection, it is much faster than polling. For submission, no — that is an HTTP call. Many bots use a WebSocket for detection and a separate delivery-focused endpoint for sends.

Is pump.fun sniping still profitable? Competition is heavy and margins depend on execution rather than strategy. The teams doing well treat submission as the core problem rather than an afterthought, because that is where the remaining edge is.

Back to all posts