WebSocket Market Streams
WebSocket Market Streams Overview
Live prices, candles and statistics. Market streams are public — no API key, no signature, no
login. Account events are on a separate, authenticated connection:
User Data Streams Overview.
Endpoints
| Form | URL |
|---|---|
| Raw | wss://trade-stream.yellowboxmarkets.com/ws |
| Raw, pre-subscribed | wss://trade-stream.yellowboxmarkets.com/ws/XAUUSD@tick |
| Combined | wss://trade-stream.yellowboxmarkets.com/stream?streams=XAUUSD@tick/BTCUSD@kline_1m |
On the raw endpoint, payloads arrive exactly as documented below.
On the combined endpoint, every payload is wrapped:
{"stream":"XAUUSD@tick","data":{"e":"tick","E":1789012345678,"s":"XAUUSD","b":"2331.15","a":"2331.42","l":"2331.15","v":8,"bd":1,"ad":-1,"T":1789012345678}}Streams in the streams= query parameter are separated by /. URL-encode the value if a symbol
name contains a character that needs it.
Subscribe protocol
Send JSON text frames.
SUBSCRIBE
{"method":"SUBSCRIBE","params":["XAUUSD@tick","BTCUSD@kline_1m"],"id":1}{"result":null,"id":1}UNSUBSCRIBE
{"method":"UNSUBSCRIBE","params":["XAUUSD@tick"],"id":2}{"result":null,"id":2}LIST_SUBSCRIPTIONS
{"method":"LIST_SUBSCRIPTIONS","id":3}{"result":["BTCUSD@kline_1m"],"id":3}Request fields
| Field | Type | Mandatory | Description |
|---|---|---|---|
method |
STRING | YES | SUBSCRIBE, UNSUBSCRIBE or LIST_SUBSCRIPTIONS. |
params |
ARRAY of STRING | conditional | Stream names. Required for SUBSCRIBE / UNSUBSCRIBE. |
id |
UNSIGNED INT | YES | Chosen by you. Echoed on the response so you can correlate. Reuse is allowed but makes correlation ambiguous. |
Error frames
{"code":-1121,"msg":"Invalid symbol.","id":1}{"code":-1120,"msg":"Invalid interval.","id":4}{"code":-1101,"msg":"Too many parameters sent for this endpoint.","id":5}| Code | When |
|---|---|
-1121 |
A stream name whose symbol does not exist (exact case), or that is malformed or of an unknown stream type. |
-1120 |
A kline_ stream with an unsupported interval. |
-1101 |
The subscription would exceed 200 streams on the connection. |
-1102 |
id, method or (for SUBSCRIBE / UNSUBSCRIBE) params missing or of the wrong type. When id itself is unusable the frame carries "id":null. |
-1020 |
An unknown method. |
-1130 |
The frame is not a JSON object. "id":null. |
An error frame never closes the connection. UNSUBSCRIBE of a stream you are not subscribed to is a
no-op and answers success.
A SUBSCRIBE with several params is all-or-nothing: if one name is invalid the whole frame is
rejected and nothing is subscribed. Subscribe in small batches so one bad symbol does not cost you
the rest.
Codes are the same ones documented in Error Codes.
Connection limits
| Limit | Value |
|---|---|
| Ping frame from the server | every 3 minutes |
| Disconnect if no pong | after 10 minutes without one |
| Maximum connection lifetime | 24 hours |
| Streams per connection | 200 |
| Inbound messages per second | 10 |
| Concurrent connections per client IP | 20 |
- Reply to every WebSocket ping frame with a pong. Most client libraries do this automatically; verify yours does. A missed pong window costs you the connection.
- You may send unsolicited pong frames as a heartbeat; they are ignored and do not count toward the message rate.
- A connection is closed at 24 hours regardless of activity. Reconnect before then. Overlap the connections — open the new one, subscribe, then drop the old one — so you do not miss ticks.
- Exceeding 10 inbound messages per second closes the connection immediately. Batch stream names
into one
SUBSCRIBErather than sending one frame per stream. - Exceeding 200 streams returns
-1101and subscribes nothing. - A connection beyond the per-IP limit — or beyond the service's overall capacity — is refused
before the WebSocket upgrade with HTTP 503 and
-1008. Put your streams on fewer connections (up to 200 each) rather than opening one per symbol. - A plain HTTP request (no WebSocket upgrade) to a stream URL is answered HTTP 400 with
-1020. - An inbound message larger than 64 KB closes the connection.
- On the pre-subscribed and combined URLs, an invalid stream name in the URL is answered with
one error frame (as above,
"id":null) and the connection is then closed — nothing is subscribed.
The server closes a connection with these WebSocket close codes:
| Close code | Reason | Cause |
|---|---|---|
1000 |
connection lifetime reached |
The 24-hour lifetime elapsed (or the service is restarting). |
1000 |
invalid stream name |
An invalid name in a pre-subscribed or combined URL. |
1008 |
message rate exceeded |
More than 10 inbound messages in one second. |
1009 |
frame too large |
An inbound message over 64 KB. |
There are no rate-limit weight headers on WebSocket. Market streams do not consume REST request weight, which is exactly why you should use them instead of polling.
Reconnect guidance
Market streams carry no state and are not replayed. On reconnect:
- Re-subscribe to everything you had.
LIST_SUBSCRIPTIONSon the new connection is the way to verify, not to discover. - Refresh anything you were accumulating from the stream: candles from
GET /v1/klines, and any last-price cache fromGET /v1/ticker/price. - Assume you missed ticks during the gap. Never derive position state from the tick stream — read
it from
GET /v1/positions.
Reconnect with backoff and jitter. A fleet of bots reconnecting in lockstep after a restart is self-inflicted load.


