> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.ninjatrader.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.ninjatrader.com/_mcp/server.

# Real-Time Data via WebSocket

WebSockets let you open an interactive session so you can send messages to the server and receive event-driven responses without polling. The protocol uses the same request semantics as the REST API, adapted to the JSON format the standard WebSocket protocol expects. The current protocol is inherited from the [SockJS protocol](http://sockjs.github.io/sockjs-protocol/sockjs-protocol-0.3.3.html#section-42) used in earlier versions.

For runnable walkthroughs, see the [WebSockets section of the JavaScript tutorial](https://github.com/tradovate/example-api-js/tree/main/tutorial/WebSockets/EX-05-WebSockets-Start) and the [C# sample project](https://github.com/tradovate/example-api-csharp-trading).

## Connecting to the WebSocket Server

Create a WebSocket instance using one of the real-time API URLs, with the `wss://` protocol prefix in place of `https://`. For example, using the Demo URL:

```text
wss://demo.tradovateapi.com/v1/websocket
```

## Server Frames

The server communicates in *frames*. A frame is a single-character type prefix concatenated with an array of JSON data, and your client is responsible for deconstructing these messages. The server sends these frame types:

* **`'o'` — Open frame.** Sent immediately whenever a new session is established. This is required so the client can distinguish a properly established connection from a broken one.
* **`'h'` — Heartbeat frame.** Sent about every 2.5 seconds to keep connections from timing out behind load balancers. The client must reply with its own heartbeat: an empty array, stringified (`'[]'`).
* **`'a'` — Array frame.** A string containing an array of JSON-encoded messages, for example `'a[{"data": "value"}]'`.
* **`'c'` — Close frame.** Sent when the client requests data on a closed connection, which may happen multiple times. It contains a code and a reason, such as `c[3000, "Go away!"]`.

### Decoding Server Frames

The `'a'` frame is the backbone of the message protocol. Here's some example data:

```text
a[{"s":200,"i":23,"d":{"id":65543,"name":"CLZ6","contractMaturityId":6727}}]
a[{"e":"props","d":{"entityType":"order","eventType":"Created","entity":{"id":210518,"accountId":25,"contractId":560901,"timestamp":"2016-11-04T00:02:36.626Z","action":"Sell","ordStatus":"PendingNew","admin":false}}}]
```

You can parse frames into more consumable data with a function such as `prepareMsg`, which turns the string message into a tuple you can destructure:

```js
function prepareMsg(raw) {
    const T = raw.slice(0, 1)
    let payload = null
    const data = raw.slice(1)
    if (data) {
        payload = JSON.parse(data)
    }
    return [T, payload]
}

// usage:
mySocket.onmessage = msg => {
    // data may be null
    const [T, data] = prepareMsg(msg.data)
    switch (T) {
        case 'a': {
            // react to data
            break
        }
    }
}
```

## Message Types

The socket servers interact with clients by sending messages whose data portion is always an array of JSON objects. There are two main categories: server events and responses to client requests.

### Server Event Message

An event message has this structure:

```json
{
  "e": "props",
  "d": {
    "entityType": "order",
    "eventType": "Created",
    "entity": {
      "id": 210518,
      "accountId": 25,
      "contractId": 560901,
      "timestamp": "2016-11-04T00:02:36.626Z",
      "action": "Sell",
      "ordStatus": "PendingNew",
      "admin": false
    }
  }
}
```

The `"e"` field specifies the event kind:

* **`"props"`** — An entity was created, updated, or deleted. The `"d"` field contains an `"entityType"` field, an `"entity"` field (whose JSON matches the entity returned by the corresponding `entityType/item` request), and an `"eventType"` field with the value `"Created"`, `"Updated"`, or `"Deleted"`.
* **`"shutdown"`** — A notification before a graceful connection shutdown. The `"d"` field contains a `"reasonCode"` (`"Maintenance"`, `"ConnectionQuotaReached"`, or `"IPQuotaReached"`) and an optional `"reason"` with a readable explanation.
* **`"md"` and `"chart"`** — Used by the market data feed only. See the [Market Data API](/market-data) for the `"d"` field.
* **`"clock"`** — A Market Replay clock-synchronization message. See [Market Replay](#market-replay).

### Response Message

A response message is issued when a client makes a request. It mirrors a REST API response:

```json
{
  "i": 26,
  "s": 200,
  "d": {
    "id": 478866,
    "name": "6EZ6",
    "contractMaturityId": 23574
  }
}
```

* `"i"` is the ID of the corresponding client request — it always matches the request that generated it.
* `"s"` is the HTTP status code of the response.
* `"d"` is the response content. For a 2xx status, this is the JSON response defined in the spec for that request; otherwise it's a string representation of the error text.

## Client Requests

SockJS doesn't define framing for client requests, so a standard text protocol is used. Each frame contains exactly one request made up of four fields:

* An endpoint name as defined in the spec — any endpoint you could call from the REST API.
* A unique integer ID for the request, unique within the current connection. The server uses it to reference the request in response messages.
* An optional field with parameters, identical to the REST API's query parameters.
* An optional field identical to a REST API body parameter.

Separate the four fields with the `'\n'` (newline) character.

```text title="Request with no query or body"
executionReport/list
4

```

```text title="Request with a query parameter"
tradingPermission/ldeps
8
masterids=1
```

```text title="Request with a body"
contract/rollcontract
33

{"name":"YMZ6","forward":true,"ifExpired":true}
```

## Authorization

Because a WebSocket is a permanent connection, you only need to authorize it once per application instance. Send an `authorize` request with your access token in the message body:

```text
authorize
2

uST01MhJMF3cR3lCs-gdQ9W0AzomYLaqsWcZ_GYgAspPRf-ZS-Wb7q3sW3pUafTm90ba4
```

Don't forget the newline between parameters. A successful response shows the status code (`s`) and the request ID (`i`):

```text
a[{"s":200,"i":2}]
```

## User Synchronization

Once your real-time connection is open, synchronize your user data with the `user/syncRequest` endpoint. It returns updates for any data changes that pertain to your user — the foundation for digesting real-time data such as calculating profit and loss or getting a snapshot of current margins. This endpoint is intended for WebSocket use.

The fields present on the response object of a `user/syncRequest` may be affected by your API Key's permissions.

## Market Replay

Market Replay follows the same trading and market data protocols as the regular services, over a dedicated host:

```text
wss://replay.tradovateapi.com/v1/websocket
```

Set the session's initial parameters right after a successful authorization, using a `replay/initializeclock` request:

* `startTimestamp` — the session's start time.
* `speed` — the replay speed as a percentage, in the range 0–400.
* `initialBalance` — a dollar amount for the replay account, which is created automatically with that balance and discarded at the end of the session.

```text
replay/initializeclock
3

{"startTimestamp":"2019-08-26T16:43:00.000Z","speed":20,"initialBalance":51000}
```

A response indicates whether the session started successfully:

```text
a[{"s":200,"i":3,"d":{"ok":true}}]
```

Only one replay session is allowed per user; initializing a new one resets the running session. Multiple connections can join the same session, and a connection that sends no initialization request joins the existing one.

To keep the server-side replay clock and the client clock in sync, the server pushes periodic clock-sync event messages:

```text
a[{"e":"clock","d":"{\"t\":\"2019-08-26T16:43:08.599Z\",\"s\":20}"}]
```

The `d` field holds a text representation of a JSON entity with `t` (the current replay timestamp) and `s` (the current replay speed). Use the clock event to determine whether the session has reached a certain time, or whether the server has limited your speed — in which case you'll need to change it.

Control the replay speed with a `replay/changespeed` request, passing a `speed` parameter in the range 0–400 (where 400 is four times real-time speed):

```text
replay/changespeed
49

{"speed":100}
```

Sometimes the server pauses your replay, in which case clock-sync messages continue with `speed` set to 0. Unpause by sending another `replay/changespeed` request. A session is discarded automatically when no connections are associated with it.

Depending on the customer's entitlements, Market Replay can be limited or disallowed. To check whether a chosen date and time is permitted before initiating a replay connection, call `replay/checkReplaySession`.

## Client Heartbeats

As noted under [Server Frames](#server-frames), the client must send a heartbeat every 2.5 seconds to avoid being closed for inactivity. A heartbeat is a frame whose text is `"[]"` (an empty array), sent with the `WebSocket.send` method.

When developing for the web, avoid relying on `setInterval` — browsers can throttle it and cause disconnections. Instead, record a timestamp with each received message, compare it against the previous message's timestamp, and send a heartbeat once more than 2,500 ms have elapsed. The [JavaScript tutorial](https://github.com/tradovate/example-api-js/tree/main/tutorial/WebSockets/EX-06-Heartbeats) shows an example.

A server that's actively streaming live data (such as a market data subscription) won't send heartbeats while it's outputting messages. As long as your client keeps sending heartbeats every 2.5 seconds, the connection stays alive.

## Reference Implementations

Reference projects are available for both [C#](https://github.com/tradovate/example-api-csharp-trading) and [JavaScript](https://github.com/tradovate/example-api-js).