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

Dashboard: totals, per-status counts, recent activity
List the caller's bots, filterable by status, type and mode
Create a bot. Starts in DRAFT and must be started deliberately
One bot in full
Update a bot. Only name, description, stop loss and take profit while RUNNING
Soft-delete a bot. Refused while RUNNING
Start a bot
Pause a running bot; positions and orders are untouched
Resume a paused bot. Runs every gate that start runs
Stop a bot; working orders are cancelled for real
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

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

Allocation

Allocation across all the caller's bots, summarised by currency
Raise a bot's cap
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

Ecosystem markets a bot may be pointed at, with a last price where one resolves
The strategy types the engine supports
Full configuration schema for every strategy type
Pre-configured templates for quick creation
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

Read the paper account, creating it on first access
Reset to the default balance; the reset count is retained

Accounts are per user and per currency.

Marketplace

Browse approved public listings — filter by type, rating, price, tags, search
One listing. Config is only included if the caller owns or bought it
List the caller's own strategies in any status
Create a strategy — this is the Strategy Builder's Save
Update a strategy. Some edits force re-review
Submit a draft or rejected strategy for review
Purchase a strategy. One transaction; nothing is charged if it fails
Deploy a bot from a purchased or owned strategy
Everything the caller has bought
Leave a review — requires a completed purchase, one per strategy
Approved reviews for a strategy
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

Fleet health, capital, performance and the moderation queues
Every bot on the install, filterable and searchable
One bot with its trades, orders and recent audit entries
Force-stop one bot: cancel orders, flatten positions, write STOPPED
Fleet-wide emergency stop. Requires a reason of at least 10 characters
All marketplace listings, any status
The review queue, oldest submission first
One listing in full
Approve a listing. Optional notes up to 1000 characters
Reject a listing. Reason required, minimum 10 characters
Suspend an approved listing. Reason required
Reinstate a suspended listing
Every purchase with its fee breakdown
Marketplace revenue and counts
Reviews awaiting moderation
Approve a review — makes it public and lets it move the rating
Reject a review
Audit trail, filterable by action and scoped by user
One audit entry in full
Read the resolved 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