API reference

Every Algo Trading Bots endpoint — user and admin — with the permission each admin route gates on, the WebSocket subscription contract, and the response conventions that catch integrators out.

3 min readUpdated 3 August 2026api, endpoints, websocket, permissions

Two API surfaces. Everything under /api/trading-bot is scoped to the calling user and carries no permission — it is gated by KYC features instead. Everything under /api/admin/trading-bot carries an explicit permission.

Conventions that will catch you out

The platform pins the HTTP status at 200 and puts the real outcome in the body. Read the body, always. A kill switch that stopped nothing returns a body saying so; a client that branches on the status code will render it as a green toast over a fleet that is still trading.

Amounts are DECIMAL columns and arrive as strings in raw form. Every serialised endpoint converts them, but if you query the tables directly, coerce before arithmetic — "1" + 1 is "11".

strategyConfig is a JSON column. MySQL returns it pre-parsed and MariaDB returns a raw string; the backend normalises both, but a direct database consumer must handle either.

User endpoints

Bots

GET/api/trading-bot
Dashboard: totals, per-status counts, recent activity
GET/api/trading-bot/bot
List the caller's bots, filterable by status, type and mode
POST/api/trading-bot/bot
Create a bot. Starts in DRAFT and must be started deliberately
GET/api/trading-bot/bot/{id}
One bot in full
PUT/api/trading-bot/bot/{id}
Update a bot. Only name, description, stop loss and take profit while RUNNING
DELETE/api/trading-bot/bot/{id}
Soft-delete a bot. Refused while RUNNING
POST/api/trading-bot/bot/{id}/start
Start a bot
POST/api/trading-bot/bot/{id}/pause
Pause a running bot; positions and orders are untouched
POST/api/trading-bot/bot/{id}/resume
Resume a paused bot. Runs every gate that start runs
POST/api/trading-bot/bot/{id}/stop
Stop a bot; working orders are cancelled for real
POST/api/trading-bot/bot/kill-all
Flatten and stop every running or paused bot the caller owns

POST /api/trading-bot/bot requires name, symbol and type. mode defaults to PAPER. Everything else is optional and falls back to the operator's configured defaults.

The update path copies an explicit whitelist, key by key. Passing usedAmount, mode, status, totalProfit or userId in the body does nothing — an earlier build wrote them straight to the row, which let a caller zero their committed capital after live losses and free the whole allocation for withdrawal.

Positions, trades and orders

GET/api/trading-bot/bot/{id}/trades
The bot's trades, filterable by status and side
GET/api/trading-bot/bot/{id}/orders
The bot's orders, including working grid rungs
GET/api/trading-bot/bot/{id}/stats
Statistics: win rate, average profit, drawdown, 30 days of daily history
GET/api/trading-bot/bot/{id}/chart-state
Everything the chart draws: levels, orders, trades, position, indicators
POST/api/trading-bot/bot/{id}/close-position
Close every open position on this bot. Works on a stopped bot
GET/api/trading-bot/trade
Trades across every bot the caller owns
GET/api/trading-bot/trade/{id}
One trade in full

Allocation

GET/api/trading-bot/allocation
Allocation across all the caller's bots, summarised by currency
POST/api/trading-bot/bot/{id}/allocation/add
Raise a bot's cap
POST/api/trading-bot/bot/{id}/allocation/remove
Release available capital — limited to allocated minus used

Both mutations row-lock the bot and write an audit entry. Neither moves money — an allocation is a cap.

Markets and strategies

GET/api/trading-bot/markets
Ecosystem markets a bot may be pointed at, with a last price where one resolves
GET/api/trading-bot/strategy
The strategy types the engine supports
GET/api/trading-bot/strategy-schema
Full configuration schema for every strategy type
GET/api/trading-bot/strategy/templates
Pre-configured templates for quick creation
POST/api/trading-bot/strategy/validate
Validate a configuration without creating anything

markets returns BASE/QUOTE symbols — the form every downstream consumer expects. A market whose price cannot be resolved is still returned, with a null price.

Paper trading

GET/api/trading-bot/paper-account
Read the paper account, creating it on first access
POST/api/trading-bot/paper-account/reset
Reset to the default balance; the reset count is retained

Accounts are per user and per currency.

Marketplace

GET/api/trading-bot/marketplace
Browse approved public listings — filter by type, rating, price, tags, search
GET/api/trading-bot/marketplace/strategy/{id}
One listing. Config is only included if the caller owns or bought it
GET/api/trading-bot/marketplace/strategy
List the caller's own strategies in any status
POST/api/trading-bot/marketplace/strategy
Create a strategy — this is the Strategy Builder's Save
PUT/api/trading-bot/marketplace/strategy/{id}
Update a strategy. Some edits force re-review
POST/api/trading-bot/marketplace/strategy/{id}/submit
Submit a draft or rejected strategy for review
POST/api/trading-bot/marketplace/strategy/{id}/purchase
Purchase a strategy. One transaction; nothing is charged if it fails
POST/api/trading-bot/marketplace/strategy/{id}/create-bot
Deploy a bot from a purchased or owned strategy
GET/api/trading-bot/marketplace/purchases
Everything the caller has bought
POST/api/trading-bot/marketplace/strategy/{id}/review
Leave a review — requires a completed purchase, one per strategy
GET/api/trading-bot/marketplace/strategy/{id}/reviews
Approved reviews for a strategy
GET/api/trading-bot/marketplace/seller/dashboard
Creator dashboard: listings, sales and performance

