Skip to main content
POST
Token launch (pumpfun / bonk / bags / meteora_dbc / meteora_cpamm)

Authorizations

apiKey
string
query
required

Body

application/json

Token launch. pumpfun, bonk and bags are implemented; meteora_dbc / meteora_cpamm return 501. Unknown keys are ignored silently, so check the exact casing of every field name — in particular jitoTipAmountSol and initialLiquiditySol end in Sol, not SOL.

bags behaves differently from the other two in ways you must plan for. pumpfun and bonk are built entirely on our side. A Bags launch cannot be: on the Meteora DBC initialize, the pool creator, the payer and the vanity …BAGS base mint are all signed by Bags, so the launch transaction comes from their API — already signed, and therefore unmodifiable.

The fee-share config is a reusable on-chain asset, not a step of the launch. Bags' launch build verifies the config exists on chain at request time, so a config created in the same request can never be referenced by it — bundling does not help. The flow is therefore:

  1. Provision — call without feeShareConfigKey (with your bagsFeeClaimers / bagsConfigType). The response is a stages entry with Bags' unsigned config-creation transactions plus config, mint and metadataUri. Sign and land the transactions, wait for confirmation. Land the stage promptly: the config transactions expire with their embedded blockhash (~60–90 s). A stage's transactions are the config creation, not the launch and not a Jito bundle — submit them individually, confirm, then do step 2; sending them as the launch bundle would spend the config rent and produce no token.

  2. Launch — call again with feeShareConfigKey=<config>, mintPubkey=<mint> and token.metadataUri=<metadataUri>, all three exactly as returned — that second call returns the full launch bundle without burning a second mint.

One config per LAUNCH — a config cannot be reused for a different mint. Bags' launch build accepts any on-chain config, but their claim attribution is per mint (measured 2026-07-31 with real launches on one config: the provisioned mint's creator roster was intact, a reused launch's roster came back empty and its mint never appeared in the fee-share admin list — its trading fees are unclaimable). This binding is invisible on chain, so the server asks Bags directly whether the mint you pass was provisioned for the config you pass, and rejects the launch if not (and rejects feeShareConfigKey without mintPubkey outright). Pass the config, mint and metadataUri exactly as the provisioning call returned them — a crossed or fresh mint is refused before anything is signed, so you cannot accidentally launch a token whose fees no one can claim.

The on-chain fees follow the config. The fee_claimer frozen in the on-chain PoolConfig receives the token's trading fees. You do not have to police this: because the server rejects any config not provisioned for your mint (above), the only config you can launch against is the one born from your own bagsFeeClaimers on step 1 — so the recipients are what you asked for. The launch response echoes feeClaimer for your records. Because there is no non-mutating way to prove a config pays a given claimer list, bagsFeeClaimers and bagsConfigType are rejected alongside feeShareConfigKey — the split and the template are already frozen in the config.

Further consequences, all observable in the response:

  • the first transaction of the launch bundle is Bags-signed (the launch itself); do not re-serialise or re-order it;

  • 5 wallets fit the bundle (1 launch + 4 buys), like bonk;

  • mintKey is rejected (the mint is theirs); mintPubkey is only accepted together with feeShareConfigKey, to name the mint a provisioning call reserved;

  • exactly one transfer of ours can ride on the launch transaction, so asking for both a feeWallet/feeBps and a tipWallet/tipLamports with only one wallet is a 400 rather than a silently dropped leg;

  • jitoTipAmountSol needs at least one extra wallet to attach to; on a single-wallet launch it is a 400 (send the tip as its own bundle transaction instead);

  • a tip can only ride on a buy transaction of ours (the launch is sealed). With 1–4 wallets the bundle has a free slot: send jitoTipAmountSol: 0 and append your own tip transaction. With 5 wallets all five slots are full — pass jitoTipAmountSol and we embed it on the last buy;

  • the curve and the fee split come from a Bags fee template, picked whole rather than tuned field by field: supply, totalBaseSell, fundRaisingSol, fundRaisingQuote, decimals, vesting and configAddress are rejected, not ignored — accepting them would let you believe you had shaped a curve you did not touch;

  • the response carries config (the Meteora DBC PoolConfig) and feeClaimer alongside mint and pool. You need config to build any later swap of your own, and it is not derivable from the mint;

  • token.description is required (Bags rejects an empty one), whereas it is optional on pumpfun and bonk — except on the follow-up call with mintPubkey, where the token info was already reserved;

  • every wallet pays its own buy and the bundle is atomic: balances are pre-checked on our side (payer and co-buyers) and an underfunded wallet is a 400 naming it, instead of a silent on-chain revert.

