We're still building this. Field names may change before launch.
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.nullskips history.sync.lastSeq: resume after a disconnect (below).marketData: optional.ticksandmarketDepthare 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:
| Frame | Carries |
|---|---|
synchronizationStarted | — |
accountInformation | accountInformation |
positions | the full list (replace yours) |
orders | the full list of pending orders (replace yours) |
historyOrders | a batch; may repeat |
deals | a batch; may repeat |
positionsSynchronized, ordersSynchronized, historyOrdersSynchronized, dealsSynchronized | — |
synchronized | Your 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
synchronizedarrives.
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.