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

# Changelog

> What changed on the partner surface, newest first.

What changed on the partner surface, newest first. The documented surface is additive-only from the
current compatibility baseline, with the PREVIEW `Challenges` group as the one named exception. An
entry marked breaking is one that moved that baseline, which can only happen before the first
partner integration; [Stability](/api-standards/stability) says where the baseline stands today.

## 2026-09-08

* **An account says which symbols it can trade.** `GET /api/account/instruments` returns the
  symbols the resolved account can trade through this engine, one row per tradable symbol with the
  search catalog's own display identity (`symbol`, `name`, `exchange`, `type`), plus a `label` for
  the account: the firm or system name where the engine stores one (`Apex`), else the account
  number. The set is the venue's own — a futures account lists the contract catalog, a crypto venue
  account lists that venue's perpetuals, and the demo lists both. Additive, and it takes the same
  `broker`/`account` selectors and answers the same errors as the other account reads.

**Breaking. The word "claim" left the wire, and this entry moves the compatibility baseline.**
It lands before the first partner integration, which is why it lands at all; see
[Stability](/api-standards/stability).

* **Connect speaks registration.** On `/api/partner/connect/accounts`: the response fields `claim`
  and `claims` are now `registration` and `registrations`, `claimedAt` is `linkedAt`, and the
  status `claimed` is `linked` (the full set is `pending`, `linked`, `revoked`, `expired`). The
  schema names follow (`PartnerRegistration*`). Routes are unchanged.
* **Webhook event types follow.** `claim.claimed` is now `registration.linked` and `claim.revoked`
  is `registration.revoked`; their payloads carry `registrationId` instead of `claimId`. The other
  event types are unchanged, and an endpoint registered with an empty filter receives the new
  names automatically.

## 2026-09-07

**Breaking. The exit-plan placement shape changed, and this entry moves the compatibility baseline.**
There is no shim and no dual delivery. It lands before the first partner integration, which is why it
lands at all; see [Stability](/api-standards/stability).

* **Protection is engine state, and it rides the account revision.** `GET /api/account/snapshot`
  and `GET /api/account/stream` now carry `brackets` and `managedExits`: every bracket the engine
  holds with its legs and their states, and every breakeven or trailing stop it is running, with
  the phase reached and the reason it is paused where it is. Both lanes carry the same `revision`
  as the rest of the account, so a protective change and the order change that caused it are
  points on one line. `GET /api/account/brackets` and `GET /api/account/managed-exits` serve the
  same two lanes for a surface that wants only one of them; a client holding a snapshot already
  has them. A leg in `pre_armed` is recorded and priced but deliberately not resting yet, because
  the position it protects does not exist; arming it also RE-PARENTS it, so a leg protecting a
  position carries a null `parentOrderId`.
* **Saved exit plans are a principal-scoped catalog with conditional writes.** `GET /api/exit-plans`
  lists the plans a trader holds and `POST /api/exit-plans` authors one. `PUT /api/exit-plans/{id}`
  and `DELETE /api/exit-plans/{id}` are CONDITIONAL: send back the opaque `revision` you read, and a
  stale one is refused with `409` and the revision the plan carries now, rather than overwriting an
  edit that arrived in between. A revision is a digest, not a counter — never construct one. Each
  plan reports the capabilities it `requires`, so a host can tell which plans a selected account can
  run before offering them.
* **A plan is placed by reference, and the engine resolves its legs.** `POST /api/account/exit-plans/preview`
  prices the ladder from the account’s own instrument facts, says what it protects and what the
  order carries that it does not, and returns a token binding the ORDER — the account, the plan and
  its revision, the instrument, the side, the quantity and the entry. `POST /api/trading/order` then
  takes `exitPlan: { planId, planRevision, previewToken }` and no levels at all: the engine reloads
  the plan at that revision, re-resolves, and refuses an edited plan, a changed account, drift or an
  expiry. The resolved-leg request shape it replaces is gone, along with the browser arithmetic it
  carried.
