WebSocket API

Stream P&L updates, market data, and make API calls — all over WebSocket!

WebSocket Streaming API

What It Is

The REST API is request-response: you ask a question, you get an answer. The WebSocket API is a persistent connection that keeps the conversation open. You connect once, and from that point forward you can send commands and receive real-time data without the overhead of establishing a new HTTP connection for every interaction.

This makes it the right choice when you need streaming market data, live P&L updates, or you're running an algo that sends frequent commands. Anything that would otherwise be a tight polling loop against the REST API is better served by the WebSocket.

The WebSocket API supports all of the same RPC functions available through the REST API. Every endpoint documented under Accounts, Positions, Orders, Strategies, Executions, and Quotes can be called through a WebSocket message instead of an HTTP request. On top of that, the WebSocket provides real-time streaming capabilities that the REST API does not offer: live market data quotes and live P&L account updates pushed directly to your connection as they happen.

Connecting

The WebSocket endpoint is:

wss://app.crosstrade.io/ws/stream

Authentication works the same way as the REST API. Include your Bearer token in the request headers when establishing the connection:

Authorization: Bearer <your-secret-key>

Python

import asyncio
import websockets
import json

async def connect():
    uri = "wss://app.crosstrade.io/ws/stream"
    headers = {"Authorization": "Bearer <your-secret-key>"}

    async with websockets.connect(uri, extra_headers=headers) as ws:
        # Subscribe to market data
        await ws.send(json.dumps({
            "action": "subscribe",
            "instruments": ["ES 09-26"]
        }))

        # Listen for incoming data
        async for message in ws:
            data = json.loads(message)
            print(data)

asyncio.run(connect())

JavaScript / Node.js

One Connection Per User

Only one WebSocket connection can be active per account at a time. If you open a second connection, the first one is immediately closed with a policy violation code and the message "Session active elsewhere."

This is enforced server-side and is not configurable. If you need to reconnect, close your existing connection cleanly first, or simply connect and let the server handle the swap. The server enforces a connection rate limit of 5 new WebSocket upgrades per IP per 60 seconds to prevent connection-storm abuse.

Sending Messages

All messages sent to the server are JSON objects with an action field that determines what happens. There are four available actions.

RPC Calls

The rpc action lets you call any function available through the REST API. Include an api field with the function name and an args object with the parameters. You can optionally include an id field to correlate the response back to your request. If you don't include one, the server generates one for you.

The response comes back with your id so you can match it:

The api field accepts the same function names used internally by the REST API: PlaceOrder, ListAccounts, GetPosition, CancelOrders, ClosePosition, GetQuote, and so on. The WebSocket API naming conventions are listed inside the docs for each endpoint. The args object accepts the same fields as the corresponding REST endpoint's request body or query parameters.

Subscribe to Market Data

The subscribe action tells the server to start streaming quotes for the specified instruments. Pass an array of NinjaTrader instrument names.

Once subscribed, you'll receive marketData events whenever new quotes arrive from your NT8 data feed. You can subscribe to additional instruments at any time by sending another subscribe message. Instruments accumulate across subscribe calls.

Unsubscribe from Market Data

Remove instruments from your subscription. You'll stop receiving quotes for these instruments immediately.

Stream P&L

Toggle real-time P&L updates for your active accounts. When enabled, you'll receive account-level profit and loss data at the interval you specify (in milliseconds). The lowest available interval is 1000ms (1 second).

Set enabled to false to stop P&L streaming.

Receiving Messages

The server pushes three types of messages to your connection.

Market Data

When you've subscribed to instruments, you'll receive quote updates filtered to only the instruments you've subscribed to:

The quote data comes directly from your NinjaTrader data feed. If the add-on is streaming quotes for subscribed instruments, they're forwarded to your WebSocket connection in real time. The quotes array may contain updates for multiple instruments in a single message.

P&L Updates

When PnL streaming is enabled, you'll receive periodic account snapshots:

RPC Responses

Every RPC call you make gets a response, delivered asynchronously. The id matches what you sent (or was generated for you):

If the RPC call fails, the data object will contain an error field instead:

Rate Limiting

The WebSocket API shares the same rate-limit budget as the REST API: 180 requests per minute (3 per second) with a burst allowance of 20. This budget is per user and is shared across both protocols. If you're sending 2 requests per second over HTTP and 1 per second over WebSocket, you're using your full 3/second allowance.

Only rpc messages count against this budget. Incoming streaming data (market quotes, P&L updates) does not consume rate-limit tokens.

Subscription management actions (subscribe, unsubscribe, streamPnl) have their own separate, tighter limit of approximately 20 total requests per minute. These actions trigger backend work on your NinjaTrader instance, so they're intentionally throttled.

When you exceed the rate limit on an RPC message, the server responds with an error on that specific message rather than closing your connection:

However, if you persistently exceed the limit (more than 10 consecutive violations without a successful request in between), the server will close your connection with a policy violation code. This is a safety measure to prevent runaway loops from consuming server resources.

For a detailed explanation of how the token bucket algorithm works and how it recovers, see the Rate Limiting page.

Error Handling and Reconnection

Your WebSocket connection can close for several reasons: the server shutting down, your add-on disconnecting, session takeover from another connection, or rate-limit abuse. Your client should always be prepared to reconnect.

A good reconnection strategy is exponential backoff: wait 1 second after the first disconnect, 2 seconds after the second, 4 after the third, and cap at around 30 seconds. Reset the backoff counter after a successful connection that stays open for more than a minute.

After reconnecting, you'll need to resubscribe to any instruments and re-enable P&L streaming. The server does not remember your previous session's subscriptions.

Add-On Requirement

Just like the REST API, the WebSocket API requires your NinjaTrader instance to be running with the CrossTrade add-on connected. RPC calls are forwarded to the add-on in real time. If the add-on is not connected, RPC calls will return {"error": "Add-on not connected"}. Market data streaming also depends on the add-on's data feed connection to NinjaTrader.

circle-info

The WebSocket API requires a minimum add-on version of v1.12.0+

Last updated