---
title: "Submit a training job (non-blocking, returns job_id for polling)"
method: POST
path: "/api/v1/train"
tags: ["Training"]
---

# Submit a training job (non-blocking, returns job_id for polling)

`POST /api/v1/train`

## Request

- Base URL: `https://api.quantifyme.ai`
- URL: `https://api.quantifyme.ai/api/v1/train`
- Auth: API key in header `X-API-Key`

## Request body

- TrainRequest
  - `aux_feeds` object[]: Extra (symbol, timeframe) feeds merged into the strategy's features as aux_* columns. Max 3; must differ from the primary.
    - `symbol` 'EURUSD' | 'GBPUSD' | 'USDJPY' | 'USDCHF' | 'AUDUSD' | 'NZDUSD' | 'USDCAD' | 'BTCUSD'
    - `timeframe` '1min' | '5min' | '15min' | '1h'
  - `capital` number: Account balance in USD. Drives the $ P&L and return-on-equity (P&L % = $ P&L / balance).
  - `claude_model` string
  - `code` string, required: Full Python strategy code (typically from /api/v1/generate).
  - `commission` number
  - `confidence_threshold` number: Signal strictness: the raw predict_proba cutoff a bar must clear to fire, as a percent (55 = a score of 0.55). NOT a calibrated probability — a 55 setting was measured delivering a 50.0% hit rate. Overrides the value in strategy_config(). Classification-only (#432) - a regression strategy (task='regression') refuses this with 400; use signal_rules instead (return/spread units).
  - `end_date` string, date
  - `indicators` Indicators: Flat indicator config. See GET /api/v1/indicator-schema for full param list.
  - `leverage` number: Margin only — sets required margin (notional / leverage); does NOT multiply P&L. Stored for future margin/liquidation modeling.
  - `lot_size` number: Position size in standard lots (1.0 = 100,000 units). This is the P&L driver: $ P&L = units × (exit−entry) / FX_conv − commission/swap.
  - `model_name` string: Optional. Auto-named Model N+1 if omitted.
  - `risk_unit` 'pips' | 'usd' | 'pct': How stop_loss/take_profit are interpreted. 'pips' = pip distance; 'usd' = $ risk at this lot; 'pct' = legacy fraction of price. The engine back-solves the price level per pair (pip_size + FX conversion).
  - `start_date` string, date
  - `stop_loss` number: Stop-loss magnitude in risk_unit (e.g. 25 pips, or $250 when risk_unit='usd'). Omit/null to disable. Overrides the value in strategy_config().
  - `swap_long` number
  - `swap_short` number
  - `symbol` 'EURUSD' | 'GBPUSD' | 'USDJPY' | 'USDCHF' | 'AUDUSD' | 'NZDUSD' | 'USDCAD' | 'BTCUSD': Must match the symbol the code was generated for.
  - `take_profit` number: Take-profit magnitude in risk_unit (e.g. 50 pips). Omit/null to disable. Overrides the value in strategy_config().
  - `timeframe` '1min' | '5min' | '15min' | '1h'
  - `train_split` number

## Response `200`

Successful response

- TrainStartResponse
  - `job_id` integer
  - `model_name` string
  - `model_stem` string: PKL filename stem: <user_id>_<SYMBOL>_<timeframe>_<model_name>
  - `status` string

## Other responses

- `400`: Bad request
- `401`: Invalid or missing API key
- `429`: Rate limit exceeded, or insufficient credits (body carries credits_remaining and credits_required)

---

[API](https://skmtc.dev/quantifyme/apis/quantifyme-api.md) · [All operations](https://skmtc.dev/quantifyme/apis/quantifyme-api/llms.txt) · [OpenAPI document](https://skmtc.dev/quantifyme/apis/quantifyme-api/revisions/089d1cee1ec5?raw)
