Quickstart
From an API key to a filled order, in about five minutes.
You need an API key (create one in the console),
an MT5 account number, its trading password, and the server name exactly as
MetaTrader shows it — VantageMarkets-Demo, ICMarkets-Demo. Use a demo
account the first time.
The investor password will not work. It can read an account but cannot trade, and the login succeeds — so the failure arrives later, as a rejected order.
Set your key
export FXAPIS_KEY="fx_live_7f3a9c21_your-secret-here"
export FXAPIS_API="https://api.fxapis.com"Keys are server-to-server credentials. Keep them out of browsers, apps and repositories. See Authentication.
Connect the account
# Keeps the new account's id for the next steps (uses jq; or copy data.id by hand).
export FXAPIS_ACCOUNT=$(curl -sS -X POST "$FXAPIS_API/v1/accounts" \
-H "Authorization: Bearer $FXAPIS_KEY" \
-H "Content-Type: application/json" \
-d '{
"login": "26177561",
"server": "VantageMarkets-Demo",
"password": "your-mt5-trading-password",
"mode": "warm_on_demand",
"label": "Demo — strategy A"
}' | jq -r .data.id)This stores the account and does not log in yet. The password is encrypted under a key bound to this one account and is never returned by any endpoint.
Bring it online
curl -sS -X POST "$FXAPIS_API/v1/accounts/$FXAPIS_ACCOUNT/warm" \
-H "Authorization: Bearer $FXAPIS_KEY"
until curl -sS "$FXAPIS_API/v1/accounts/$FXAPIS_ACCOUNT/status" \
-H "Authorization: Bearer $FXAPIS_KEY" | grep -q '"ready"'
do sleep 2; donewarm answers 202 at once, while the account logs in at the broker. Its
state moves through starting, connecting and synchronizing to ready, in
about 10 seconds in our measurement. Only ready accepts orders.
Place an order
curl -sS -X POST "$FXAPIS_API/v1/accounts/$FXAPIS_ACCOUNT/orders/market" \
-H "Authorization: Bearer $FXAPIS_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{ "symbol": "EURUSD", "side": "buy", "volume": "0.01" }'{
"data": {
"id": "b1c7…9e2a",
"symbol": "EURUSD",
"side": "buy",
"volume": "0.01",
"state": "filled",
"filledPrice": "1.13426",
"brokerOrderId": "2109584418"
}
}Volumes and prices are strings, never floats. Keep the Idempotency-Key if you
retry: the same key never places a second order. An order ends filled,
rejected, or unknown while it is reconciled against the broker — see
Trading.
Close it
# Positions refresh by themselves about every 15 s; reconcile refreshes them now.
curl -sS -X POST "$FXAPIS_API/v1/accounts/$FXAPIS_ACCOUNT/reconcile" -H "Authorization: Bearer $FXAPIS_KEY"
export POSITION_TICKET=$(curl -sS "$FXAPIS_API/v1/accounts/$FXAPIS_ACCOUNT/positions" \
-H "Authorization: Bearer $FXAPIS_KEY" | jq -r '.data[0].brokerPositionId')
curl -sS -X POST "$FXAPIS_API/v1/accounts/$FXAPIS_ACCOUNT/positions/$POSITION_TICKET/close" \
-H "Authorization: Bearer $FXAPIS_KEY" -H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" -d '{}'A warm_on_demand account goes offline by itself after a quiet spell with no
orders; POST /cool takes it offline now.
Stop losses and take profits live at the broker and keep working while the
account is offline.
If it does not reach ready
| State | Meaning | What to do |
|---|---|---|
invalid_credentials | The broker rejected the login | Fix the password and reconnect. Do not retry — repeated failures are how a broker locks an account. |
needs_2fa | The account requires a second factor | Not supported headlessly. Disable 2FA or use another account. |
needs_certificate | The broker requires a client certificate | Contact us. |
trading_disabled | Login worked, trading is off | The broker has disabled trading for this login. (An investor password instead reaches ready and its orders are rejected.) Ask the broker to enable trading. |
error | Something temporary | Retryable. Bring it online again. |
Next
- Use an SDK. The official TypeScript and Python SDKs wrap these same calls, with typed errors and idempotency keys built in — walkthroughs for TypeScript and Python.
- Run a complete example. fxapis-examples has this quickstart, click-to-trade and a trade copier in Python, Node/TypeScript and curl, and the Next.js starter is a small working app (how to run the examples, how the starter is built).
- Stop polling. Webhooks send a signed
POSTto your server when an order fills, a position closes or an account changes state. - Go deeper. Trading covers every outcome an order can have, and the guides have complete programs in seven languages.