platform
enum<string>
required
Available options:
pumpfun,
bonk,
bags,
meteora_dbc,
meteora_cpamm
wallets
object[]
required
token
object
required
pumpType
boolean
cashBack
boolean
quoteMint
string
default:SOL

Quote asset for the launch. wallets[].amount is always denominated in it. The accepted values and the failure mode differ per platform — do not generalise from one to the other.

pumpfun: "SOL"/"wSOL"/the wSOL mint (or omitted), or USDC — either the string "USDC" or the mint EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v. Anything else is a 400 — never a fallback (since 2026-07-31; before that an unrecognized value silently launched in SOL, so a mistyped or wrong-cased USDC gave you the wrong asset with no error). The amount and any feeBps are denominated and charged in the chosen asset.

bonk: "SOL"/So111…112 (default) or "USD1"/USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB. Anything else is a 400 — never a fallback, and the server additionally reads the launchpad config's own quote_mint back and refuses if it disagrees. USDC is not accepted here: LaunchLab has no USDC global_config.

bags: "SOL"/So111…112 or omitted. Anything else is a 400 — never a fallback. Bags' configs are SOL-quoted and their API takes the first buy in lamports.

mintKey
string

bs58-encoded 64-byte mint secret key. The create transaction is signed locally with it, so the returned bundle needs only your wallet signatures. Wins over mintPubkey if both are sent. Accepted on both platforms.

Omitting it differs per platform: on pumpfun the server reaches for a …pump vanity mint; on bonk it just generates a keypair in-process — the official …bonk suffix only exists behind letsbonk's own endpoint and is not available here.

mintPubkey
string

bs58-encoded 32-byte mint address. On pumpfun: a Pump.fun vanity mint you already reserved — the mint signature slot is filled via the Pump frontend API, and the wallet legs stay unsigned for you to complete. Ignored when mintKey is also present.

On bags (since 2026-07-31): the …BAGS mint a provisioning call reserved, accepted only together with feeShareConfigKey and token.metadataUri — the follow-up launch then reuses it instead of burning a second mint. Without the key it is a 400.

On bonk this is a 400, not a silent downgrade: the base mint must sign initialize and LaunchLab has no equivalent of pump's sign-create-tx, so an address without its secret is unsignable by anyone. Send mintKey instead.

slippageBps
integer

Buy slippage tolerance, 0–10000. Defaults to 9900 (99%) on pumpfun, 500 (5%) on bonk, and 500 (5%) on bags — on both of the latter the later buyers' prices are modelled exactly against the curve, so a 99% floor would be protection in name only.

bonkType
enum<string>
default:standard

bonk only. Selects the LaunchLab platform_config, which decides the swap fee and whether the token creator earns anything. letsbonk's own three modes, with their own names accepted as aliases:

| value | address | swap fee | creator fee | |---|---|---|---| | standard · letsbonk · memes · platformId | FfYek5vE… | 1.25% | 0 | | bonkers · tech · techPlatformId | 82NMHVCK… | 1.00% | 0.05% | | balanced · balancedPlatformId | BuM6KDpW… | 1.25% | 0 |

🔴 Changed 2026-07-30. bonkers used to resolve to BuM6KDpW…, which is letsbonk's Balanced mode — 1.25% and no creator fee, the same economics as standard, and the opposite of what their UI promises for the mode it labels "Bonkers" ("This mode has creator fees"). It now resolves to 82NMHVCK…. If you were sending bonkers and want the old target, send balanced.

Any other value is rejected. For a config none of these names covers, pass platformConfig.

Available options:
standard,
letsbonk,
memes,
platformId,
bonkers,
tech,
techPlatformId,
balanced,
balancedPlatformId
platformConfig
string

bonk only. Explicit LaunchLab platform_config address — there are ~2000 on chain and 30 alone are named letsbonk.fun, so the named modes above cannot cover them. Also accepted as platformId.

