POST Flat Place Order
- NT8
- Tradovate
Close position and place order NT8
Unlike reverse positions, flat placing an order will close any existing position and continue on to place the order regardless of whether or not the position existed. This is useful to ensure you are always cleanly entering a new positions. The equivalent of a webhook signal with the flatten_first flag enabled.
Endpoint
POST /v1/api/accounts/{account}/orders/flatplace
Headers
| Name | Value |
|---|---|
| Content-Type | application/json |
| Authorization | Bearer <token> |
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
account | string | Required | Name of account in NT8 |
Body parameters
| Name | Type | Required | Description |
|---|---|---|---|
instrument | string | Required | Name of underlying instrument (e.g., "ES 12-25") |
action | string | Required | BUY, SELL |
quantity | int | Required | Contract quantity of new order |
orderType | string | Required | MARKET, LIMIT, STOPMARKET, STOPLIMIT |
timeInForce | string | Required | DAY, GTC |
limitPrice | float | Optional | Limit price when submitting limit order type |
stopPrice | float | Optional | Stop price when submitting stop order type |
ocoId | string | Optional | Create or append to OCO order by ID |
strategy | string | Optional | ATM strategy name if opening with ATM template |
Code examples
- Python
- JavaScript
- cURL
import requests
token = 'my-secret-token'
url = "https://app.crosstrade.io/v1/api/accounts/Sim101/orders/flatplace"
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
}
data = {
"instrument": "MES 12-25",
"action": "BUY",
"orderType": "MARKET",
"quantity": 1,
"timeInForce": "DAY"
# "limitPrice": 5500
# "stopPrice": 0,
# "ocoId": "abc123",
# "strategy": "MyAtmStrategy"
}
try:
response = requests.post(url, headers=headers, json=data)
print(f"Response Code: {response.status_code}, Response Text: {response.text}")
except Exception as e:
print(f"An error occurred: {e}")
const token = 'my-secret-token';
const url = "https://app.crosstrade.io/v1/api/accounts/Sim101/orders/flatplace";
const data = {
instrument: "MES 12-25",
action: "BUY",
orderType: "MARKET",
quantity: 1,
timeInForce: "DAY"
// limitPrice: 5500,
// stopPrice: 0,
// ocoId: "abc123",
// strategy: "MyAtmStrategy"
};
fetch(url, {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Content-Type": "application/json"
},
body: JSON.stringify(data)
})
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.error(err));
TOKEN="my-secret-token"
curl -X POST "https://app.crosstrade.io/v1/api/accounts/Sim101/orders/flatplace" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"instrument": "MES 12-25",
"action": "BUY",
"orderType": "MARKET",
"quantity": 1,
"timeInForce": "DAY"
}'
Response
- 200
- 400
{
"orderId": "1ede9d7ad8124fd48e3177399bf90a04",
"success": true
}
{
"error": "Invalid request"
}
Platform nuances
- Flattening and order cancellation are limited to the requested instrument on the selected account.
- If a position or working order exists, the add-on waits up to 4.5 seconds for the position to become flat and every order on that instrument to become terminal. If they do not clear, the request returns an error and does not place the new entry.
- If the account is already flat with no working orders on the instrument, the request proceeds directly to placing the new order.
WebSocket API
This request can also be made over the WebSocket API. The account path parameter and request body fields are all passed inside args.
{
"action": "rpc",
"id": "my-request",
"api": "FlatPlace",
"args": {
"account": "Sim101",
"instrument": "ES 09-26",
"action": "Buy",
"orderType": "Market",
"quantity": 1,
"timeInForce": "Gtc"
}
}
Close position and place order Tradovate
Flattens any open position and clears same-contract working orders before placing a new entry, exactly like a webhook signal with flatten_first enabled. No NinjaTrader add-on is involved: the operation runs server-side with the same field validation, Account Manager locks, and Trade Copier fan-out as a webhook signal.
Endpoint
POST /v1/api/tv/accounts/{account}/orders/flatplace
Headers
| Name | Value |
|---|---|
| Content-Type | application/json |
| Authorization | Bearer <token> |
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
account | string | Required | Tradovate account name, for example DEMO12345678. |
Body parameters
| Name | Type | Required | Description |
|---|---|---|---|
instrument | string | Required | Continuous (ES1!), NT8 (ES 09-26), or Tradovate (ESU6) instrument form. |
action | string | Required | buy or sell for the new entry. |
qty | int | Required | New-entry contract quantity. |
orderType | string | Required | Same order-type values supported by Place Order. |
limitPrice | number | Optional | Limit price for an order type that uses one. |
stopPrice | number | Optional | Stop price for an order type that uses one. |
tif | string | Optional | Time in force. |
takeProfit | number | Optional | Absolute target price for an attached server-side OCO bracket. |
stopLoss | number | Optional | Absolute stop price for an attached server-side OCO bracket. |
orderId | string | Optional | Caller-supplied order reference. |
text | string | Optional | Free-form Tradovate order note. Truncated to 64 characters (Tradovate's limit). |
expireTime | string | Optional | ISO-8601 expiry. Required when tif=gtd. |
maxShow | int | Optional | Native iceberg display quantity. |
trailOffset | number | Optional | Native trailing-stop distance. Required for trailing order types. |
pegDifference | number | Optional | Alias of trailOffset. |
requireMarketPosition | string | Optional | Gate the operation on flat, long, or short. |
maxPositions | int | Optional | Block the new entry when this many positions are already open. |
cancelAfter | int | Optional | Cancel an unfilled limit entry after 1 to 180 minutes. |
syncStrategy | bool | Optional | Enable Tradovate Strategy Sync for this entry command. |
marketPosition | string | Optional | Remote strategy target side: flat, long, or short. |
prevMarketPosition | string | Optional | Remote strategy side before this signal. |
outOfSync | string | Optional | Mismatch policy: wait, flatten, ignore, or resync. |
targetQuantity | int | Optional | Exact signed target quantity for resync mode. |
strategyExitBlock | bool | Optional | Reject non-opening strategy transitions. |
atmTargets | string | Optional | Inline ATM profit-target tiers in ticks or points. |
atmStops | string | Optional | Inline ATM stop tiers in ticks or points. |
atmQtys | string | Optional | Contract quantities for the inline ATM tiers. |
atmTrail | string | Optional | Per-tier trailing-stop toggles. |
atmTrailTrigger | string | Optional | Profit distance that activates trailing tiers. Set with atmTrailOffset. |
atmTrailOffset | string | Optional | Distance the activated stop follows behind price. Set with atmTrailTrigger. |
atmBreakeven | int | Optional | Target tier whose fill moves remaining stops to breakeven. |
atmBreakevenOffset | string | Optional | Breakeven offset for the inline ATM bracket. |
Targets, stops, scale-out quantities, and triggerless continuous trails are Tradovate native. Triggered trail activation, restart-safe trigger memory, and target-fill breakeven are CrossTrade-exclusive beta features. Triggered trails use CrossTrade's own live pricing rather than Tradovate entitlement data; breakeven is driven by broker fill state. Managed fields require a Day entry.
Code examples
- Python
- JavaScript
- cURL
import requests
token = 'my-secret-token'
url = "https://app.crosstrade.io/v1/api/tv/accounts/DEMO12345678/orders/flatplace"
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
}
data = {
"instrument": "ES1!",
"action": "buy",
"qty": 1,
"orderType": "market"
}
try:
response = requests.post(url, headers=headers, json=data)
print(f"Response Code: {response.status_code}, Response Text: {response.text}")
except Exception as e:
print(f"An error occurred: {e}")
const token = 'my-secret-token';
const url = "https://app.crosstrade.io/v1/api/tv/accounts/DEMO12345678/orders/flatplace";
const data = {
instrument: "ES1!",
action: "buy",
qty: 1,
orderType: "market"
};
fetch(url, {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Content-Type": "application/json"
},
body: JSON.stringify(data)
})
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.error(err));
TOKEN="my-secret-token"
curl -X POST "https://app.crosstrade.io/v1/api/tv/accounts/DEMO12345678/orders/flatplace" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"instrument": "ES1!", "action": "buy", "qty": 1, "orderType": "market"}'
Response
The response is the response envelope with api set to flat_place.
{
"success": true,
"destination": "tradovate",
"api": "flat_place",
"account": "DEMO12345678",
"instrument": "ES1!",
"response": {},
"durationMs": 214
}
Platform nuances
- The entry is sent only after the same account and exact contract report a flat position and no nonterminal working orders.
- A settlement timeout fails closed and returns an error without placing the entry. Mapped Trade Copier followers run their own settlement barrier.
- Account Manager locks and Trade Copier fan-out apply because this command uses the shared dispatcher.
- On failure, the response is
{"success": false, "error": "<message>"}.
See the Tradovate API overview for the full field grammar, mutation safety guarantees, and error table.