* **The futures catalog states its fractional roots in executable form.** A row of
  `GET /api/instruments` for a product the exchange quotes in thirty-seconds now carries
  `priceFraction`: `denominator`, the number of parts one point divides into (32, 64 or 128), and
  `subFraction` (2 or 4) where the writing divides one of those again. It comes from the same
  reading of the tick and the quotation convention that writes the fractional price format on
  `GET /api/market/symbol-info`, so a ticket sizes and snaps against the served fact rather than
  deriving a denominator of its own. A product quoted in decimals carries no `priceFraction` at all.
* **The order warnings are named for the plan.** `exit_plan_remainder_unplaced` replaces
  `atm_remainder_unplaced` and `exit_plan_not_recorded` replaces `atm_management_not_registered`.
  Both still mean what they meant: the protected bracket is live either way, and the message says
  what did not happen.
* **A preview names the order it will be spent on.** `POST /api/account/exit-plans/preview` takes the
  `clientOrderId` the placement will ride under, and the token binds it. A preview is therefore good
  for one submission rather than for any order until it expires. Generate the client order id before
  you preview and send the same one when you place.
* **The two protective one-shots carry the revision they were read at.** `GET /api/account/brackets`
  and `GET /api/account/managed-exits` answer `{ revision, items }`. The number is the account's
  current one, read rather than allocated: these reads do not advance the sequence your stream folds.
* **Exit plans are reachable with a tenant key.** The catalog and the preview take a tenant key as
  well as a signed-in session, because a saved plan belongs to a principal and a key is one. A key
  reaches only its own plans.
* **A capability descriptor says which parts of a plan the account can run.** Every account frame's
  `capabilities` carries `exitPlanSupport`: the subset of `stop_loss`, `take_profit`,
  `multiple_targets`, `runner_leg`, `breakeven` and `trailing_stop` this account can execute. Compare
  it against a plan's `requires` to offer only the plans that will work.

## 2026-09-06

**Breaking. The account stream changed shape, and this entry moves the compatibility baseline.**
There is no shim and no dual delivery. It lands before the first partner integration, which is why
it lands at all; see [Stability](/api-standards/stability).

* **One event carries the whole account.** `GET /api/account/stream` sends one `account` event, on
  connect and on every change alike, and it carries the summary, the positions and the working
  orders as they were at one moment, with the `revision` that names that moment. The `snapshot`,
  `positions` and `orders` events are gone. A client that switched on those event names, or that
  merged them into a picture of its own, must be changed: subscribe to `account` and replace your
  whole picture with each frame.
* **Fold by the revision and nothing else.** Hold the newest frame you have received for an
  `accountId`. Drop a frame at or behind that revision. Replace everything with any frame ahead of
  it. A frame whose revision skips ahead is still complete, so there is no gap to detect and no
  resync to perform; a client written to resync on a jump should stop doing so. Never compute a
  revision of your own.
* **`GET /api/account/snapshot` serves the same body.** Read it when you have no stream open, or
  when you come back after a disconnect. Combining the one-shot summary, positions and orders reads
  is no longer the way to build a picture: three reads are three moments, and nothing in them says
  whether they agree.
* **`accountId` is how an account is named.** It is an opaque token on every frame. Key panels,
  subscriptions and state by it; it is not a structure and must not be taken apart. An account
  number is unique at its own firm and nowhere else.
* **`capabilities` says what the account supports.** The frame carries what the broker adapter
  behind it implements, so you render only controls the venue can accept. A time-in-force absent
  from `tifs` is refused, never mapped to a different lifetime.
* **`clock` says what the revision counts.** `engine` means trdrs owns the account's state and the
  number is the account's own history. `observation` means the account lives at a venue and the
  number stamps our reading of it, so the order of readings is exact and the interval is not.
* **`positionModel` says the book is net.** One instrument in one account holds at most one signed
  position, so a frame carries at most one row per instrument.

## 2026-08-29

* **Connect makes the firm the only customer messenger.** trdrs no longer sends account-ready
  emails on a firm's behalf. `POST /api/partner/connect/accounts` no longer accepts `handover`, its
  response no longer includes `emailSent`, and claim reads no longer include `handover`. Requests
  that still send the retired field receive `400`; there is no compatibility shim. Firms notify
  traders and deliver venue credentials through their own secure onboarding process. This contract
  correction landed before the first partner integration and is the Connect compatibility baseline.
