> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trdrs.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Create an exit plan

> Creates a plan and returns it, revision included, because the next thing a caller does is edit it and it needs the revision to do so. The definition is validated here: every leg carries a stop, targets widen, stops do not tighten down the ladder, a trail only tightens, and at most one leg is a runner.



## OpenAPI

````yaml /partner-platform/openapi.json post /api/exit-plans
openapi: 3.1.0
info:
  title: trdrs Engine API
  version: 1.1.0
  description: >-
    ## API Reference


    This is the served OpenAPI contract for the trdrs engine: market data,
    trading and account

    routes for your firm's traders, trdrs Connect account-registration handoff,
    and preview

    challenge routes.


    See Quick Start for the first integration path: key setup, market config,
    chart data, Connect

    account registrations, idempotency, stream reconnects, and conformance.


    See Overview and API Standards for the cross-cutting contract rules.
servers:
  - url: https://app.trdrs.co
    description: Production
  - url: /
    description: This engine
security: []
tags:
  - name: Market data
    description: >-
      Symbol search and resolution, OHLCV history, quote snapshots, the server
      clock, and the live bar stream. Crypto rides each venue’s public feed;
      futures stream from the caller’s own connected Rithmic account. With none
      connected, futures requests answer 503 `feed_requires_connection`.
  - name: News
    description: >-
      Aggregated market news and the economic calendar, from licensed/open
      sources, keyword-tagged with futures roots at ingest. Platform-wide
      content (nothing per-user), admitted exactly like Market data: a licensed
      origin, a session, or a firm API key. Headlines page by published time,
      scope by instrument root, and stream live over SSE; thumbnails serve
      through the image proxy.
  - name: Trading
    description: >-
      The money surface: entries, exits, replaces, cancels, and position/account
      flattening. Every order-placing call uses `clientOrderId` as its
      idempotency key.
  - name: Account
    description: >-
      Reading a connected account. You do not create trading accounts here: a
      trader connects their own broker account (or creates a free demo account)
      in the app, and firms create evaluation accounts through the Partner API
      (Firm accounts → Create evaluation accounts) or register venue accounts
      through Connect (Create an account registration). Account state and the
      durable ledgers: balances, positions, working orders, fills, P&L history,
      and the live account stream.
  - name: Connect
    description: >-
      trdrs Connect account registration, for partner firms. Register an account
      you issued on your own venue — a pending account registration — with the
      trader’s sign-in email, optionally the venue account id and the login name
      your venue issued. The trader finds it waiting in the connect flow the
      moment they sign in with that email: the connect step is pre-filled with
      everything except the credential, which the trader always enters
      themselves. A registration never transmits a password and never grants
      access to anything before the trader’s own login succeeds. These routes
      answer a partner-scoped key only; a firm API key or a user session gets
      401. Registrations expire after 30 days; re-registering the same email +
      account refreshes the expiry instead of duplicating. The end-to-end flow
      guide is **[Quick Start](/docs/guides/quick-start)**.
  - name: Firm accounts
    description: >-
      Evaluation accounts your firm issues on the trdrs venue, through your
      partner key — the other half of account setup. Connect registrations hand
      off accounts that exist on your venue; these routes create and manage
      accounts on ours: the trader trades them on trdrs, and your firm owns the
      lifecycle. Every route is scoped to accounts your firm created through
      this API — an account the same trader opened themselves is invisible and
      untouchable here, by construction. Creation is batched with per-item
      results, and every write carries your own `referenceId`, so a crashed
      pipeline retries safely. Served when the deployment runs the prop engine;
      without it, every route in this group answers `404`.
  - name: Webhooks
    description: >-
      The outbound event bus: register an https endpoint and the platform pushes
      events to it instead of your back office polling us. Every delivery is
      signed (`trdrs-signature: t=<unix>,v1=<hmac-sha256>` over
      `${t}.${rawBody}`) so you can prove it came from us and is fresh, and
      every delivery is durable — a failed attempt is retried with backoff for
      about nine hours and the whole log is readable, so an endpoint that was
      down is a delay rather than a lost event. Serves brokers and prop firms
      alike: the account-registration (`registration.*`) events fire wherever
      Connect does, and the account events fire where the prop engine runs.
  - name: Challenges
    description: >-
      The prop evaluation surface: challenge programs and a trader’s own
      enrollments. **Preview: the one group on this page outside the
      additive-only guarantee** (the pre-contract v1 scaffold; the Phase-1
      rebuild will change these shapes; see Stability). **Cookie-authenticated,
      not key-authenticated**, and served only when the engine runs with
      `CHALLENGES_ENABLED`; without that flag the bundle is absent and every
      route below returns `404`. The firm-console/admin half of this surface is
      deliberately not documented here. It is back office, not licensed surface.
