> 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.

# Create and Manage Users and Accounts

When you're ready to onboard traders, this guide walks you through creating users, setting up evaluation accounts, and assigning entitlements.

Use batched creation operations when possible, even for single users. Batched endpoints are more efficient than individual API calls.

***

## Prerequisites

Before you start, gather the following IDs. You'll reuse them for every user and account you create.

### Tradovate Subscription Plan ID

Each organization has a unique Tradovate Subscription Plan. You'll use this ID as the `tradovateSubscriptionPlanId` field when creating users.

To find your organization's Tradovate subscription plan ID:

From the environment (staging or production) that matches where you'll be creating accounts, call `/tradovateSubscriptionPlan/list` to get all available subscription plans. Use the plan associated with your firm, named `\<YOUR FIRM NAME\>_MONTHLY`.

### Request

GET [https://live.tradovateapi.com/v1/tradovateSubscriptionPlan/list](https://live.tradovateapi.com/v1/tradovateSubscriptionPlan/list)

```curl
curl https://live.tradovateapi.com/v1/tradovateSubscriptionPlan/list \
     -H "Authorization: Bearer <token>"
```

```python
import requests

url = "https://live.tradovateapi.com/v1/tradovateSubscriptionPlan/list"

headers = {"Authorization": "Bearer <token>"}

response = requests.get(url, headers=headers)

print(response.json())
```

```javascript
const url = 'https://live.tradovateapi.com/v1/tradovateSubscriptionPlan/list';
const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://live.tradovateapi.com/v1/tradovateSubscriptionPlan/list"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("Authorization", "Bearer <token>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://live.tradovateapi.com/v1/tradovateSubscriptionPlan/list")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://live.tradovateapi.com/v1/tradovateSubscriptionPlan/list")
  .header("Authorization", "Bearer <token>")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://live.tradovateapi.com/v1/tradovateSubscriptionPlan/list', [
  'headers' => [
    'Authorization' => 'Bearer <token>',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://live.tradovateapi.com/v1/tradovateSubscriptionPlan/list");
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer <token>");
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = ["Authorization": "Bearer <token>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://live.tradovateapi.com/v1/tradovateSubscriptionPlan/list")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: \{ (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

1. From the Admin Dashboards in the environment (staging or production) that matches where you'll be creating accounts, click **Query Builder** on the left pane.

2. Choose `tradovateSubscriptionPlans` from the **Repository** drop-down.

3. Set **Order By** to `id` and **Limit** to 100+.

4. Run the query.
   * [Example query (staging)](https://dashboards.staging.ninjatrader.dev/query-builder?asc=true\&ids=\&limit=1000\&masterIds=\&orderBy=id\&queryType=regular\&recentPeriodSeconds=3600\&repository=tradovateSubscriptionPlans\&selection=id%20name%20title%20price%20startDate%20discontinuedDate%20admin%20category%20trial%20duration%20durationUnits%20multipleAccounts%20replaySessions%20footnote%20replayProducts%20simOnly%20ntcSalesCode%20lifetimeInstallments%20riskCategory%20%7B%20name%20%7D%20organization%20%7B%20name%20%7D\&where=name%20like%20%22%28%3Fium%29.%2A_MONTHLY%22)
   * [Example query (production)](https://dashboards.tradovate.com/query-builder?asc=true\&ids=\&limit=1000\&masterIds=\&orderBy=id\&queryType=regular\&recentPeriodSeconds=3600\&repository=tradovateSubscriptionPlans\&selection=id%20name%20title%20price%20startDate%20discontinuedDate%20admin%20category%20trial%20duration%20durationUnits%20multipleAccounts%20replaySessions%20footnote%20replayProducts%20simOnly%20ntcSalesCode%20lifetimeInstallments%20riskCategory%20%7B%20name%20%7D%20organization%20%7B%20name%20%7D\&where=name%20like%20%22%28%3Fium%29.%2A_MONTHLY%22)

5. Find the plan labeled `\<YOUR PROP FIRM\>_MONTHLY` and record its ID.

### Template Account ID

Eval Support sets up template accounts for your organization based on your requirements. You'll use the template account ID as the `templateAccountId` field when creating evaluation accounts.

To find your template account ID:

1. From the Admin Dashboards in the environment (staging or production) that matches where you'll be creating accounts, click **Query Builder** on the left pane.
2. Choose `accounts` from the **Repository** drop-down.
3. Find accounts with "template account" names.
   * Typically a query like this works: `name like "(?ium).*5K" OR name like "(?ium).*0K"` (query examples [production](https://dashboards.tradovate.com/query-builder?asc=false\&ids=\&limit=10000\&masterIds=\&orderBy=id\&queryType=regular\&recentPeriodSeconds=\&repository=accounts\&selection=id%20name%20active%20evaluationSize%20readonly%20organization%20customerApplicationId%20accountType%20marginAccountType%20legalStatus%20archived%20cashAmount%20dollarOpenPL%20dollarTotalPL%20netLiq%20initialMargin%20maintenanceMargin%20marginToEquity%20dayMargin%20totalUsedMargin%20totalAvailableMargin%20positionMargin%20availablePositionMargin%20liqOnlyLevel%20distToLiqOnly%20autoLiqLevel%20distToAutoLiq%20exposedPos%20hasPosition%20autorenewal%20membership%20membershipExpiration%20accountStatus%20dailyProfitLimit%20weeklyProfitLimit%20dailyLossLimit%20distToDailyLossLimit%20dailyLossLimitPercentage%20weekLoss%20weeklyLossLimit%20distToWeeklyLossLimit%20weeklyLossLimitPercentage%20trailingMaxDrawdown%20maxNetLiq%20drawdownAutoLiqLevel%20distDrawdownNetLiq%20customSalesCode%20migratedName%20customVendorId%20customVendorName%20ccEmail%20clearingHouse%20%7B%20name%20%7D%20riskCategory%20%7B%20name%20%7D%20autoLiqProfile%20%7B%20name%20%7D%20riskStatus%20%7B%20adminAction%20adminActionReasonCode%20approvalDeadline%20liquidateOnly%20autoLiqStarted%20autoLiqStopped%20totalLiqFee%20autoLiqCounter%20autoLiqDailyCounter%20autoLiqEmergencyMode%20autoLiqEmergencyMultiplier%20maxNetLiq%20maxNetLiqTimestamp%20notes%20notesExpiration%20%7D\&where=name%20like%20%22%28%3Fium%29.%2A5K%22%20OR%20name%20like%20%22%28%3Fium%29.%2A0K%22), [staging](https://dashboards.staging.ninjatrader.dev/query-builder?asc=false\&ids=\&limit=10000\&masterIds=\&orderBy=id\&queryType=regular\&recentPeriodSeconds=\&repository=accounts\&selection=id%20name%20active%20evaluationSize%20readonly%20organization%20customerApplicationId%20accountType%20marginAccountType%20legalStatus%20archived%20cashAmount%20dollarOpenPL%20dollarTotalPL%20netLiq%20initialMargin%20maintenanceMargin%20marginToEquity%20dayMargin%20totalUsedMargin%20totalAvailableMargin%20positionMargin%20availablePositionMargin%20liqOnlyLevel%20distToLiqOnly%20autoLiqLevel%20distToAutoLiq%20exposedPos%20hasPosition%20autorenewal%20membership%20membershipExpiration%20accountStatus%20dailyProfitLimit%20weeklyProfitLimit%20dailyLossLimit%20distToDailyLossLimit%20dailyLossLimitPercentage%20weekLoss%20weeklyLossLimit%20distToWeeklyLossLimit%20weeklyLossLimitPercentage%20trailingMaxDrawdown%20maxNetLiq%20drawdownAutoLiqLevel%20distDrawdownNetLiq%20customSalesCode%20migratedName%20customVendorId%20customVendorName%20ccEmail%20clearingHouse%20%7B%20name%20%7D%20riskCategory%20%7B%20name%20%7D%20autoLiqProfile%20%7B%20name%20%7D%20riskStatus%20%7B%20adminAction%20adminActionReasonCode%20approvalDeadline%20liquidateOnly%20autoLiqStarted%20autoLiqStopped%20totalLiqFee%20autoLiqCounter%20autoLiqDailyCounter%20autoLiqEmergencyMode%20autoLiqEmergencyMultiplier%20maxNetLiq%20maxNetLiqTimestamp%20notes%20notesExpiration%20%7D\&where=name%20like%20%22%28%3Fium%29.%2A5K%22%20OR%20name%20like%20%22%28%3Fium%29.%2A0K%22))

#### What Information is Needed to Build My Templates?

If you don't already have template accounts set up for your organization, reach out to Eval Support. To create a template account or set of template accounts, provide the following:

* A name for the account template
* Lot limits for the account type, such as how many E-mini or Micro contracts the account can hold at maximum
* Restricted products. You can restrict access to any products, product categories, or even whole exchanges for an account type.
* Liquidation time. By default, automatic liquidation is set between 4:00 PM and 5:00 PM CT, but you can specify something more specific (or edit the value yourself after creation via `RiskTimePeriod`).

***

## Step 1: Create Your Users

Call `/user/createEvaluationUsers` to create new users (up to 100 in a single request). Use the Tradovate Subscription Plan ID from [Prerequisites](#prerequisites) as the `tradovateSubscriptionPlanId` field.

This endpoint handles user registration and Tradovate subscription assignment in a single call; you don't need to call `signUpOrganizationMember` or `addTradovateSubscription` separately.

**Endpoint**: `POST /user/createEvaluationUsers`

**Environments:** Live

### Request Parameters

### Request

POST [https://live.tradovateapi.com/v1/user/createevaluationusers](https://live.tradovateapi.com/v1/user/createevaluationusers)

```curl
curl -X POST https://live.tradovateapi.com/v1/user/createevaluationusers \
     -H "Authorization: Bearer <token>" \
     -H "Content-Type: application/json" \
     -d '{
  "users": [
    {
      "name": "string",
      "email": "string",
      "password": "string",
      "firstName": "string",
      "lastName": "string"
    }
  ]
}'
```

```python
import requests

