PearPear
API IntegrationExecuting Trade

Managing Open Order

List, cancel, and change resting orders (triggers, schedules, ladders).

Resting orders, the ones that open or close a basket later, are triggers, TWAP schedules, and ladders. See Orders and Executions for how each relates to the executions and fills it produces.

In the SDK these are sdk.core.triggers.list / .cancel / .cancelAll, sdk.core.schedules.list / .cancel / .cancelAll, and sdk.core.ladders.list / .get / .cancel.

Triggers and schedules have no single-resource endpoint. Find one by filtering its list.

Listing

All three lists are cursor-paginated and take cursor, limit, and connector. Beyond that they differ:

ListExtra filters
GET /triggersstatus: ACTIVE, COMPLETED, CANCELLED. COMPLETED means the trigger fired.
GET /schedulesstatus: ACTIVE, COMPLETED, CANCELLED. COMPLETED also returns schedules that failed.
GET /laddersNone. There is no status filter, so cancelled and completed ladders come back with the active ones. Read status on each row.

Ladder rungs are triggers

A ladder's rungs are ordinary triggers, and they appear in GET /triggers like any other. Three consequences:

Rungs do not count against the five active triggers per position limit.

Cancelling

A cancel takes no body:

curl -X PATCH "https://pro-gateway.pearprotocol.io/triggers/$TRIGGER_ID/cancel" \
  -H "x-api-key: $PEAR_API_KEY" \
  -H "x-trade-account-id: $TRADE_ACCOUNT_ID"

Cancelling places no order and never unwinds what already happened. What it stops, and what it leaves behind, differs by type:

CancellingStopsLeaves
A triggerThe trigger firing.Nothing, as long as it never fired.
A TWAP scheduleIts pending slices.Every slice that already filled, as part of your position.
A ladderIts unfired rungs.Every rung that already filled.

So a half-finished TWAP leaves you holding whatever it built. Read that exposure with GET /positions, and close it with POST /trade/{positionId}/close if you did not want it.

A trigger that has already fired cannot be cancelled at all: it is TRIGGERED, not ACTIVE, and the cancel returns 409. That is true even when the close it launched failed or filled only part of the basket, which is exactly the case where residual exposure is left behind. See Take Profit / Stop Loss.

Cancelling covers both kinds of trigger: the open triggers that would have entered a basket, and the take-profit and stop-loss triggers resting on an open position. Cancelling a stop loss leaves the position open and unprotected.

Find the ids to cancel with the list endpoints above, or from Open Order. Cancellations stream over the WebSocket as trigger.cancelled, schedule.cancelled, or ladder.cancelled.

Cancel-all covers the whole trade account

cancel-all is not scoped to a position. PATCH /triggers/cancel-all cancels every active trigger on the trade account — every stop loss and every take profit, on every open position, plus every ladder rung and every resting open trigger. PATCH /schedules/cancel-all does the same for schedules.

To clear the triggers on one position, list them and cancel them by id.

Both return the ids they cancelled. Both return 409 NOOP_ERROR when nothing is active — No active triggers to cancel and No active schedules to cancel. Treat that 409 as "nothing to do", not as a failure.

Cancel status rules differ

CancelOn a resting orderOn one that is not active
PATCH /triggers/{triggerId}/cancelCancels it409 RESOURCE_BUSY
PATCH /schedules/{scheduleId}/cancelCancels it409 RESOURCE_BUSY
POST /ladders/{ladderId}/cancelCancels its active rungsSucceeds anyway. It only 404s on a ladder id that does not exist.

The ladder cancel is safe to repeat, and tells you nothing about whether the ladder was still running. Read status from GET /ladders/{ladderId} if you need to know.

Changing a resting order

Resting orders are not edited in place. To change one, cancel it and create a new one with the updated terms:

Cancel first, then create. The two calls are not atomic, so the market is unwatched in between. See Order Type for the shape of each.

Auto-rebalance is the exception

An auto-rebalance config can be changed in place, and swapped atomically:

It is a standing config rather than an instruction that fires once, which is why it behaves differently. Note that replace hands back a new config id. See Auto-Rebalance.

On this page