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

# OpenPX Changelog

> New features, breaking changes, and fixes — newest first.

The full, machine-generated changelog is on
[GitHub](https://github.com/openpx-trade/openpx/blob/main/CHANGELOG.md).
This page summarizes user-facing releases.

## Unreleased

### Breaking

* **`market_id` parameter renamed to `market_ticker` across the REST surface.** Every trait method, request struct (`OrderbookRequest`, `PriceHistoryRequest`, `TradesRequest`, `OrderbookHistoryRequest`, `MidpointRequest`, `UserTradesRequest`, `NewOrder`, `FetchOrdersParams`), and unified output model (`Order`, `Position`, `Fill`, `MarketTrade`, `Orderbook`, `OrderbookSnapshot`, `UserTrade`) now uses `market_ticker` to make explicit that the value is a unified ticker (Kalshi market ticker / Polymarket slug) — never a numeric id. WebSocket layer keeps `market_id` (`WsUpdate::{Snapshot,Delta,Clear}`, `SessionEvent::BookInvalidated`, `ActivityTrade`, `ActivityFill`) since the streamed value is the parent condition\_id on Polymarket, not a ticker. `FetchMarketsParams.tickers` renamed to `market_tickers` for the same reason. `Polymarket.neg_risk_market_id` is unchanged (Polymarket-specific internal id).

* **`fetch_event`, `fetch_events`, `fetch_series`, `fetch_series_one` removed; replaced by `fetch_market_lineage(ticker) -> MarketLineage { market, event, series }`.** One call returns the market plus its parent event and series; `event` and `series` are `Option`, so a dangling parent reference yields `None` rather than failing the whole call. Kalshi pays 1–3 sequential round-trips (market → event → series); Polymarket pays 2 (the event payload embeds the parent series).

* **`Event` and `Series` identifier rename — `id`/`slug` collapsed into `ticker`; Polymarket numeric REST ids move to `numeric_id`.** Matches the discipline already in place on `Market`. Also: `Event.series_id` → `Event.series_ticker`; `Event.market_ids` → `Event.market_tickers`. Numeric event/series ids on Polymarket now live on `numeric_id` (None on Kalshi).

* **`EventsRequest` and `SeriesRequest` removed** along with the four trait methods; `ExchangeInfo` flags `has_fetch_event`, `has_fetch_events`, `has_fetch_series`, `has_fetch_series_one` collapsed into `has_fetch_market_lineage`.

* **`fetch_market` removed; `fetch_markets` now handles single- and multi-ticker lookups.** Pass `tickers: ["…"]` (a `Vec<String>` of Kalshi tickers or Polymarket slugs) for an explicit lookup — single round-trip, no pagination. Kalshi calls `/markets?tickers=…`; Polymarket calls `/markets?slug=…&slug=…`.

* **`FetchMarketsParams.series_id` renamed to `series_ticker`.** Slug-semantic on both venues. Kalshi continues to filter by series ticker upstream; Polymarket ignores this field for now and will gain support via a future `series_numeric_id` field that maps to Polymarket's numeric series id.

* **`FetchMarketsParams.event_ticker` is slug-only on Polymarket.** Numeric event ids are no longer accepted and will be supported via a future `event_numeric_id` field. Kalshi event tickers are unchanged.

* **Polymarket CLOB V2 + pUSD migration (cutover 2026-04-28 \~11:00 UTC)** —
  no V1 backward compatibility. The OpenPX Polymarket adapter now depends
  on `polymarket_client_sdk_v2 = "=0.5.1"` and signs orders against the
  V2 EIP-712 domain (`version: "2"`). The order struct drops `nonce`,
  `feeRateBps`, and `taker`; adds `timestamp` (ms), `metadata` (bytes32),
  and `builder` (bytes32). Trading collateral is now **pUSD** (not USDC.e);
  approvals + balance reads target `0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB`.
  V1 builder-promotion (HMAC headers on order signing) is removed; builder
  attribution moves into the signed order's `builder` field via
  `SdkConfig::builder().builder_code(...)`. Relayer `POLY_BUILDER_*` HMAC
  headers are preserved for gasless tx auth (per the Polymarket migration
  guide). ([#54](https://github.com/openpx-trade/openpx/pull/54))

### Added

* **core**: 14 new unified `Exchange` trait methods scaffolded (default `Err(NotSupported)`); per-venue impls land in follow-up PRs. New surface: `fetch_events`, `fetch_event`, `fetch_series`, `fetch_series_one`, `fetch_market_tags`, `fetch_orderbooks_batch`, `fetch_midpoint`, `fetch_midpoints_batch`, `fetch_spread`, `fetch_last_trade_price`, `fetch_open_interest`, `fetch_user_trades`, `cancel_all_orders`, `create_orders_batch`. New models: `Event`, `Series`, `SettlementSource`, `Tag`, `Spread`, `LastTrade`, `UserTrade`. New request types: `EventsRequest`, `SeriesRequest`, `MidpointRequest`, `UserTradesRequest`, `NewOrder`. ([#56](https://github.com/openpx-trade/openpx/pull/56))
* **core**: `Exchange::fetch_server_time()` returns each venue's wall-clock as `DateTime<Utc>` for clock-skew correction in signing-sensitive paths. `ExchangeInfo` gains `has_fetch_server_time: bool`. ([#26](https://github.com/openpx-trade/openpx/pull/26))

### Fixed

* **sdk**: TypeScript `models.d.ts` was a 13-line empty stub; the codegen now emits all 35+ interfaces (`ExchangeInfo`, `Market`, `Fill`, `WsUpdate`, `OrderStatus`, and more). ([#34](https://github.com/openpx-trade/openpx/pull/34))

## 0.2.6 — 2026-04-24

### Breaking

* **Polymarket `Market.id` is now the `condition_id` hex string**
  (e.g. `0x311d0c4b…`), not the numeric REST id. Callers that need the
  numeric id should read `Market.native_numeric_id` instead.

## 0.2.5 — 2026-04-23

### Breaking

* **`WsUpdate::Snapshot.market_id` and `Delta.market_id`** carry the parent
  condition ID on Polymarket (not the CLOB token). Consumers keying by
  `market_id` expecting a token should switch to the new `asset_id` field.
* **Kalshi `fetch_markets` cursor format changed.** Old 0.2.3 cursors are
  rejected; restart pagination after upgrading.

### Added

* New `WsUpdate::Clear` variant with `InvalidationReason` for per-market book
  invalidation on the same stream as `Snapshot`/`Delta`.
* Reconnect parity across all exchanges.

### Fixed

* Kalshi `fetch_markets` rewritten on `/markets` + `/historical/markets`.

## 0.2.0 — 2026-04-22

### Breaking

* **WebSocket surface rewritten.** Per-token `orderbook_stream(token_id)`
  and `activity_stream(token_id)` are gone. Consumers now read
  `ws.updates()` (multiplexed `WsUpdate`) and `ws.session_events()`
  (connection-level `SessionEvent`).
* Both stream methods are **take-once** — calling either twice returns
  `None` (Rust) or raises (Python/TS).
* **`WsUpdate::Raw` removed.** Untyped escape-hatch variant retired.
* **Timestamps unified to `u64` millis** on the entire WS surface.
* **Python WS variants are real classes** (`Snapshot`, `Delta`, `Trade`,
  `Fill`, `Connected`, `Reconnected`, `Lagged`, `BookInvalidated`,
  `SessionError`) — not dicts. `match` and `isinstance` work directly.
* `tokio::sync::broadcast` replaced with `async-channel` plus explicit
  `Lagged` + `BookInvalidated` signaling.

## Earlier versions

See the [full changelog on GitHub](https://github.com/openpx-trade/openpx/blob/main/CHANGELOG.md)
for 0.1.x and 0.2.1 – 0.2.4.
