> ## 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.

# Run a venue end to end

> From an empty venue to a customer account with books, a route, a collar and a stage — using only published material.

This is the whole venue surface in one sequence. It starts with nothing and ends with a customer
account that has a balance, a route, an admission collar and a stage it can advance out of.

Everything here is a `/api/partner/` route and a venue key. It is a private preview: the routes
answer `404` unless the deployment enables `VENUE_CONFIGURATION_ENABLED` and has a configured vault.
Nothing in this guide creates a trading-ready account on its own — readiness needs margin, a fresh
price and a proven stream, and each of those is refused rather than assumed.

Set these once:

```bash theme={null}
export TRDRS_API_BASE_URL=https://sandbox.trdrs.co
export TRDRS_VENUE_KEY=trdrs_vk_sandbox_...
export VENUE=00000000-0000-0000-0000-000000000000
```

Every write takes an `Idempotency-Key`. Retrying with the same key and the same body recovers the
same result; the same key with a *different* body is a `409`, because two intents under one name is
the thing the key exists to prevent.

<Steps>
  <Step title="Describe what you trade">
    An instrument candidate is immutable and describes executable facts: the quantity grid, the tick
    bands, the contract multiplier, the session calendar, the expiry and which connection maps to
    which provider symbol.

    ```bash theme={null}
    curl -X POST "$TRDRS_API_BASE_URL/api/partner/venues/$VENUE/instruments" \
      -H "Authorization: Bearer $TRDRS_VENUE_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: es-mar26-v1" \
      -d @instrument.json
    ```

    Publishing a candidate changes nothing. It is not a catalog and it is not tradable; it is a
    version you may later point at.
  </Step>

  <Step title="Decide where orders go, and what protects them">
    A route is internal — your own book — or external, naming both a connection and the dedicated
    account at it. A half-configured route is refused at save rather than at the first order it
    swallows.

    ```bash theme={null}
    curl -X POST "$TRDRS_API_BASE_URL/api/partner/venues/$VENUE/routes" \
      -H "Authorization: Bearer $TRDRS_VENUE_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: book-v1" \
      -d '{
        "routeId":"book","name":"Internal book","mode":"internal",
        "collar":{"kind":"ticks","maxAdverseTicks":4},
        "feeReservePerUnit":"2.50","uncappedMarketAllowed":false,
        "expectedRevision":null
      }'
    ```

    The collar is how far past a fresh executable quote a fill may still be accepted. A buy is
    collared off the ask and a sell off the bid — never off a mid, which is a price nobody was
    offering. Your own markup is measured inside the same collar: a markup that reaches past it
    refuses the fill rather than charging more than your stated protection allows.

    An omitted collar is **zero adverse ticks**, which is the strictest reading and not "no collar".
    Widening one waits for quiescence, because it changes the worst case of a trade already in flight.
  </Step>

  <Step title="Activate the version you dispatch against">
    Activation needs something that can route the instrument: a live provider mapping, or the
    offered internal route from the previous step. A venue that runs only its own book has no
    provider symbol to map, and requiring one would lock it out of activating anything at all.
    External dispatch stays gated either way — an unmapped version can never leave through an
    external route.

    Activation is a compare-and-swap on a revision you must name. `null` means you saw no activation.

    ```bash theme={null}
    curl -X POST "$TRDRS_API_BASE_URL/api/partner/venues/$VENUE/instruments/active" \
      -H "Authorization: Bearer $TRDRS_VENUE_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: activate-es-1" \
      -d '{"instrumentId":"ES-MAR26","instrumentVersionId":"...","expectedRevision":null}'
    ```

    A rename or an entry halt applies at once. Any other change is economic and requires every
    account bound to the venue to be provably flat in that instrument. A refusal is `409
            not_quiescent` and it names the blocking accounts — without them you would have a conflict and
    no way to find what to settle.
  </Step>

  <Step title="Say what an account is charged">
    A condition profile states margin, commission, markup, financing and safety limits. Every policy
    is explicitly tagged: zero commission and `financing: none` are real choices, and an omitted
    field is inheritance rather than a default.

    ```bash theme={null}
    curl -X POST "$TRDRS_API_BASE_URL/api/partner/venues/$VENUE/conditions/profiles" \
      -H "Authorization: Bearer $TRDRS_VENUE_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: standard-v1" \
      -d '{"name":"Standard","profile":{ ... }}'
    ```

    Then apply it with `POST /api/partner/venues/{venueId}/conditions/active`, again by compare-and-swap. Tightening safety, or
    renaming, applies immediately; changing margin, commission, markup or financing waits for the
    affected accounts to be flat.
  </Step>

  <Step title="Check before you are refused">
    `POST /api/partner/venues/{venueId}/conditions/preview` answers whether a proposal changes economics at all, how many accounts
    it reaches, and which of them are not ready — before you attempt it. It writes nothing and holds
    no lock, so an account can open a position between the preview and the activation. That is why
    the activation rechecks rather than trusting it.
  </Step>

  <Step title="Group accounts and point them at the route">
    A group is one flat configuration reference — not a tree, not a copier group, not a pooled
    balance. `POST /api/partner/venues/{venueId}/conditions/groups` creates it,
    `POST /api/partner/venues/{venueId}/groups/{groupId}/route` points it at a route, and
    `POST /api/partner/venues/{venueId}/conditions/accounts/{accountId}/group` moves an account in.
    `POST /api/partner/venues/{venueId}/conditions/accounts/{accountId}/risk` tightens one account's
    own safety limits, and `GET /api/partner/venues/{venueId}/conditions/accounts/{accountId}/effective`
    reads the resolved answer with the layer that decided each value.

    There is no default route. An account whose group names none cannot open new exposure, though it
    can always close what it holds.
  </Step>

  <Step title="Read one account's books">
    ```bash theme={null}
    curl "$TRDRS_API_BASE_URL/api/partner/venues/$VENUE/accounts/$ACCOUNT/ledger" \
      -H "Authorization: Bearer $TRDRS_VENUE_KEY"
    ```

    Balance, collateral held against working orders, open positions with their exact average cost,
    and the route the account dispatches through. Only for accounts whose balance authority is
    TRDRS: an account its provider owns has one set of books and they are not these.

    `GET /api/partner/venues/{venueId}/accounts/{accountId}/instruments` reads the venue's activated
    catalog resolved against this one account — its conditions, its route and its open liquidation.
    A blocked instrument comes back with its reasons rather than being left out, so a trader who
    cannot find what was there yesterday can be told whether it was a halt, an allowlist or a
    retired route. Every reason there is an ENTRY gate: a halted or de-listed account can still
    close what it holds. It answers configuration only and cannot see a price, a balance or a
    stream, which is why an empty `blockedBy` is not a promise that an order will be accepted.

    `GET /api/partner/venues/{venueId}/accounts/{accountId}/incident` reads the open liquidation and every reduction step recorded
    against it. An open incident is itself the entry halt, and closing one does not lift it —
    whether the account may trade again is your decision, not an arithmetic side effect.
  </Step>

  <Step title="If you run an evaluation, state the rule">
    A stage policy is published as a version and activated, exactly like a condition profile.

    ```bash theme={null}
    curl -X POST "$TRDRS_API_BASE_URL/api/partner/venues/$VENUE/stages/policies" \
      -H "Authorization: Bearer $TRDRS_VENUE_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: evaluation-1-v1" \
      -d '{"name":"Evaluation stage one","policy":{
        "stageId":"evaluation-1","profitTarget":"2000","minimumTradingDays":5,
        "session":{"timeZone":"America/Chicago","rolloverHour":17},
        "disqualifying":["stop_out"],"nextGroupId":"funded"
      }}'
    ```

    `GET /api/partner/venues/{venueId}/stages/policies` lists what you have published, and
    `POST /api/partner/venues/{venueId}/stages/active` puts one version in force by
    compare-and-swap. Moving the target waits for every account running that stage to be flat;
    changing only where a passing account lands applies at once, because it decides the next
    account rather than this one.

    It is stored rather than sent with the advancement request for one reason: a target that arrives
    with the question can be made easier by whoever asks it.

    `disqualifying` names the recorded breaches that void a cycle. Naming a rule nothing records is
    refused rather than satisfied — an empty breach list means *nothing went wrong* or *nothing was
    watching*, and the second is the most expensive kind of pass there is.
  </Step>

  <Step title="Advance, or find out why not">
    ```bash theme={null}
    curl "$TRDRS_API_BASE_URL/api/partner/venues/$VENUE/accounts/$ACCOUNT/stages/evaluation-1/eligibility" \
      -H "Authorization: Bearer $TRDRS_VENUE_KEY"
    ```

    The decision is measured from the account's own books, never supplied by you. Net trading P\&L
    excludes allocations and balance operations and is taken after all fill fees; trading days are
    counted from when each fill actually traded rather than when it was booked. `reasons` lists every
    failing condition at once, so you are not told one per attempt.

    `POST /api/partner/venues/{venueId}/accounts/{accountId}/stages/{stageId}/advance` issues the successor. One per source cycle and stage: a second attempt with a
    different idempotency key returns the account the first one made, because an account once issued
    cannot be un-issued. `startingAllocation` is required and `null` is a real value meaning a
    zero-balance successor.
  </Step>
</Steps>

## What this guide deliberately does not do

* It does not make anything trading-ready. Admission still needs margin, entitlement, a fresh price
  and a stream-ready account, and each is checked at the order rather than assumed here.
* It does not connect a provider. That is [Connect a provider](/partner-platform/operator-concepts/connect),
  and a connection is not usable for execution until a validation passes against the manifest it
  declared.
* It does not describe a market. The [reference provider](/partner-platform/conformance/provider-self-check)
  has no book, no slippage and no latency; passing every rule says your service follows the contract,
  not that your venue fills the way you expect.
