We're still building this. Field names may change before launch.

View as Markdown

Streaming

The per-account WebSocket protocol. Full sync, incremental updates, market data, sequence numbers and resume.

There are two ways to stream:

  • A socket.io protocol for existing clients that already speak it, alongside the /users/current/… REST API. See Switching from another provider.
  • Tickwire’s plain WebSocket protocol (this page): JSON frames, one socket per account, easy to use from any language without an SDK.

Connect

wss://api.tickwire.io/users/current/accounts/{accountId}/ws?auth-token=<token>

Or, better, leave the key out of the URL and send it as the auth-token (or X-API-Key, or Authorization: Bearer) header on the upgrade, if your client can set headers. Browsers can’t, so they use the query parameter; give a browser a short-lived scoped token, not a full key. See WebSockets: header or query parameter.

Subscribe

{
  "type": "subscribe",
  "sync": { "startingHistoryTime": "2026-09-01T00:00:00Z", "lastSeq": null },
  "marketData": [
    { "symbol": "EURUSD", "subscriptions": [
      { "type": "quotes", "intervalInMilliseconds": 500 },
      { "type": "candles", "timeframe": "1m" },
      { "type": "ticks" },
      { "type": "marketDepth" }
    ] }
  ]
}
  • sync.startingHistoryTime: send history (deals and history orders) from this time. null skips history.
  • sync.lastSeq: resume after a disconnect (below).
  • marketData: optional. ticks and marketDepth are MT5 only.

Send {"type": "unsubscribe", "marketData": [...]} to drop market data, and {"type": "ping"} whenever you like; you’ll get pong.

Frames

Every server frame has type, seq (increasing by one per frame) and time (UTC).

Full synchronization, in this order:

FrameCarries
synchronizationStarted—
accountInformationaccountInformation
positionsthe full list (replace yours)
ordersthe full list of pending orders (replace yours)
historyOrdersa batch; may repeat
dealsa batch; may repeat
positionsSynchronized, ordersSynchronized, historyOrdersSynchronized, dealsSynchronized—
synchronizedYour state is complete

Incremental updates after that: accountInformationUpdated, positionUpdated, positionRemoved, orderUpdated, orderCompleted, historyOrderAdded, dealAdded.

Market data: prices (with the account’s equity, margin, freeMargin and marginLevel), candles, ticks and book.

Status: health (our health snapshot) whenever it changes, and brokerConnectionStatus with connected: true|false.

Warnings: warning, for example when you read too slowly (below).

{ "type": "positionUpdated", "seq": 1842, "time": "2026-09-23T11:02:14.120Z",
  "position": { "id": "46870472", "symbol": "EURUSD", "type": "POSITION_TYPE_BUY", "volume": 0.01,
                "openPrice": 1.07182, "profit": 0.42, "brokerTime": "2026-09-23 14:02:14.120" } }

Resume after a disconnect

Remember the last seq you processed. Reconnect and subscribe with "lastSeq": <that seq>:

  • If we still hold the frames after it, we replay them and carry on. No gap, no full sync.
  • If not, we run a full synchronization. Replace your state when synchronized arrives.

Slow consumers

If you don’t read fast enough, we don’t buffer forever. We drop frames and send:

{ "type": "warning", "seq": 2210, "code": "slow_consumer", "firstMissingSeq": 2011 }

Reconnect with lastSeq: 2010 to get the missing frames back, or accept a fresh sync.

Heartbeats

We send a frame at least every 15 seconds, a health frame if nothing else is happening. If you hear nothing for 60 seconds, reconnect.