User Data Streams
User Data Streams Overview
Executions, order changes, position changes and balance changes, pushed as they happen.
This is the only low-latency way to learn that an order filled. POST /v1/order with the
default ACK tells you the order was accepted; the fill arrives here.
Connect
- Create a listenKey:
POST /v1/listenKey. - Connect to:
wss://trade-stream.yellowboxmarkets.com/ws/<listenKey>- Keep the key alive with
PUT /v1/listenKeyevery 30 minutes.
There is no SUBSCRIBE step. The connection starts delivering immediately and carries everything
in the key's scope — exactly the logins GET /v1/accounts lists. A login
the REST endpoints would answer -2022 for (for example an archived account) is not streamed either.
The connection limits are the same as the market streams: server ping every 3 minutes, dropped after 10 minutes without a pong, 24-hour maximum lifetime, 10 inbound messages per second (inbound messages are otherwise ignored on this stream). See websocket-market-streams.md § Connection limits.
- A listenKey that is unknown, expired or deleted is not refused at the HTTP level: the connection
opens, receives one
listenKeyExpiredevent and is closed. - While the trading surface is switched off, the upgrade is refused with HTTP 503 and
-1017.
Common fields
Every event carries these three:
| Field | Type | Description |
|---|---|---|
e |
STRING | Event type. |
E |
LONG | Event time, Unix ms. |
L |
LONG | MT5 login the event belongs to. |
listenKeyExpired is the exception — it is a connection-level event and carries no L.
Ordering
- Events for one login are ordered by
E.Eis non-decreasing within a login. - There is no ordering guarantee across logins. One login's events may interleave arbitrarily
with another's. Do not use
Eas a global sequence. DEAL,ORDER_UPDATEandPOSITION_UPDATEdescribing the same fill can arrive in any order relative to each other, and can share anE. Do not build a state machine that requiresDEALbeforePOSITION_UPDATE.DEALcan repeat. Dedupe ond.ORDER_UPDATEandPOSITION_UPDATEcan also repeat with identical content; treat them as state snapshots, applying the latest byE, rather than as deltas.
Because they are snapshots, an out-of-order or duplicate POSITION_UPDATE is harmless if you
compare E and keep the newest — which is the recommended way to hold position state.
Connection close
Besides the ordinary cases — you closed it, the 24-hour lifetime elapsed, the server restarted — two closes carry a reason you should act on. The reason is the WebSocket close frame's description, not a JSON event.
| Close code | Reason | What happened | What to do |
|---|---|---|---|
1011 |
queue overflow; resnapshot |
Your connection was not reading fast enough and the server's outbound buffer for it filled — or the server's own intake for your logins fell behind under a burst. The alternative was to drop frames silently, and this stream has no sequence number, so you could not have detected that. | Assume you missed events, including fills. Reconnect, then resnapshot (below) before trusting your state, and read GET /v1/userTrades from your last dealId. |
1008 |
scope empty; check /v1/accounts |
Every account the API key could see has left its scope — the accounts were closed, their owner was disabled, or the key's configuration changed. Nothing can be delivered on this connection any more. | Do not reconnect in a loop. Read GET /v1/accounts; if it is empty, the key has no accounts and this is an operator change, not a fault. |
The scope is re-checked while a connection is open, not only when it is accepted: a login removed from the key's scope stops delivering within about 30 seconds, matching when REST stops answering for it. The connection stays open as long as at least one login remains.
Reconnect
Events that occurred while you were disconnected are not replayed. There is no sequence number to resume from and no backfill.
After any reconnect — a new listenKey, a dropped connection, the 24-hour lifetime, a process restart — resnapshot before trusting your state:
GET /v1/positions?login=... per login in scope
GET /v1/openOrders?login=... per login in scopeThen apply stream events on top, keeping the newest E per entity.
For executions you may have missed, read
GET /v1/userTrades with fromId set to the last
dealId you processed. That is the durable record; the stream is the fast one.
Reconnect with exponential backoff and jitter.
listenKey management
Base URL https://trade-api.yellowboxmarkets.com. Conventions, signing and error format:
General Info.
These three endpoints manage the listenKey that authenticates a user data stream connection. The events themselves are documented in User Data Streams Overview.
| Endpoint | Security | Weight |
|---|---|---|
POST /v1/listenKey |
USER_STREAM |
1 |
PUT /v1/listenKey |
USER_STREAM |
1 |
DELETE /v1/listenKey |
USER_STREAM |
1 |
USER_STREAM endpoints need the X-YBX-APIKEY header but no signature — there is nothing to
sign, and the key itself is the credential. They take no login: one listenKey covers every
login the key may trade.


