TradeAon · Guides · Pending orders
Webhooks · Reference

Pending Orders from a Webhook: limit, stop and the Four Types

By the TradeAon team · Published · Updated · 7 min read

By default an alert opens a position immediately at whatever the market is offering. Adding two fields — order_type and price — turns the same alert into an instruction to wait for a price instead. That is a useful change, and it introduces a class of mistakes that market orders simply cannot make: an order that sits there forever, or one the broker refuses because the price is on the wrong side of the market.

Key takeaways
Contents
  1. What order_type actually changes
  2. The four types, and which one you want
  3. The shorthand that picks a side for you
  4. Who rejects what: two different layers
  5. Cancelling: the four CANCEL actions
  6. When a reported failure is actually a live order

What order_type actually changes

A normal alert carries an action, a symbol and a volume, and that is enough. The order is sent to the market and filled at the current price — the field order_type defaults to market when it is absent, so a market order requires no extra configuration at all.

Supplying a pending type changes the instruction from "buy now" to "buy if price reaches this level". Two things follow from that, and both catch people out. First, price becomes mandatory, because an order to wait for a level is meaningless without the level. Second, the order is placed good-till-cancelled: it does not expire at the end of the day or when your strategy changes its mind. It waits until it fills or until something removes it.

That second property is the one worth planning for. A strategy that fires a pending order on every setup, without ever cancelling the previous one, accumulates orders on the chart — and they can trigger hours later in a market that no longer resembles the one they were designed for.

The four types, and which one you want

The four types are not four flavours of the same idea. Two of them wait for a better price than the current one, and two wait for a worse price. That distinction is the whole thing:

TypePrice sitsThe idea
buy_limitBelow marketBuy the dip — enter cheaper than now
sell_limitAbove marketSell the rally — enter higher than now
buy_stopAbove marketBuy the breakout — enter once it proves upward
sell_stopBelow marketSell the breakdown — enter once it proves downward

A limit order expresses patience: you believe price will come back to you, and you would rather not pay the current price. A stop order expresses confirmation: you do not want in until price has moved your way, because that move is your signal.

The practical test when writing an alert is mechanical. Work out whether your target price is above or below the market at the moment the alert fires, then read the correct type off the table. Getting this wrong is not a subtle strategy error — the broker will simply refuse the order, because a buy limit above the market is a request to buy at a price worse than one already available, which is not a thing an order book can express.

The shorthand that picks a side for you

Because the side is usually implied by the action you already sent, you can leave it out. If order_type is just "limit" or "stop", the buy or sell prefix is filled in from the action itself:

{"action": "BUY",  "order_type": "limit", ...}   ->  buy_limit
{"action": "SELL", "order_type": "limit", ...}   ->  sell_limit
{"action": "BUY",  "order_type": "stop",  ...}   ->  buy_stop
{"action": "SELL", "order_type": "stop",  ...}   ->  sell_stop

This is genuinely useful in Pine Script, where the same alert template often serves both directions and the action is already a variable. Writing "order_type": "limit" once beats building the string buy_limit or sell_limit conditionally.

Both forms are equally valid, so pick by clarity rather than by brevity. If a template only ever sends one direction, spelling out buy_limit makes the alert self-documenting for whoever reads it in six months. If it is shared between directions, the shorthand avoids a class of copy-paste bug where the type says buy_ and the action says SELL.

Who rejects what: two different layers

Pending orders can be refused in two entirely different places, and knowing which is which turns a confusing failure into an obvious one.

ProblemRejected byWhat you see
No price fieldServer, on arrivalAn immediate error naming the order type
price of zero or negativeTerminal, before sendingLogged as requiring a price above zero
An order_type that is not one of the fiveTerminalLogged with the list of supported types
Price on the wrong side of the marketBrokerAn invalid-price rejection from the broker
Price too close to the marketBrokerRejected under the broker's stop-level rule

The split matters because the first three are configuration bugs you can fix in your alert, and the last two are conditions of the market and the broker at the moment the order arrived. The last one in particular surprises people: most brokers enforce a minimum distance between the market and any pending order, so a level that is technically on the correct side can still be too close to accept. The same alert then works or fails depending on volatility — which looks like the integration being flaky, but is the broker's rule doing exactly what it says.

The full list of rejection messages and what each one means is in the error reference. The habit worth building is checking the event log rather than the chart: the chart shows you that no order appeared, and the log tells you which of these five things happened.

Cancelling: the four CANCEL actions

Because pending orders are good-till-cancelled, removing them has to be part of the strategy rather than an afterthought. Four actions exist for this, and they mirror the shape of the close actions for open positions:

ActionRemoves
CANCELOne specific order, by ticket or by symbol
CANCEL_ALLEvery pending order
CANCEL_BUYPending buy orders only
CANCEL_SELLPending sell orders only

Two behaviours are worth knowing. Cancelling when there is nothing to cancel is treated as success, not as an error — the same idempotent rule the close actions follow, so a strategy can cancel defensively at the start of a setup without generating noise in its own log. And CANCEL targeting a single ticket exists specifically so a signal can move one pending order — cancel it, place a new one at a better level — without disturbing every other order on that side.

Like the close actions, cancellation only touches orders placed through the integration. Pending orders you placed by hand in the terminal are not affected, for the same ownership reasons that keep manual positions out of reach of automated closes.

When a reported failure is actually a live order

One behaviour deserves explaining because it looks like a bug in a log and is in fact a guard against one. Occasionally a terminal reports that placing an order failed — a non-success return code — while the order actually exists at the broker. The response travelled badly, or the terminal's view of the result disagreed with reality.

Taking the return code at face value there is the dangerous choice. The system would record a failure, the follower's records would say no order exists, and the order would sit at the broker unmanaged and unmentioned in anything you look at. So after every send, the account is searched for the order that was just placed — by comment and by resolved symbol — and if it is really there, the account wins the argument and the send is treated as successful.

The rule generalises usefully: a return code is a report about an action, while the account is the action's result. When the two disagree, the account is the one holding your money. The same principle is why acknowledgements report the volume that actually filled rather than the volume that was requested — the record should describe the position that exists, not the one that was intended.

TradeAon is a technical automation tool, not financial advice. Trading involves substantial risk of loss. You are responsible for your own strategy, risk and capital.