Buy, sell & batches
Buy and sell from one wallet or many, convert, burn and lock tokens, and claim creator fees from code.
These calls trade from your wallets. They need a key with the trade scope, except the read-only checks noted below.
POST /buy, POST /sell and POST /trade/batch send real transactions unless you add "dryRun": true. Try every new call as a dry run first.
Pick the wallet#
Every trade names one wallet, in one of two ways:
walletId— the id of a wallet in your account, like"812". List them withGET /wallets.privateKey— a wallet's private key. The API adds this wallet to your account and trades from it. A key limited to a wallet list cannot send private keys.
Send exactly one of the two.
Buy#
POST /buy spends the chain's coin to buy a token.
curl -s -X POST https://api.vortexdeployer.com/api/v1/buy \
-H "Authorization: Bearer vd_…" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: buy-7xKX-0001" \
-d '{ "mint": "7xKX…pump", "walletId": "812", "amountSol": 0.1, "dryRun": true }'mint— the token's mint address. Base58 on Solana,0xplus 40 hex characters on an EVM chain.amountSol— how much to spend, as a number. It is SOL on Solana and ETH on an EVM chain. Up to 1,000,000.amountRaw— the same amount as a string in base units. SendamountSoloramountRaw, not both.slippageBps— the most the price may move against you, 1–10000 basis points. Without it, the key's default slippage applies.dryRun—truechecks the trade without sending it. Defaultfalse.chain—solanaor an enabled EVM chain. Leave it out and the API picks it from the address.poolAddress,dex— trade through one pool. Leave them out and the API picks the route.computeUnitLimit(1–1,400,000),computeUnitPriceMicroLamports(0–100,000,000) — Solana fee settings. Leave them out for the defaults.
Unknown fields are refused with 400 validation_failed.
Sell#
POST /sell takes the same body, with one of these amounts:
percentage— the share of the wallet's balance to sell, above 0 and up to 100.amountRaw— the token amount as a string in base units.
{ "mint": "7xKX…pump", "walletId": "812", "percentage": 50 }A wallet that holds none of the token gets 422. So does a percentage that rounds down to zero tokens.
What a trade returns#
{
"signature": "3BNE…L98",
"confirmed": true,
"dryRun": false,
"walletId": "812",
"mint": "7xKX…pump",
"side": "buy",
"poolAddress": "B8Ge…oH7V",
"dex": "pump_swap",
"amountIn": "100000000",
"expectedOut": "3512000000",
"minOut": "3336400000",
"landedOut": "3509871234",
"err": null
}signature— the transaction signature, once sent.nullon a dry run.confirmed—trueonce the chain confirmed it.falsewhen nothing was sent.amountIn,expectedOut,minOut,landedOut— amounts in base units.minOutis the slippage floor.landedOutis what actually arrived, once known.err— why the send failed, ornull.
Batch: many wallets at once#
POST /trade/batch buys or sells one token from many wallets in one call.
{
"mint": "7xKX…pump",
"side": "buy",
"walletIds": ["812", "813", "814"],
"amountMode": { "type": "uniform", "amountRaw": "50000000" },
"intervalMs": [500, 2000],
"dryRun": true
}walletIds— at least one, no repeats.amountMode— how much each wallet trades, in base units. A buy spends the chain's coin; a sell spends the token.{ "type": "uniform", "amountRaw": "…" }— the same amount for every wallet.{ "type": "individual", "amountsRaw": ["…", "…"] }— one amount per wallet, in the same order aswalletIds.{ "type": "token_percentage", "percentage": 25 }— a share of each wallet's token balance.
intervalMs—[min, max]milliseconds to wait between wallets.maxmust be at leastmin. Default no wait.slippageBps,poolAddress,dex,chain,dryRun— as for a single trade.dryRundefaults tofalse.
The answer lists one result per wallet:
{ "results": [ { "walletId": "812", "signature": "…", "confirmed": true, "err": null, "expectedOut": "…", "landedOut": "…" } ] }Slow batches become a task#
If the number of wallets times the max wait is over 60 seconds, the API does not wait. It starts a task of type batch, labelled "API batch", and answers 202:
{ "taskId": "4321", "status": "started", "task": { "id": "4321", "type": "batch", "label": "API batch" } }Follow it with GET /tasks/4321/executions or the live tasks topic. See Tasks API.
A slow buy batch needs real amounts (uniform or individual). A key with a max per buy or a daily cap must also send real amounts for any buy batch.
Convert (Solana)#
Convert swaps one asset in a wallet for another, like a leftover token into SOL. It works on Solana wallets only.
POST /convert/assets(read) —{ "walletIds": [...] }lists what the wallets hold and where it can go.POST /convert/quote(read) — prices a conversion without sending it.POST /convert(trade) — converts.
The quote and convert body:
walletId,inputMint,outputMint— the wallet and the two assets. They must differ. Native SOL isSo11111111111111111111111111111111111111112;wrapped-solmeans wrapped SOL (WSOL).amountRawor"all": true— send one.slippageBps— 1–500, default 100.maxPriceImpactBps— 1–500, default 300.minimumOutputRaw— refuse if less would arrive.dryRun— defaulttruehere. Sendfalseto convert for real.
A pair with no route gets 422.
Burn and lock#
POST /tokens/burn— a burn destroys tokens for good. Body:walletId,mint,amount,amountType,chain,dryRun. On an EVM chain, the tokens go to the dead address0x…dEaD.POST /tokens/lock— locks tokens until a date. Solana only. Same body, plusunlockDays(1/24 to 3650) orunlockTimestamp(Unix seconds), and an optionalname(up to 64 characters).
Both default to dryRun: true.
amount is a string. What it means depends on amountType:
tokens— a whole number of base units, like"3500000000"for 3.5 tokens with 9 decimals. It may not be more than the wallet holds. Do not send a decimal like"1.5": the first check lets it through, but the burn or lock then fails.percentage— a whole number from1to100: that share of what the wallet holds."50"is half.
A wrong amount does not get a 400. The answer is 200 with "ok": false and the reason in error, like amount must be a base-unit integer string. Always check ok. A dry run checks the amount too, so try it first.
{ "ok": true, "signature": "…", "burnedAmount": "3500000000", "walletAddress": "…", "mint": "…" }A lock answers with txId, metadataId, lockedAmount and unlockTimestamp. The lock service takes its fee in the token, on top of the locked amount. If the wallet cannot cover both, the lock is made smaller, so lockedAmount can be less than you asked.
A burn with dryRun: false removes the tokens forever. Locked tokens stay locked until the unlock time.
Creator fees#
Creator fees are what a launchpad pays the token's creator from trading.
GET /tokens/creator-fees?mint=…&chain=…(read) — what is waiting to be claimed. Some entries carryunswept.POST /tokens/creator-fees/claim—{ "mint": "…", "chain": "solana" }. It is real by default (dryRun: false).
Only your own launches with a creator wallet you keep in the app can claim. One transaction claims every place that holds at least 0.001 SOL for you. A place claimed in the last minute is skipped. On Robinhood Chain, and for pump.fun tokens with Holder Rewards, there is nothing to claim. The fees move by themselves.
If the creator wallet cannot pay what the claim costs, the claim is not sent. The answer has "ok": false and an error saying why.
Refusals#
| Status | Code | When |
|---|---|---|
400 | validation_failed | A field is missing, out of range or unknown. details names it. |
403 | insufficient_scope | The key lacks trade. |
403 | over_trade_cap | A buy is over the key's max per buy. |
403 | over_daily_cap | A buy would pass the key's daily cap. |
403 | sandbox_key | A sandbox key sent a real trade. |
403 | wallet_not_allowed | The wallet is not on the key's list. A percentage sell from a wallet that is not yours also gets this. |
403 | forbidden | The wallet is not yours. |
403 | private_key_not_allowed | A wallet-list key sent a private key. |
422 | unprocessable | Nothing to sell, or no route. |