Sorting on the browse endpoint accepts purchaseCount, totalPurchases, avgRating, price and createdAt. Anything else falls back to totalPurchases rather than producing an unknown-column error.

KYC gates on user routes

Feature Guards
view_trading_bot GET /api/trading-bot, /bot, /markets, /marketplace
trade_bot_live Creating, starting or resuming a live bot; deploying one from a strategy
buy_bot_strategy Purchasing
become_bot_seller Submitting for review

Admin endpoints

GET/api/admin/trading-bot/dashboardpermission: access.trading_bot
Fleet health, capital, performance and the moderation queues
GET/api/admin/trading-bot/botpermission: view.trading_bot.bot
Every bot on the install, filterable and searchable
GET/api/admin/trading-bot/bot/{id}permission: view.trading_bot.bot
One bot with its trades, orders and recent audit entries
POST/api/admin/trading-bot/bot/{id}/stoppermission: manage.trading_bot.bot
Force-stop one bot: cancel orders, flatten positions, write STOPPED
POST/api/admin/trading-bot/emergency-stoppermission: manage.trading_bot.bot
Fleet-wide emergency stop. Requires a reason of at least 10 characters
GET/api/admin/trading-bot/marketplacepermission: view.trading_bot.marketplace
All marketplace listings, any status
GET/api/admin/trading-bot/marketplace/pendingpermission: view.trading_bot.marketplace
The review queue, oldest submission first
GET/api/admin/trading-bot/marketplace/strategy/{id}permission: view.trading_bot.marketplace
One listing in full
POST/api/admin/trading-bot/marketplace/strategy/{id}/approvepermission: edit.trading_bot.marketplace
Approve a listing. Optional notes up to 1000 characters
POST/api/admin/trading-bot/marketplace/strategy/{id}/rejectpermission: edit.trading_bot.marketplace
Reject a listing. Reason required, minimum 10 characters
POST/api/admin/trading-bot/marketplace/strategy/{id}/suspendpermission: edit.trading_bot.marketplace
Suspend an approved listing. Reason required
POST/api/admin/trading-bot/marketplace/strategy/{id}/reinstatepermission: edit.trading_bot.marketplace
Reinstate a suspended listing
GET/api/admin/trading-bot/marketplace/purchasespermission: view.trading_bot.marketplace
Every purchase with its fee breakdown
GET/api/admin/trading-bot/marketplace/statspermission: view.trading_bot.marketplace
Marketplace revenue and counts
GET/api/admin/trading-bot/reviewspermission: view.trading_bot.review
Reviews awaiting moderation
POST/api/admin/trading-bot/reviews/{id}/approvepermission: edit.trading_bot.review
Approve a review — makes it public and lets it move the rating
POST/api/admin/trading-bot/reviews/{id}/rejectpermission: edit.trading_bot.review
Reject a review
GET/api/admin/trading-bot/logspermission: view.trading_bot.log
Audit trail, filterable by action and scoped by user
GET/api/admin/trading-bot/logs/{id}permission: view.trading_bot.log
One audit entry in full
GET/api/admin/trading-bot/settingspermission: view.trading_bot.settings
Read the resolved settings
PUT/api/admin/trading-bot/settingspermission: edit.trading_bot.settings
Update settings. Unknown fields are refused, omitted fields unchanged

WebSocket

Connect to /api/trading-bot and use the platform's generic subscription frames.

{ "action": "SUBSCRIBE", "payload": { "channel": "bot", "botId": "…", "userId": "…" } }
{ "action": "SUBSCRIBE", "payload": { "channel": "bots", "userId": "…" } }

UNSUBSCRIBE takes the identical payload.

Broadcasts are matched by serialising the payload, so the key order above is part of the contract. Hand-writing a subscription object with the keys in a different order produces a socket that connects, subscribes without error, and then receives nothing at all.

userId is required and load-bearing for security. The platform registers the subscription key before the route handler runs and rejects any payload whose userId is not the session's own, and every broadcast is addressed with the bot owner's id — so a subscription forged with someone else's botId can never match a broadcast.

Streams

Stream Channel Carries
bot_tick bot Heartbeat: price, whether it traded, the signal or error. Fires every engine interval
bot_trade bot A trade opened or closed
bot_order bot An order placed, filled or cancelled
status change bot and bots A lifecycle transition

On the worker-thread backend entry, a broadcast raised by the engine on the main thread does not reach a socket held by a worker. The Bot Terminal also polls chart-state every 15 seconds, which is what keeps it correct on those deployments. Build any integration the same way: treat the socket as an accelerator, not as the source of truth.

Tables

If you read the database directly:

Table Holds
trading_bot The bots. Soft-deleted (paranoid), so filter deletedAt
trading_bot_trade Positions, with cost, fee, profit and closedAt
trading_bot_order Orders — PENDING, OPEN, PARTIAL, FILLED, CANCELLED, EXPIRED, FAILED
trading_bot_stats One row per bot per day, with an isPaper flag
trading_bot_paper_account Per user and currency
trading_bot_strategy Listings, with gross, seller and platform revenue columns
trading_bot_purchase Sales, with the fee rate charged and a config snapshot
trading_bot_strategy_review Reviews and their moderation status
trading_bot_audit_log The trail. Pruned after 90 days