url = "https://live.tradovateapi.com/v1/user/createevaluationusers"

payload = { "users": [
        {
            "name": "string",
            "email": "string",
            "password": "string",
            "firstName": "string",
            "lastName": "string"
        }
    ] }
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript
const url = 'https://live.tradovateapi.com/v1/user/createevaluationusers';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"users":[{"name":"string","email":"string","password":"string","firstName":"string","lastName":"string"}]}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://live.tradovateapi.com/v1/user/createevaluationusers"

	payload := strings.NewReader("{\n  \"users\": [\n    {\n      \"name\": \"string\",\n      \"email\": \"string\",\n      \"password\": \"string\",\n      \"firstName\": \"string\",\n      \"lastName\": \"string\"\n    }\n  ]\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://live.tradovateapi.com/v1/user/createevaluationusers")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"users\": [\n    {\n      \"name\": \"string\",\n      \"email\": \"string\",\n      \"password\": \"string\",\n      \"firstName\": \"string\",\n      \"lastName\": \"string\"\n    }\n  ]\n}"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://live.tradovateapi.com/v1/user/createevaluationusers")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"users\": [\n    {\n      \"name\": \"string\",\n      \"email\": \"string\",\n      \"password\": \"string\",\n      \"firstName\": \"string\",\n      \"lastName\": \"string\"\n    }\n  ]\n}")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://live.tradovateapi.com/v1/user/createevaluationusers', [
  'body' => '{
  "users": [
    {
      "name": "string",
      "email": "string",
      "password": "string",
      "firstName": "string",
      "lastName": "string"
    }
  ]
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://live.tradovateapi.com/v1/user/createevaluationusers");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"users\": [\n    {\n      \"name\": \"string\",\n      \"email\": \"string\",\n      \"password\": \"string\",\n      \"firstName\": \"string\",\n      \"lastName\": \"string\"\n    }\n  ]\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = ["users": [
    [
      "name": "string",
      "email": "string",
      "password": "string",
      "firstName": "string",
      "lastName": "string"
    ]
  ]] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://live.tradovateapi.com/v1/user/createevaluationusers")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: \{ (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Response

