> This page is for NT Prop.

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

# User Synchronization

> **Info**
>
> Use `user/syncrequest` to maintain real-time synchronization of user and account data. This is essential for accurate user and account updates, position and order tracking, risk management, and auto-liquidation/admin alerts.

### Signature and Overview

The JSON body for `user/syncrequest` looks like this:

```json
{
  "splitResponses": "boolean",
  "users": "number[]",
  "accounts": "number[]",
  "shardingExpression": {
    "divisor": "number",
    "remainder": "number",
    "expressionType": "modAccountId" | "modUserId"
  },
  "entityTypes": "string[]"
}
```

### Parameters

* **`splitResponses`** (boolean, required) - Should be `true` for any B2B vendor.
* **`users`** (number\[], optional) - Do not use with `shardingExpression` or `entityTypes`.
* **`accounts`** (number\[], optional) - Do not use with [Socket Sharding](#sharding).
* **`shardingExpression`** (object, optional) - Controls sharding behavior.
  * **`divisor`** (number) - Total number of socket shards desired.
  * **`remainder`** (number) - If userId or accountId divided by divisor has a remainder of 1, they will come to the socket with remainder: 1.
  * **`expressionType`** (string) - Either `"modAccountId"` or `"modUserId"`. Determines which entity type's IDs are used for the modulus operation.
* **`entityTypes`** (string\[], optional) - List of entity types you wish to receive.

> **Note**
>
> **Important:** You must specify `entityTypes` explicitly: an empty array (`[]`) delivers no entity updates, and omitting the field delivers every type. Pass strings such as `"user"`, `"account"`, `"fill"`, `"fillPair"`, and `"order"`; these are common examples, not a complete list. They control which updates you receive.
>
> You'll still receive user- and account-level events (such as `userSessionStats`) even if they aren't in your `entityTypes`. You receive them for the users and accounts in your shard (per your `shardingExpression`); `entityTypes` doesn't filter them.

## Filter by Entity Type

To filter WebSocket updates by entity type, pass an `entityTypes` string array as described above.

This affects both the initial incoming dataset and the types of updates you receive over the socket's lifetime.

> **Warning**
>
> An empty array (`[]`) delivers no entity updates, except the user- and account-level events that bypass the filter. Omitting `entityTypes` instead delivers every type, so set it to exactly the types you want.
>
> Entity type values are not validated. A misspelled or unrecognized type (for example, `fil` instead of `fill`) is accepted silently and simply delivers no events for that type, so double-check your spelling.

## Session Events

The `userSessionStats` entity updates every time a new authenticated session is created for the user, including plain REST sessions, not just new WebSocket connections. Because it is user-owned, the update fans out to all of that user's subscribed sockets, so you may receive `userSessionStats` events without opening a new connection. These events are informational and are not a disconnect signal.

## Sharding

### What is Socket Sharding?

Sharding splits a workload among multiple instances to reduce load on any single actor. For our sockets, this means that if an actor fails, only a subset of users are affected.

### Sharding Behavior

1. An entity change occurs.
2. The server looks at the entity ID and considers the `expressionType` config option passed to `syncRequest`.
3. The entity ID is divided by `divisor`, and the remainder controls which socket the event is published to.
4. Create or Update "props" event is fired.
5. The vendor socket application processes the event.
6. Only the socket with the correct remainder receives the event.

For example, socket A with `divisor = 3`, `remainder = 1` only receives updates when `entityId % divisor == 1`.

### Sharding Gotchas

* **`remainder` must be less than `divisor`.** The server checks that `divisor` is greater than 0 and `remainder` is 0 or more, but it does not check that `remainder` is less than `divisor`. A shard with, for example, `divisor: 3` and `remainder: 5` is accepted and silently receives no events. Make sure your remainders cover `0` through `divisor - 1`.
* **User-scoped entities skip `modAccountId` shards.** Entities owned by the user rather than an account (such as `userSession` and `userSessionStats`) are not delivered to `modAccountId` shards. If you shard by account but also need user-level events, keep one additional unsharded (or `modUserId`) connection to receive them.

### Implementation Example

Set up sharded socket instances by determining the total number of desired shards and configuring that many sockets with corresponding remainders.

```typescript
// This function assumes you've created a class called Socket that wraps the actual WebSocket instance.
// This pseudo-version calls user/syncRequest as part of its startup routine, but you can configure
// the timing for the API command any sensible way you like.
function createSocketShard(
    accessToken: string, 
    divisor: number, 
    remainder: number
): Socket {
    return new Socket({
        url: 'https://demo-api.staging.ninjatrader.dev/v1/websocket',
        accessToken: accessToken,
        // The types filter used in syncRequest
        entityTypes: [
            'user',
            'account',
            'accountRiskStatus',
            'cashBalance',
            'fill',
            'accountRiskStatus'
        ],
        // The sharding expression used in syncRequest
        shardingExpression: {
            divisor,
            remainder,
            expressionType: 'modAccountId'
        }
    });
}

// Usage
const main = async () => {
  // You'll need to have acquired an access token,
  // here's a made-up function to grab one using the REST API
  const { accessToken } = await getAccessToken();

  // The shard function passes 3 as the divisor for each socket,
  // then we can set up the remainders configuratively.
  const socketA = createSocketShard(accessToken, 3, 0);
  const socketB = createSocketShard(accessToken, 3, 1);
  const socketC = createSocketShard(accessToken, 3, 2);

  // Subscribe to 'message' events on each socket instance.
  socketA.on('message', x => console.log('A', JSON.stringify(x)));
  socketB.on('message', x => console.log('B', JSON.stringify(x)));
  socketC.on('message', x => console.log('C', JSON.stringify(x)));

  // user/syncRequest is called as part of the connect routine
  await socketA.connect();
  await socketB.connect();
  await socketC.connect();
}

// Entry
main();
```

## Connecting and Requesting Data

After your WebSocket is authorized, send `user/syncrequest` once as a one-time bootstrap for that connection. It initializes your account state and streams updates for the entity types you list in `entityTypes` (see the parameters above), and the backend expects exactly one sync request per connection lifecycle. After that, the system pushes changes automatically for as long as the connection stays open, so you request only what you need rather than sending another sync request.

Every WebSocket request uses the same format: the endpoint, a request ID, an optional query, and an optional body, each on its own line. Send each message separately, and note that the blank line before a body is the empty query line. Message IDs 0 and 1 typically authorize the socket and send the one-time sync request, so the follow-on requests below start at 2. For example, to read a user, list accounts, list positions, and place an order:

```
user/item
2
id=<userId>

account/list
3
userId=<userId>

position/list
4
accountId=<accountId>

order/placeorder
5

{"accountId":<accountId>,"accountSpec":"<username>","symbol":"ESM6","action":"Buy","orderQty":1,"orderType":"Market","isAutomated":true}
```

For the full order request and response, see the

[place order endpoint](/prop/api/rest-api-endpoints/orders/place-order)

.

### Example Script

`ws_interactive.py` is an illustrative, boilerplate client that opens a WebSocket, authorizes, and sends the one-time sync request. It requires the `websocket-client` package (`pip install websocket-client`). Run it from a terminal with the WebSocket URL and an access token:

```bash
python ws_interactive.py --url <ws-url> --token <access-token>
```

The staging WebSocket URL is `wss://live-api.staging.ninjatrader.dev/v1/websocket`.

Download ws_interactive.py

You can use either the user token or the admin token for the sync request and to place orders.