Mutually exclusive with bonkType: sending both is a 400, because two sources of truth for the same account is how a caller ends up on a config they did not pick.

Verified on chain before use — the account must exist, be owned by the LaunchLab program and carry the PlatformConfig discriminator. A wrong value is a 400, never a silent fall back to the default.

Since 2026-07-31 the config's on-chain fee rates (fee_rate, creator_fee_rate, plus the global trade_fee_rate) also price the buys: every minimumAmountOut floor is computed with the real total fee of the config you picked, not LetsBonk's 1.5%.

💰 Funding floor (bonk, all configs): a LaunchLab create debits wallets[0] 24_532_480 lamports (0.02453248 SOL) of rent and Metaplex fees — mint 1_461_600 + pool 3_876_720 + two vaults 2_039_280 each + metadata 15_115_600 (of which 10_000_000 is the Metaplex fee). Measured on three mainnet creates, reconciled to the lamport. On top of that the server's pre-check counts, because the runtime deducts or debits them too: the create transaction's own fees (10_000 base + the priority fee on the requested compute units — 20_000 at the defaults, scaling with computeUnitPrice); and, when the first buy is fused in: 2_039_280 for the creator's token ATA, the buy amount itself, another 2_039_280 for the transient wSOL account (recovered at close, but payable mid-transaction), the feeBps cut and any tipLamports. The rejection names the exact lamport total instead of letting the bundle die on chain after the vanity mint and the IPFS pin are already spent.

supply

bonk only. Total token supply in base units. Defaults to the LetsBonk shape (1e15). Must be ≥ the launchpad's on-chain min_supply_a.

⚠️ Send this as a string from JavaScript. It is a u64, and the letsbonk UI offers supplies up to 1e18 base units — well past Number.MAX_SAFE_INTEGER (9.007e15), so a numeric literal like 123456789123456789 is already rounded to …780 before your request is sent. A decimal string carries all 64 bits, and letsbonk's own frontend sends it that way. Numbers are still accepted (added 2026-07-30; before that a string was a 422).

totalBaseSell
integer<uint64>

bonk only. Tokens sold on the curve before graduation; the remainder seeds migration liquidity. Defaults to 793_100_000_000_000 (79.31% of the default supply). Must satisfy the launchpad's min_sell_rate_a and min_migrate_rate_a.

fundRaisingQuote
number

bonk only. Amount raised on the curve before graduation, in whole quote tokens — 85 means 85 SOL on a SOL-quoted launch, 5000 means 5000 USD1 on a USD1-quoted one. Must be ≥ that config's on-chain min_fund_raising_b (24 SOL / 5 000 USD1 at the time of writing — read live, so treat these as indicative). Defaults to 85 SOL on a SOL launch; required on a USD1 launch.

fundRaisingSol
number

bonk only. SOL-denominated alias for fundRaisingQuote, kept for compatibility. fundRaisingQuote wins when both are sent, and sending this on a non-SOL launch is rejected rather than reinterpreted.

decimals
integer

bonk only. Base mint decimals. Defaults to 6.

vesting
object

bonk only. LaunchLab VestingParams — a creator lock carved out of the supply. Omitted ⇒ all zeroes (no lock), which is what every sampled mainnet LetsBonk create emits. totalLockedAmount is checked against the config's max_lock_rate (80% of supply today) before the transaction is built; the program enforces the rest.

configAddress
string

meteora_dbc / meteora_cpamm only, both of which return 501 today.

Rejected on pumpfun, bonk and bags (since 2026-07-30) rather than ignored: it used to be accepted and dropped there — including values that are not even valid base58 — so a caller could not tell "ignored" from "accepted" without deserialising the returned transaction and reading which config it references. On bonk, use bonkType or platformConfig.

initialLiquiditySol
number

Note the casing: ...Sol, not ...SOL.

initialTokenPercent
number
tipWallet
string

Custom tip recipient wallet (defaults to the Raze relay tip wallet).

tipLamports
integer

Flat tip in lamports attached once to the create tx (payer pays). feeTipLamports is the legacy alias.

feeTipLamports
integer

Legacy alias for tipLamports.

feeWallet
string

