- every execution, including each partial fill of an order that is still working
- order changes (submitted, cancelled)
- position updates (net quantity, average price, open P&L, version)
- account updates (balance, equity, P&L, drawdown, status)
- rule violations
The stream is enabled per organization. Contact us to turn it on for yours.
Until it is enabled, connections are refused with HTTP 403.
How it compares
Use the trading stream for what is happening now and webhooks or REST for the
durable record. Many integrations use both.
Connect
X-API-Key header of the
WebSocket handshake. The key is not accepted in the query string.
If the handshake is refused, the response body is JSON with an
error
message:
Frames
Every message is one JSON object with atype. Event frames share this
envelope:
execution
One frame per execution. A 5-lot limit order filled 2 then 3 produces two
frames, each with its own executionId, executedQuantity and
executedPrice, and the order’s running state after that execution.
order.status is partially_filled while the order is still working and
filled on its last execution. accountBalanceAfter is the account balance
right after this execution.
order
Order changes other than executions. data.change is submitted or
cancelled; data.order has the same fields as execution.data.order.
position
The position in one contract after a change. It follows the execution frame
that caused it.
Open positions are re-marked about once a second while the market moves
(
reason: "mark"). Pass marks=false if you only want changes caused by
executions.
account
failed or passed) arrives as an account
frame with the new status. Updates where only open P&L moved are marks and
are dropped by marks=false.
rule_violation
Control frames
Ordering and delivery
- Frames for one account arrive in the order they happened. Frames of different accounts can interleave.
- The live stream delivers each event once. After a reconnect with
resume, events can be repeated: deduplicate executions bydata.executionIdand other frames byid. - Apply positions by
versionand treatexecutionframes as the source of truth for executed quantity.
Resume after a reconnect
The stream keeps a short replay window (the last 5 minutes, up to 20,000 events, per organization). Store theid of the last frame you processed and
reconnect with it:
resume.complete, then live
frames, with no gap and no overlap between the two. If the id is outside the
window you get resume.unavailable: fetch current state over REST (below) and
continue from the live frames.
Reconcile over REST
- Balance, equity and status:
GET /platform/v1/organization/trading-accounts/{accountId} - Executions:
GET /platform/v1/organization/trading-accounts/{accountId}/order-events?eventType=fill_partial,fill_final - Finished orders for the day:
GET /platform/v1/organization/snapshots/fills
Limits
Read frames as fast as they arrive. If a connection falls behind and its
backlog passes the limit, the stream closes it with code
4008 rather than
let it slow down anyone else. Reconnect with resume to catch up.
Close codes
Reconnect with exponential backoff (for example 0.5 s, 1 s, 2 s … up to 30 s,
with jitter), except after
4001.
Example clients
Measuring latency
Eachexecution carries executedAt (when the execution happened) and
receivedAt (when the stream received it). Compare executedAt with your own
receive time to measure delivery to your system. Keep your server clock
synchronized (NTP) for meaningful numbers.