Skip to main content
An exit plan is a saved ladder: how much comes off at each rung, where the stop sits, whether the stop moves to breakeven, whether it trails. It belongs to the person who authored it and to no account, so the same ladder applies to whichever account is selected. The point of the whole surface is that levels are never retyped. You preview the plan against a real account and a real order, and you place against the token that preview gave you.
1

Author the plan

Create an exit plan takes a name, an optional applicability filter, and the definition. It returns the plan with its revision, because the next thing you do is edit it and you need the revision to do so.
The definition is validated on write. A 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

Each plan carries 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.
  • managedQuantity and unmanagedQuantity — 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.
The token expires at 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 exitPlan on Place an order — the plan, the revision you previewed, and the token you were given. No levels.
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.

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 why exitPlan 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

A 200 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 carries planId 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