* **The futures contract catalog joins the licensed surface.** `GET /api/instruments` serves one
  row per futures product root — exchange, tick size and value, dollar multiplier, roll cycle, and
  the listed months of products whose roll is not modelled — the same static facts the trdrs order
  ticket sizes, snaps and prices with. Admission is the market-data model: your tenant key or your
  allowlisted origin.
* **Risk controls join the Account group.** `GET /api/risk` reads an account's five risk controls
  (daily and weekly loss limits, daily and weekly profit targets, the end-of-day close) together
  with its lock state; `PUT /api/risk` replaces the controls in one write, live from the moment it
  lands; `POST /api/risk/unlock` is the manual unlock. These are the controls behind every
  `423 risk_locked` a trading route answers, and the `lock` object is the same one that streams as
  the `lock` event on `/api/account/stream`, so a front end holds one lock truth. Admission is the
  trading model exactly: your tenant key, acting as the accounts' owner. `broker` is required on
  all three; `account` targets one account under a multi-account login.
* **News and economic calendar join the licensed surface.** A new News group in API Reference:
  `GET /api/news` (aggregated market headlines, newest first, keyset-paged, scoped by futures root
  with `instrument`), `GET /api/news/stream` (SSE: `news_item` frames), `GET /api/news/image/{id}`
  (the keyless thumbnail proxy), `GET /api/calendar` (scheduled events in a bounded window, with
  impact tiers and display-string forecast/previous/actual), and `GET /api/calendar/stream` (SSE:
  `calendar_update` nudges). News and the calendar each carry their own live stream. Admission is
  the market-data model exactly: your tenant key or your allowlisted origin.

## 2026-08-28

* **Market data: one connection, many charts.** `GET /api/market/streams` multiplexes up to 24
  bar subscriptions over a single SSE connection: `subs` is a comma-separated list of
  `INSTRUMENT~tf` tokens, every event payload carries `instrument` and `tf` for demultiplexing,
  and a refused subscription becomes a tagged error event while the rest live on. Built for
  multi-chart layouts, where browsers cap concurrent connections per origin.
* **Market data: spread expressions are instruments.** `/api/market/history` and the bar streams
  accept arithmetic over instruments — `ES-NQ`, `1/ESU6`, `(ES+NQ)/2`; operators `+ - * / ^`,
  parentheses, numeric literals, up to four legs. The engine evaluates server-side over the
  bucket intersection of the legs; spread bars carry volume 0, and a string that matches a
  catalog symbol exactly is always that symbol, never arithmetic.

## 2026-08-24

* **Webhooks: pushed events with signed delivery.** A new Webhooks group. Register up to five
  `https://` endpoints per firm with `POST /api/partner/webhooks` (optionally filtered to specific
  event types), list them with `GET`, and remove one with `DELETE`. Six event types in v1:
  `claim.claimed`, `claim.revoked`, `account.reset`, `balance.recorded`, `risk.locked`, and
  `risk.unlocked`. Every delivery is signed (`trdrs-signature`: HMAC-SHA256 over
  `timestamp.body`, so a replayed payload cannot wear a fresh clock) and retried on failure for
  \~9 hours across 6 attempts. `POST /api/partner/webhooks/test` delivers a signed ping right now
  and reports the outcome; `GET /api/partner/webhooks/deliveries` is the per-endpoint delivery
  log — every attempt's status, response code, and error, kept for 60 days — so "did you get it"
  is answerable from your side.
* **Firm accounts: risk controls, trading halt, and balance operations.** The control half of the
  Firm accounts group. `GET`/`PUT /api/partner/accounts/risk` reads and sets the five per-account
  risk controls (daily/weekly loss, daily/weekly profit, end-of-day auto-close) — the same controls
  the trader sees, enforced live by the risk monitor from the moment of the write.
  `POST /api/partner/accounts/halt` blocks all new orders until your firm's own
  `POST /api/partner/accounts/resume`; the halt survives restarts, the trader cannot self-unlock it,
  and it never replaces a lock that is not yours. `POST /api/partner/balance-op` credits, debits, or
  adjusts an account outside of trading — ledger-first on your `referenceId`, so a retried payout
  can never fire twice.
