# FxSocket

This project uses FxSocket, a cloud API for MetaTrader 4 and MetaTrader 5. Every linked broker account runs in its own MT4 or MT5 terminal in FxSocket's cloud and is controlled over REST and WebSocket. Read the docs instead of guessing endpoints or field names:

- All docs in one file: https://fxsocket.com/llms-full.txt
- Any docs page as Markdown: append .md to its URL, e.g. https://fxsocket.com/docs/mt5/trading.md

## SDKs and keys

- Prefer the official SDKs over raw HTTP. Python: `pip install fxsocket` (`Client`, `AsyncClient`). Node.js / TypeScript: `npm install @fxsocket/sdk` (`FxSocket`). One interface covers MT4 and MT5.
- Both SDKs read the key from the `FXSOCKET_API_KEY` environment variable. Never hardcode an API key or commit one.
- `fxs_live_` keys can trade. `fxs_ro_` keys are read-only: GET endpoints only, and they can be limited to selected accounts. Use a read-only key for anything that only reads.

## URLs and auth

- Platform API: https://api.fxsocket.com/v1 (accounts, multi-account orders, wallet). OpenAPI spec: https://api.fxsocket.com/v1/schema
- Per-account terminal API: https://api.fxsocket.com/mt5/{account_id}/... or https://api.fxsocket.com/mt4/{account_id}/... where {account_id} is the UUID from GET /v1/accounts. Each account serves its own OpenAPI spec at .../api-doc/openapi.json (no key needed).
- Send the key in the `X-API-Key` header. Terminal routes do not accept `Authorization: Bearer`; /v1 and the MCP server do.
- WebSocket: wss://api.fxsocket.com/mt5/{account_id}/ws?api_key=... (the query parameter is the only auth WebSocket supports). One socket per account, topics prices, bars, account, positions, trades, terminal. Prefer it over polling REST.

## Before sending orders

- A new account reads `connecting` for 1 to 3 minutes. Wait for `connected` on GET /v1/accounts/{account_id} and `ready` on GET /status before trading.
- Symbol names are broker-specific (EURUSD, EURUSD.sd, EURUSDm). Get the exact name from GET /symbols; never assume the plain name.
- Read GET /SymbolInfo first: keep volume within volumeMin, volumeMax and volumeStep, and round prices to `digits`.
- Timestamps are broker server time even though they end in Z. Convert with GET /ServerTimezone: utc = serverTime - utcOffsetSeconds.

## Order results

- HTTP 200 from OrderSend, OrderModify or OrderClose only means the terminal answered. Check `success` and `retcode`: 10009 is done, 10008 is placed, anything else is a rejection (report `retcodeDescription`). 10025 on a modify means nothing changed because the values were already set.
- A 500 or 504 with an error envelope can still mean the order executed. Check GET /OpenedOrders before sending again; never retry an order blindly.
- To trade many accounts at once use POST /v1/orders and POST /v1/orders/close (at most 20 legs or accounts, snake_case fields, unknown fields are a 400). Send an `Idempotency-Key` header so a retry cannot trade twice.

## Errors

- 401 `MRPC_UNAUTHORIZED`: missing or wrong key. 404: unknown account_id or path.
- Other errors use `{"error", "message", "command_id"}`. A 5xx without that envelope means the terminal is restarting (for example right after a key rotation): retry with backoff. Trading routes can return 503 briefly after a terminal starts.
- /v1 answers 429 with a `Retry-After` header when rate limited. Wait that long.

## Safety

- Build and test against a demo account.
- Do not place, modify or close orders on a live account unless the user explicitly asks for it.
