1
Author the plan
Create an exit plan takes a name, an optional
applicability filter, and the definition. It returns the plan with its The definition is validated on write. A
revision, because the
next thing you do is edit it and you need the revision to do so.400 means it broke one of the plan invariants:- every leg carries a stop — a plan cannot save an unprotected rung
- targets widen down the ladder
- stops do not tighten down the ladder
- a trail only tightens
- at most one leg is a runner (a leg with no
targetDistance, held with a stop and nothing else)
2
List what you have, and what an account can run
requires — what it needs an account to support, derived from the plan
itself. Compare it against capabilities.exitPlanSupport on the selected account (from List
accounts or the snapshot) and offer only the plans that
will actually run. Both use the same tokens: stop_loss, take_profit, multiple_targets,
runner_leg, breakeven, trailing_stop.3
Edit and delete conditionally
Both writes carry the revision you read. There is no unconditional write.A replacement is the whole plan, not a patch — send the definition you want to end up with.A delete puts the revision in the query string:A stale revision is refused with
409 and an exit_plan_conflict body carrying
expectedRevision and actualRevision, so you can show the difference rather than only the
refusal. Revisions are opaque: echo back exactly what you read, and never construct one.4
Preview it against the account and the order
Preview an exit plan resolves every leg from that
account’s own instrument facts and returns the token that binds the placement. The request
names the order and nothing else — the engine supplies every price.Read three things off the response before you show it:
legs— each with both the tick distance and the absolute price, so a client renders one and the venue takes the other.managedQuantityandunmanagedQuantity— the ladder was authored for a quantity, and an order may carry more. The surplus is an unmanaged remainder the plan never protects. Show it.engineManaged— true when the engine itself will ratchet the stop, rather than the venue holding it still.
expiresAt, and it is bound to the clientOrderId you sent, so a
confirmation is spent on one submission rather than being good for any order until it lapses.
A market entry’s levels are indicative: its ladder is measured from the mark at placement.5
Place by reference
Send The engine reloads the plan at that revision and re-resolves it. It refuses an edited plan, a
deleted one, a changed account, drift, or an expiry.
exitPlan on Place an order — the plan, the
revision you previewed, and the token you were given. No levels.Why the token, and not the prices
The token is a signed binding over the order — the account, the client order id, the plan and its revision, the instrument, the side, the quantity and the entry. It is never a binding over the prices. Placement reloads the plan and re-resolves the levels, so the preview proves what was agreed rather than carrying a price a client could have chosen. That is also whyexitPlan and the plain stopLoss/takeProfit legs are mutually exclusive:
sending both answers 400. One order has one source of truth for its exits.
Warnings you have to surface
A200 from the order route can still carry warnings. Two codes belong to this surface:
After the fill
List server-managed stops shows the instances the engine is running. Each carriesplanId and planRevision — a receipt for the revision that
instance accepted. The definition it runs was frozen then, so editing the saved plan cannot reach
an already-open position.
Where to go deeper
- Protect a position — the plain stop-and-target path, without a plan.
- Place your first order — where
exitPlansits in the order body. - List position exits — what the plan actually placed.
- Errors —
409and the conflict shape in full.