Launch a token
Launch from code — the token, its image, the creator, bundled buys and launch tasks.
POST /launch is the create-token flow. It needs the launch scope. The token becomes a project in your account, with its tasks, exactly like a launch from the app.
A launch simulates unless you send "dryRun": false. Simulate first; the response shows what would happen without sending anything.
Body#
{
"launchpad": "pump",
"name": "Vortex Cat",
"symbol": "VCAT",
"description": "gm",
"twitter": "https://x.com/…",
"imageUrl": "https://example.com/cat.png",
"creatorWalletId": "812",
"devBuySol": 0.5,
"buys": [
{ "walletId": "813", "amountSol": 0.3 },
{ "privateKey": "…", "amountSol": 0.2 }
],
"dryRun": false
}| Field | |
|---|---|
launchpad | Defaults to pump. The same launchpads as the create modal (Chains & launchpads). Ask GET /launchpads for the list |
quoteToken | What the curve is priced in: sol (default), usdc, usd1, eth or stock. Each launchpad accepts its own set — see Which quotes can I launch with? |
pairToken | The mint or contract of the stock or pair token, when the quote needs one (every StonkFun launch, a pump.fun stock quote, an optional pons pair token) |
name, symbol | 1–32 and 1–10 characters |
description, twitter, telegram, website | Optional |
imageUrl or imageBase64 | Exactly one. PNG, JPEG, GIF or WebP, up to 10 MB. With imageBase64, also send imageContentType |
creatorWalletId or creatorPrivateKey | Exactly one: the wallet that creates the token |
devBuySol | The creator's own first buy |
buys | Solana only, up to 24. Each is walletId or privateKey, plus amountSol. They ride the launch as a Bundle |
tasks | Up to 20 launch tasks written inline, nothing to pre-create. See Launch tasks |
launches | 1–10: mint the same token several times in a row |
launchAt | Schedule the launch for later. The response is 202 with scheduled: true |
dryRun | true simulates, false sends. Default true |
Private keys become wallets in your account, the same as importing them on the Wallets page.
Launch tasks#
tasks is step 3 of the create wizard, in JSON: the tasks that should fire the moment the token exists, written on the launch itself. You don't create them first on the Tasks API; the launch creates them for its mint. Each task is:
| Field | |
|---|---|
type | The engine: bundle, sniper, buy, volume, antisniper, holderboost, handswitcher, fakevolume, protrader_boost, limit_order, ladder, mirror, dca or trailing_stop |
walletIds | The wallets it trades with, yours (and on the key's list, if it has one). The creator wallet can't be a bundle buyer |
config | The engine's settings, the same keys as a POST /tasks body (Tasks API and each engine's page). No mint and no chain: both are the launch's |
label | Optional |
autostart | Default true: start the instant the mint lands. false leaves the task idle on the new project |
{
"launchpad": "pump",
"name": "Vortex Cat",
"symbol": "VCAT",
"imageUrl": "https://example.com/cat.png",
"creatorWalletId": "812",
"devBuySol": 0.5,
"buys": [{ "walletId": "813", "amountSol": 0.3 }],
"tasks": [
{ "type": "volume", "walletIds": ["814", "815"], "config": { "minBuySol": 0.02, "maxBuySol": 0.05, "minDelayMs": 2000, "maxDelayMs": 8000 } },
{ "type": "antisniper", "walletIds": ["813", "814", "815"], "config": { "thresholdPercent": 5, "action": "sell_all" } },
{ "type": "dca", "walletIds": ["816"], "autostart": false, "label": "later", "config": { "side": "buy", "everyMs": 60000, "sizeUnit": "native", "sizeValue": 0.01, "maxFires": 10 } }
],
"dryRun": false
}buysis the short form of onebundletask; you can send both.- Settings are checked at the door with the engine's own rules. A wrong value refuses the whole launch as
400 validation_failed, namingtasks[i].config, before anything is pinned or minted. - The tasks follow the launch: a sent launch creates them on the new project and starts the
autostartones; the response lists them intaskswith theirtaskId,started, or anerror. Engines with no simulation of their own (bundle,volume,antisniper, the order tasks) can't ride a simulated launch, so simulate with the other tasks and send with all of them. - A task's
dryRunsetting is ignored: the launch'sdryRundecides for every task on it.
POST /launch/affordability takes the same tasks shape, so you can price the plan before you send.
Which quotes can I launch with?#
Two read calls answer it, from the same rules and lists the create modal uses:
| Call | Returns |
|---|---|
GET /launchpads | Every launchpad with its chain, the quoteToken values it accepts and, per quote, whether a pairToken is needed and which dev-buy field applies |
GET /launchpads/:launchpad/quotes | What a launch on that launchpad can be quoted in right now, each entry with the exact quoteToken and pairToken to send |
GET /launchpads:
{
"launchpads": [
{
"launchpad": "pump",
"name": "Pump.fun",
"chain": "solana",
"quoteTokens": ["sol", "usdc", "stock"],
"quotes": [
{ "quoteToken": "sol", "symbol": "SOL", "decimals": 9, "address": null, "pairToken": "none", "devBuyField": "devBuySol" },
{ "quoteToken": "usdc", "symbol": "USDC", "decimals": 6, "address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", "pairToken": "none", "devBuyField": "devBuyQuote" },
{ "quoteToken": "stock", "symbol": "STOCK", "decimals": null, "address": null, "pairToken": "required", "devBuyField": "devBuySol" }
],
"liveQuoteList": true
}
]
}GET /launchpads/stonkfun/quotes — the tokenized stocks StonkFun launches in today. Copy quoteToken and pairToken straight into the launch body:
{
"launchpad": "stonkfun",
"chain": "solana",
"quotes": [
{
"quoteToken": "stock",
"pairToken": "Xsc9qvGR1efVDFGLrVsmkzv3qi45LTBjeUKSPmx9qEh",
"symbol": "TSLAx",
"name": "Tesla xStock",
"decimals": 8,
"address": "Xsc9qvGR1efVDFGLrVsmkzv3qi45LTBjeUKSPmx9qEh",
"kind": "stock",
"devBuyField": "devBuySol",
"approved": true,
"category": "Technology",
"logoUrl": "https://…"
}
]
}pumplists SOL, USDC and the stocks pump.fun's on-chain whitelist allows.stonkfunlists only stocks.raydium_launchlab,bonkandbonkerslist SOL and USD1.meteora_dbclists SOL.ponslists ETH plus the approved pair tokens (USDG, tokenized stocks) launches on Robinhood Chain have used; any other approved contract can still be sent aspairToken.devBuyFieldtells you where the creator's first buy goes:devBuySolis spent in SOL and swapped into the quote when needed,devBuyQuoteis spent in the quote the creator holds,devBuyEthon pons.- A stock quote is a live list: an entry can disappear when the venue stops listing it. The launch checks the pair again when it runs. When the venue's list is unreachable the answer is
503withcode: "service_unavailable"; retry. - An unknown launchpad is
404withcode: "not_found".
Response#
A sent launch returns the mint, the on-chain signature, the hosted metadata uri and imageUri, the new projectId, and the tasks it created:
{
"mint": "J11LopwNEF3wkMQGskM3jVmEMmncqdkadQ1b6PuXpump",
"creator": "6729VKWPgq1qTaxkv2n1SVPzDc1A2tajiNTvS3uUCE88",
"launchpad": "pump",
"quoteToken": "sol",
"pool": null,
"dryRun": false,
"signature": "3BNESKPXnqoAfSpgSrjCsz9CnWNCTRiXzHQYuR3jLgqx8KQSJgvVLrdu7WRvjZDpFYjGDtZKnhQviRj7MngM5L98",
"confirmed": true,
"err": null,
"devBuyTokens": null,
"projectId": "1021",
"uri": "https://api.vortexdeployer.com/metadata/….json",
"imageUri": "https://api.vortexdeployer.com/image/….png",
"tasks": []
}A simulation (dryRun: true) returns the same shape with confirmed: false, signature: null, and a simulation object instead of projectId/imageUri:
{
"mint": "J11LopwN…pump",
"creator": "6729…CE88",
"launchpad": "pump",
"quoteToken": "sol",
"pool": null,
"dryRun": true,
"signature": null,
"confirmed": false,
"err": null,
"devBuyTokens": null,
"simulation": { "err": null, "unitsConsumed": 100811, "logsTail": ["…"] },
"uri": "https://api.vortexdeployer.com/metadata/….json"
}With launches over 1, a batch report lists every mint and where the run stopped.
Before you launch: the helpers#
The create modal's checks are routes too. All are read except the upload, which is launch.
| Method & path | Does |
|---|---|
GET /launch/readiness | { "killSwitch", "lut": { "configured", "address", "live" }, "selfRugThresholdPercent" } — killSwitch: true means real sends are off platform-wide |
GET /launch/mint-address?launchpad=pump | The mint address the next launch on that launchpad will use (from the keypair pool), so you can pre-announce it |
POST /launch/clone | { "chain", "address" } of a token that exists: its name, symbol, description, socials, imageUrl, the image as base64 and warnings — the app's Vamp button, ready to paste into a launch body |
POST /launch/affordability | How many of the launches the creator and buyers can pay for from live balances: { "creatorWalletId", "launchpad", "quoteToken", "devBuySol", "launches", "tasks" } → { "requested", "affordable", "stop", "creatorPerLaunch", "buyers" } |
POST /launch/supply-preview | What each bundled buy lands on a fresh curve: { "launchpad", "quoteToken", "wallets": [ { "walletId", "mode", "sol" } ] } → per wallet the coin it spends and its % of supply |
POST /launch/metadata | Host a token's metadata JSON and image ahead of time: the launch body's name, symbol, description, socials and image → { "uri", "imageUri" } |
GET /launch/pons/launch-terms?chain=… · GET /launch/otcdesks/rewards | The venue's current launch terms (pons fees, pair tokens and configs; OTC Desks holder-reward terms) |
Supply plans#
A supply plan is a saved bundle layout in % of supply per wallet slot. GET /supply-plans lists yours (paged), POST /supply-plans saves one (trade), DELETE /supply-plans/:id removes it.
{
"name": "12 wallets, 18%",
"slots": [ { "targetPercent": 1.5, "walletId": "812" }, { "targetPercent": 1.5, "role": "trading" } ],
"maxTotalPercent": 18,
"maxWalletPercent": 2
}A slot pins a walletId or names the role a wallet must carry; an open slot takes the next wallet you select when the plan is mounted. POST /supply-plans/:id/mount resolves the plan against wallets and a curve: { "walletIds": [ … ], "launchpad": "pump", "quoteToken": "sol" } for a fresh curve, or mint for a token already trading, and answers per row the wallet, its slot, the coin it must spend and any shortfall.
Refusals#
| Status | Code | When |
|---|---|---|
400 | validation_failed | Missing or double image or creator, a field out of range, or a launch task's config the engine refuses. details names it |
400 | bad_request | Unknown launchpad, buys on an EVM launchpad, a bundle (or buys) on a simulated launch, or an image that isn't a real picture |
403 | key_restricted | A restricted key sending dryRun: false |
403 | private_key_not_allowed | A wallet-list key using a private key |
403 | wallet_not_allowed | A wallet (the creator's, a buyer's or a task's) that isn't yours, or isn't on the key's list |
A restricted key (caps, wallet list or sandbox) can only simulate launches. See API overview & keys.
See also#
- Create a project in the app
- Create, edit and delete a project: a draft project before the launch, wallets in it, close-out after
- Tasks API