What a MetaTrader 5 REST API Actually Looks Like
There's no native MetaTrader 5 REST API — MT5 speaks a binary desktop protocol. Here's the mental model for the hosted kind, one worked example end to end, and the three things that trip developers up.
You searched for a MetaTrader 5 REST API, and somewhere around the third
result you learned the awkward truth: there isn't one. MT5 talks to its broker
over a binary protocol between the desktop terminal and the server — there's
no HTTP endpoint to call, and the official MetaTrader5 Python package just
drives a local terminal over IPC.
So when people say "MT5 REST API," they mean a hosted service that runs the MT5 side and re-exposes it as REST + WebSocket. This post isn't the endpoint reference (that's what the docs are for) — it's the mental model, one example end to end, and the handful of things that actually trip developers up.
The one idea that makes it click
Almost every mistake I see comes from missing a single distinction: REST is how you drive the account; the WebSocket is how you watch it.
Get this split right and the rest of the API almost designs itself. Get it wrong
and you end up polling GET /prices in a loop, hammering the API for data the
WebSocket would have pushed you for free.
One example, start to finish
Forget the endpoint catalog. Here's a complete, realistic slice: connect, check you can afford the trade, place it with a stop and target, then watch the position live. That's REST, REST, REST, then WebSocket — the whole model in one screen.
from tickerall import Tickerall
client = Tickerall(api_key="cf_...")
# 1. Connect once. Every later call rides this session — you never resend the password.
session = client.sessions.start(
broker="mt5", server="Your-Broker-Server", account=12345678, password="...",
)
acc = session.account_id
# 2. Drive: read state before you act.
info = client.accounts.get(acc)
if info.free_margin < 200:
raise SystemExit("not enough free margin")
# 3. Drive: place a guarded entry. The result comes straight back — no polling.
order = client.orders.place(acc, symbol="EURUSD", side="buy",
volume=0.10, sl=1.0850, tp=1.0950)
print("filled", order.ticket, "at", order.price)
# 4. Watch: react to the position over the stream instead of re-fetching it.
stream = client.stream.connect()
stream.on("position", lambda p: print(p.ticket, "P/L", p.profit))
stream.subscribe_positions(acc)
Every line maps to the model: steps 1–3 drive the account (each a single request that returns a result), and step 4 watches it (the server pushes updates as the market moves). No terminal, no polling loop, no binary protocol — just an HTTP client and a socket.
Three things that trip people up
1. Connect once, then reuse. The sessions.start call is the only place a
password appears. After that, the account is warm and every request and the
stream ride that session. If you find yourself re-authenticating per call, you've
misunderstood the lifecycle — and you're paying a connection cost on every trade.
2. Don't poll what you can stream. The single most common performance
mistake is calling GET on prices or positions in a tight loop. Prices are a
firehose; that's what the WebSocket is for. Poll on-demand facts (candles,
account snapshot); subscribe to anything that changes on its own.
A good rule: if you'd refresh it by hitting F5, it's REST. If you'd sit and watch it, it's the WebSocket.
3. A trade result is synchronous. orders.place returns the fill — ticket,
price, status — in the response. You don't submit an order and then poll to find
out what happened. The hosted terminal does the round-trip to your broker over
MT5's native protocol and hands you the clean result. (The position's later
life — its moving P/L, its close — is the streaming part.)
Why it's shaped this way
A native app has to speak MT5's wire protocol, manage a stateful socket, and run a terminal. Collapsing all of that into "one bearer token, REST to drive, WebSocket to watch" is the entire value of a hosted API — and it's why the same integration runs unchanged on Linux, in a container, or in CI. (For the why behind skipping a local terminal, see Running MetaTrader 5 from Python on Linux.)
Wrapping up
There's no MetaTrader 5 REST API in the box because MT5 isn't an HTTP service. But the hosted shape is small and predictable: authenticate with a key, connect a session once, drive the account over REST, and watch it over a WebSocket. Hold that model in your head and the full reference reads like a formality.