Alert Payload Syntax & Reference
This page is the syntax reference for the text payloads CrossTrade accepts from TradingView (and any other webhook source). Payloads are key=value pairs separated by semicolons. Every field must end with a semicolon. Field names are normalized on the server, so case is technically not enforced, but values (instruments, actions, TIF) are case-sensitive in some cases — stick to the formats shown.
Frequently Asked Questions
What does a basic CrossTrade alert payload look like?
A minimal market-buy payload to a single account uses eight fields: key, command=PLACE, account, instrument, action, qty, order_type=MARKET, and tif=DAY. Every line ends in a semicolon. key is your CrossTrade secret key, found under Security in My Account or on the Dashboard Manual Trading example.
key=your-secret-key;
command=PLACE;
account=sim101;
instrument=MNQ 09-26;
action=BUY;
qty=1;
order_type=MARKET;
tif=DAY;
What fields are required in every payload?
At minimum: key (your CrossTrade secret key), command (what to do, e.g., PLACE, FLATTEN, CANCELORDERS), account (the NT8 account name), and instrument (the contract in an NT8-recognized format). For command=PLACE; you also need action, qty, order_type, and tif. NT8 requires a valid whole-number qty on every place order — if you send a payload without qty, NT8 will reject it with 'Check message format, missing required field: QTY'.
What are all the commands CrossTrade supports?
Common commands: PLACE (submit a new order), CANCEL/CANCELORDERS (cancel working orders e.g. by instrument), FLATTEN (close all open positions and cancel all working orders for the account + instrument specified), FLATTENEVERYTHING (close all positions and orders across all accounts), CLOSEPOSITION (close an existing position; supports partial qty), CHANGE (modify a pending unfilled order; requires passing the order_id), and CANCELANDBRACKET (replace working protection with a new bracket around an existing position). See the full list at crosstrade.io/docs/webhooks/commands.
What's the difference between FLATTEN and CLOSEPOSITION?
FLATTEN closes positions and cancels any working orders (including orphaned ATM stop/target orders) for the specified account + instrument. CLOSEPOSITION closes an existing position and supports partial quantity — you can send multiple CLOSEPOSITION commands with different qty values to exit in pieces. FLATTENEVERYTHING is the nuclear option — closes all positions and orders across all accounts in the payload.
key=your-secret-key;
command=FLATTEN;
account=Sim101;
instrument=MES 09-26;
What does command=CHANGE do and when do I use it?
CHANGE lets you modify a pending limit order. If you pass an order_id along with a PLACE-style payload, you can update the limit price or quantity of that order. It only works on orders that are still pending/unfilled — once an order fills, it's removed from the order book and no longer exists. For a resting limit, you can keep moving the price with CHANGE as often as you need while it's still open.
How do I send an alert to multiple accounts at once?
Put account names separated by commas (no spaces) inside the single account= field, and end with a semicolon (e.g., account=Sim101,Sim102,Sim103;). Do not separate accounts with semicolons — a payload like account=ACCT_A; ACCT_B; is a common error and will be parsed as a single malformed field.
key=your-secret-key;
command=PLACE;
account=Sim101,Sim102,Sim103;
instrument=ES 09-26;
action=BUY;
qty=1;
order_type=MARKET;
tif=DAY;
Can I apply a different ATM template to each account in a multi-account payload?
No. The strategy= (ATM template) line accepts only one template name, and it's applied to every account listed in account=. If you need different ATMs per account, you have to send separate alerts.
How do I format instruments (the instrument field)?
Valid NT8 contract formats include MNQ1! (continuous/front-month auto-rollover), MNQ 09-26 (numeric month-year), MNQ SEP26 (month abbreviation), MNQU6 (NT8 short code), and NQU2026 (full-year NT8 short code). Alerts must be in a format NinjaTrader recognizes. CrossTrade is just the message broker — it does not impose instrument limits.
Do I capitalize the instrument ticker?
Yes. NT8 expects the ticker capitalized. instrument=mes 09-26; is wrong; use instrument=MES 09-26;. Also make sure your TradingView {{ticker}} variable produces the same format your NT8 is configured for — if you're using MNQ SEP26 style, change NT8 to Month Abbreviation; if you want MNQ 09-26 style, keep NT8 on numerical.
What is MNQ1! (the continuous contract)?
MNQ1! is the continuous front-month contract — NT8 resolves it to whichever contract month is active (auto-rollover). This is the recommended format because you set it once and forget it; NT8 handles the roll. Common mistake: writing MNQ! instead of MNQ1!. The 1 is required. You can also use the 1! form for other tickers: ES1!, NQ1!, GC1!, MES1!, etc.
How do I handle contract rollover for open positions?
If you have an open position on an expiring contract during the week of rollover, the safest workflow is: temporarily change your payload's instrument= from the continuous form (e.g., ES1!) to the explicit contract (e.g., ESU6 or ES 09-26) for the duration the position is open, then once the position on the old contract is closed, switch the payload back to the continuous form. This manual intervention is recommended during the rollover week and avoids front-month discrepancies.
Why did CANCELORDERS stop working when I changed the instrument format?
NT8 understands both MNQ 09-26 and MNQ SEP26 for placing orders, but when you call CANCELORDERS, CrossTrade filter-matches working orders against the given instrument string. If an order was placed as MNQ 09-26 and you try to cancel with MNQ SEP26, the filter won't match. Keep the format consistent between placement and cancellation.
I get "no market data for ES 9-26" — what's wrong?
The format is wrong — use two-digit month: ES 09-26 (not ES 9-26). If it still fails, the market may be closed or the contract may have expired; use the active front month or the continuous ES1! format.
Are /MNQ and /NQ treated as the same or different instruments?
They are different instruments. You can hold a long /MNQ and a short /NQ at the same time — CrossTrade treats them as independent.
What are the supported order types?
Both destinations support MARKET, LIMIT, STOPMARKET, and STOPLIMIT. Tradovate additionally supports MIT (market-if-touched), TRAILINGSTOP, and TRAILINGSTOPLIMIT. MIT uses limit_price as its touch price. Tradovate trailing orders require a positive trail_offset; TRAILINGSTOP also requires stop_price, and TRAILINGSTOPLIMIT requires both stop_price and limit_price. NT8 trailing management remains an ATM-template feature.
How do I send a LIMIT order with a price offset?
limit_price accepts four forms: limit_price=12345; (absolute price), limit_price=25 ticks; (offset in ticks from underlying), limit_price=2%; (percentage offset), limit_price=-250 ticks; (negative offset = below spot). If you submit order_type=LIMIT; with no limit_price, the order will be rejected.
key=your-secret-key;
command=PLACE;
account=sim101;
instrument=ES1!;
action=BUY;
qty=1;
order_type=LIMIT;
limit_price=-250 ticks;
tif=DAY;
How do I send a STOPMARKET order with stop_price?
Provide stop_price (absolute or offset) along with order_type=STOPMARKET;. Props sometimes reject orders whose limit_price or stop_price is too far from market — that's a broker restriction, not a CrossTrade restriction.
key=your-secret-key;
command=PLACE;
account=Sim101;
instrument=MNQ1!;
action=BUY;
qty=5;
order_type=STOPMARKET;
stop_price=26555;
tif=DAY;
stop_loss=26500.50;
take_profit=26600.50;
Can I set take_profit and stop_loss values with a STOPMARKET entry order?
Yes. On NT8, CrossTrade waits for the STOPMARKET entry fill, then creates the OCO children from the actual fill and filled quantity. On Tradovate, the entry and absolute bracket prices are submitted as a broker-side OSO. Verify the resulting protection because either broker can still reject an invalid child price.
What values does take_profit / stop_loss accept?
Three accepted forms. A bare number is a literal price level, not an offset: take_profit=19700; is absolute, while take_profit=40 ticks; and take_profit=40ticks; are offsets. Use positive distance magnitudes for take_profit and stop_loss; CrossTrade derives direction from the entry side. This does not change signed entry offsets: limit_price and stop_price may still use positive or negative relative values to select above or below the quote. To use an offset, always include a ticks, points, dollars, or % unit.
Which side should be negative — take_profit or stop_loss?
Neither offset needs a direction sign. Use positive distances for take_profit and stop_loss; CrossTrade places targets and stops on the correct side for Buy versus Sell automatically. Bare numeric values remain absolute price levels.
What are the valid TIF (Time-In-Force) values?
DAY and GTC work on both destinations. Tradovate additionally accepts IOC, FOK, and GTD (with expire_time). The NT8 webhook path supports its documented platform TIF set, so check the Destinations matrix before sharing one template across brokers.
What are the valid values for action?
BUY and SELL work on both destinations. Tradovate additionally accepts LONG as an alias for BUY and SHORT as an alias for SELL; use BUY/SELL on NT8. Other literal strings (e.g., "BUY OR SELL") are rejected. When you use a TradingView strategy variable, use action={{strategy.order.action}};. That variable only works if the alert is fired from a strategy (not an indicator). From an indicator, {{strategy.order.action}} passes through as literal text and the alert will fail.
Which TradingView variables work in payloads?
Common usable variables: strategy.order.action (BUY or SELL), strategy.order.contracts (trade quantity, use for qty=), strategy.order.quantity (same purpose depending on script), strategy.market_position and strategy.prev_market_position (for sync), strategy.position_size (for target_quantity=), ticker (symbol from TradingView; only works if the ticker symbol is valid on both platforms), close (close price, usable for limit prices). All strategy variables require the alert to be fired from a TradingView strategy, not an indicator. A common typo is misspelling strategy (e.g., stratety) — if the value comes through literally in the payload, check the spelling.
Can I send a bracket (TP/SL) without a primary order?
Inline take_profit / stop_loss fields need a primary PLACE order. To replace protection on an existing position, use CANCELANDBRACKET: it cancels the instrument's working orders and applies a new bracket without opening another entry. For that command, action names the protected position side: BUY protects a long and SELL protects a short. Tradovate also accepts LONG and SHORT as aliases; NT8 requires BUY or SELL.
Is there a way to delay the TP/SL to a bar after entry?
Not in a single alert. That would require two separate alerts.
What's the standard "strategy" payload for a TradingView strategy?
Use key, command=PLACE, account, instrument, action=strategy.order.action, qty=strategy.order.contracts, order_type=MARKET, tif=DAY. If your strategy is stop-and-reverse, add flatten_first=true;. Otherwise that's everything you need for a basic strategy entry.
key=your-secret-key;
command=PLACE;
account=sim101;
instrument=ES 09-26;
action={{strategy.order.action}};
qty={{strategy.order.contracts}};
order_type=MARKET;
tif=DAY;
Can I link two LIMIT orders as OCO without sending a bracket?
On the NT8 destination, yes: send two separate LIMIT orders with the same oco_id= (e.g., oco_id=bracket1;). Manual oco_id is not supported on destination=tradovate; use take_profit plus stop_loss so CrossTrade creates the broker-side OCO bracket.
What does cancel_after do and why did I get a CANCEL_AFTER error?
cancel_after only works with order_type=LIMIT;. Market orders execute immediately so they can't be canceled after a delay. If you try to use cancel_after with any non-limit order type, you'll get: 'CANCEL_AFTER requested but order type is not LIMIT.'
What's the most common payload formatting mistake?
Missing semicolons. Every field must end with ;. Frequent examples: rate_limit=1 (missing — broken) vs. rate_limit=1; (correct); strategy=sumotrail (missing — broken) vs. strategy=sumotrail; (correct). A missing semicolon anywhere in the payload — including at the end — will cause 'Check message format' failures.
What are other common payload errors?
Literal variable value: qty={{stratety.order.contracts}}; — strategy is misspelled, so TradingView passes the text through unevaluated. Wrong separator between accounts: account=ACCT_A; ACCT_B; — use comma: account=ACCT_A,ACCT_B;. Wrong instrument case: instrument=mes 09-26; — capitalize: instrument=MES 09-26;. Wrong action value: action=BUY OR SELL; — use BUY or SELL (Tradovate also accepts LONG/SHORT aliases). Wrong qty format: qty=5.00; — must be a whole number: qty=5;. Missing qty: NT8 requires qty — a strategy that doesn't emit a number will error out. Missing 1 in continuous contract: instrument=MNQ!; — should be instrument=MNQ1!;. Partial apex account name: some prop accounts include an exclamation mark — use the name exactly as it appears on the prop dashboard or Rtrader. TP/SL treated as price: take_profit=225; on MNQ at 19,586 is interpreted as price 225 — use take_profit=225 ticks;.
Does field-name case matter in the payload?
Technically no — CrossTrade normalizes field names on the server. Key, KEY, and key all work. That said, lowercase is the convention in the docs and examples. Values are not normalized — BUY/SELL are case-sensitive for action, and instrument strings must match NT8's expected casing.
Can I add a note/comment to an alert?
Yes, use notes= (e.g., notes=some-free-text;). You can drop TradingView variables into notes (e.g., notes={{timenow}};) if you want them logged, though the practical value is limited.
How do I rate-limit an alert to fire only once per trading session?
Combine id= with rate_limit=1/86400; (once per 86,400 seconds = 1 day). The id groups related alerts together for rate-limit counting. More info at crosstrade.io/docs/webhooks/advanced-options/rate-limiting.
key=your-secret-key;
command=FLATTEN;
account=Sim101;
instrument=MES 09-26;
rate_limit=1/86400;
id=OncePerDay;
Can I send sl_price alongside an ATM strategy?
Yes, but sl_price does not override or replace the ATM SL — it gets placed in addition to it. If you want the ATM stop replaced, you have to adjust the ATM template itself.
What does the CANCELANDBRACKET command do?
CANCELANDBRACKET replaces working protection around an existing position: it cancels the specified account + instrument's working orders, confirms the position still exists, then places a new take-profit and/or stop-loss bracket. action names the position side being protected, so BUY protects a long and SELL protects a short. Tradovate also accepts LONG/SHORT aliases; NT8 requires BUY/SELL. More info at crosstrade.io/docs/webhooks/commands/cancel-and-bracket.
key=your-secret-key;
command=CANCELANDBRACKET;
account=sim110;
instrument=ES1!;
action=BUY;
qty=1;
take_profit=100 ticks;