### Response (200)

```json
{
  "results": [
    {
      "errorText": "string",
      "userId": 1
    }
  ],
  "errorText": "string"
}
```

Store the returned `userId` and map it to your internal user records. You'll need it for subsequent operations.

The `createEvaluationUsers` endpoint accepts an `entitlementIds` field, but do not pass Sim+ entitlement IDs (such as T-Prop) here. The entitlement must be assigned using the `addEntitlementSubscription` endpoint after the user signs the Market Data Agreement. See [Step 5](#step-5-add-the-t-prop-entitlement) for details.

***

## Step 2: Add Contact Information

Add contact information for the user. If you skip this step, the user will be prompted to enter it on their first login.

**Endpoint**: `POST /contactInfo/updateContactInfo`

**Environments:** Live

### Request Parameters

### Key Requirements

* **State**: Only required when `country == "US"`
* **Country**: Use two-letter country codes (Alpha-2 format)
* **Phone**: String format supporting international prefixes

***

## Step 3: Create Evaluation Accounts

From the `demo-api` (staging) or `demo` (production) domain, call `/user/createEvaluationAccounts` to create new accounts and automatically assign them to users by user ID. Use the Template Account ID from [Prerequisites](#prerequisites) as the `templateAccountId` field.

**Endpoint**: `POST /user/createEvaluationAccounts`

**Environments:** Demo

### Request

POST [https://live.tradovateapi.com/v1/user/createevaluationaccounts](https://live.tradovateapi.com/v1/user/createevaluationaccounts)

```curl
curl -X POST https://live.tradovateapi.com/v1/user/createevaluationaccounts \
     -H "Authorization: Bearer <token>" \
     -H "Content-Type: application/json" \
     -d '{
  "accounts": [
    {
      "userId": 1,
      "templateAccountId": 1,
      "name": "string",
      "initialBalance": 1.1
    }
  ]
}'
```

```python
import requests

url = "https://live.tradovateapi.com/v1/user/createevaluationaccounts"

payload = { "accounts": [
        {
            "userId": 1,
            "templateAccountId": 1,
            "name": "string",
            "initialBalance": 1.1
        }
    ] }
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript
const url = 'https://live.tradovateapi.com/v1/user/createevaluationaccounts';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"accounts":[{"userId":1,"templateAccountId":1,"name":"string","initialBalance":1.1}]}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://live.tradovateapi.com/v1/user/createevaluationaccounts"

	payload := strings.NewReader("{\n  \"accounts\": [\n    {\n      \"userId\": 1,\n      \"templateAccountId\": 1,\n      \"name\": \"string\",\n      \"initialBalance\": 1.1\n    }\n  ]\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://live.tradovateapi.com/v1/user/createevaluationaccounts")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"accounts\": [\n    {\n      \"userId\": 1,\n      \"templateAccountId\": 1,\n      \"name\": \"string\",\n      \"initialBalance\": 1.1\n    }\n  ]\n}"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://live.tradovateapi.com/v1/user/createevaluationaccounts")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"accounts\": [\n    {\n      \"userId\": 1,\n      \"templateAccountId\": 1,\n      \"name\": \"string\",\n      \"initialBalance\": 1.1\n    }\n  ]\n}")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://live.tradovateapi.com/v1/user/createevaluationaccounts', [
  'body' => '{
  "accounts": [
    {
      "userId": 1,
      "templateAccountId": 1,
      "name": "string",
      "initialBalance": 1.1
    }
  ]
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://live.tradovateapi.com/v1/user/createevaluationaccounts");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"accounts\": [\n    {\n      \"userId\": 1,\n      \"templateAccountId\": 1,\n      \"name\": \"string\",\n      \"initialBalance\": 1.1\n    }\n  ]\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = ["accounts": [
    [
      "userId": 1,
      "templateAccountId": 1,
      "name": "string",
      "initialBalance": 1.1
    ]
  ]] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://live.tradovateapi.com/v1/user/createevaluationaccounts")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: \{ (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Response (200)

```json
{
  "results": [
    {
      "errorText": "string",
      "accountId": 1,
      "tradingPermissionId": 1
    }
  ],
  "errorText": "string"
}
```

The response includes a `tradingPermissionId`. This endpoint creates the account and assigns a trading permission in one operation.

Include `preTradeRisk` and `postTradeRisk` fields in your `createEvaluationAccounts` request when applicable. This reduces the number of API calls compared to making a separate call to `userAccountAutoLiq/update` after account creation.

Values such as daily loss limits or trailing drawdown are set via [Post-Trade Risk](/overview/prop-firm-management/risk-management/post-trade-risk), and aren't defined at the template level. You must set these values at the time of account creation.

***

## Step 4: Confirm the Market Data Agreement Signature

Before you can assign the T-Prop entitlement, users must sign the non-professional Market Data Agreement. There are two ways to detect when a user signs:

\<Tabs>

**Endpoint**: `POST /user/syncrequest`

To receive Market Data Agreement signature events in real time, set up a [WebSocket](/overview/core-concepts/web-sockets/connection-overview) and perform a [`syncRequest`](/api/rest-api-endpoints/users/sync-request).

### Request

POST [https://live.tradovateapi.com/v1/user/syncrequest](https://live.tradovateapi.com/v1/user/syncrequest)

```curl
curl -X POST https://live.tradovateapi.com/v1/user/syncrequest \
     -H "Authorization: Bearer <token>" \
     -H "Content-Type: application/json" \
     -d '{}'
```

```python
import requests

url = "https://live.tradovateapi.com/v1/user/syncrequest"

payload = {}
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript
const url = 'https://live.tradovateapi.com/v1/user/syncrequest';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://live.tradovateapi.com/v1/user/syncrequest"

	payload := strings.NewReader("{}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://live.tradovateapi.com/v1/user/syncrequest")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{}"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://live.tradovateapi.com/v1/user/syncrequest")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{}")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://live.tradovateapi.com/v1/user/syncrequest', [
  'body' => '{}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://live.tradovateapi.com/v1/user/syncrequest");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = [] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://live.tradovateapi.com/v1/user/syncrequest")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: \{ (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

You can then listen for messages like the following:

```json
[
  {
    "e": "props",
    "d": [
      {
        "entityType": "OtherEnvAdminAlertSignal",
        "eventType": "Created",
        "entity": {
          "adminAlertSignal": {
            "id": 2179591,
            "timestamp": "2025-10-03T15:18:56.885Z",
            "adminAlertId": 70,
            "relatedToUserId": 29721,
            "text": "User TPropTestUser1001 signed non-professional market data form, <br />User name: Bill Rando <br />Date: 10/03/2025 <br />Timestamp: 2025-10-03 15:18:56 UTC <br />",
            "emailSent": false,
            "archived": false,
            "subjectId": 12081
          }
        }
      }
    ]
  }
]
```

In staging, use `adminAlertId=70`. In production, use `adminAlertId=68`.&#x20;

\<Tab title="API">

**Endpoint**: `GET /adminAlertSignal/deps`

To retrieve all recent Market Data Agreement signatures for your organization, call `/adminAlertSignal/deps`.

In staging, use `/deps?masterid=70`. In production, use `/deps?masterid=68`. The `custapp:nonpro-signed` event ID is different in the two environments.

The `/adminAlertSignal/deps` endpoint only returns recent signals. Signals are archived at the end of each week, so you'll only see data from the current week. If you need historical records, use BigQuery.

Do not poll `/adminAlertSignal/deps` on a schedule. You will eventually hit the rate limit and the operation will fail. Instead, use a WebSocket to receive signature events in real time.

\<End### Request

GET [https://live.tradovateapi.com/v1/adminAlertSignal/deps](https://live.tradovateapi.com/v1/adminAlertSignal/deps)

```curl
curl -G https://live.tradovateapi.com/v1/adminAlertSignal/deps \
     -H "Authorization: Bearer <token>" \
     -d masterid=1
```

```python
import requests

url = "https://live.tradovateapi.com/v1/adminAlertSignal/deps"

querystring = {"masterid":"1"}

headers = {"Authorization": "Bearer <token>"}

response = requests.get(url, headers=headers, params=querystring)

print(response.json())
```

```javascript
const url = 'https://live.tradovateapi.com/v1/adminAlertSignal/deps?masterid=1';
const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://live.tradovateapi.com/v1/adminAlertSignal/deps?masterid=1"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("Authorization", "Bearer <token>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://live.tradovateapi.com/v1/adminAlertSignal/deps?masterid=1")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://live.tradovateapi.com/v1/adminAlertSignal/deps?masterid=1")
  .header("Authorization", "Bearer <token>")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://live.tradovateapi.com/v1/adminAlertSignal/deps?masterid=1', [
  'headers' => [
    'Authorization' => 'Bearer <token>',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://live.tradovateapi.com/v1/adminAlertSignal/deps?masterid=1");
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer <token>");
IRestResponse response = client.Execute(request);
```

````swift
import Foundation

let headers = ["Authorization": "Bearer <token>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://live.tradovateapi.com/v1/adminAlertSignal/deps?masterid=1")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: \{ (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```Tab>
</Tabs>

---

## Step 5: Add the T-Prop Entitlement

After the system confirms the user has contact info and has signed the Market Data Agreement, assign the T-Prop entitlement. 

If you call `addEntitlementSubscription` before the user signs the Market Data Agreement, the call fails. It returns an HTTP 200 with the `errorText` "Live account is required", meaning the user hasn't signed the Market Data Agreement yet.

**Endpoint**: `POST /userPlugin/addEntitlementSubscription`

**Environments:** Live

<End### Request

POST https://live.tradovateapi.com/v1/userPlugin/addentitlementsubscription

```curl
curl -X POST https://live.tradovateapi.com/v1/userPlugin/addentitlementsubscription \
     -H "Authorization: Bearer <token>" \
     -H "Content-Type: application/json" \
     -d '{
  "entitlementId": 1
}'
````

```python
import requests

url = "https://live.tradovateapi.com/v1/userPlugin/addentitlementsubscription"

payload = { "entitlementId": 1 }
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript
const url = 'https://live.tradovateapi.com/v1/userPlugin/addentitlementsubscription';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"entitlementId":1}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://live.tradovateapi.com/v1/userPlugin/addentitlementsubscription"

	payload := strings.NewReader("{\n  \"entitlementId\": 1\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://live.tradovateapi.com/v1/userPlugin/addentitlementsubscription")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"entitlementId\": 1\n}"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://live.tradovateapi.com/v1/userPlugin/addentitlementsubscription")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"entitlementId\": 1\n}")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://live.tradovateapi.com/v1/userPlugin/addentitlementsubscription', [
  'body' => '{
  "entitlementId": 1
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://live.tradovateapi.com/v1/userPlugin/addentitlementsubscription");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"entitlementId\": 1\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

````swift
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = ["entitlementId": 1] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://live.tradovateapi.com/v1/userPlugin/addentitlementsubscription")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: \{ (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```# Restricted Countries

Per CME Group policy, market data must not be accessed, distributed, or consumed in certain countries and regions. To learn more, see [Restricted Countries](/resources/reference/cme-restricted-countries).

---

## Revoking and Canceling

When users fail evaluations or leave your program:

1. **Revoke trading permissions** to remove access to specific accounts
2. **Cancel subscriptions** to stop platform access and billing

See [Revoke and Cancel Users and Accounts](./revoke-and-cancel-users-and-accounts) for detailed instructions.

---

## Next Steps

After you've created users and provisioned their accounts, continue with:

1. **[Risk Management Setup](./risk-management-setup)**: Configure account risk parameters
2. **[Market Data Renewals](/resources/reference/market-data-renewals)**: Automatic renewals for market data subscriptions
````