Position Lifecycle
The sequence every integration implements, in the order the API enforces. Four rules shape it:
Step 4 folds into step 1 if you attach the stop to the entry as a bracket order: the TP/SL legs are accepted with the entry and arm themselves once it fills, so the position is never unprotected while you poll steps 2 and 3. Everything from step 5 on applies unchanged once they are armed.
1. Enter
POST /orders — one MARKET leg, limit_price as your slippage bound.
The leg returns SUBMITTED — queued, not filled.
2. Confirm the fill
Poll GET /orders/{orderId} until a terminal status.
An early 404 means not yet persisted. FILLED or PARTIALLY_FILLED_CANCELLED is a fill; avg_fill_price is the executed price.
3. Read the position
Poll GET /account/{account_id}/positions until the market appears. A single read right after the fill regularly returns an empty array on a position that exists.
Direction is the sign of size: positive long, negative short.
4. Attach the stop
POST /orders — one reduce-only TRIGGER leg with size: "0", which closes the whole position at fire time. (Skip this step if the stop was attached at entry — it is already armed, and it replaced any older whole-position stop of the same kind.)
- Derive the level from the current mark, not
entry_price; a trigger already past the mark on its fire side is rejected. limit_priceis where the IOC fires;trigger.trigger_priceis what arms it.- Keep the returned
order_idfor the modify and the exit.
5. Move the stop
POST /orders/{orderId}/modify — every field, every call; there is no partial modify.
- Only
limit_price,size,trigger_pricechange. Resendsize: "0". - A stop still waiting for its entry (
parent_order_idset) cannot be modified — move the entry instead, or cancel the stop and attach a new one once the entry fills. client_order_idmust be new and is signed here, unlike on an order leg.- Success returns a new
order_id; the old one is dead.
An armed trigger reads SUBMITTED for its whole life. That is not a stuck order.
6. Exit
In this order:
- Cancel every armed trigger on the market —
GET /account/position-triggers?wallet=…, thenPOST /orders/{orderId}/cancelwithorder_type: "TRIGGER"for each. - Wait until they are gone — cancellation is asynchronous; poll
position-triggers. - Close — one reduce-only
MARKETleg,sideagainst the position,sizefromcloseable. Reduce-only legs are exempt frommin_order_value.
Closing while a trigger is still armed fails with close_trigger_coexistence. There is no atomic flip: reverse by exiting, then entering again.
Next: Account Data