Tradovate API
The /v1/api/tv surface exposes your linked Tradovate accounts through CrossTrade. Reads return account state (positions, orders, fills, balances). Mutations (place, cancel, change, close, flatten, reverse) run through the same webhook parser and dispatcher that a destination=tradovate alert uses, so validation, account locks, and trade-copier fan-out behave exactly like a webhook signal.
The Tradovate API is in a limited alpha. Endpoints and response shapes may change. The in-app Tradovate Account Manager and Trade Copier pages that pair with it are admin-only for now.
Prerequisites
- Link a Tradovate account. Connect at least one Tradovate identity under My Account, Brokers tab. Requests for an unlinked user return
403 tradovate_not_linked. - API access on your plan. The same plan gate as
/v1/apiapplies. Requests without it return401 api_requires_pro. - A bearer token. Use the same token as the rest of the CrossTrade API. See Authentication.
Base URL and auth
All paths are under https://app.crosstrade.io. Every request carries a bearer token:
| Name | Value |
|---|---|
| Content-Type | application/json |
| Authorization | Bearer <token> |
The {account} path segment is the Tradovate account name (for example DEMO12345678), matched case-insensitively.
Response envelope
Reads return {"success": true, "data": ...}. Mutations return the dispatcher envelope:
{
"success": true,
"destination": "tradovate",
"api": "place_order",
"account": "DEMO12345678",
"instrument": "MES1!",
"response": { "orderId": 123456789 },
"duration_ms": 214
}
On failure the shape is {"success": false, "error": "<message>"} with a 400 status (or the auth status below).
Read endpoints
| Method | Path | Description |
|---|---|---|
<mark style={{color: 'green'}}>GET | /v1/api/tv/status | Token and connection status for your Tradovate identities. |
<mark style={{color: 'green'}}>GET | /v1/api/tv/accounts | List your linked Tradovate accounts. |
<mark style={{color: 'green'}}>GET | /v1/api/tv/accounts/snapshot | Live per-account P&L, positions, and working orders in one call. |
<mark style={{color: 'green'}}>GET | /v1/api/tv/accounts/{account} | One account plus a cash-balance snapshot. |
<mark style={{color: 'green'}}>GET | /v1/api/tv/positions | Open positions across all linked accounts. |
<mark style={{color: 'green'}}>GET | /v1/api/tv/accounts/{account}/positions | Open positions on one account. |
<mark style={{color: 'green'}}>GET | /v1/api/tv/accounts/{account}/orders | Working orders on one account. |
<mark style={{color: 'green'}}>GET | /v1/api/tv/accounts/{account}/orders/{id} | One order by Tradovate order id or a prior ORDER_ID. |
<mark style={{color: 'green'}}>GET | /v1/api/tv/fills | Recent fills across linked accounts. |
<mark style={{color: 'green'}}>GET | /v1/api/tv/accounts/{account}/fills | Recent fills for one account's identity. |
<mark style={{color: 'green'}}>GET | /v1/api/tv/cashbalances | Cash-balance snapshots. |
<mark style={{color: 'green'}}>GET | /v1/api/tv/marginsnapshots | Margin snapshots. |
<mark style={{color: 'green'}}>GET | /v1/api/tv/contracts/find?name= | Resolve a contract by symbol. |
<mark style={{color: 'green'}}>GET | /v1/api/tv/contracts/suggest?text= | Contract search suggestions. |
<mark style={{color: 'green'}}>GET | /v1/api/tv/exchanges | Exchange list. |
Trading endpoints
| Method | Path | Description |
|---|---|---|
<mark style={{color: 'orange'}}>POST | /v1/api/tv/accounts/{account}/orders/place | Place an order. Market, limit, or stop, with an optional take-profit / stop-loss bracket. |
<mark style={{color: 'orange'}}>POST | /v1/api/tv/accounts/{account}/orders/{id}/cancel | Cancel one order. |
<mark style={{color: 'orange'}}>POST | /v1/api/tv/accounts/{account}/orders/{id}/change | Change one order (price, quantity). |
<mark style={{color: 'orange'}}>POST | /v1/api/tv/accounts/{account}/orders/{id}/replace | Cancel and replace one order. |
<mark style={{color: 'orange'}}>POST | /v1/api/tv/accounts/{account}/orders/cancel | Cancel working orders on the account. |
<mark style={{color: 'orange'}}>POST | /v1/api/tv/orders/cancelall | Cancel all working orders. |
<mark style={{color: 'orange'}}>POST | /v1/api/tv/accounts/{account}/orders/cancel_and_bracket | Cancel working orders, then place a bracket. |
<mark style={{color: 'orange'}}>POST | /v1/api/tv/accounts/{account}/orders/flatplace | Flatten the position, then place a new order. |
<mark style={{color: 'orange'}}>POST | /v1/api/tv/accounts/{account}/positions/close | Close a position, full or partial by qty or percent. |
<mark style={{color: 'orange'}}>POST | /v1/api/tv/accounts/{account}/positions/flatten | Flatten one account. |
<mark style={{color: 'orange'}}>POST | /v1/api/tv/positions/flatten | Flatten every linked account. |
<mark style={{color: 'orange'}}>POST | /v1/api/tv/accounts/{account}/positions/reverse | Reverse the position. |
<mark style={{color: 'orange'}}>POST | /v1/api/tv/accounts/{account}/positions/reverseposition | Reverse the position (position-scoped variant). |
Request fields
Mutation bodies use the CrossTrade webhook vocabulary in lower-case JSON. The command and account come from the path, so a body only needs the trade fields. Common fields:
| Field | Example | Notes |
|---|---|---|
instrument | MES1! | Symbol. Continuous (MES1!), root (MES), or full contract are accepted. |
action | buy / sell | Order side. |
qty | 1 | Quantity. quantity is also accepted. |
order_type | market / limit / stop | Defaults to market when omitted. |
limit_price | 5000.25 | Required for limit orders. |
stop_price | 4995.00 | Required for stop orders. |
take_profit | 20 | Optional bracket target (ticks or price, per webhook grammar). |
stop_loss | 10 | Optional bracket stop. |
percent | 50 | For positions/close, close half. |
See Webhook Trading for the full field grammar. The same fields, semantics, and bracket options apply.
Example: place a market order
<mark style={{color: 'orange'}}>POST /v1/api/tv/accounts/DEMO12345678/orders/place
TOKEN="my-secret-token"
curl -X POST "https://app.crosstrade.io/v1/api/tv/accounts/DEMO12345678/orders/place" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"instrument": "MES1!", "action": "buy", "qty": 1, "order_type": "market"}'
A limit order with a bracket looks like this:
curl -X POST "https://app.crosstrade.io/v1/api/tv/accounts/DEMO12345678/orders/place" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"instrument": "MES1!", "action": "buy", "qty": 2, "order_type": "limit", "limit_price": 5000.25, "take_profit": 20, "stop_loss": 12}'
Locks and trade copier
Because mutations flow through the webhook dispatcher, two behaviors come for free:
- Account locks apply. If the Tradovate Account Manager (or a manual switch) has locked the account, a blocked request returns
{"success": false, "error": "Signal blocked, kill switch engaged ..."}. A closing-only lock rejects opening orders unless they carry flatten-first semantics. - Copiers fan out. If a signal-mode Trade Copier is configured on the account as a leader, an order placed here mirrors to its followers, exactly as a webhook would.
Errors
| Status | error | Meaning |
|---|---|---|
| 401 | invalid_bearer | Missing or invalid token. |
| 401 | inactive_subscription | Subscription is not active. |
| 401 | api_requires_pro | Your plan does not include API access. |
| 403 | tradovate_not_linked | No linked Tradovate identity on your account. |
| 403 | endpoint_not_available | Path is not part of the current /v1/api/tv surface. |
| 429 | rate_limited | Request rate exceeded. |
| 429 | egress_limited | Response egress budget exceeded. |
| 503 | temporarily_disabled | The Tradovate API is paused by a kill switch. |
Limitations
- Trades placed manually inside the Tradovate app are not seen by this API and are not blocked by account locks. The Account Manager can still flatten after the fact.
- Enforcement and live data run server-side, so flatten and lock latency is measured in seconds, not milliseconds.
- Account names use realistic placeholders in this doc (
DEMO12345678). Use your own account names.