Where this payload works
Use the same create-bot payload in three places: the web dashboard, the REST create-bot endpoint, and the chat clients via `/bots create` followed by one JSON object. The backend schema is the source of truth — chat clients add convenience aliases for quick-create mode, but raw JSON bypasses those aliases and uses the canonical field names shown here.
Raw JSON rules
- Send one JSON object, not partial fragments. In Telegram/Discord the format is `/bots create` followed by a JSON object.
- Use real JSON syntax: double-quoted keys, double-quoted strings, lowercase `true`/`false`, commas between fields, and square brackets for arrays.
- Use fractional percentages in most risk fields. Example: `0.05` means 5%, `0.25` means 25%, and `1` means 100%.
- Numbers can be integers or decimals. UUID references like `credential_id` must be strings.
- If you omit optional fields, the backend fills many of them with defaults. Those defaults are documented in section 3.
- The backend create flow defaults differ from the chat template in a few places. For predictable behavior, set fields explicitly instead of relying on the template.
Smallest valid payload
This is the minimum the backend accepts for a standard spot bot. Everything else is filled in by the defaults in the next section.
{
"name": "btc-sim",
"broker": "binance_spot",
"symbol": "BTCUSDT",
"quantity": 0.01
}Backend defaults when fields are omitted
These are the create-time defaults wired in the backend bot API. A raw JSON payload that omits these fields inherits the values listed here — not whatever the chat template happens to display.
Chat template ≠ backend defaults
The chat bot template advertises `timeframe: "15m"`, richer stop/take examples, and `is_minimal: false`. If you send a tiny raw JSON payload without those fields, the backend still defaults to `timeframe: "1m"`, `is_minimal: true`, and its own built-in stop/take values. If a value matters to you, write it explicitly.
Advanced top-level fields
These are the most useful advanced fields beyond `name`, `broker`, `symbol`, and `quantity`.
watchliststring[]Optional list of symbols to scan. When `only_best_signal=true`, the backend ensures the primary `symbol` is included even if you forgot it.
only_best_signalbooleanTells the bot to choose the best signal from the watchlist instead of trading only the primary symbol. If true and `watchlist` is empty, the backend seeds the list with the main symbol.
simulation_modebooleanPaper trading switch. Defaults to `true` when omitted in the backend create flow, so raw JSON can safely start in simulation unless you explicitly turn it off.
is_minimalbooleanMarks the bot as a minimal/basic bot. Defaults to `true` in the backend create flow, even though the chat template shows a richer example payload.
position_sizing_modefixed_quantity | percent_of_equity | risk_per_tradeSizing mode. `fixed_quantity` uses `quantity` directly. `percent_of_equity` requires `balance_allocation_pct`. `risk_per_trade` requires `risk_per_trade_pct`.
balance_allocation_pctdecimal (0, 1]Required when `position_sizing_mode=percent_of_equity`. Use fractions, not whole percents: `0.25` means 25% of equity.
risk_per_trade_pctdecimal (0, 1]Required when `position_sizing_mode=risk_per_trade`. Also expressed as a fraction: `0.01` means 1% risk per trade.
credential_idUUID stringReference an already-saved credential instead of sending raw exchange keys inline. If this is present, the backend ignores inline `api_key`, `secret_key`, and `passphrase` for storage.
strategy_idUUID stringOptional strategy grouping/reference id. Useful when the bot belongs to a higher-level workflow or catalog entry.
org_idUUID stringOptional organization scope. The authenticated user must have at least trader-level access in that org.
leverageintegerFutures-only setting. Safe to omit for spot/on-chain bots. Pair it with `margin_type` and optionally `position_side`.
margin_typestringUsually `cross` or `isolated`. The chat clients accept those lowercase values and pass them through.
position_sidestringUsually `both`, `long`, or `short` depending on broker capabilities and hedge mode.
timeframestringKline timeframe like `1m`, `5m`, `15m`, `1h`. Backend default is `1m` if omitted from raw JSON.
chainstringRequired when `broker` is `onchain` (and recommended for `pancakeswap`/`sushiswap`). Example values include `polygon`, `ethereum`, or `bsc`.
indicator_config.bot_typesignal | gridExecution mode embedded inside `indicator_config`. Omit it or set `signal` for the indicator-driven strategy engine. Set `grid` to enable grid trading.
indicator_config.grid_configobjectRequired when `indicator_config.bot_type=grid`. Must include valid price bounds, grid count, and total quote allocation. See section 6.
indicator_config.ml_configobjectOptional machine-learning settings. `enabled=true` is restricted to VIP, Fund, and Enterprise tiers in the backend. See section 7.
Indicator config
`indicator_config` is the deep customization object. Some fields are signal weights, some are periods/thresholds, and two of them switch the bot into alternate execution modes (grid in section 6, ML in section 7).
sma_weightdecimalSignal weight for simple moving average contribution.
ema_weightdecimalSignal weight for EMA contribution.
wma_weightdecimalSignal weight for WMA contribution.
hma_weightdecimalSignal weight for HMA contribution.
vwma_weightdecimalSignal weight for VWMA contribution.
macd_weightdecimalSignal weight for MACD contribution.
adx_weightdecimalSignal weight for ADX contribution.
parabolic_sar_weightdecimalSignal weight for Parabolic SAR contribution.
ichimoku_weightdecimalSignal weight for Ichimoku contribution.
supertrend_weightdecimalSignal weight for Supertrend contribution.
rsi_weightdecimalSignal weight for RSI contribution.
stoch_rsi_weightdecimalSignal weight for Stoch RSI contribution.
mfi_weightdecimalSignal weight for MFI contribution.
cci_weightdecimalSignal weight for CCI contribution.
momentum_weightdecimalSignal weight for momentum contribution.
roc_weightdecimalSignal weight for rate-of-change contribution.
bollinger_weightdecimalSignal weight for Bollinger contribution.
atr_weightdecimalSignal weight for ATR contribution.
keltner_weightdecimalSignal weight for Keltner channel contribution.
donchian_weightdecimalSignal weight for Donchian contribution.
obv_weightdecimalSignal weight for OBV contribution.
vwap_weightdecimalSignal weight for VWAP contribution.
volume_osc_weightdecimalSignal weight for volume oscillator contribution.
cmf_weightdecimalSignal weight for Chaikin money flow contribution.
support_resistance_weightdecimalSignal weight for support/resistance contribution.
pivot_points_weightdecimalSignal weight for pivot points contribution.
fibonacci_weightdecimalSignal weight for Fibonacci contribution.
candles_weightdecimalSignal weight for candle-pattern contribution.
ml_weightdecimalSignal weight for the ML model contribution when enabled.
bollinger_stddevnumberStandard deviation multiplier for Bollinger Bands.
macd_fast / macd_slow / macd_signalintegerMACD period tuple.
rsi_period / rsi_overbought / rsi_oversoldinteger / decimalRSI tuning values.
stoch_rsi_period / stoch_overbought / stoch_oversoldinteger / decimalStoch RSI tuning values.
mfi_period / mfi_overbought / mfi_oversoldinteger / decimalMoney Flow Index tuning values.
cci_period / cci_overbought / cci_oversoldinteger / decimalCCI tuning values.
momentum_period / roc_period / adx_periodintegerMomentum, ROC, and ADX window lengths.
adx_trend_thresholddecimalThreshold that defines a strong ADX trend.
supertrend_period / supertrend_multiplierinteger / decimalSupertrend configuration.
atr_period / keltner_multiplier / donchian_periodinteger / decimalATR/Keltner/Donchian configuration.
volume_osc_short / volume_osc_longintegerVolume oscillator windows.
cmf_period / support_resistance_lookbackintegerCMF and support/resistance windows.
Chat command shortcut
In quick-create mode, the Telegram and Discord bots let you set common indicator fields with `key=value` flags and any arbitrary indicator field with the `ic_` prefix, e.g. `ic_supertrend_period=10`. In raw JSON mode, write the final nested structure under `indicator_config` directly.
Grid config (`grid_config`)
Required when `indicator_config.bot_type="grid"`. The backend validates the bounds, level count, and quote allocation strictly — invalid grids are rejected at create time.
lower_pricedecimalBottom of the grid range. Must be greater than 0.
upper_pricedecimalTop of the grid range. Must be strictly greater than `lower_price`.
grid_countintegerNumber of grid levels. Must be between 2 and 500 (inclusive).
total_quotedecimalTotal quote currency allocated to the grid. Must be greater than 0.
spacingarithmetic | geometricDistribution of grid levels between `lower_price` and `upper_price`.
stop_lowerdecimal (optional)If set, must be strictly below `lower_price`. The grid halts when price falls through it.
stop_upperdecimal (optional)If set, must be strictly above `upper_price`. The grid halts when price breaks through it.
ML config (`ml_config`)
Optional. Lives under `indicator_config.ml_config`. When `enabled=true`, the request is tier-gated.
enabledbooleanMaster switch. Setting `true` is tier-gated to VIP, Fund, and Enterprise; the backend rejects the create call otherwise.
feature_keysstring[]Indicator keys fed to the ML model (e.g. `rsi`, `macd`, `adx`, `vwap`). External data-layer columns use the `ext:` prefix (e.g. `ext:funding_z`, `ext:ofi_z`, `ext:user_mydata_col_chg`) and each must be covered by an entry in `feature_specs` — unknown or uncovered keys are rejected at validation.
feature_specsobject[] (optional)Data-layer specs backing the `ext:` feature keys. Each spec is `{"kind": ...}` with kind one of `funding`, `taker_flow`, `open_interest`, `basis`, `liquidations`, `macro` (needs `dataset`, e.g. `VIXCLS`), or `custom` (needs `dataset` = your uploaded slug). Training resolves them from history and the live engine resolves the same specs live, so the model sees identical columns both times. Use the dashboard's Research Data panel to discover columns and screen them for signal first.
data_timeframestring (optional)Kline timeframe used to build the training dataset, e.g. `1h`. Independent of the bot's live `timeframe`.
data_dirstring (optional)Optional path override for cached training data. Most users should omit this.
horizoninteger (optional)Number of forward bars the model tries to predict.
min_samplesinteger (optional)Minimum number of training samples required before the model will produce signals.
epochsinteger (optional)Training epochs. Higher = longer training, more overfitting risk.
learning_ratenumber (optional)Optimizer learning rate. Common values: `1e-3` to `1e-4`.
batch_sizeinteger (optional)Mini-batch size used during training.
l2_regularizationnumber (optional)L2 weight decay. Helps fight overfitting.
validation_splitnumber (optional)Fraction of training data held out for validation, e.g. `0.2`.
early_stop_patienceinteger (optional)Stop training after this many epochs without validation improvement.
label_clipnumber (optional)Clip target labels to limit outlier influence on training.
prediction_thresholddecimal (optional)Confidence threshold the model must clear before its signal contributes.
signal_weightdecimal (optional)Weight applied to the ML signal when it does fire (separate from `ml_weight` in `indicator_config`).
Full examples
Futures bot with stored credentials
Use this when you want an authenticated live futures bot without embedding exchange secrets in the message body.
{
"name": "btc-futures-live",
"broker": "binance_futures",
"symbol": "BTCUSDT",
"quantity": 0.01,
"simulation_mode": false,
"is_minimal": false,
"timeframe": "15m",
"leverage": 5,
"margin_type": "cross",
"position_side": "both",
"credential_id": "11111111-2222-3333-4444-555555555555",
"sensitivity_buy": 1.0,
"sensitivity_sell": 1.0,
"threshold": 0.95,
"stop_loss_partial": 0.05,
"stop_loss_lower_half_average": 0.05,
"stop_loss_last": 0.05,
"stop_loss_trailing_start": 0.02,
"stop_loss_trailing_end": 0.01,
"take_profit_partial": 0.1,
"take_profit_lower_half_average": 0.15,
"take_profit_last": 0.2,
"take_profit_trailing_start": 0.05,
"take_profit_trailing_end": 0.03
}Best-signal scanner with watchlist
Use this when one bot should watch several symbols and act only on the strongest opportunity.
{
"name": "majors-scanner",
"broker": "binance_spot",
"symbol": "BTCUSDT",
"quantity": 0.005,
"only_best_signal": true,
"watchlist": ["BTCUSDT", "ETHUSDT", "SOLUSDT", "BNBUSDT"],
"timeframe": "5m",
"indicator_config": {
"rsi_period": 14,
"rsi_overbought": 70,
"rsi_oversold": 30,
"macd_fast": 12,
"macd_slow": 26,
"macd_signal": 9,
"vwap_weight": 0.4,
"pivot_points_weight": 0.2
}
}Grid bot
Grid mode lives under `indicator_config.bot_type="grid"`. The backend validates the bounds and quote allocation strictly.
{
"name": "eth-grid",
"broker": "binance_spot",
"symbol": "ETHUSDT",
"quantity": 0.01,
"simulation_mode": true,
"indicator_config": {
"bot_type": "grid",
"grid_config": {
"lower_price": 2800,
"upper_price": 3600,
"grid_count": 12,
"total_quote": 1500,
"spacing": "arithmetic",
"stop_lower": 2600,
"stop_upper": 3800
}
}
}On-chain bot
When `broker` is `onchain`, `chain` becomes mandatory. Without it the backend rejects the request.
{
"name": "polygon-usdc",
"broker": "onchain",
"chain": "polygon",
"symbol": "WETH/USDC",
"quantity": 100,
"simulation_mode": true
}ML-enabled indicator config
ML mode is tier-gated. The request shape is still valid, but the backend refuses it outside VIP/Fund/Enterprise tiers.
{
"name": "ml-major-trend",
"broker": "binance_spot",
"symbol": "BTCUSDT",
"quantity": 0.01,
"indicator_config": {
"ml_weight": 1.0,
"ml_config": {
"enabled": true,
"model_type": "mlp",
"hidden_layers": [16, 8],
"activation": "relu",
"feature_keys": ["rsi", "macd_hist", "adx", "vwap", "ema_short", "ema_long", "atr", "momentum", "ext:funding_z"],
"feature_specs": [{ "kind": "funding" }],
"data_timeframe": "1h",
"horizon": 6,
"epochs": 200,
"batch_size": 64,
"learning_rate": 0.005,
"l2_regularization": 0.0001,
"validation_split": 0.2,
"early_stop_patience": 15,
"walk_forward_folds": 4,
"feature_importance": true,
"prediction_threshold": 0.002,
"signal_weight": 1.0
}
}
}Validation & edge cases
Supported `broker` slugs
binanceAlias accepted by the backend; resolves to Binance Spot in most paths.
binance_spotBinance Spot exchange (centralized).
binance_futuresBinance USDⓈ-M Futures.
coinbaseCoinbase Advanced Trade. Requires `passphrase` for inline credentials.
krakenKraken Spot.
kucoinKuCoin Spot. Requires `passphrase` for inline credentials.
coinexCoinEx Spot.
pancakeswapPancakeSwap (BSC). Treated as on-chain liquidity routing.
sushiswapSushiSwap. Treated as on-chain liquidity routing.
onchainGeneric on-chain broker. `chain` is mandatory (e.g. `polygon`, `ethereum`, `bsc`).
Other server-side checks
- `quantity` must be greater than zero.
- `balance_allocation_pct` and `risk_per_trade_pct` must be greater than 0 and at most 1.
- `position_sizing_mode=percent_of_equity` without `balance_allocation_pct` is rejected.
- `position_sizing_mode=risk_per_trade` without `risk_per_trade_pct` is rejected.
- If `broker=onchain`, `chain` is mandatory.
- If `indicator_config.bot_type="grid"`, then `grid_config` is mandatory and must satisfy: `lower_price > 0`, `upper_price > lower_price`, `grid_count` between 2 and 500, `total_quote > 0`, `stop_lower < lower_price`, and `stop_upper > upper_price` when provided.
- If `indicator_config.ml_config.enabled=true`, the request is tier-gated to VIP, Fund, and Enterprise.
- If you send `credential_id`, the backend stores no new inline API keys for that bot.
- For Coinbase- and KuCoin-style credentials, include `passphrase` when using inline credential fields.
Raw JSON vs quick-create flags
Telegram and Discord support two creation styles. Quick-create looks like:
/bots create mybot binance_futures BTCUSDT 0.01 timeframe=5m leverage=10 margin_type=isolatedRaw JSON mode uses `/bots create` followed by a full JSON object. Quick-create is easier for simple cases, but covers only a subset of the backend schema and relies on alias parsing. Raw JSON is the better choice when you need watchlists, nested indicator config, grid config, ML config, organization linkage, or a payload you can reuse in scripts.
Recommended workflow
- Start from the smallest valid payload and add one advanced feature at a time.
- Keep `simulation_mode=true` until the payload is stable.
- Use `credential_id` instead of pasting secrets into chat whenever possible.
- Pin key fields explicitly (`timeframe`, stop/take values, sizing mode) so backend defaults do not surprise you.
- For grid bots and ML bots, test the exact JSON in simulation first — those modes are more configuration-sensitive than standard signal bots.