Managing Open Position
Adjust, close, reverse, rebalance, and set risk on an open basket.
Once a basket is open, manage it through the trade, trigger, and rebalance endpoints, all scoped to the trade account that holds it. Get the positionId from GET /positions.
| Action | Endpoint |
|---|---|
| Grow or trim it | POST /trade/{positionId}/adjust, with reduceOnly to trim |
| Close | POST /trade/{positionId}/close |
| Close everything | POST /trade/close-all |
| Reverse every leg | POST /trade/{positionId}/reverse |
| Take Profit / Stop Loss | POST /triggers/close |
| Set leverage | PUT /leverage |
| Rebalance now | POST /rebalance/manual/{positionId} |
| Keep weights on target | POST /rebalance/auto |
| Read what a rebalance did | GET /rebalance/{positionId}/events |
Adjust, close and reverse all need the position to be OPEN. On any other status they return 409.
Reverse a position
POST /trade/{positionId}/reverse (SDK: sdk.core.trade.reverse) flips every leg to the opposite side at the same size. A long BTC / short ETH basket becomes short BTC / long ETH.
{
"type": "MARKET",
"clientId": "your-client-id"
}The body carries no legs and no size. clientId is optional; type accepts only "MARKET".
It is not a close followed by an open. The position keeps the same positionId, and its exposure is negated in place. To get from +0.002 BTC to −0.002 BTC in one order, Pear trades twice the current size on the opposite side, one order per non-zero leg. The order closes the existing exposure and opens the mirror in a single fill, so you are never flat in between.
The call answers 202 with an execution carrying intent: "REVERSE". The result arrives over the WebSocket as position.updated.
A reverse tears down everything that was watching the old exposure. On any real fill — including a partial fill that did not finish the flip — it:
- Cancels every trigger on the position, with
cancelledReason: "POSITION_REVERSED". That includes your stop losses. - Cancels every schedule on the position, with the same reason.
- Pauses the position's auto-rebalance config, with
pausedReason: "POSITION_CHANGED".
A reverse that fills nothing leaves all three alone. Re-arm your risk after any reverse: read the position back, then create the triggers you still want.
Rebalancing
Legs drift apart as prices move, so the basket stops matching the weights you intended.
POST /rebalance/manual/{positionId} trades back to shares you name, once. POST /rebalance/auto does it continuously on a drift threshold, in weights mode or beta mode.
See Auto-Rebalance for both, including how drift is measured in each mode and what pauses a config. What it actually did is on Rebalance Activity.
What each call gives back
Three of these calls are fire-and-forget. The rest hand back the finished result.
| Call | Response |
|---|---|
POST /trade/{positionId}/adjust | 202 with an execution, still IDLE. |
POST /trade/{positionId}/close | 202 with an execution, still IDLE. |
POST /trade/{positionId}/reverse | 202 with an execution, still IDLE. |
POST /trade/close-all | 202, but the call blocks until the whole run finishes. The body carries every execution the run created, each already in its final status. |
POST /triggers/close | 200 with the resting trigger. Nothing trades yet. |
PUT /leverage | 200, synchronous. |
POST /rebalance/manual/{positionId} | 200 with a plan, after the rebalance has run. |
POST /rebalance/auto | 200 with the created config. |
For the three 202 calls, poll the execution or watch the WebSocket for position.updated or position.closed. A 202 means the order is queued, not filled: an execution can still end FAILED. See Error Handling.