paths:
  /api/exit-plans:
    post:
      tags:
        - Account
      summary: Create an exit plan
      description: >-
        Creates a plan and returns it, revision included, because the next thing
        a caller does is edit it and it needs the revision to do so. The
        definition is validated here: every leg carries a stop, targets widen,
        stops do not tighten down the ladder, a trail only tightens, and at most
        one leg is a runner.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ExitPlanWriteRequest'
      responses:
        '200':
          description: The plan as saved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExitPlanResponse'
        '400':
          description: The definition breaks a plan invariant
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Missing/unknown/revoked credential
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - tenantKey: []
      x-codeSamples:
        - lang: javascript
          label: TypeScript
          source: |-
            const res = await fetch('https://app.trdrs.co/api/exit-plans', {
              method: 'POST',
              headers: {
                'content-type': 'application/json',
                Authorization: `Bearer ${process.env.TRDRS_API_KEY}`,
              },
              body: JSON.stringify({
                "name": "Two rungs and a runner",
                "revision": "q2Jm4XxT0aVnR7cLp1sZfE9d",
                "applicability": {
                  "assetClasses": [
                    "futures"
                  ],
                  "instruments": [
                    "ES"
                  ]
                },
                "definition": {
                  "unit": "ticks",
                  "quantity": 2,
                  "tif": "gtc",
                  "entryType": "limit",
                  "legs": [
                    {
                      "seq": 1,
                      "quantity": 1,
                      "stopDistance": 12,
                      "targetDistance": 20,
                      "breakeven": null,
                      "trail": []
                    },
                    {
                      "seq": 2,
                      "quantity": 1,
                      "stopDistance": 12,
                      "targetDistance": null,
                      "breakeven": {
                        "triggerDistance": 8,
                        "plusDistance": 0
                      },
                      "trail": [
                        {
                          "stepSeq": 1,
                          "triggerDistance": 16,
                          "trailDistance": 8,
                          "frequencyTicks": 2
                        }
                      ]
                    }
                  ]
                }
              }),
            })
            const data = await res.json()
        - lang: shell
          label: cURL
          source: |-
            curl -X POST 'https://app.trdrs.co/api/exit-plans' \
              -H "Authorization: Bearer $TRDRS_API_KEY" \
              -H 'content-type: application/json' \
              -d '{"name":"Two rungs and a runner","revision":"q2Jm4XxT0aVnR7cLp1sZfE9d","applicability":{"assetClasses":["futures"],"instruments":["ES"]},"definition":{"unit":"ticks","quantity":2,"tif":"gtc","entryType":"limit","legs":[{"seq":1,"quantity":1,"stopDistance":12,"targetDistance":20,"breakeven":null,"trail":[]},{"seq":2,"quantity":1,"stopDistance":12,"targetDistance":null,"breakeven":{"triggerDistance":8,"plusDistance":0},"trail":[{"stepSeq":1,"triggerDistance":16,"trailDistance":8,"frequencyTicks":2}]}]}}'