Custom fee recipient wallet. Only charged together with feeBps.

feeBps
integer

Percentage fee in basis points of each buyer's raw quote amount, paid by that buyer alongside its buy. pumpfun and bonk differ here: on bonk the creator's buy fused into the create is charged like any other buyer; on pumpfun the fee rides the buy transactions only, so wallets[0]'s fused buy is not charged. On a USD1-quoted bonk launch the fee is an SPL transfer in USD1 (the fee wallet's associated account is created if missing, paid for by the buyer); otherwise it is a lamport transfer. This is our fee leg, unrelated to LaunchLab's native share_fee_rate, which we always send as 0.

On a USDC-quoted pumpfun launch the fee is an SPL transfer in USDC (the fee wallet's associated account is created if missing, paid for by the buyer), exactly as on USD1-quoted bonk — the fee is always charged in the quote asset, never mis-scaled.

bagsConfigType
string

bags only. The fee template (Bags' MeteoraConfigType id). It decides the swap fee, the pre- vs post-migration split, how much compounds back into liquidity and, in some templates, how much of the supply is locked.

Omitted ⇒ ba28db46-ea6f-4452-8218-5587f6aca0a1 (DEFAULT_96_LOCKED), the value Bags' own SDK defaults to. We always send it downstream rather than leaving it out, so the template can never change under a caller because Bags changed a server-side default. Choosing one here overrides our pin, not theirs.

Rejected on pumpfun and bonk, which have no fee-share config — and rejected alongside feeShareConfigKey, where the template is already frozen in the on-chain config.

Example:

"ba28db46-ea6f-4452-8218-5587f6aca0a1"

bagsFeeClaimers
object[]

bags only. Who earns the coin's trading fees besides the creator.

List only the other recipientswallets[0] keeps the remainder, so the numbers you send are the ones you give away and you never restate your own share. Giving away all 10000 is allowed and simply leaves the creator out of the split.

Recipients are named by handle, not address: Bags resolves (provider, username) to that person's embedded wallet, so a collaborator can be paid before they have ever connected one. A handle that does not resolve is a 400 — never a silent fall back to the creator, which would quietly redirect someone else's fees.

Rejected on pumpfun and bonk — and rejected alongside feeShareConfigKey, because the split is already frozen in the on-chain config and there is no non-mutating way to prove it matches this list (check the response's feeClaimer instead). Errors, all 400 and all before any transaction is built: a total above 10000; more than 15 recipients once the creator's own slot is counted (past that Bags needs address lookup tables created in a separate transaction, which this endpoint does not do — refused rather than truncated); a repeated handle; a 0-bps entry; an unknown provider.

Maximum array length: 15
Example:
feeShareConfigKey
string

bags only. The Meteora DBC PoolConfig a provisioning call created for this launch, already landed on chain — the launch then completes in one call. Always sent together with mintPubkey and token.metadataUri from the same provisioning response: one config per LAUNCH. Without mintPubkey it is rejected — Bags' claim attribution is per mint, and a config reused for a different mint makes that token's trading fees unclaimable (measured 2026-07-31).

This input moves money: the token's trading fees go to the fee_claimer frozen inside the config. The server validates the account (exists, owned by the DBC program, carries the PoolConfig discriminator, SOL-quoted) and returns the config's feeClaimer so you can verify the destination before signing — but it cannot prove the config pays any particular claimer list, which is why bagsFeeClaimers / bagsConfigType are rejected alongside it.

Not configAddress (a Meteora field of ours, still rejected on bags): this key names a config of Bags'.

jitoTipAmountSol
number
default:0

Jito tip in SOL embedded by the server on the LAST buy transaction of the bundle, on both pumpfun and bonk. Omitting it means no tip — attach your own, which is what most integrators do. Note the exact casing: ...Sol, not ...SOL — an unrecognised key is silently ignored, which also lands you on no tip.

computeUnitPrice
integer
default:50000

Priority fee in micro-lamports per compute unit, emitted as a SetComputeUnitPrice instruction. Defaults to 50000 on both platforms. There is no priorityFeeSol / priorityFee field — this is the only priority-fee knob, and an unrecognised key is dropped silently.

The compute budget costs 52 bytes (a program key plus the two instructions), and the widest bonk shapes land within that of the 1232-byte wire limit. Rather than reject a launch that would otherwise fit, a transaction gives things up in a fixed order, recoverable losses first:

  1. a rent-reclaim instruction — on a SOL launch the trailing close_account, which leaves ~0.00204 SOL of rent (not funds) in your own wSOL account for you to close whenever you like; on a USD1 launch an idempotent account create that was a no-op anyway. 2. the default compute price. 3. the default compute limit, i.e. the whole budget.

Stranded rent is undone with one instruction at any time; a priority fee that was never attached cannot be recovered — hence that order. A bonk create with a long name, a USD1 fee leg and a tip measures 1196 bytes with the whole budget dropped (it needed all three rungs; keeping just the limit would have been 1236, four bytes over). It lands, with no priority fee, and the server logs the rung it settled on.

Nothing you asked for is ever on that list — not the fee leg, not the tip, not the swap, and not a computeUnitPrice / computeUnitLimit you sent explicitly. If an explicit value cannot fit, the request fails and says so rather than returning a transaction without the priority fee you were told you would pay. Want a fee on a shape that tight? Shorten token.name / token.symbol / the metadata URI, or drop a wallet — the error names those options.

computeUnitLimit
integer

Compute-unit cap. Sent explicitly, it applies to every transaction in the launch. Omitted, each transaction gets a per-shape default:

pumpfun — 400000 on the create / deploy-buy, 600000 on the buys.

bonk400000 on the create (+ fused first buy), 120000 on each subsequent buy. These are ≈1.8× the measured worst case (219000 CU for a create with a fused buy; ~70000 for a buy), not copied from pumpfun: Solana charges the priority fee on the units requested, not consumed, so an inflated limit costs real money.

encoding
enum<string>
Available options:
base64,
base58
simulate
boolean

Response

200 - application/json

Response envelope. For pumpfun, transactions holds the partially-signed bundle legs (and stages when a lookup table has to be created first). Unimplemented platforms return success: false.

Shared envelope for every /utils/sol/* write endpoint. Optional fields are omitted from the JSON when unset.

success
boolean
required
transactions
string[]

Serialized partially-signed transactions in submission order.

batches
object[]

For batch endpoints (transfer, burn): packing metadata. batches[i] describes transactions[i].

mint
string

Set by /utils/sol/launch — the mint of the launched token.

platform
string

Set by /utils/sol/launch and /utils/sol/fees/claim.

stages
object[]

Set by /utils/sol/launch when the launch needs preparatory transactions (today: creating an address lookup table for a many-wallet bundle). Submit each stage, in order, as its own bundle before transactions; a stage with waitForActivation: true must also be given a slot to activate (~10 s for a new lookup table) or the main bundle cannot resolve its addresses.

lookupTableAddress
string

Set by /utils/sol/launch when a lookup table was created for the bundle — the address the stage transaction provisions.

pool
string

Venue pool/curve address, returned by launches that derive one up front (bonk, bags). Absent on pumpfun, whose bonding curve is derivable from the mint alone.

config
string

Venue config account, when the venue keys its curve on one. Present on bags: the Meteora DBC PoolConfig the launch runs against. You need it to build any later swap of your own, it is not derivable from the mint — and on a provisioning response it is the feeShareConfigKey to pass on the follow-up call, together with the returned mint and metadataUri (the config belongs to that mint only — see feeShareConfigKey).

feeClaimer
string

bags launches: where the config sends the token's trading fees — the fee_claimer frozen in the on-chain PoolConfig. Echoed for your records; you do not have to police it, since the server only lets you launch against the config provisioned for your own mint (see feeShareConfigKey).

metadataUri
string

bags provisioning responses: the reserved mint's metadata URI. Pass it back as token.metadataUri (with mintPubkey = the returned mint) on the follow-up launch call.

isAdvancedMode
boolean

Set by /utils/sol/launch — true when the wallet count pushed the launch onto the multi-stage / lookup-table path.

status
object

Set by /utils/sol/fees/config for action=status reads.

simulations
object[]

Set when the request had simulate: true. One entry per built tx, in the same order as transactions. Each entry is the RPC simulateTransaction value object (logs / unitsConsumed / err).

error
string