A stop-loss or take-profit watches one price and places one child order when that price reaches
its trigger price. Create one with CreateTrigger (POST /v1/triggers). Both work on either side: a sell protects or closes a holding, and a buy enters
or buys back. This page covers standalone triggers. For legs attached to an order, see Attached take-profit and stop-loss.
Which way the price must move
You do not set a direction. Polyester derives it from the trigger type and the child order's side,
and returns it as stop.trigger_direction.
| Type and side | Fires when the price | Typical use |
|---|---|---|
STOP_LOSS SELL | Falls to or below the trigger | Limit the loss on a holding |
STOP_LOSS BUY | Rises to or above the trigger | Buy on a breakout, or buy back |
TAKE_PROFIT SELL | Rises to or above the trigger | Lock in a gain |
TAKE_PROFIT BUY | Falls to or below the trigger | Buy at a lower price |
The price is the one named by trigger_price_source: the last traded price by default, or the index price. See The price a trigger watches.
If the price has already reached the trigger price when the trigger is installed, it fails with TRIGGER_WOULD_TRIGGER_IMMEDIATELY and places nothing. Use an ordinary order to trade at once.
Child order
child selects the order placed when the trigger fires. Either side can use any of them.
market_ioc· Fields:max_slippage_ticksormax_slippage_bps
Takes liquidity at once, within a slippage cap measured from the fire price.limit_gtc· Fields:price_ticks,post_only
Rests at your limit price until it fills or you cancel it.limit_ioc· Fields:price_ticks
Takes what it can at your limit price or better, then cancels the rest.limit_fok· Fields:price_ticks
Fills completely at your limit price or better, or not at all.
A market child without a cap uses the Pair's default market slippage for its side, as a market order does. See Market order price protection. On a price gap past the cap, a market child can fill partly or not at all.
Fields and validation
| Field | Rule |
|---|---|
qty_scaled | Required, positive. The child order's quantity in the Pair's base scale |
trigger_price_ticks | Required, positive, and on the Pair's tick size |
side | Required: BUY or SELL |
child | Required: exactly one of the four children |
price_ticks (limit children) | Required, positive, and on the Pair's tick size |
max_slippage_bps (market child) | Optional. 1 to 10000 for a buy, 1 to 9999 for a sell |
max_slippage_ticks (market child) | Optional, positive. Set at most one of the two caps |
trigger_price_source | Optional: LAST_PRICE (default) or INDEX_PRICE |
fee_asset | Optional. BASE only for a buy; a sell must use QUOTE |
self_trade_prevention_mode | Optional. Defaults to EXPIRE_MAKER |
client_trigger_id | Required, 1 to 36 bytes |
Limit children take no slippage cap. In REST, prices and the quantity are decimal strings, such as "triggerPrice": "60000" and "qty": "0.5", and the Pair is named by symbol.
Funds reserved at creation
A standalone stop-loss or take-profit reserves its funds when it is created, so the child can be
placed when it fires. A create that the available balance cannot cover is rejected with INSUFFICIENT_FUNDS. A create whose child could never pass the Pair's minimum quantity, step size,
or minimum notional is rejected with that check's code, such as MIN_NOTIONAL. The child is valued
where the fire would value it: a limit child at its limit price, a market child at its slippage
bound from the trigger price.
| Child | Reserved |
|---|---|
| Any sell | The quantity, in the base Asset |
| Buy with a limit child | The limit price times the quantity, plus the fee, in the quote Asset |
| Buy with a market child | The trigger price raised by the slippage cap, or by the Pair's default, times the quantity, plus the fee |
A buy with a market child never pays more than the trigger price raised by its cap. The reserve moves to the child order when the trigger fires, and is released if the trigger is canceled or fails.
Examples
A stop-loss that sells 0.5 BTC at market if BTC-USDT trades at 60,000 or lower, with a 1% slippage cap.
POST /v1/triggers
{
"trigger": {
"symbol": "BTC-USDT",
"qty": "0.5",
"clientTriggerId": "sl-btc-1",
"stopLoss": {
"side": "SELL",
"triggerPrice": "60000",
"triggerPriceSource": "LAST_PRICE",
"child": { "marketIoc": { "maxSlippageBps": 100 } }
}
}
}/triggers.v1.TriggersService/CreateTrigger. The example assumes BTC-USDT has Pair ID 1 and a base_quantity_scale of 8; read both from GetSpotConfig.
{
"trigger": {
"symbolId": 1,
"qtyScaled": "50000000",
"clientTriggerId": "sl-btc-1",
"stopLoss": {
"side": "SELL",
"triggerPriceTicks": "60000000000000",
"triggerPriceSource": "LAST_PRICE",
"child": { "marketIoc": { "maxSlippageBps": 100 } }
}
}
}The response returns the trigger ID and the time it was accepted:
{
"triggerId": "2NEpo7TZRRrLZSi2W",
"clientTriggerId": "sl-btc-1",
"acceptedAt": "2026-11-03T09:15:02.481Z",
"acceptedAtTsNs": "1793697302481000000"
}Sells 0.5 BTC with a GTC limit order at 72,000 once the last price reaches 71,500. The limit order rests on the book if it cannot fill at once.
{
"trigger": {
"symbol": "BTC-USDT",
"qty": "0.5",
"clientTriggerId": "tp-btc-1",
"takeProfit": {
"side": "SELL",
"triggerPrice": "71500",
"child": { "limitGtc": { "price": "72000", "postOnly": false } }
}
}
}Buys 0.5 BTC with an IOC limit order at up to 66,200 once the index price rises to 66,000. On a
Pair without an index price, the trigger fails with INDEX_PRICE_UNAVAILABLE.
{
"trigger": {
"symbol": "BTC-USDT",
"qty": "0.5",
"clientTriggerId": "sl-btc-buy-1",
"stopLoss": {
"side": "BUY",
"triggerPrice": "66000",
"triggerPriceSource": "INDEX_PRICE",
"child": { "limitIoc": { "price": "66200" } }
}
}
}When it fires
When the watched price reaches the trigger price, the trigger places its child order once and
records EVENT_FIRED with the child's order ID and the fire price.
- Child admitted: the trigger is
COMPLETED. Follow the child as an ordinary order. Canceling the trigger no longer affects it. - Child rejected: the trigger is
FAILED, itsfailure_reasonis the child's rejection, such asMARKET_HALTEDorPOST_ONLY_CROSS, and its reserved funds are released. It does not re-arm. - Placement budget empty, or the account under an automatic repair: the trigger stays
ARMED, recordsEVENT_FIRE_REFUSEDwithRATE_LIMITEDorACCOUNT_REPAIRING, and fires again shortly if the latest price still meets its condition.
Modify
ModifyTrigger (PUT /v1/triggers/{trigger_id}) changes:
trigger_price_ticks. A price the watched price has already reached is refused withTRIGGER_WOULD_TRIGGER_IMMEDIATELY.- The slippage cap of a market child, with
max_slippage_ticksormax_slippage_bps. A value of0clears the cap, and the Pair's default applies again.
For a buy with a market child, changing the trigger price or the cap re-sizes the reserved funds. A change that needs more than your available balance is refused, and the trigger is unchanged.
A modify meets the same minimums as a create. The child order is valued on the terms the change
leaves: a market buy at its maximum price, a market sell at its protection price, and a limit child
at its limit price. A change that would put the child below the Pair's minimum quantity, step size,
or minimum notional is refused with MIN_QTY, QTY_STEP_SIZE, or MIN_NOTIONAL, and the trigger
keeps its previous price, cap, and reserved funds.
A trigger price off the Pair's tick size is refused with PRICE_TICK_SIZE and a tick_size violation on trigger_price_ticks (REST triggerPrice), with or without the optional symbol_id.
The trigger is unchanged.
The child's limit price cannot change: setting limit_price_ticks is refused with TRIGGER_CHILD_PRICE_NOT_MODIFIABLE. Cancel the trigger and create a new one instead.
Errors
PRICE_TICK_SIZE
A trigger or limit price is not on the Pair's tick size.MAX_SLIPPAGE_INVALID
A sell's slippage cap is10000bps.TRIGGER_PRICE_SOURCE_UNSUPPORTED
The source isMARK_PRICEor not a defined source.FEE_ASSET_NOT_ALLOWED
A sell setfee_assettoBASE, or the Pair does not allow it for a buy.INSUFFICIENT_FUNDS
The available balance cannot cover the reserve.MIN_QUANTITY,STEP_SIZE,MIN_NOTIONAL,MAX_NOTIONAL
The child order could never pass the Pair's order limits.MIN_QTY,QTY_STEP_SIZE,MIN_NOTIONALon a modify
The change would leave the child order below the Pair's minimums. The trigger is unchanged.VALIDATION_ERROR
A required field is missing, such aschild, or a price, quantity, or cap is not positive.
See Error codes for HTTP and ConnectRPC statuses, and Order types and lifecycle for how the child order behaves after it is placed.