DocsAPI

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.

Buys, sells and batches are real by default

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 with GET /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, 0x plus 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. Send amountSol or amountRaw, not both.
  • slippageBps — the most the price may move against you, 1–10000 basis points. Without it, the key's default slippage applies.
  • dryRun — true checks the trade without sending it. Default false.
  • chain — solana or 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. null on a dry run.
  • confirmed — true once the chain confirmed it. false when nothing was sent.
  • amountIn, expectedOut, minOut, landedOut — amounts in base units. minOut is the slippage floor. landedOut is what actually arrived, once known.
  • err — why the send failed, or null.

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 as walletIds.
    • { "type": "token_percentage", "percentage": 25 } — a share of each wallet's token balance.
  • intervalMs — [min, max] milliseconds to wait between wallets. max must be at least min. Default no wait.
  • slippageBps, poolAddress, dex, chain, dryRun — as for a single trade. dryRun defaults to false.

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 is So11111111111111111111111111111111111111112; wrapped-sol means wrapped SOL (WSOL).
  • amountRaw or "all": true — send one.
  • slippageBps — 1–500, default 100.
  • maxPriceImpactBps — 1–500, default 300.
  • minimumOutputRaw — refuse if less would arrive.
  • dryRun — default true here. Send false to 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 address 0x…dEaD.
  • POST /tokens/lock — locks tokens until a date. Solana only. Same body, plus unlockDays (1/24 to 3650) or unlockTimestamp (Unix seconds), and an optional name (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 from 1 to 100: 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.

Burning cannot be undone

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 carry unswept.
  • 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#

StatusCodeWhen
400validation_failedA field is missing, out of range or unknown. details names it.
403insufficient_scopeThe key lacks trade.
403over_trade_capA buy is over the key's max per buy.
403over_daily_capA buy would pass the key's daily cap.
403sandbox_keyA sandbox key sent a real trade.
403wallet_not_allowedThe wallet is not on the key's list. A percentage sell from a wallet that is not yours also gets this.
403forbiddenThe wallet is not yours.
403private_key_not_allowedA wallet-list key sent a private key.
422unprocessableNothing to sell, or no route.

See also#