Tasks API
Create, start, edit and follow tasks from code, and read your activity feed.
A task is a job that trades for you over time, like a volume run or a ladder of sells. The API makes the same tasks as the app, and they show up in the app too.
Before you start#
- Reading tasks needs the
readscope. Creating and controlling them needstrade. - Creating, editing, starting and resuming need a key with no limits. A restricted key gets
403 key_restricted. Pausing, stopping and deleting work with anytradekey. - Tasks are real by default. They send real transactions unless their
configsays"dryRun": true, and many types cannot do a dry run at all. See Dry runs.
Routes#
| Call | Scope | What it does |
|---|---|---|
GET /tasks | read | Your tasks. |
GET /tasks/:id | read | One task. |
POST /tasks | trade | Create a task. |
PATCH /tasks/:id | trade | Change its label, settings or wallets, even while it runs. |
POST /tasks/:id/start | trade | Start it. |
POST /tasks/:id/pause | trade | Pause it. |
POST /tasks/:id/resume | trade | Go on after a pause. |
POST /tasks/:id/stop | trade | Stop it. |
DELETE /tasks/:id | trade | Delete a task that is not running. |
POST /tasks/stop-all | trade | Stop all your running and paused tasks. |
POST /tasks/:id/preview | read | What a start would do now. Sends nothing. |
GET /tasks/:id/executions | read | The trades it sent. |
GET /tasks/:id/postmortem | read | How each wallet did, and why any failed. |
GET /tasks/:id/playbook | read | Live state of a limit order, ladder, mirror, DCA or trailing stop. |
GET /tasks/:id/mixer-orders | read | A mixer task's orders. |
POST /tasks/:id/mixer-orders/:orderId/recipients/:recipientId/execute | trade | Skip the wait for one mixer recipient. |
GET /tasks/:id/disperse | read | A SOL-spreading task's wallets and progress. |
GET /tasks/presets, POST /tasks/presets, DELETE /tasks/presets/:id | read / trade | Saved settings. |
GET /events | read | Your activity feed. |
GET /warmup/candidates | read | Tokens the wallet warm-up task would trade now. |
Create a task#
POST /tasks:
{
"type": "buy",
"mint": "7xKX…pump",
"walletIds": ["812", "813"],
"label": "morning buys",
"config": {
"buyMode": "exact",
"walletAmounts": { "812": 0.1, "813": 0.05 },
"minDelayMs": 2000,
"maxDelayMs": 9000
},
"autostart": false
}type— the engine. See Task types.mint— the token's mint address.walletIds— the wallets it uses. They must be yours. It may be empty only for alimit_orderwhoseconfig.walletSourceisallorroles.config— the engine's settings. Each engine has its own fields.chain— optional. Left out, it comes from the mint's address.label— optional, up to 120 characters.projectId— optional. Puts the task under one of your projects.autostart—truestarts it at once. Defaultfalse.
The answer is 201 with the task. A wallet that is not yours gets 403 forbidden. Bad settings get 400 validation_failed, and details names the field.
A config field the engine does not know is ignored, and its default is used instead. Some defaults spend a lot. For buy, the default buyMode is full_balance: each wallet spends almost all its coin. Read the task back with GET /tasks/:id and check config before you start it.
Task types#
Each type's settings match its form in the app. Its docs page explains them.
type | Page |
|---|---|
buy | Buy |
volume | Volume |
fakevolume | Fake volume |
holderboost | Holder boost |
protrader_boost | Pro trader boost |
handswitcher | Hand switcher |
antisniper | Anti-sniper |
bundle | Bundle |
migrate_and_buy | Migrate and buy |
tokendisperser | Token sender |
mixer | Mixer |
warmup | Wallet warm-up |
limit_order | Limit order |
ladder | Ladder |
mirror | Mirror |
dca | DCA |
trailing_stop | Trailing stop |
Some types follow special rules:
sniperis a launch task only. Add it totasksonPOST /launch. On a token that already trades, usebuy.batchis made for you by a slowPOST /trade/batch. See Buy, sell & batches.scheduled_launchis made for you byPOST /launchwithlaunchAt. See Launch a token.devwarmupneeds exactly one wallet. Starting it needs the highest fee tier, or it gets403.soldisperser,solcollector,tokencollectorandsendsolmove coins between your wallets.
Dry runs#
Types such as buy, migrate_and_buy, warmup, tokendisperser and mixer take "dryRun": true inside config. The task walks through its steps and sends nothing. Its trades show up as simulated.
These types have no dry run: volume, bundle, antisniper, holderboost, handswitcher, fakevolume, protrader_boost, limit_order, ladder, mirror, dca and trailing_stop. They refuse "dryRun": true with 400 validation_failed. Start them with small amounts first.
POST /tasks/:id/preview shows what a start would do right now, from live balances. Nothing moves. A type with no preview, like the ones above, gets 400.
Control a task#
A task's status is one of:
idle— made, not started.running— working now.paused— waiting forresume.completed— done.failed— stopped by an error.lastErrorsays why.stopped— stopped by you.timeout— ran out of time.
start, pause, resume and stop answer with the task. A call that does not fit the status, like pause on a stopped task, gets 409 conflict. A finished task can be started again.
PATCH /tasks/:id takes label (null clears it), config and walletIds. Send at least one. A running task picks up the change in place.
DELETE /tasks/:id works only when the status is idle, completed, failed, stopped or timeout. Otherwise it gets 409, so stop the task first. The answer is { "ok": true, "id": "6186" }. The task leaves your lists, but its trades stay in your history.
POST /tasks/stop-all stops all your running and paused tasks. One failure does not block the rest:
{ "requested": 3, "stopped": ["6186", "6190"], "failed": [ { "id": "6201", "error": "…" } ] }Read a task#
GET /tasks answers { "tasks": [ … ] }.
- Filter with
?status=or?type=. - Page with
?limit=(1–500, default 200) and?offset=. The full count is inX-Total-Count. ?status=activelists your running and paused tasks, with no paging.?mint=lists the tasks on one token, with no paging.
A task looks like this:
{
"id": "6186",
"type": "buy",
"status": "running",
"running": true,
"chain": "solana",
"mint": "7xKX…pump",
"label": "morning buys",
"projectId": null,
"walletIds": ["812", "813"],
"config": { "buyMode": "exact", "…": "…" },
"lastError": null,
"createdAt": "2026-09-16T01:09:24.500Z",
"updatedAt": "2026-09-16T01:09:24.531Z",
"startedAt": "2026-09-16T01:09:24.531Z",
"stoppedAt": null
}GET /tasks/:id/executions answers { "executions": [ … ] }, newest first. Each row has:
walletId,side(buyorsell),signature,confirmed,errandcreatedAt;amountInandamountOut, in base units;outcome—filled,pending,failedorsimulated.
Take up to 500 rows with ?limit= (default 50). For older rows, send the last row's id as ?before=.
A task that is not yours answers 404, as if it did not exist.
Presets#
A preset saves a task's settings under a name.
GET /tasks/presets— answers{ "presets": [ … ] }.POST /tasks/presets— send{ "name": "fast buys", "type": "buy", "config": { … } }. The name is 1–64 characters. Saving under a name you already used replaces that preset. Answers201with{ "preset": … }.DELETE /tasks/presets/:id— answers{ "deleted": "…" }, or404.
A preset's settings are not checked when you save it. They are checked when you send them in POST /tasks.
Events#
GET /events is your activity feed: every task change and every trade, one row each, newest first.
{
"events": [
{ "id": "918273", "ts": "2026-09-16T20:11:02.000Z", "category": "execution", "type": "task_execution",
"severity": "success", "taskId": "6605", "mint": "7xKX…pump", "walletId": "812", "title": "Buy landed", "data": { } }
],
"nextBefore": "918200"
}- Filter with
category(taskorexecution),taskId,mintorseverity(info,success,warn,error). limitis 1–200, default 50.- For the next older page, send
nextBeforeback as?before=. It isnullon the last page.
GET /warmup/candidates?chain=solana&limit=20 lists the tokens the warm-up task would trade right now.
Follow a task live#
Subscribe to the tasks topic on the live stream with a read key. You get your tasks now, then every change as it happens. This beats asking GET /tasks again and again.