> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://partner.ninjatrader.com/eval/overview/prop-firm-management/create-and-manage-users-and-accounts/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. > **Tip** > > 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: #### API 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 `_MONTHLY`. ### Request GET [https://demo.tradovateapi.com/v1/tradovateSubscriptionPlan/list](https://demo.tradovateapi.com/v1/tradovateSubscriptionPlan/list) ```curl curl https://demo.tradovateapi.com/v1/tradovateSubscriptionPlan/list \ -H "Authorization: Bearer " ``` ```python import requests url = "https://demo.tradovateapi.com/v1/tradovateSubscriptionPlan/list" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.json()) ``` ```javascript const url = 'https://demo.tradovateapi.com/v1/tradovateSubscriptionPlan/list'; const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; 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://demo.tradovateapi.com/v1/tradovateSubscriptionPlan/list" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") 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://demo.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 ' response = http.request(request) puts response.read_body ``` ```java import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.Unirest; HttpResponse response = Unirest.get("https://demo.tradovateapi.com/v1/tradovateSubscriptionPlan/list") .header("Authorization", "Bearer ") .asString(); ``` ```php request('GET', 'https://demo.tradovateapi.com/v1/tradovateSubscriptionPlan/list', [ 'headers' => [ 'Authorization' => 'Bearer ', ], ]); echo $response->getBody(); ``` ```csharp using RestSharp; var client = new RestClient("https://demo.tradovateapi.com/v1/tradovateSubscriptionPlan/list"); var request = new RestRequest(Method.GET); request.AddHeader("Authorization", "Bearer "); IRestResponse response = client.Execute(request); ``` ```swift import Foundation let headers = ["Authorization": "Bearer "] let request = NSMutableURLRequest(url: NSURL(string: "https://demo.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() ``` #### Dashboards 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 `_MONTHLY` and record its ID. ### Template Account ID Evaluation 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 Evaluation 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`](/api/rest-api-endpoints/users/create-evaluation-users) 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`](/api/rest-api-endpoints/users/create-evaluation-users) **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 " \ -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 ", "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 ', '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 ") 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 ' 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 response = Unirest.post("https://live.tradovateapi.com/v1/user/createevaluationusers") .header("Authorization", "Bearer ") .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 request('POST', 'https://live.tradovateapi.com/v1/user/createevaluationusers', [ 'body' => '{ "users": [ { "name": "string", "email": "string", "password": "string", "firstName": "string", "lastName": "string" } ] }', 'headers' => [ 'Authorization' => 'Bearer ', '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 "); 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 ", "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" } ``` > **Info** > > Store the returned `userId` and map it to your internal user records. You'll need it for subsequent operations. > **Warning** > > The [`createEvaluationUsers`](/api/rest-api-endpoints/users/create-evaluation-users) 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 [`createEvaluationAccounts`](/api/rest-api-endpoints/users/create-evaluation-accounts) 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. Each account's `name` must use uppercase letters followed by digits (e.g., `TESTACCOUNT123`). See [`createEvaluationAccounts`](/api/rest-api-endpoints/users/create-evaluation-accounts) for details. **Endpoint:** [`POST /user/createEvaluationAccounts`](/api/rest-api-endpoints/users/create-evaluation-accounts) **Environments:** Demo ### Request POST [https://demo.tradovateapi.com/v1/user/createevaluationaccounts](https://demo.tradovateapi.com/v1/user/createevaluationaccounts) ```curl curl -X POST https://demo.tradovateapi.com/v1/user/createevaluationaccounts \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "accounts": [ { "userId": 12345, "templateAccountId": 67890, "name": "SIMACCOUNT001", "initialBalance": 100000 } ] }' ``` ```python import requests url = "https://demo.tradovateapi.com/v1/user/createevaluationaccounts" payload = { "accounts": [ { "userId": 12345, "templateAccountId": 67890, "name": "SIMACCOUNT001", "initialBalance": 100000 } ] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = 'https://demo.tradovateapi.com/v1/user/createevaluationaccounts'; const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: '{"accounts":[{"userId":12345,"templateAccountId":67890,"name":"SIMACCOUNT001","initialBalance":100000}]}' }; 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://demo.tradovateapi.com/v1/user/createevaluationaccounts" payload := strings.NewReader("{\n \"accounts\": [\n {\n \"userId\": 12345,\n \"templateAccountId\": 67890,\n \"name\": \"SIMACCOUNT001\",\n \"initialBalance\": 100000\n }\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") 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://demo.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 ' request["Content-Type"] = 'application/json' request.body = "{\n \"accounts\": [\n {\n \"userId\": 12345,\n \"templateAccountId\": 67890,\n \"name\": \"SIMACCOUNT001\",\n \"initialBalance\": 100000\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 response = Unirest.post("https://demo.tradovateapi.com/v1/user/createevaluationaccounts") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"accounts\": [\n {\n \"userId\": 12345,\n \"templateAccountId\": 67890,\n \"name\": \"SIMACCOUNT001\",\n \"initialBalance\": 100000\n }\n ]\n}") .asString(); ``` ```php request('POST', 'https://demo.tradovateapi.com/v1/user/createevaluationaccounts', [ 'body' => '{ "accounts": [ { "userId": 12345, "templateAccountId": 67890, "name": "SIMACCOUNT001", "initialBalance": 100000 } ] }', 'headers' => [ 'Authorization' => 'Bearer ', 'Content-Type' => 'application/json', ], ]); echo $response->getBody(); ``` ```csharp using RestSharp; var client = new RestClient("https://demo.tradovateapi.com/v1/user/createevaluationaccounts"); var request = new RestRequest(Method.POST); request.AddHeader("Authorization", "Bearer "); request.AddHeader("Content-Type", "application/json"); request.AddParameter("application/json", "{\n \"accounts\": [\n {\n \"userId\": 12345,\n \"templateAccountId\": 67890,\n \"name\": \"SIMACCOUNT001\",\n \"initialBalance\": 100000\n }\n ]\n}", ParameterType.RequestBody); IRestResponse response = client.Execute(request); ``` ```swift import Foundation let headers = [ "Authorization": "Bearer ", "Content-Type": "application/json" ] let parameters = ["accounts": [ [ "userId": 12345, "templateAccountId": 67890, "name": "SIMACCOUNT001", "initialBalance": 100000 ] ]] as [String : Any] let postData = JSONSerialization.data(withJSONObject: parameters, options: []) let request = NSMutableURLRequest(url: NSURL(string: "https://demo.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": "", "accountId": 98765, "tradingPermissionId": 54321 } ], "errorText": "" } ``` The response includes a `tradingPermissionId`. This endpoint creates the account and assigns a trading permission in one operation. > **Tip** > > Include `preTradeRisk` and `postTradeRisk` fields in your [`createEvaluationAccounts`](/api/rest-api-endpoints/users/create-evaluation-accounts) request when applicable. This reduces the number of API calls compared to making a separate call to `userAccountAutoLiq/update` after account creation. > **Warning** > > 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: \ #### WebSocket **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://demo.tradovateapi.com/v1/user/syncrequest](https://demo.tradovateapi.com/v1/user/syncrequest) ```curl curl -X POST https://demo.tradovateapi.com/v1/user/syncrequest \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{}' ``` ```python import requests url = "https://demo.tradovateapi.com/v1/user/syncrequest" payload = {} headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = 'https://demo.tradovateapi.com/v1/user/syncrequest'; const options = { method: 'POST', headers: {Authorization: 'Bearer ', '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://demo.tradovateapi.com/v1/user/syncrequest" payload := strings.NewReader("{}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") 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://demo.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 ' 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 response = Unirest.post("https://demo.tradovateapi.com/v1/user/syncrequest") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{}") .asString(); ``` ```php request('POST', 'https://demo.tradovateapi.com/v1/user/syncrequest', [ 'body' => '{}', 'headers' => [ 'Authorization' => 'Bearer ', 'Content-Type' => 'application/json', ], ]); echo $response->getBody(); ``` ```csharp using RestSharp; var client = new RestClient("https://demo.tradovateapi.com/v1/user/syncrequest"); var request = new RestRequest(Method.POST); request.AddHeader("Authorization", "Bearer "); request.AddHeader("Content-Type", "application/json"); request.AddParameter("application/json", "{}", ParameterType.RequestBody); IRestResponse response = client.Execute(request); ``` ```swift import Foundation let headers = [ "Authorization": "Bearer ", "Content-Type": "application/json" ] let parameters = [] as [String : Any] let postData = JSONSerialization.data(withJSONObject: parameters, options: []) let request = NSMutableURLRequest(url: NSURL(string: "https://demo.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,
User name: Bill Rando
Date: 10/03/2025
Timestamp: 2025-10-03 15:18:56 UTC
", "emailSent": false, "archived": false, "subjectId": 12081 } } } ] } ] ``` > **Warning** > > In staging, use `adminAlertId=70`. In production, use `adminAlertId=68`. \ **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. > **Note** > > 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. > **Warning** > > 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. \" \ -d masterid=1 ``` ```python import requests url = "https://demo.tradovateapi.com/v1/adminAlertSignal/deps" querystring = {"masterid":"1"} headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers, params=querystring) print(response.json()) ``` ```javascript const url = 'https://demo.tradovateapi.com/v1/adminAlertSignal/deps?masterid=1'; const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; 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://demo.tradovateapi.com/v1/adminAlertSignal/deps?masterid=1" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") 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://demo.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 ' response = http.request(request) puts response.read_body ``` ```java import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.Unirest; HttpResponse response = Unirest.get("https://demo.tradovateapi.com/v1/adminAlertSignal/deps?masterid=1") .header("Authorization", "Bearer ") .asString(); ``` ```php request('GET', 'https://demo.tradovateapi.com/v1/adminAlertSignal/deps?masterid=1', [ 'headers' => [ 'Authorization' => 'Bearer ', ], ]); echo $response->getBody(); ``` ```csharp using RestSharp; var client = new RestClient("https://demo.tradovateapi.com/v1/adminAlertSignal/deps?masterid=1"); var request = new RestRequest(Method.GET); request.AddHeader("Authorization", "Bearer "); IRestResponse response = client.Execute(request); ``` ````swift import Foundation let headers = ["Authorization": "Bearer "] let request = NSMutableURLRequest(url: NSURL(string: "https://demo.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>
--- ## 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 " \ -H "Content-Type: application/json" \ -d '{ "entitlementId": 1 }' ```` ```python import requests url = "https://demo.tradovateapi.com/v1/userPlugin/addentitlementsubscription" payload = { "entitlementId": 1 } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = 'https://demo.tradovateapi.com/v1/userPlugin/addentitlementsubscription'; const options = { method: 'POST', headers: {Authorization: 'Bearer ', '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://demo.tradovateapi.com/v1/userPlugin/addentitlementsubscription" payload := strings.NewReader("{\n \"entitlementId\": 1\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") 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://demo.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 ' 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 response = Unirest.post("https://demo.tradovateapi.com/v1/userPlugin/addentitlementsubscription") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"entitlementId\": 1\n}") .asString(); ``` ```php request('POST', 'https://demo.tradovateapi.com/v1/userPlugin/addentitlementsubscription', [ 'body' => '{ "entitlementId": 1 }', 'headers' => [ 'Authorization' => 'Bearer ', 'Content-Type' => 'application/json', ], ]); echo $response->getBody(); ``` ```csharp using RestSharp; var client = new RestClient("https://demo.tradovateapi.com/v1/userPlugin/addentitlementsubscription"); var request = new RestRequest(Method.POST); request.AddHeader("Authorization", "Bearer "); 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 ", "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://demo.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 CME Group market data access is strictly prohibited in comprehensively sanctioned and high-risk jurisdictions. To learn more, see [Restricted Countries](/eval/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](/eval/resources/reference/market-data-renewals)**: Automatic renewals for market data subscriptions ````