Skip to Content
MT5 TraderAPI Reference

API Reference

All endpoints are served by FastAPI at 127.0.0.1:8000. Interactive OpenAPI docs are available at GET /docs. Signal endpoints require the X-API-Key header (compared in constant time); a missing or wrong key returns 401 and logs only whether a key was present.

Endpoints

Method & pathAuthPurpose
POST /v1/signalsX-API-KeyValidate and execute a signal (idempotent by signal_id).
GET /v1/signals/{signal_id}X-API-KeyRetrieve the durable stored state of a signal.
GET /health/livenoneLiveness — the process is running.
GET /health/readynoneReadiness — terminal connected and TRADING_ENABLED=true (else 503).

Submitting a signal

POST /v1/signals. Required fields: signal_id, occurred_at, execution_type, symbol, direction, volume. entry_price is required for limit and stop, and prohibited for market. Optional: stop_loss, take_profit, expires_at, deviation_points, note. Unknown fields are rejected (extra="forbid"), and timestamps must be timezone-aware.

FieldTypeNotes
signal_idstring (UUID)Idempotency key. Never reuse with changed fields.
occurred_atRFC 3339 datetimeWhen the signal fired; used for freshness checks.
execution_typemarket | limit | stopOrder type.
symbolstringExact, case-sensitive broker symbol (must be in ALLOWED_SYMBOLS).
directionbuy | sellTrade side.
volumedecimal stringLots; validated against the broker volume step and MAXIMUM_VOLUME.
entry_pricedecimal stringRequired for limit/stop, prohibited for market.
stop_loss, take_profitdecimal stringOptional; validated for precision and stop distance.
expires_atRFC 3339 datetimeOptional expiry for pending orders.
deviation_pointsintegerOptional slippage cap (bounded by MAX_DEVIATION_POINTS).
notestringOptional free-text tag.

Example — market entry

{ "signal_id": "3a939594-f36e-4dc7-96a5-97e84e21c36e", "occurred_at": "2026-07-14T15:00:00Z", "execution_type": "market", "symbol": "EURUSD", "direction": "buy", "volume": "0.10", "stop_loss": "1.08000", "take_profit": "1.10000", "deviation_points": 10, "note": "strategy-a breakout" }

Example — expiring pending (limit) entry

{ "signal_id": "c0c95e51-13d4-4567-b543-a0e41098f008", "occurred_at": "2026-07-14T15:00:00Z", "execution_type": "limit", "symbol": "EURUSD", "direction": "buy", "volume": "0.10", "entry_price": "1.08500", "expires_at": "2026-07-14T18:00:00Z" }

Example — client call (PowerShell)

$headers = @{ "X-API-Key" = $env:API_KEY } $body = Get-Content .\signal.json -Raw Invoke-RestMethod -Method Post -Uri http://127.0.0.1:8000/v1/signals ` -Headers $headers -ContentType "application/json" -Body $body

Response statuses

A successful response reports one of these states, plus broker tickets and the normalized result:

StateMeaning
filledThe order was fully executed.
partially_filledThe order was partially executed.
placedA pending (limit/stop) order was accepted and is resting.

GET /v1/signals/{signal_id} returns the durable stored state, including terminal states like rejected and unknown.

Error codes

HTTPCodeWhen
401Missing or invalid X-API-Key.
409idempotency_conflictSame signal_id re-sent with a different payload.
409signal_in_progressThe same signal is still being processed.
422validation errorPayload failed Pydantic validation (bad/missing fields, wrong types).
422preflight_rejectedThe broker’s order_check() preflight returned a nonzero retcode.
503not readyReadiness failed — terminal disconnected or TRADING_ENABLED=false.
503execution_outcome_unknownorder_send() result is ambiguous. The order is not retried — a human must inspect.

Idempotency contract. Re-sending an identical payload for a completed signal_id replays the stored response (or re-raises the stored error) — it never places a second trade. Changing any field for an existing signal_id is a 409 idempotency_conflict.

See Architecture for how these outcomes are produced and reconciled.

Last updated on