POST Place Order
Place an order
POST /v1/api/accounts/{account}/orders/place
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
| 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 |
orderId | string | Optional | Custom order ID to assign at placement. If provided, this ID can be used to look up or cancel the order later. |
requireMarketPosition | string | Optional | Comma-separated list of position states that must be true for the order to be accepted: "flat", "long", "short". Example: "flat" blocks the order if a position is already open. "flat,long" allows entry from flat or adding to a long. If the condition is not met, a 400 error is returned and no order is placed. |
maxPositions | int | Optional | Maximum allowed position size after the order is accepted. If the order would exceed this value, the request is rejected. |
orderId behavior
The optional orderId body field is a caller-supplied reconciliation ID, not the same field as NinjaTrader's live Order.OrderId. If you provide orderId, CrossTrade stores it inside the NT8 order's UserData XML as AutomatedTradingOrderId so the order can still be found later by your original ID.
NT8, the connected broker, or a prop firm connection has ultimate control over the actual order ID. That ID can change over the lifetime of an order, so CrossTrade stores your custom ID separately from the current NT8 order ID instead of trying to overwrite NT8's own identifier.
The orderId returned by a successful place response is the current NT8-assigned order ID at placement time. It may be different from the custom orderId you sent. For later lookup, cancel, change, replace, or lifecycle calls, you can use either the returned NT8 ID or the custom orderId you supplied.
If you are retrying after a timeout, dropped connection, or ambiguous placement result, generate a unique custom orderId for the intended order, send it with the first request, then query by that same ID before sending another placement. Do not assume a separate duplicate-suppression window beyond this ID-based reconciliation path.
Code Examples
- Python
- JavaScript
- cURL
import requests
token = 'my-secret-token'
url = "https://app.crosstrade.io/v1/api/accounts/Sim101/orders/place"
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
}
data = {
"instrument": "MES 12-25",
"action": "BUY",
"orderType": "MARKET",
"quantity": 1,
"timeInForce": "DAY",
"orderId": "my-strategy-entry-001",
# "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/place";
const data = {
instrument: "MES 12-25",
action: "BUY",
orderType: "MARKET",
quantity: 1,
timeInForce: "DAY",
orderId: "my-strategy-entry-001",
// 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/place" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"instrument": "MES 12-25",
"action": "BUY",
"orderType": "MARKET",
"quantity": 1,
"timeInForce": "DAY",
"orderId": "my-strategy-entry-001"
}'
Response
- 200
- 400
{
"orderId": "cb1fc8d4e1a84d29ae38fea964aaac8c",
"success": true
}
In this example, cb1fc8d4e1a84d29ae38fea964aaac8c is the NT8-assigned order ID returned by the add-on. The custom ID my-strategy-entry-001 remains stored in NT8 UserData under AutomatedTradingOrderId and can also be used for subsequent order lookups.
{
"error": "Invalid request"
}
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": "PlaceOrder",
"args": {
"account": "Sim101",
"instrument": "ES 09-26",
"action": "Buy",
"orderType": "Market",
"quantity": 1,
"timeInForce": "Gtc",
"orderId": "my-strategy-entry-001"
}
}