Triggers
Triggers are conditional orders held by the exchange and submitted when the market reaches a trigger price. Product behavior is described in Take Profit and Stop Loss.
Add a trigger
import { Side, TriggerKind } from "@n1xyz/nord-ts";
const { actionId, triggerId } = await user.addTrigger({
marketId: 0,
side: Side.Ask,
kind: TriggerKind.StopLoss, // or TriggerKind.TakeProfit
triggerPrice: 45000,
limitPrice: 44900, // optional; omit for a market-style exit
limitBaseSize: 0.1, // optional
limitQuoteSize: 4490, // optional
accountId, // optional
referrer, // optional referral identifier
});
triggerPrice must be positive. limitPrice, limitBaseSize, and
limitQuoteSize limit the order created when the trigger fires. You can set
either size limit or both; when both are set, the smaller resulting order
applies. With no size limit, the trigger tries to close the full position.
addTrigger returns actionId and the new triggerId as bigint. The
trigger ID is the trigger's identity: two triggers can share the same prices
and limits. An account can have at most 16 active and pending triggers per
market.
Attach TP/SL to an order
Pass triggers to placeOrder to attach a take-profit and stop-loss to the order.
import { FillMode, Side } from "@n1xyz/nord-ts";
const { orderId, triggerMutations } = await user.placeOrder({
marketId: 0,
side: Side.Bid,
fillMode: FillMode.Limit,
isReduceOnly: false,
size: 0.01,
price: 60000,
triggers: {
Pair: {
take_profit_prices: { trigger: 66000 },
stop_loss_prices: { trigger: 57000, limit: 56900 }, // limit is optional
},
},
});
The pair is one-cancels-other (OCO): when one trigger executes, the other is
canceled. To attach a single trigger, use
{ Single: { kind: "takeProfit" | "stopLoss", prices: { trigger, limit? } } }.
Attached triggers take only prices; their size follows the parent's fills. The
parent must not be reduce-only. The triggers stay pending while the parent
rests and become active when it fills. placeOrder, cancelOrder, and
cancelOrderByClientId report affected triggers in
triggerMutations.placed, triggerMutations.activated, and
triggerMutations.cancelled.
Replace and remove
replaceTrigger replaces the trigger's parameters, so pass the full definition —
triggerId, marketId, side, kind, triggerPrice, and any limit fields —
not just the fields you are changing.
await user.replaceTrigger({
triggerId,
marketId: 0,
side: Side.Ask,
kind: TriggerKind.TakeProfit,
triggerPrice: 72000,
});
await user.removeTrigger({ triggerId });
replaceTrigger takes the same price, size, and referrer fields as
addTrigger, but no accountId: the account comes from triggerId. Both calls
return { actionId } and work on pending and active triggers.
Triggers in atomic actions
atomic accepts addTrigger, replaceTrigger, and removeTrigger
subactions. The trigger type is triggerKind, because kind names the
subaction.
await user.atomic(
[
{ kind: "removeTrigger", triggerId },
{
kind: "addTrigger",
marketId: 0,
side: Side.Ask,
triggerKind: TriggerKind.StopLoss,
triggerPrice: 43000,
},
],
accountId,
);
Per market, cancels and trigger removals go first and placements, trigger additions, and replacements go last. One atomic action can't replace or remove the same trigger twice, or touch a trigger it adds.
Query triggers
| SDK method | Endpoint | Purpose |
|---|---|---|
getAccountTriggers | GET /account/{account_id}/triggers | Pending and active triggers |
getAccountTriggerPlaceHistory | GET /account/{account_id}/triggers/history/placements | Placement history |
getAccountTriggerFinaliseHistory | GET /account/{account_id}/triggers/history/finalisations | Finalization history |
const triggers = await nord.getAccountTriggers({ accountId });
const active = triggers.filter((t) => t.orderId == null);
const placements = await nord.getAccountTriggerPlaceHistory({
accountId,
since: "1970-01-01T00:00:00Z",
until: new Date().toISOString(),
pageSize: 50,
});
All three methods require accountId. A trigger with a parent orderId is
pending on that order; one without is active. Each trigger also carries marketMode and,
for OCO pairs, the sibling trigger ID. Trigger IDs are strings in these
responses, so wrap them in BigInt() before passing them to removeTrigger.
History pages return nextStartInclusive; pass it back unchanged as
startInclusive to fetch the next page. Finalization rows add status
(such as Success, Removed, Cancelled, or Failed) and an optional error.
A trigger stays live until it executes, is canceled, or is removed. Closing or flipping the position, or switching the market from CLOB to RFQ, cancels its triggers, so reconcile against the finalization history rather than assuming a trigger is still live. There is no exchange-wide trigger endpoint.