components:
  schemas:
    ExitPlanWriteRequest:
      type: object
      description: >-
        Author or replace a plan. A replacement carries `revision`: the value
        the caller read. A revision that is not the stored one is refused with
        409 rather than overwriting an edit nobody saw.
      properties:
        name:
          type: string
        revision:
          type: string
          description: Required on a replacement; ignored on a create.
        applicability:
          type: object
          properties:
            assetClasses:
              type: array
              items:
                type: string
            instruments:
              type: array
              items:
                type: string
        definition:
          $ref: '#/components/schemas/ExitPlanDefinition'
      required:
        - name
        - definition
      example:
        name: Two rungs and a runner
        revision: q2Jm4XxT0aVnR7cLp1sZfE9d
        applicability:
          assetClasses:
            - futures
          instruments:
            - ES
        definition:
          unit: ticks
          quantity: 2
          tif: gtc
          entryType: limit
          legs:
            - seq: 1
              quantity: 1
              stopDistance: 12
              targetDistance: 20
              breakeven: null
              trail: []
            - seq: 2
              quantity: 1
              stopDistance: 12
              targetDistance: null
              breakeven:
                triggerDistance: 8
                plusDistance: 0
              trail:
                - stepSeq: 1
                  triggerDistance: 16
                  trailDistance: 8
                  frequencyTicks: 2
    ExitPlanResponse:
      type: object
      properties:
        plan:
          $ref: '#/components/schemas/SavedExitPlan'
      required:
        - plan
      example:
        plan:
          id: 0f6c2d18-7b4a-4a3e-9d21-8c5e4b0a9f37
          name: Two rungs and a runner
          revision: q2Jm4XxT0aVnR7cLp1sZfE9d
          applicability:
            assetClasses:
              - futures
            instruments:
              - ES
          definition:
            unit: ticks
            quantity: 2
            tif: gtc
            entryType: limit
            legs:
              - seq: 1
                quantity: 1
                stopDistance: 12
                targetDistance: 20
                breakeven: null
                trail: []
              - seq: 2
                quantity: 1
                stopDistance: 12
                targetDistance: null
                breakeven:
                  triggerDistance: 8
                  plusDistance: 0
                trail:
                  - stepSeq: 1
                    triggerDistance: 16
                    trailDistance: 8
                    frequencyTicks: 2
          requires:
            - stop_loss
            - take_profit
            - runner_leg
            - breakeven
            - trailing_stop
          updatedAt: 1787581400000
    ErrorResponse:
      type: object
      properties:
        error:
          type: string
      required:
        - error
      example:
        error: invalid_instrument
    ExitPlanDefinition:
      type: object
      description: >-
        WireExitPlanDefinition (@trdrs/contracts): the structured plan —
        everything the engine needs to resolve concrete legs, and nothing about
        an account, a venue or a price. `unit` says what the distances mean;
        `price` and `currency` are resolved to ticks by the engine against the
        account's own instrument facts. `quantity` is what the ladder was
        authored for: an order may carry more, and the surplus is an unmanaged
        remainder the plan never protects.
      properties:
        unit:
          type: string
          enum:
            - ticks
            - price
            - currency
        quantity:
          type: number
        tif:
          type: string
        entryType:
          type: string
          enum:
            - market
            - limit
            - stop
            - stop_limit
        legs:
          type: array
          items:
            $ref: '#/components/schemas/ExitPlanLeg'
      required:
        - unit
        - quantity
        - tif
        - entryType
        - legs
      example:
        unit: ticks
        quantity: 2
        tif: gtc
        entryType: limit
        legs:
          - seq: 1
            quantity: 1
            stopDistance: 12
            targetDistance: 20
            breakeven: null
            trail: []
          - seq: 2
            quantity: 1
            stopDistance: 12
            targetDistance: null
            breakeven:
              triggerDistance: 8
              plusDistance: 0
            trail:
              - stepSeq: 1
                triggerDistance: 16
                trailDistance: 8
                frequencyTicks: 2
    SavedExitPlan:
      type: object
      description: >-
        WireSavedExitPlan (@trdrs/contracts): one saved plan. `revision` is
        opaque — echo back exactly the value you read on a save or a delete, and
        never construct one. `requires` is what the plan needs an account to
        support, derived from the plan itself, so a host can tell which plans a
        selected account can run.
      properties:
        id:
          type: string
        name:
          type: string
        revision:
          type: string
        applicability:
          type: object
          properties:
            assetClasses:
              type: array
              items:
                type: string
            instruments:
              type: array
              items:
                type: string
          required:
            - assetClasses
            - instruments
        definition:
          $ref: '#/components/schemas/ExitPlanDefinition'
        requires:
          type: array
          items:
            type: string
            enum:
              - stop_loss
              - take_profit
              - multiple_targets
              - runner_leg
              - breakeven
              - trailing_stop
        updatedAt:
          type: integer
          description: Epoch milliseconds
      required:
        - id
        - name
        - revision
        - applicability
        - definition
        - requires
        - updatedAt
      example:
        id: 0f6c2d18-7b4a-4a3e-9d21-8c5e4b0a9f37
        name: Two rungs and a runner
        revision: q2Jm4XxT0aVnR7cLp1sZfE9d
        applicability:
          assetClasses:
            - futures
          instruments:
            - ES
        definition:
          unit: ticks
          quantity: 2
          tif: gtc
          entryType: limit
          legs:
            - seq: 1
              quantity: 1
              stopDistance: 12
              targetDistance: 20
              breakeven: null
              trail: []
            - seq: 2
              quantity: 1
              stopDistance: 12
              targetDistance: null
              breakeven:
                triggerDistance: 8
                plusDistance: 0
              trail:
                - stepSeq: 1
                  triggerDistance: 16
                  trailDistance: 8
                  frequencyTicks: 2
        requires:
          - stop_loss
          - take_profit
          - runner_leg
          - breakeven
          - trailing_stop
        updatedAt: 1787581400000
    ExitPlanLeg:
      type: object
      description: >-
        WireExitPlanLeg (@trdrs/contracts): one rung of the ladder. Every leg
        carries a stop, because a plan cannot save an unprotected rung. A leg
        with no `targetDistance` is a runner: held with a stop and nothing else,
        and a plan holds at most one.
      properties:
        seq:
          type: integer
        quantity:
          type: number
        stopDistance:
          type: number
        targetDistance:
          type:
            - number
            - 'null'
        breakeven:
          oneOf:
            - $ref: '#/components/schemas/ExitPlanBreakeven'
            - type: 'null'
        trail:
          type: array
          items:
            $ref: '#/components/schemas/ExitPlanTrailStep'
      required:
        - seq
        - quantity
        - stopDistance
        - trail
      example:
        seq: 2
        quantity: 1
        stopDistance: 12
        targetDistance: null
        breakeven:
          triggerDistance: 8
          plusDistance: 0
        trail:
          - stepSeq: 1
            triggerDistance: 16
            trailDistance: 8
            frequencyTicks: 2
    ExitPlanBreakeven:
      type: object
      description: >-
        WireExitPlanBreakeven (@trdrs/contracts): a one-shot move of the stop to
        the entry plus `plusDistance`, once the position is `triggerDistance` in
        profit. Zero is exact breakeven.
      properties:
        triggerDistance:
          type: number
        plusDistance:
          type: number
      required:
        - triggerDistance
        - plusDistance
      example:
        triggerDistance: 8
        plusDistance: 0
    ExitPlanTrailStep:
      type: object
      description: >-
        WireExitPlanTrailStep (@trdrs/contracts): one tier of a trailing stop.
        Once the position is `triggerDistance` in profit the stop follows the
        best price by `trailDistance`, re-issued only after it has advanced a
        whole `frequencyTicks`. The frequency throttles venue calls, so it is
        always whole ticks whatever unit the distances are in. Tiers ascend by
        trigger and can only tighten.
      properties:
        stepSeq:
          type: integer
        triggerDistance:
          type: number
        trailDistance:
          type: number
        frequencyTicks:
          type: integer
      required:
        - stepSeq
        - triggerDistance
        - trailDistance
        - frequencyTicks
      example:
        stepSeq: 1
        triggerDistance: 16
        trailDistance: 8
        frequencyTicks: 2
  securitySchemes:
    tenantKey:
      type: http
      scheme: bearer
      description: >-
        Your firm’s API key (the API calls this the `tenant` key; `trdrs_sk_…`),
        server-to-server only.

````