MT5 — Real-time (subscriptions & WebSocket)

Real-time data is a two-step model:

  1. Tell the terminal what to stream with the REST subscription endpoints below (keyed by instance id (UUID), not the MT5 login).
  2. Receive the stream by connecting a WebSocket client to /ws/service and subscribing to the relevant channels.

Subscribe to ticks

POST /api/external/instances/{instanceId}/subscribe-tick — body { "symbol": "EURUSD" }. {instanceId} is the instance id (UUID).

curl -s -X POST "$ATLAS_BASE_URL/api/external/instances/$INSTANCE_ID/subscribe-tick" \
  -H "Authorization: Bearer $ATLAS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "symbol": "EURUSD" }'

Unsubscribe from ticks

POST /api/external/instances/{instanceId}/unsubscribe-tick — { "symbol": "EURUSD" }, or an empty body to unsubscribe from all.

List tick subscriptions

GET /api/external/instances/{instanceId}/tick-subscriptions

Subscribe to candles

POST /api/external/instances/{instanceId}/subscribe-candle — { "symbol": "EURUSD", "timeframe": "M15" }.

Unsubscribe from candles

POST /api/external/instances/{instanceId}/unsubscribe-candle — { "symbol", "timeframe" }, or empty body for all.

List candle subscriptions

GET /api/external/instances/{instanceId}/candle-subscriptions

WebSocket stream — /ws/service

Connect, authenticate with your service key, then subscribe to channels. The server pings periodically; reply with {"type":"pong"} to stay connected.

const ws = new WebSocket("wss://api.atlaas.dev/ws/service")

ws.onopen = () => {
  // 1. Authenticate
  ws.send(JSON.stringify({ type: "service_auth", apiKey: process.env.ATLAS_API_KEY, clientName: "my-bot" }))
}

ws.onmessage = (e) => {
  const msg = JSON.parse(e.data)
  switch (msg.type) {
    case "hello_from_atlas":      break // greeting; authRequired: true
    case "service_auth_success":  // { accountId, accountName, ts }
      // 2. Subscribe to channels (optionally filter by accountIds / symbols)
      ws.send(JSON.stringify({
        type: "subscribe",
        channels: ["ticks", "candles", "positions", "trades", "orders"],
        accountIds: ["5012345"],
        symbols: ["EURUSD"]
      }))
      break
    case "service_auth_failed":   break // { reason }
    case "subscribed":            break // echo of your subscription
    case "ping":                  ws.send(JSON.stringify({ type: "pong" })); break
    case "mt5_tick":              break // { accountId, symbol, bid, ask, ts }
    case "mt5_candle":            break // { accountId, symbol, timeframe, open, high, low, close, volume, isNew, ts }
    case "mt5_position_update":   break // { accountId, balance, equity, margin, freeMargin, positions: [...] }
    case "mt5_trade_event":       break // { accountId, symbol, orderType, orderState, volume, price, ... }
  }
}

Subscribe message

{
  "type": "subscribe",
  "channels": ["ticks", "candles", "positions", "trades", "orders"],
  "accountIds": ["5012345"],
  "symbols": ["EURUSD"]
}

You only ever receive events from terminals and broker connections your account owns. If accountIds, brokerConnectionIds or brokerOrderConnectionIds names one you don't own, it is left out of the filter and listed in the subscribed reply under refusedAccountIds, refusedBrokerConnectionIds or refusedBrokerOrderConnectionIds.

Unsubscribe with { "type": "unsubscribe", "channels": [...] }.