Developer Portal

Websocket API

Real-time streaming — quotes, depth, account metrics, and execution events over a single WebSocket connection, authenticated or as a guest.

View as Markdown

The Trader WebSocket API delivers real-time market data and account events over a single connection. Authenticated connections get the full surface; guests get public quotes without signing in.

Connect

wss://<trader-host>/api/v1/ws?token=<JWT>

Pass the JWT obtained from POST /api/v1/login as the token query parameter. Connections without a valid token are closed immediately. Respond to server pings with WebSocket pong frames to keep the connection alive.

Guest connections (no auth)

wss://<trader-host>/public/ws

No token is required. Note the path sits at the root, outside /api/v1. Guest access is enabled by default; a deployment may turn it off, in which case the path returns HTTP 404.

Guests share the envelope and the subscribe / unsubscribe flow below, with these limits:

  • Only subscribe and unsubscribe are accepted. Any other message type is answered with an error ("guest connections only support quote subscriptions").
  • Only quoteEvent is delivered. Other requested event types are dropped from the acknowledged subscription.
  • Only active symbols can be subscribed — unknown or inactive IDs are omitted from the acknowledgement.
  • At most 10 concurrent connections per client IP. Connection-limit and rate-limit rejections return HTTP 429 before the upgrade; invalid handshakes return HTTP 400.

Message envelope

Every message — client → server and server → client — uses the same envelope:

{ "type": "<message-type>", "payload": { ... } }

The type field selects the payload schema below.

Client → server messages

TypePurposePayload
subscribeSubscribe to quote / execution / portfolio events for a symbol list{ symbols: string[], events: ("quoteEvent" | "executionEvent" | "portfolioEvent")[] }
unsubscribeStop a subscribe stream{ symbols: string[], events: string[] }
depthSubscribeSubscribe to order-book depth for a symbol{ symbol: string, depth?: number }
depthUnsubscribeStop depth stream{ symbol: string }
metricsSubscribeSubscribe to account metrics updates{ accountId: string }
createOrder / cancelOrder / amendOrderTrading actionsSame body as the equivalent REST endpoint, e.g. POST /accounts/{account_id}/orders
closePosition / amendPositionPosition managementSame body as the equivalent REST endpoint
orderHistory / positionHistory / dealHistoryHistorical queriesSame body as the equivalent REST endpoint

Server → client messages

TypeSent when
subscribedAcknowledges a subscribe request
unsubscribedAcknowledges an unsubscribe request
quoteEventA subscribed symbol's quote changes
executionEventAn order belonging to the authenticated account fills, partially fills, or is cancelled
portfolioEventThe account's portfolio (positions, balances) changes
depthEventOrder-book depth update for a subscribed symbol
metricsEventAccount metrics update (equity, margin, P&L)
errorThe server rejected a message; payload includes a code and message

Example

Subscribe to quotes and executions for two symbols, then stream events:

// → client
{ "type": "subscribe", "payload": { "symbols": ["EURUSD", "GBPUSD"], "events": ["quoteEvent", "executionEvent"] } }

// ← server
{ "type": "subscribed", "payload": { "symbols": ["EURUSD", "GBPUSD"], "events": ["quoteEvent", "executionEvent"] } }

// ← server (continuous)
{ "type": "quoteEvent", "payload": { "symbol": "EURUSD", "bid": 1.0843, "ask": 1.0844, "ts": "2026-06-01T12:00:00Z" } }

To send a trading action, wrap the REST request body in the envelope:

{
  "type": "createOrder",
  "payload": {
    "accountId": "acc_123",
    "symbol": "EURUSD",
    "side": "BUY",
    "quantity": 10000,
    "type": "MARKET"
  }
}

The server replies with an executionEvent once the order is accepted, then again on each fill.