New API Features: WebSocket Streaming, Historical Bars, Cross-Account Queries, and More

tream market data, pull historical bars, and manage orders across all accounts from your own code with CrossTrade's expanded API and new WebSocket streaming endpoint.

NinjaTrader logo with checklist showing real-time data, profit and loss, and historical bars over a candlestick chart — CrossTrade API feature update

If you've built anything against the CrossTrade API, you've probably hit the same ceiling: the REST API is request-response. You ask for a quote, you get a quote. You want another one, you ask again. It works, but it doesn't scale to anything that needs continuous data. Running a tight polling loop at 3 requests per second against a REST endpoint to approximate a live feed is the kind of thing that works in a demo and falls apart in production.

This update fixes that. The API now supports persistent WebSocket connections with real-time streaming, along with a set of new endpoints that fill gaps in what you could previously query. You can now pull historical bars, check whether the market is open, get quotes without naming a specific account, query all positions and orders across every account in one call, look up fills by order ID, read your account manager watermarks, and atomically replace protective bracket orders on a live position.

All of these are available now on the Pro plan. Here's what each one does and why it matters.

WebSocket Streaming

The biggest addition is /ws/stream, a persistent WebSocket endpoint that keeps a two-way channel open between your code and NinjaTrader. Once connected, you can subscribe to live market data for any instrument and receive quote updates as they happen, stream P&L updates for your accounts at configurable intervals, and make any RPC call available through the REST API without the overhead of establishing a new HTTP connection for each one.

The connection is authenticated with the same Bearer token you already use. You send JSON messages with an action field and receive responses tagged with a correlation ID so you can match them asynchronously. A simple example that subscribes to ES quotes and places an order:

{
    "action": "subscribe",
    "instruments": ["ES 09-26"]
}

{
    "action": "rpc", 
    "id": "order-1", 
    "api": "PlaceOrder", 
    "args": {
        "account": "Sim101", 
        "instrument": "ES 09-26",
        "action": "Buy", 
        "orderType": "Market",
        "quantity": 1, 
        "timeInForce": "GTC"
    }
}

Market data arrives as {"type": "marketData", "quotes": [...]} messages filtered to only the instruments you've subscribed to.

P&L updates arrive as {"type": "pnlUpdate", "accounts": [...]} at a constant rate of approximately 1000ms (1 second).

One connection per user. If you open a second connection, the first one gets closed. The rate limit budget (180 req/min) is shared between HTTP and WebSocket RPC calls, but incoming streaming data doesn't count against it.

Full documentation: WebSocket API

Historical Bars

The REST API could already quote live prices, but there was no way to pull OHLCV history. Now there is.

POST /v1/api/market/bars requests historical bar data for any instrument available in NinjaTrader, with configurable period types (minute, day, week, month, year), date ranges, and bar counts.

{
  "instrument": "ES 09-26",
  "periodType": "minute",
  "period": 5,
  "daysBack": 1,
  "limit": 100
}

The response includes timestamped OHLCV bars with both ISO and epoch time formats. This is useful for backtesting setups that need to pull history at startup, dashboards that display intraday charts, or any algo that needs context about recent price action before making a decision.

There's a ceiling of 10,000 bars per request to keep response sizes reasonable. If you need more, paginate with from and to date ranges. The request has a 10-second timeout, which is more than enough for daily bars across a year, but can be tight for very granular data across long date ranges.

Full documentation: GET Historical Bars

Market Info: Is the Market Open?

If your algo needs to know whether it should be placing orders right now, GET /v1/api/market/info returns the real-time session status for any instrument. It tells you whether the market is currently open or closed, the exact UTC boundaries of the current (or next) session, a countdown to the next state change, and the exchange time zone.

{
  "status": {
    "isOpen": true, 
    "state": "Open"
  },
  "session": {
    "countdown": "06:30:00",
    "action": "Until Close",
    "secondsRemaining": 23400
    ...
  }
}

You can pass an instrument name or nothing at all (defaults to ES front month). This replaces the pattern of trying to place an order and checking if it errors out as a proxy for "is the market open" — which, if you've done it, you know is not a great approach.

Full documentation: GET Market Info

Account-less Quotes

The original quote endpoint required an account name in the URL path. That made sense for the initial implementation, but was awkward for use cases where you just want a price and don't care which account context it comes from. GET /v1/api/market/quote drops that requirement. Pass an instrument name and get a quote back.

It also supports quoting multiple instruments in a single request by passing a comma-separated list. All instruments are quoted concurrently and returned as an array. This is the endpoint to use if you're building a watchlist or a dashboard that needs to poll several symbols at once.

Full documentation: GET Quote

Cross-Account Positions and Orders

Previously, listing positions or orders required specifying an account. If you had five accounts and wanted a complete picture, that was five separate API calls. Two new endpoints collapse this into a single request.

GET /v1/api/positions returns positions across all accounts. Flat positions are excluded by default (pass ?includeFlat=true if you want them).

GET /v1/api/orders returns orders across all accounts, defaulting to active (working) orders only. Pass ?activeOnly=false with an optional ?lookbackTime=86400 to include historical orders from the past N seconds.

If you're running a multi-account setup — prop firm evaluations, funded accounts, a personal account — these endpoints give you a single-call portfolio view instead of iterating through accounts one by one.

Full documentation: GET All Positions · GET All Orders

Cancel and Bracket

Managing protective orders on a live position has always been multi-step: cancel the existing stops and limits, wait for the cancellations to process, then place new ones. If anything goes wrong between steps, the position is unprotected.

POST /v1/api/accounts/{account}/orders/cancel_and_bracket makes this atomic. It cancels all working orders on an instrument, waits a configurable delay for broker acknowledgment, then places a new OCO bracket (take profit + stop loss) in a single operation. If the position goes flat during the cancel window (because a stop was hit), it aborts the bracket placement entirely instead of accidentally opening a new position.

Full documentation: POST Cancel and Bracket

Executions by Order ID

GET /v1/api/executions/order/{orderId} returns all fills associated with a specific order. It searches across all accounts and matches against both the current broker-assigned order ID and the original order ID, so it finds fills even if the order was modified or replaced during its lifetime. Useful for confirming fills, checking exact execution prices, and auditing commission on replaced order chains.

Full documentation: GET Execution by Order ID

Watermarks

GET /v1/api/accounts/{account}/watermarks exposes the high-water mark and current P&L statistics tracked by the Account Management service. If you're building your own monitoring dashboard or want to check where an account stands relative to its session peaks, this endpoint returns the data without requiring an RPC call to the add-on. It reads directly from CrossTrade's server-side session cache, so it responds instantly even if the add-on is temporarily disconnected.

Full documentation: GET Watermarks

What's Next

We're working on expanding the WebSocket API with additional streaming event types and are actively developing the scripting engine that will allow you to deploy and manage dynamic strategies directly through the API.

Follow the Updates page for release announcements, or join the Discord to talk to other developers building on the API.

All of the endpoints above require the Pro plan and are available now. Full API documentation is at docs.crosstrade.io.


New to CrossTrade? Start your free 7-day trial — full access, unlimited alerts, no credit card required.

Start your free trial

Try CrossTrade for 7 days.

Sign Up