* **Firm accounts: provision and reset evaluation accounts by API.** A new route group for partner
  firms running traders on the trdrs venue. `POST /api/partner/accounts` batch-creates evaluation
  accounts for your traders by email (per-item results, idempotent on your own `referenceId`);
  `GET /api/partner/accounts` lists the accounts your firm provisioned, with live balances; and
  `POST /api/partner/accounts/reset` puts one back to its starting state, ledger-first so a retried
  reset can never fire twice. Every route is scoped to accounts your firm created through the API —
  an account the trader opened themselves is invisible here by construction.
* **`GET /api/partner/usage/accounts` is live.** The drill-down behind the usage number: each
  account that counted in the month, with the real fills that made it count and their first/last
  timestamps. Computed from the same query as the count, so the list always sums to the billed
  number — invoice reconciliation without asking us for a breakdown, account by account.
* **`GET /api/partner/usage` is live.** A firm can now pull its own metered usage for a month
  under its partner key: the distinct accounts that actually traded, the agreed per-account price,
  and the total. It is the same computation the trdrs invoice is built from, so a bill can be
  reconciled straight from the API. Scoped to the calling firm by its key, with no parameter that
  widens it, and read-only.
* **Keys, permissions, and data policy are documented.** API Standards gained a Data policy page
  (what the engine stores, who sees what, and the per-trader market data rule), and the Keys page
  now covers all three permission levels, issuance, and revocation.
* **Programmatic accounts.** Operator Concepts gained a guide to running Connect claim
  registration, listing, and revocation as an automated pipeline. Its initial `handover` modes
  were retired before the first partner integration on 2026-08-29.
* **The Quick Start examples now match the wire exactly.** History takes `instrument`, `tf`, and
  `countBack`; orders take `instrument` and `orderType` with `broker`/`account` as query
  parameters. The previous examples used field names the engine never accepted.
* **Worked examples on every operation.** All 38 operations now render one coherent trading
  session instead of placeholder payloads: real ES prices, a fill that reappears in the
  executions ledger, an evaluation whose drawdown floors follow from its program's terms.
* **TypeScript and curl samples on every operation.** Streaming routes show a real SSE reader,
  cookie-authenticated routes show first-party fetch, and every sample targets the production
  host with realistic parameter values.
* **The spec's first server is production** (`https://app.trdrs.co`), so generated snippets never
  point at a relative host.

## 2026-08-23

* **The docs moved to this site.** Overview, Quick Start, API Standards, Conformance, Operator
  Concepts, HTTP clients, and the API Reference now live in one place with one sidebar; old
  guide URLs redirect.
* **`GET /api/market/config` declares what the engine accepts:** the timeframe grammar with
  per-unit ceilings, the bars/symbols/quotes limits, and the asset classes this deployment
  serves. A client can validate an ask without a round trip.
* **The Connect partner routes document the key that actually works there.** Partner routes are
  secured under the partner-scoped key in the spec itself; a tenant key is refused on
  `/api/partner/` by design.

## 2026-08-22

* **The prop evaluation surface returned as a PREVIEW group.** Challenges and enrollments are
  documented again, marked outside the additive-only guarantee, with the `CHALLENGES_ENABLED`
  gate stated on every operation.
* **The reference covers the whole licensed surface**, grouped by tag (Market data, Trading,
  Account, Connect, Challenges), with an onboarding guide.

## 2026-08-14

* **The holiday calendar is served.** `GET /api/market/symbol-info` carries the session model's
  holiday table (`sessionCalendar`), so clients never ship their own calendar updates.
* **Trailing stops became exclusively engine-managed.** The broker-native `trailing_stop` entry
  type is refused with a pointer at the ATM path, which manages trails identically on every venue.

## 2026-08-05

* **Market data became licensed surface.** The market routes answer first-party origins and
  authenticated principals only, and are documented under the tenant key.
