Audience: Operator
Local HTTP access to mtdata for dashboards, notebooks, scripts, and apps — and the bundled chart workspace served at /app.
If you want to use the website, start at WEBUI.md. This page is the route reference.
Dedicated chart routes (/history, /forecast/price, …) are a focused research subset. The Tools invoke path (POST /api/v1/tools/{name}/invoke) can run almost the full CLI/MCP catalog. Tune jobs stay CLI/MCP-only. A trade_* invocation is live-capable only when the wrapper has "confirm": true and its arguments set "dry_run": false.
Base URL: http://localhost:8000 (default)
| Versioning | Guidance |
|---|---|
/api/... and /api/v1/... |
Both work for every route below |
| New integrations | Prefer /api/v1 |
| Examples on this page | Use /api for brevity |
Related: Web UI (User) · Setup · Deployment · Env vars · Output contract · Trading safety
Build the production SPA once with Node.js 22.12 or newer (Node is only required for this step, not at runtime):
cd webui
npm ci
npm run build
cd ..
mtdata-webapiThen open the chart workspace:
http://127.0.0.1:8000/app/
The Python package does not ship generated webui/dist/ assets. Without a build, REST stays available and /app returns a deliberate enablement page (HTML or JSON) with the same commands — not a silent skip or bare framework 404. Run mtdata-webapi from the repository root, or override the dist path with an absolute WEBUI_DIST_DIR.
curl http://127.0.0.1:8000/api/v1/health
curl "http://127.0.0.1:8000/api/v1/history?symbol=EURUSD&timeframe=H1&limit=50"By default the API binds to 127.0.0.1. Loopback clients may use read-only
routes and invoke read-only tools without a token. Every invocation of a
mutation-capable tool requires a configured WEBAPI_AUTH_TOKEN and a matching
Authorization: Bearer <token> header, including dry_run=true previews.
Loopback location, X-API-Key, and "confirm": true do not replace that
credential.
If you want remote access, set WEBAPI_ALLOW_REMOTE=1, use a non-loopback WEBAPI_HOST, and provide WEBAPI_AUTH_TOKEN. When a token is configured, read-only clients may send either:
Authorization: Bearer <token>X-API-Key: <token>
Mutation-capable Tools calls must use the Bearer form. If the server has no
token configured, those calls fail with HTTP 503 and
error_code=web_api_mutation_auth_not_configured. Set a long random value in
.env, restart mtdata-webapi, then enter the same value in the Web UI
Auth control or send it in the request:
WEBAPI_AUTH_TOKEN=replace-with-a-long-random-secretcurl -X POST http://127.0.0.1:8000/api/v1/tools/trade_place/invoke \
-H "Authorization: Bearer $WEBAPI_AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d '{"arguments":{"symbol":"EURUSD","volume":0.01,"order_type":"BUY","dry_run":true},"confirm":false}'The bundled Web UI has an Auth control in the chart toolbar. Enter the same token there after the page loads. The token is held only in the current tab's JavaScript memory, is attached as a Bearer token to API requests, and is cleared by a page reload or the control's Clear action. It is never embedded in the Vite build or written to browser storage.
Credentialed CORS requests require explicit origins. CORS_ORIGINS=* is rejected.
Security checklist for remote access:
- Keep the default local bind (
127.0.0.1) unless another machine must connect. - Set
WEBAPI_AUTH_TOKENbefore invoking any mutation-capable tool or usingWEBAPI_ALLOW_REMOTE=1. - Use explicit
CORS_ORIGINS; do not rely on browser defaults. - Treat API access as sensitive because endpoints can expose account, symbol, and market context from the running MT5 terminal.
Responses are JSON. Most endpoints return compact, UI-oriented payloads rather than the full CLI/MCP output contract. Use the detail=full request parameter for richer historical rows or method diagnostics. When a successful Web API wrapper echoes that choice, the response field is detail_level; detail is not overloaded as both a verbosity string and an error container.
Every response includes X-Request-ID. Clients may supply a log-safe identifier
in the same request header (1–128 letters, digits, ., _, :, or -); the
server otherwise generates one. Error envelopes and request-scoped operation
logs use that same identifier so a failed HTTP call can be traced end to end.
Validation failures, raised HTTP errors, and unexpected route failures return
the canonical envelope directly at the top level:
{success: false, error, error_code, request_id, operation}. They are always
JSON; FastAPI's nested {detail: ...} and plain-text 500 shapes are not used.
Basic health check. Returns JSON, not the SPA.
Same liveness payload as /.
Readiness probe. Returns HTTP 200 when the API can establish an MT5 connection and HTTP 503 when MT5 is unavailable. Also available at GET /api/ready and GET /api/v1/ready.
Serves the production chart workspace when webui/dist/index.html exists (or WEBUI_DIST_DIR). Asset URLs use the /app/ base. If the dist is missing, responds with HTTP 503 and a professional enablement page (HTML by default; JSON when Accept: application/json) describing npm run build and restart.
API liveness check. Also available at GET /api/v1/health.
Search for available trading symbols.
- Query Params:
search(string, optional): Search query for symbol name/description.limit(int, optional): Max results to return.
- Response: Items use
symbol,group, anddescription; passsymboldirectly to history, tick, and analysis routes.
Get supported timeframes.
Fetch OHLCV candles for a symbol.
- Query Params:
symbol(string, required): e.g., "EURUSD".timeframe(string): Default "H1".limit(int): Number of bars (default 20, matching the data tool default).start,end(string, optional): ISO dates or relative strings.ohlcv(string): Column selector (default "ohlc").include_spread(bool): Append the historical candlespreadfield without changing the default row shape.include_incomplete(bool): Include the latest forming candle.allow_stale(bool): Return fetched history even when freshness validation fails (defaultfalse). This is an explicit research override; it does not make stale data suitable for live decisions. A forming bar is still included only wheninclude_incomplete=true.timestamp_format(epoch|iso|iso_utc): Requested timestamp encoding for returned rows. Defaultiso_utc(UTCZstrings).isorenders rows inCLIENT_TZ.detail(compact|standard|summary|full): Usefullfor diagnostics and runtime metadata.indicators(string, optional): Same compact spec asdata_fetch_candles(for exampleEMA(20), EMA(50), RSI(14), MACD(12,26,9)). Extra numeric columns are attached to each row using the display-normalized names (ema_20,rsi_14,macd_12_26_9,macd_h_12_26_9,macd_s_12_26_9).denoise_method(string, optional): Apply denoising (e.g., "ema").denoise_params(string, optional): JSON or comma-separatedk=vdenoising settings. Both forms acceptwhen,causality,keep_original, andcolumns; other keys are method parameters. Use JSON for multiple columns.
- Response Notes:
- Response
timestamp_formatdescribes the actual row representation asiso_utc,iso_offset, orepoch_seconds; see OUTPUT.md. - Compact responses expose
server_utc_offset_secondswhen available.detail=fullincludes the full runtime timezone tree undermeta.runtime.timezone. The legacyusedcompatibility field is not emitted. - When
indicatorsis set, compact responses keep the extra row columns plusindicator_columns(added names) andindicators_spec(normalized request). Unknown names fail the request; they are not silently dropped.
- Response
Get the latest quote using the same compact schema as market_ticker, including
mid/spread, ISO and epoch timestamps, and the usable_for_live_trading gate.
Healthy freshness telemetry is omitted; stale, closed, locked, or conflicting
quotes carry structured warnings.
Unavailable FX last and volume values are omitted rather than represented as zero.
- Query Params:
symbol(string, required).detail(compact|standard|summary|full): Response detail level (defaultcompact).
Calculate pivot points.
- Query Params:
symbol(string, required).timeframe(string): Default "H1".method(string): "classic", "fibonacci", "woodie", "camarilla", "demark".detail(compact|standard|summary|full): Response detail level (defaultcompact).
Compact confluence zones for chart overlays (price, type, score, optional range).
- Query:
symbol(required),pivot_timeframe(defaultD1),sr_timeframe(defaultauto).
Compact POC / VAH / VAL prices for the chart.
- Query:
symbol(required),timeframe(defaultH1).
Read-only open positions and pending orders for one symbol. No mutations.
- Query:
symbol(required).
Batched watchlist rows for the chart workspace. Cap is 20 symbols.
- Query:
symbols(comma-separated; omit to seed majors / top markets),timeframe(defaultH1),rank_by(watchlistkeeps requested order;live_price_change_pctandabs_live_price_change_pctrank forming-bar movers),limit(1–20). - Unusable quotes stay in ordinary watchlists and are marked
quote_not_live_ready; live-change rankings exclude them.
Read-only account / news / exposure summary. Individual sections may fail without failing the whole payload.
- Query: optional
symbolfor session status and related headlines.
Compose a preview-only research idea (session, forecast, volatility, one
barrier pair, optional confluence, sizing, dry-run trade_place). The
composer cannot send a live order. See TRADE_IDEAS.md.
- Body:
symbol(required),timeframe(defaultH1),horizon(default12),direction(auto/long/short),template(quick/standard),risk_pct(default0.5), optionalas_of,detail. - Response: compact
TradeIdeawithactionabilityofpreview_onlyorresearch. Historicalas_ofideas skip sizing and preview.
Also available at POST /api/v1/trade-ideas.
Identify support and resistance levels, plus Fibonacci retracement/extension levels from the most relevant completed swing.
- Query Params:
symbol(string, required).timeframe(string): Default"H1". Passautoto merge levels fromM15,H1,H4, andD1.lookback(int): History depth to analyze (default200, matching the support/resistance tool).tolerance_pct(float): Clustering tolerance in percentage points (default0.15, meaning 0.15%).min_touches(int): Minimum touches per level (default 2).max_levels(int): Max levels per side (default 4).max_distance_pct(float, optional): Percentage distance cap from current price (default5.0).volume_weighting(off|auto): Volume weighting mode (defaultoff).reaction_bars(int): Reaction window used for level qualification (default6).adx_period(int): ADX period used in scoring (default14).decay_half_life_bars(int, optional): Half-life for recency decay.detail(compact|standard|summary|full): Response detail level.
- Response Notes:
- The default response is compact: it returns actionable support/resistance lists and omits heavier diagnostics.
- Pass
detail=fullfor the rich shape described below. - Rich level rows include a price
zone_low/zone_highenvelope rather than only a single line. - Rich output includes
statusandbreakout_analysisfor broken levels and role-reversal confirmations. - In
automode, overlapping same-event confirmations across timeframes are deduped instead of fully double-counted. - Qualification now uses distinct test
episodes, while rawtouchesremain available as secondary detail. - Rich output includes both base and effective adaptive settings:
tolerance_pct/reaction_barsare the inputs, whileeffective_tolerance_pct/effective_reaction_barsreflect the current ATR regime. - Rich output includes a
fibonaccisection with retracement levels23.6%,38.2%,50%,61.8%,78.6%and extensions127.2%,161.8%, anchored to ATR-filtered historical swings and labeled relative to the latest price.
List available denoising algorithms and their parameters.
List available wavelet families/names (when PyWavelets is installed).
List available dimensionality reduction methods (PCA, UMAP, t-SNE, etc.) with parameter suggestions.
List available forecasting models and their requirements.
- Query Params:
detail(compact|standard|summary|full, defaultcompact).
List trained model artifacts currently available in the model store.
- Query Params:
method(optional method-name filter),detail(response detail level; defaultcompact) - Default response: compact model rows plus
count,detail_level, andsuccess; requestdetail=fullfor storage paths, timestamps, TTL, and artifact-size diagnostics.
List available volatility models and their requirements.
Generate price forecasts.
Body (JSON):
{
"symbol": "EURUSD",
"timeframe": "H1",
"library": "native",
"method": "theta",
"horizon": 12,
"lookback": null,
"as_of": null,
"start": null,
"end": null,
"params": {},
"ci_alpha": 0,
"quantity": "price",
"denoise": {
"method": "ema",
"params": {"alpha": 0.2}
},
"features": null,
"dimred": null,
"target_spec": null,
"async_mode": false,
"model_id": null,
"detail": "compact"
}librarysupports the same forecast libraries exposed by the forecast tool:native,statsforecast,sktime,mlforecast, andpretrained.- Use
as_offor a point-in-time cutoff orstart/endfor a bounded training range; do not combine those window styles. async_mode=truesubmits trainable methods to the Web API's persistent task runtime. A pending or already-running submission returns HTTP 202 with atask_idinstead of waiting for the fit. A duplicate in-flight identity is202withstatus=running.model_idreuses a compatible stored artifact instead of training a new one. Usedetail=fullwhen you need model and runtime diagnostics.
Generate volatility forecasts.
Body (JSON):
{
"symbol": "EURUSD",
"timeframe": "H1",
"horizon": 1,
"method": "ewma",
"proxy": null,
"params": {"lambda_": 0.94},
"as_of": null,
"start": null,
"end": null,
"denoise": null,
"detail": "compact"
}Use as_of or a start / end range, not both. detail=full includes the
richer volatility diagnostics supported by the selected method.
List registered MCP tools for the Web UI runner (bootstraps the full tool surface).
- Query Params:
category(canonical catalog ID),search,detail(compact|standard|full, defaultcompact),include_fields(bool),limit(default 20, max 1000),offset(default 0) - Unknown
categoryordetailvalues return HTTP 422 with the parameter name and valid values. An emptytoolsarray is reserved for a valid filter that matched nothing. - Response: a page of tools with top-level
detail_level,surface(dedicated_ui|generic_runner|intentional_omit) andsafetymetadata, pluspagination(total,returned,offset,limit,has_more,more_available).categoriesandsurfacescover the full filtered set, not only the current page.
Return one tool for the form runner.
- Query Params:
detail(compact|standard|full, defaultcompact),include_fields(bool, defaulttrue) - Compact keeps
name,description,safety, and the canonicalinput_schemaused to build the form. The wrapper reports the selected mode asdetail_level.detail=fulladds CLI bindings, module, and parameter metadata. Setinclude_fields=falseto omitinput_schema.
Invoke a registered tool.
{
"arguments": {
"symbol": "EURUSD",
"timeframe": "H1",
"detail": "full",
"output_fields": "symbol,summary"
},
"confirm": false
}Generic invocation uses the shared structured-output contract. Output is compact
by default; detail=full requests richer sections and adds related-tool
suggestions when the tool defines them. output_fields accepts comma-separated
names or dotted paths and keeps the standard envelope fields alongside each
match.
forecast_tune_genetic, forecast_tune_optuna, and wait_event are cataloged
as intentional_omit: they can run longer than an HTTP request and the generic
runner has no progress or cancellation contract. Run those tools through CLI or
MCP instead.
Bearer authentication is required for every invocation whose tool can mutate
trading or stored state, even when that request is a dry-run preview.
"confirm": true is a separate intent gate required only when the invocation
can actually mutate state.
Trade tools and destructive model/task tools that expose dry_run default
to preview (dry_run=true, including when the flag is omitted) and do
not need confirm. Live submission needs both "dry_run": false inside
arguments and "confirm": true, and remains subject to account
guardrails. forecast_task_cancel has no dry-run flag, so it always
needs confirm. See TRADING_SAFETY.md and
WEBUI_TOOL_COVERAGE.md.
A successful invoke returns HTTP 200 with {success: true, tool, surface, result}.
Every failed invoke returns HTTP 4xx/5xx with the canonical error envelope at
the top level: {success: false, error, error_code, operation, request_id}.
The envelope may include details. Confirmation blocks use error_code=confirmation_required
and keep requires_confirmation, safety, and hint under details. Unknown
tools use error_code=tool_not_found. Invalid parameters are 422, not-found codes
404, omitted long-running tools 403, MT5 connection failures 503, internal faults
500, and other domain failures 400. The wrapper never reports success=true
around a failed domain result.
Run a rolling-origin backtest.
Body (JSON):
{
"symbol": "EURUSD",
"timeframe": "H1",
"horizon": 12,
"steps": 20,
"spacing": 10,
"methods": ["theta", "naive"],
"params_per_method": null,
"quantity": "price",
"denoise": null,
"params": null,
"features": null,
"dimred": null,
"slippage_bps": 0.0,
"trade_threshold": 0.0,
"detail": "compact"
}Compact response shape is the default. Use detail=full when you need richer
sections such as per-anchor detail records and diagnostics.
Start the API server using the packaged entry point:
mtdata-webapiOr directly via Uvicorn (if installed):
uvicorn mtdata.core.web_api:app --host 127.0.0.1 --port 8000Control the server host and port via environment variables:
WEBAPI_HOST: Bind address (default127.0.0.1).WEBAPI_PORT: Listen port (default8000).WEBAPI_ALLOW_REMOTE: Set to1to allow non-loopback binds.WEBAPI_AUTH_TOKEN: Bearer/API key token required for authenticated API access.CORS_ORIGINS: Comma-separated list of explicit allowed origins.WEBUI_DIST_DIR: Override the built SPA directory (defaultwebui/dist, resolved from the process working directory). Use an absolute path when launching outside the repository root.
- SETUP.md — Install and run modes
- DEPLOYMENT.md — Long-lived local service
- CLI.md — Full tool surface via CLI
- OUTPUT.md — Shared payload contract
- TROUBLESHOOTING.md — Common issues