> For the complete documentation index, see [llms.txt](https://docs.hydromancer.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.hydromancer.xyz/readme/websocket/changelog.md).

# WebSocket changelog

## 2026-08-20 — Opt-in merge for l4BookUpdates

* Coin-list `l4BookUpdates` stays one stream per subscribe by default. `{"type":"l4BookUpdates","coins":["ETH"]}` then `{"type":"l4BookUpdates","coins":["BTC"]}` is still two frames per block.
* Set `"merge": true` on a coin-list subscribe to union those coins into the connection's existing coin-list slots. The next block is one frame covering the merged set, so adding an instrument does not need an unsubscribe/resubscribe cycle. The subscribe confirmation echoes the merged coin list. `merge` is subscribe-only: it is rejected on an `unsubscribe`, on the all-markets firehose, and on other subscription types.
* `unsubscribe` with `coins` **subtracts** when the connection holds a single coin-list slot (one batched subscribe, or the result of `merge: true`). Several coin-list slots keep exact-match unsubscribe. Coins you do not hold are ignored. `unsubscribe` without `coins` still removes the all-markets firehose only. A coin-scoped unsubscribe against only the firehose is rejected.
* The tier coin cap now applies to the **effective** (post-merge) coin set rather than to each raw request, so repeated `merge: true` (and the existing `trades` / `allFills` unions) cannot walk past it. A single request is still capped at 200 names.
* When a subscribe carries a `cursor`, replay covers the coins named in **that request**. After a merge the ack still echoes the full merged list.
* After a coin-scoped `unsubscribe` is acknowledged, one already-in-flight block may still deliver a frame containing the dropped coins. Steady state resumes from the next block.
* Draining the coin-list while the all-markets firehose is still held does **not** set `unsubscribed: ["l4BookUpdates"]` — that field means the channel is gone, and the firehose is still on it.
* **Upcoming:** `merge` will become the **default** for coin-list `l4BookUpdates` in a future release. Set it explicitly now — `"merge": true` to adopt early, `"merge": false` to pin today's one-stream-per-subscribe behaviour through the change. The flag stays accepted afterwards; only clients that send neither will see a behaviour change.

## 2026-08-07 — Trigger TWAP fields and userTwapStatusUpdates

* New `userTwapStatusUpdates` subscription: TWAP status events filtered to the subscribed `addresses` (multi-address, merge-on-resubscribe, cursor replay supported) — the user-scoped counterpart of `allTwapStatusUpdates`.
* TWAP status updates (both channels) now carry the trigger-TWAP fields the node added on 2026-07-25: `triggerPx`, `triggerAbove`, and `stopPx`. The fields are omitted for plain TWAPs.
* New TWAP `status` values from the same node update: `waitingForTrigger` and `stopped`.

## 2026-08-04 — requestId bounds and outcome market activity

* Optional `requestId` is capped at 128 characters and must not contain control characters. Violations reject with `code: "invalid_request_id"` (oversized values are not echoed).
* Inbound WebSocket frames are capped (default 256 KiB, `WS_MAX_INBOUND_MESSAGE_BYTES`) so control-plane messages cannot use Axum’s 64 MiB default.
* Active-market metadata refresh now includes HIP-4 outcome markets via `outcomeMeta`, so outcome wire coins (`#{outcome_id * 10 + side_index}`) receive the same active/inactive advisories as perps and spot. If `outcomeMeta` fails, the server still commits the perp+spot snapshot (`partial_success`) and treats outcome activity as unavailable until the next full refresh.

## 2026-07-22 — Attributable subscription feedback

* Subscribe and unsubscribe requests may include an optional string `requestId`; confirmations and rejects echo it.
* `subscriptionUpdate` retains `subscribed` and `failed` and adds `operation`, `subscription`, and, for unsubscribe confirmations, `unsubscribed`.
* Subscription errors retain `type` and `message` and add request context. Orderbook-family invalid-coin and coin-count rejects also include stable `code` and `details` fields.
* `l2Book`, `l2BookDiff`, `l4BookUpdates`, and `bbo` confirmations may include advisory `warnings` for inactive coins or unavailable activity metadata. These warnings do not fail the subscription.
* Orderbook invalid-name errors now name every distinct invalid value. Requests containing more than 200 coin entries now report a coin-count error instead of an address-format error.

These changes are additive except for the corrected error text. Clients should continue reading the existing fields they need and ignore unknown fields and message types.
