{"content":"# Changelog\n\n## Unreleased\n\n### Vol-surface pagination, options contract filters, and coverage discovery\n\nVol-surface history now determines pagination from one additional qualified\noutput bucket. A page advertises `next_cursor` only when a later result exists,\nand additive `meta.has_more` makes that state explicit. The existing cursor\nencoding, limits, row shapes, and `data` envelope are unchanged.\n\nOptions trades and snapshot history accept optional `settlement_currency` and\n`margin_type` (`inverse` or `linear`) filters. They use instrument metadata to\nseparate contract books, including Deribit USDC-linear options, without\nchanging unfiltered requests. The same optional filters are available through\nthe corresponding MCP tools.\n\n`GET /api/v1/changelog/data-coverage` now lists coverage-capable endpoint IDs\nand returns selector-scoped earliest/latest observed timestamps. Empty\nvol-surface REST responses and vol-surface MCP tools use the same\nexchange/currency-scoped availability contract. Observed bounds describe\nstored rows; they are not a completeness or availability-lag guarantee.\n\n### Historical query bounds, reference-price quality, and correction revisions\n\nFutures and perpetuals volume history now applies the requested `end` bound\nbefore limiting or cursoring the result, matching the other bounded historical\nendpoints.\n\nReference-price rollups now exclude incomplete or non-positive source minutes\ninstead of allowing a null-index/zero-mark minute to create a zero open or low\nin coarser bars.\n\nThe correction feed now identifies those two v2 changes separately and also\nrecords the deployed v1 gamma-band/global-activity/Hyperliquid follow-up and\nthe completed Coinbase v1 spot-history restoration, including effective\ntimestamps and re-collection scopes.\n\nThe data-corrections feed now has explicit revision semantics. Each record has\nan `updatedAt`, the feed has a monotonic `feedRevision`, and the response\ndefines how `publishedAt`, `updatedAt`, and `deployment.deployedAt` should be\nused. Polling clients should watch top-level `lastUpdated` and compare both ids\nand `updatedAt` values when it changes.\n\n### Machine-readable availability and completeness metadata\n\nAPI v1 GET responses that return a `data` envelope now use one shared\navailability contract. Empty arrays include `meta.empty_reason`:\n\n* `unsupported_exchange` — the endpoint does not serve the requested exchange.\n* `ineligible_instrument` — the exchange is served, but the instrument is not\n  eligible for that endpoint and product family.\n* `outside_coverage` — an eligible selector is wholly before its first observed\n  stored row, or requests a future interval.\n* `no_matching_data` — the selector is eligible and overlaps observed history,\n  but no stored row matched all supplied filters.\n* `classification_unavailable` — the endpoint cannot yet safely distinguish\n  the empty result from its available machine-readable evidence.\n\nResponses include `meta.coverage`, with a stable endpoint identifier,\nexchange support, instrument eligibility, and the earliest/latest stored rows\nobserved for the exact endpoint, exchange, and instrument selector when that\nclassification is supported. These timestamps remain observed event boundaries,\nnot completeness watermarks or maximum availability-lag guarantees.\n\nMinute-based historical endpoint families also expose `meta.completeness` for\nan exact exchange and instrument selector. When `status=available`,\n`complete_from` and the exclusive `complete_through` bound a gap-free run of\npersisted, closed one-minute source rows. A missing minute stops the certified\ninterval. `complete_through` is monotonic; published corrections and backfills\nmay still revise values at or before it. Endpoints without a safe completeness\nsignal report `status=unavailable` and a machine-readable reason.\n\nThis is an additive response change: existing `data` and `meta.next_cursor`\nfields are unchanged. When rows are returned, `meta.empty_reason` is `null`.\n\nThe same availability and completeness contract is now returned by the MCP\nmarket-data tools, including an explicit `not_supported` status for tool\nfamilies without a certified completeness source. MCP also exposes the\ncanonical corrections, data-status, release-changelog, and running-version\nrecords from the same service used by REST.\n\nThe public `/api/v1/changelog/*` routes are now included in OpenAPI discovery.\nTheir canonical response bodies bypass request-time response decoration, so\npolling clients receive stable feed content until a correction, incident, or\nrelease record actually changes.\n\nThe initial futures and perpetuals liquidation classifier became effective in\nproduction on 2026-08-07 07:19:39 UTC. The broader shared contract and\ncompleteness metadata become effective with this release.\n\n## 1.33.0 (2026-07-13)\n\n### x402 pay-per-call fix for MCP tool calls\n\nPaying for MCP tool calls now works with a standard x402 client, such as `@x402/fetch`. Previously the 402 response from `POST /api/v1/mcp` was rejected by the client before payment was attempted, so pay-per-call could not complete. If you worked around this by editing the 402 response before handing it to your payment client, you can remove that workaround.\n\nAlso fixed:\n\n* 402 responses now give the resource address as `https`. It was previously `http`.\n* `POST /api/v1/vol-surface/risk/*` and the WebSocket pass endpoints are now correctly described as taking a JSON request body. They were previously described as taking query parameters, so an agent that built a request from the endpoint description — the risk endpoints' `positions` payload, for example — would have sent it the wrong way. Requests you already send by hand were never affected.\n\nNothing else changes: the request and response formats of these endpoints are the same, and API-key and OAuth access are unaffected.\n\n### Lighter live API and websocket coverage\n\nAdds Lighter to the live v2 exchange catalog and MCP perpetuals tools. The websocket gateway now emits live open-interest and funding-rate updates for Lighter, alongside aggregated OHLC, trades, liquidations, and orderbook data.\n\n## 1.32.1 (2026-06-29)\n\n### MCP connector sign-in fix\n\nFixes connecting the Laevitas MCP server from Claude.ai (and other OAuth-based clients), which could fail before reaching the sign-in step. The OAuth login flow now works end to end.\n\n* **Setting up the Claude.ai connector:** use the URL `https://apiv2.laevitas.ch/api/v1/mcp`, enter the OAuth **Client ID** shown in the [MCP connection docs](https://apiv2.laevitas.ch/mcp), and leave the Client Secret blank. Click Add, then sign in with your API key.\n* API-key access and x402 pay-per-call are unchanged.\n\n## 1.32.0 (2026-06-15)\n\n### Options dealer GEX API surface\n\nAdds a new dealer gamma exposure surface under `/api/v1/options/gex/*`, focused on current and historical options positioning pressure.\n\n**REST endpoints**\n\n* `GET /api/v1/options/gex/catalog` - discovers available currencies, history depth, and latest state.\n* `GET /api/v1/options/gex/latest` - latest aggregate dealer GEX with snapshot freshness metadata.\n* `GET /api/v1/options/gex/history` - paginated aggregate GEX history with standard time resolutions.\n* `GET /api/v1/options/gex/regime-changes` - transitions between positive, negative, and neutral dealer-gamma regimes.\n* `GET /api/v1/options/gex/strikes` - strike-level GEX, with aggregate all-expiries rows by default and optional per-expiry rows.\n* `GET /api/v1/options/gex/term-structure` - per-expiry GEX concentration and contributing strike counts.\n* `GET /api/v1/options/gex/profile` - interpolated GEX profile points for plotting the shape of dealer exposure across strikes.\n\nThe detail endpoints expose both raw and weighted GEX values. Use the `weighted_*` fields when reconciling strike or expiry detail with the headline aggregate GEX; use raw fields when analyzing the unweighted decomposition.\n\nThe surface is available for Deribit options first, including `BTC`, `ETH`, `SOL`, `XRP`, `BTC_USDC`, and `ETH_USDC` where populated. API docs, examples, and agent tool descriptions have been updated with the new endpoints and field semantics.\n\n**MCP and x402 coverage**\n\n* Adds seven MCP tools backed by the same `OptionsService` methods as REST: `get_options_gex_catalog`, `get_options_gex_latest`, `get_options_gex_history`, `get_options_gex_regime_changes`, `get_options_gex_strikes`, `get_options_gex_term_structure`, and `get_options_gex_profile`.\n* `/api/v1/options/gex/*` is part of the existing paid options REST route set. API-key customers are unaffected; wallet customers can discover and pay for the GEX endpoints through the same x402 flow as the rest of `/api/v1/options/*`.\n\n## 1.31.0 (2026-06-11)\n\n### Vol-surface risk hardening: exchange-native expiries, honest no-entry PnL, and faster live risk responses\n\nThis release hardens the `POST /api/v1/vol-surface/risk/*` endpoints (decompose, scenario, ladder) end to end with the vol-surface engine. It fixes the bug where a position expiry in Deribit shorthand (`26JUN26`) hung the request until the full `timeout_ms` instead of failing fast, and eliminates the intermittent 5–15s transport stalls found while testing that fix.\n\n**Exchange-native expiry formats**\n\n* Position `expiry` now accepts five formats on any position, auto-detected by pattern, never constrained by the position's `exchange`: ISO 8601 timestamp (`2026-06-26T08:00:00Z`, time respected), ISO date (`2026-06-26`), DDMMMYY (`26JUN26`, month case-insensitive), YYMMDD (`260626`), and YYYYMMDD (`20260626`). Date-only forms resolve to the 08:00 UTC settlement.\n* REST and agent-tool validation now accept the same expiry formats. Malformed values fail fast with an error naming all accepted formats.\n* Engine-side (same release train): missing option `strike`/`expiry`/`option_type` are derived from the instrument name for all six venue layouts (Deribit, Bybit incl. trailing quote, Binance, OKX, Bullish, Derive); explicit fields that contradict the name are per-position validation errors naming both values; cross-venue naming (e.g. an OKX-style symbol priced on the Deribit surface) attaches a non-fatal `warnings` entry instead of rejecting.\n\n**Honest no-entry PnL on delta-one legs**\n\n* A perpetual/future/spot position with `mark_price` but no `entry_price` now reports zero unrealized PnL with `entry_price_source: \"mark_fallback\"` (previously the full notional leaked into `unrealized_pnl` and portfolio `total_pnl`). Explicit entries are unchanged and report `entry_price_source: \"input\"`.\n* Delta-one legs serialize `expiry: null` instead of the Go zero time `0001-01-01T00:00:00Z`. `funding_status` (realized-PnL provenance) and `funding_carry_status` (projected carry from the live rate) are documented as independent axes.\n\n**Live risk response reliability**\n\nRisk calculations now recover quickly from transient request-path failures instead of waiting for the full timeout. Slow, retried, or failed calls also emit clearer timing diagnostics for operators.\n\nValidated against the deployed builds: identical pricing across all supported expiry spellings, fast format-listing errors on invalid inputs, and no transport timeouts in the final smoke round.\n\n**HyperCore fixes**\n\n* Bounds the HyperCore instruments mapping query and optimizes resting-order mark lookups.\n\n## 1.30.0 (2026-06-10)\n\n### Hyperliquid - HyperCore ergonomics and data-quality release\n\nThis release keeps the HyperCore REST namespace backward compatible while adding the fields and filters needed to use the node-derived data safely in production workflows.\n\n**Phase 0 data review**\n\nValidated a suspect deep BTC resting bid against Hyperliquid's public order\nstatus. The order was genuine deep crash-fishing liquidity rather than an\ninstrument-mapping error.\n\n**REST additions**\n\n* `GET /api/v1/hyperliquid/node/resting-orders`\n  * Adds `mark_price`, `mark_time`, `distance_from_mark_pct`, `snapshot_interval_ms`, `snapshot_time`, `staleness_ms`, and review-only `monitoring_alerts`.\n  * Adds `max_distance_from_mark` so clients can separate near-mark liquidity from full-depth crash bids/asks.\n* `GET /api/v1/hyperliquid/node/wallet-flow`\n  * Adds `sort_by` (`time`, `total_notional`, `buy_notional`, `sell_notional`, `net_notional`, `realized_pnl`, `trade_count`), `min_notional`, `net_notional`, `net_volume`, and `total_notional`.\n  * Fixes cursor pagination by encoding the sort key plus wallet/instrument tiebreakers.\n* `GET /api/v1/hyperliquid/node/liquidations`\n  * Adds `role`, `dedupe`, `is_backstop`, and wallet labels.\n  * Adds aggregated mode with `resolution=5m|15m|1h|1d`, returning long/short liquidation notional, event count, and max single notional.\n* `GET /api/v1/hyperliquid/node/wallet-positions`\n  * Adds wallet labels, latest `mark_price`, `mark_time`, `position_notional_usd`, nullable `avg_entry_px`, and nullable `unrealized_pnl`.\n* `GET /api/v1/hyperliquid/node/twap-events`\n  * Removes the hard `wallet`/`twap_id` requirement.\n  * Adds `min_target_notional` and computed `target_notional` for recent large-TWAP discovery.\n* `GET /api/v1/hyperliquid/node/instruments`\n  * New raw-coin mapping endpoint for `BTC`, HIP-3 names like `xyz:NVDA`, spot aliases like `@305`, and prediction aliases like `#40`.\n  * Returns normalized `instrument_name`, `market_type`, `currency`, tick/lot sizing where available, display name, deployer, status, and last-seen time.\n\n**Wallet labels**\n\nAdds curated wallet labels to positions, resting orders, liquidations, and\nwallet flow. Labels are curated metadata rather than facts supplied by the\nvenue.\n\n**Docs, MCP, and x402**\n\n* Updates REST OpenAPI decorators for the new params and response fields.\n* Updates MCP tool schemas/descriptions for wallet-flow sorting, liquidation dedupe/aggregation, TWAP discovery, resting-order distance/staleness metadata, and the new `get_hyperliquid_instruments` tool.\n* Updates x402 discovery hints for the new HyperCore query parameters. `/api/v1/hyperliquid/*` remains part of the paid REST route set.\n* Adds canonical `*_iso` timestamp companion fields where existing fields used legacy `YYYY-MM-DD HH:mm:ss` formatting.\n* Documents negative `fees_paid` / `fee` values as maker rebates.\n\n**Testing**\n\nValidated wallet-flow `sort_by=total_notional` cursor pagination, liquidation\ndeduplication and aggregation, TWAP discovery with only\n`min_target_notional`, resting-order `max_distance_from_mark`, and raw coin\ninstrument mapping.\n\n## 1.29.0 (2026-06-09)\n\n### Proprietary Vol Surface and live portfolio risk\n\nAdds a new top-level **Vol Surface** API surface under `/api/v1/vol-surface/*`. This is separate from the legacy `/api/v1/options/vol-surface/*` endpoints because it is backed by the proprietary vol-surface engine output rather than reconstructing surface points from option ticker history.\n\n**New REST endpoints**\n\n* `GET /api/v1/vol-surface/catalog` - lists available `(exchange, currency, margin, model)` tuples with latest calibration time, index price, slice count, and forward-knot count.\n* `GET /api/v1/vol-surface/snapshots` - surface-level calibration snapshots: index price, forward curve, calendar-arbitrage diagnostics, slice counts, and model metadata.\n* `GET /api/v1/vol-surface/slices` - per-expiry rows: ATM IV, 25d/10d skew and butterfly metrics, SVI/SABR model parameters, fit diagnostics, spread-model coefficients, quote-quality counts, `quality_tier`, `slice_source`, and fallback age.\n* `GET /api/v1/vol-surface/term-structure` - constant-maturity rows: ATM IV, total variance, fixed-tenor skew, forward, term slope, forward vol, forward-tenor label, and source.\n* `GET /api/v1/vol-surface/strikes` - per-strike rows: market/model IV diagnostics, deviation, sticky-strike greeks, smile-adjusted delta, min-variance delta, and SVI parameter sensitivities.\n\nAll endpoints explicitly filter `margin` (`inverse` or `linear`) so inverse and\nlinear books cannot be accidentally mixed. Slice requests default to\n`model=svi`; callers can pass another model when intentionally comparing model\nfamilies. The strikes endpoint additionally requires `expiry` or `instrument`\nfor historical scans.\n\n**New live portfolio risk endpoints**\n\n* `POST /api/v1/vol-surface/risk/decompose` - returns full portfolio risk decomposition, per-tenor buckets, per-position greeks, model/market edge, mark PnL, and funding carry fields.\n* `POST /api/v1/vol-surface/risk/scenario` - reprices the portfolio under spot, parallel-vol, skew, curvature, and time-decay shocks.\n* `POST /api/v1/vol-surface/risk/ladder` - reprices the portfolio across a spot x parallel-vol matrix, capped at 400 cells.\n\nStandalone pricing and stored-position transport are intentionally not exposed as separate REST routes in this release. Pricing is embedded inside decomposition and scenario outputs, and each request must provide its own `positions` array.\n\n**MCP**\n\nAdds 8 MCP tools backed by the new proprietary vol-surface services:\n\n* `get_vol_surface_catalog`\n* `get_vol_surface_snapshots`\n* `get_vol_surface_slices`\n* `get_vol_surface_term_structure`\n* `get_vol_surface_strikes`\n* `get_vol_surface_risk_decompose`\n* `get_vol_surface_risk_scenario`\n* `get_vol_surface_risk_ladder`\n\nThe existing legacy MCP tools (`get_vol_surface_by_expiry`, `get_vol_surface_by_tenor`, `get_vol_surface_by_time`) remain available for backwards compatibility.\n\n**Docs and discovery**\n\n* Swagger/OpenAPI now has a top-level **Vol Surface** section ordered after **Options** and before **Predictions**.\n* `/llms.txt`, `/mcp`, `/x402`, Slate/source docs, README, and the API home page now describe the new proprietary surface and live risk endpoints.\n* `/api-json`, `/openapi.json`, and `/.well-known/x402` include the new vol-surface paid resources.\n\n**x402 coverage**\n\n`/api/v1/vol-surface/*` is part of the paid REST route set. Unlike most historical data routes, this release also explicitly registers the three `POST /api/v1/vol-surface/risk/*` endpoints for x402 because they are request-body based live risk calls. API-key customers are unaffected.\n\n**Validation**\n\nValidated volatility-surface filtering, live-risk error mapping, and x402\ndiscovery.\n\n**Backwards compatibility**\n\nExisting `/api/v1/options/vol-surface/by-expiry`, `/api/v1/options/vol-surface/by-tenor`, and `/api/v1/options/vol-surface/by-time` routes remain mounted and unchanged. They continue to serve the legacy option-derived surface view under the **Options** tag.\n\n## 1.28.0 (2026-06-08)\n\n### Hyperliquid - HyperCore wallet and onchain data surface\n\nAdds a new top-level Hyperliquid L1 HyperCore REST surface under\n`/api/v1/hyperliquid/node/*`. This is separate from the existing\n`/api/v1/perpetuals/*`, `/api/v1/spot/*`, and `/api/v1/predictions/*` endpoints\nbecause its wallet-attributed and on-chain fields do not fit the normalized\ncross-exchange market-data schema: raw node coins, wallet addresses, fees,\nclosed PnL, builder/deployer fees, hashes, block numbers, TWAP state, resting\nL4 orders, and deep HyperCore-derived L2 books.\n\n**New REST endpoints**\n\n* `GET /api/v1/hyperliquid/node/fills` - enriched wallet-attributed fills with price, size, notional, direction, start position, closed PnL, fee token, builder/deployer fees, order ids, hash, block number, and liquidation flag. Requires `wallet`.\n* `GET /api/v1/hyperliquid/node/prediction-fills` - HIP-4 prediction fills with condition/token ids, outcome fields, event/category fields, wallet attribution, fees, hash, and block number. Requires `condition_id`, `token_id`, or `instrument_name`.\n* `GET /api/v1/hyperliquid/node/liquidations` - liquidation fills with liquidated user, liquidator, mark price, method, closed PnL, hash, trade id, and block number.\n* `GET /api/v1/hyperliquid/node/wallet-flow` - 1-minute wallet flow rollups with buy/sell volume, buy/sell notional, trade count, realized PnL, and fees paid. Requires `wallet`, `instrument_name`, `instrument_name_raw`, or `currency`.\n* `GET /api/v1/hyperliquid/node/wallet-positions` - latest wallet positions by instrument with position, realized PnL, last fill time, last trade id, and update time. Requires `wallet`, `instrument_name`, `instrument_name_raw`, or `currency`.\n* `GET /api/v1/hyperliquid/node/funding-payments` - wallet-level funding payments with payment amount, funding rate, sample count, block time, and transaction hash. Requires `wallet`.\n* `GET /api/v1/hyperliquid/node/twap-events` - TWAP lifecycle events with wallet, status, side, target size, executed size/notional, duration, reduce-only/randomize flags, and block time. Requires `wallet` or `twap_id`.\n* `GET /api/v1/hyperliquid/node/resting-orders` - latest per-wallet resting orders from HyperCore-derived L4 state, ranked by notional. Requires `wallet`, `instrument_name`, `instrument_name_raw`, or `currency`.\n* `GET /api/v1/hyperliquid/node/l2-orderbook` - latest deep HyperCore-derived L2 orderbook snapshot for an instrument with full bid/ask arrays, 10/20/50/100-level liquidity, imbalance, and microprice. Requires `instrument_name`.\n\n**MCP**\n\nAdds 9 MCP tools with the same filters, guardrails, pagination, and results as\nREST:\n\n* `get_hyperliquid_node_fills`\n* `get_hyperliquid_prediction_fills`\n* `get_hyperliquid_node_liquidations`\n* `get_hyperliquid_wallet_flow`\n* `get_hyperliquid_wallet_positions`\n* `get_hyperliquid_funding_payments`\n* `get_hyperliquid_twap_events`\n* `get_hyperliquid_resting_orders`\n* `get_hyperliquid_node_l2_orderbook`\n\n**Docs and discovery**\n\n* Swagger/OpenAPI now has a dedicated **Hyperliquid - HyperCore** tag.\n* `/llms.txt`, `/slate`, and `/mcp` docs now list the Hyperliquid - HyperCore REST endpoints and MCP tools.\n* The API overview/README now distinguishes Hyperliquid L1 HyperCore wallet/onchain data from the existing Hyperliquid futures/perpetuals coverage.\n\n**x402 coverage**\n\n`/api/v1/hyperliquid/*` is now part of the paid REST route set. API-key customers are unaffected. Wallet customers can discover and pay for the new endpoints through the same x402 flow as futures, perpetuals, options, spot, predictions, instruments, analytics, and macro.\n\n**Operational guardrails**\n\nSome datasets are extremely large, so broad scans are intentionally restricted.\nWallet fills and funding payments require `wallet`; wallet flow, wallet\npositions, and resting orders require at least one narrowing filter; prediction\nfills require a prediction identifier; latest orderbook and resting-order\nrequests use a recent-window constraint.\n\n**Backwards compatibility**\n\nExisting `/api/v1/perpetuals/*`, `/api/v1/spot/*`, `/api/v1/predictions/*`, WebSocket channels, and normalized Hyperliquid market-data response shapes are unchanged. This release only adds a new product namespace.\n\n## 1.27.2 (2026-05-25)\n\n### Incident — Binance and Bybit futures data gaps\n\nFrom **2026-05-24 20:00 UTC** through **2026-05-25 15:00 UTC**, Binance and Bybit futures market data (OHLC, trades, liquidations) had intermittent gaps. Options data and all other exchanges were unaffected. Service was fully restored at **2026-05-25 15:00 UTC**. Partial backfill from raw archives is in progress; some historical data is unrecoverable.\n\n## 1.27.1 (2026-05-13)\n\n### REST latency — service-side fix\n\nResolved a service-side issue that was causing REST endpoint latency to spike to ~13s during peak WebSocket reference-data traffic. All REST routes (futures, perpetuals, options, spot, predictions) are now back to their normal sub-300ms response times. No API contract or response shape changes.\n\n## 1.27.0 (2026-05-11)\n\n### WebSocket — dedicated open interest and funding channels\n\nOpen interest and funding can now be subscribed to directly without consuming the full trade or OHLC ticker payload.\n\n```text\nopen-interest.{perpetuals|futures|options}.{exchange}.{instrument}\nfunding-rate.perpetuals.{exchange}.{instrument}\n```\n\nWildcards work in the same market, exchange, and instrument positions as other WebSocket channels, so `open-interest.*` and `funding-rate.perpetuals.*` are valid broad subscriptions. Open interest is available for perpetuals, dated futures, and options when the upstream venue publishes it; funding rate is scoped to perpetuals.\n\n**Source of truth**\n\n- OI and funding WS events now come from raw venue ticker/open-interest/funding streams, not the enriched trade stream. That gives dense venue-rate updates instead of sparse updates that only fire when a trade occurs.\n- Added raw options OI sources for Deribit, OKX, Bybit, Binance, Bullish, and Derive.\n- Expanded raw options OI coverage across the available market-data streams.\n\n**WebSocket playground and docs**\n\n- Added Open Interest and Funding Rate choices to the `/websocket` playground.\n- Added dedicated event renderers for open-interest and funding-rate payloads.\n- Added channel docs, payload examples, wildcard examples, and code snippets for the new channel families.\n\n**Backwards compatibility**\n\n- Existing `trades.*`, `ohlc.ticker.*`, `ohlc.vt.*`, `liquidations.*`, and `book.*` subscriptions are unchanged.\n- Existing trade payload fields are unchanged, but trade messages no longer generate `open-interest.*` or `funding-rate.*` events.\n\n## 1.26.0 (2026-05-04)\n\n### Predictions — Hyperliquid HIP-4 added as a second venue\n\nHyperliquid HIP-4 prediction markets are now queryable through the existing `/api/v1/predictions/*` endpoints. Pass `exchange=hyperliquid` to any predictions route — catalog, categories, snapshot, ohlcvt, ticker-history, trades, orderbook-raw, metadata — and the response shape is identical to Polymarket.\n\n```bash\n# List active HIP-4 markets\nGET /api/v1/predictions/catalog?exchange=hyperliquid\n\n# OHLCVT for a HIP-4 instrument\nGET /api/v1/predictions/ohlcvt?exchange=hyperliquid&instrument_name=btc-above-79980-20260505-0600&resolution=1m\n\n# Latest snapshot for HIP-4 with a keyword filter\nGET /api/v1/predictions/snapshot?exchange=hyperliquid&keyword=btc\n```\n\nPolymarket continues to be the default when `exchange` is omitted, so existing integrations are unchanged.\n\n**MCP**\n\n- `get_predictions_catalog`, `get_predictions_categories`, `get_predictions_metadata`, `get_predictions_ohlcvt`, `get_predictions_ticker_history`, `get_predictions_trades`, `get_predictions_orderbook_raw`, `get_predictions_snapshot` — all accept `hyperliquid` as the `exchange` argument.\n\n**Backwards compatibility**\n\n- No schema changes; only a new accepted value for the `exchange` parameter. Requests with `exchange=polymarket` (or no `exchange`) return the same data as v1.25.3.\n\n## 1.25.3 (2026-05-04)\n\n### WebSocket streaming passes are now live\n\nWallet customers can now stream live data without an API key. Buy a pre-paid time slot with a single x402 payment (USDC on Base mainnet), then connect to `wss://apiv2.laevitas.ch/ws` or `/stream` with the returned credit token. No metering, no per-event billing — you reserved the time, what you do during it is your business.\n\n| Pass | Price | Streaming |\n|---|---|---|\n| 1 hour | $0.50 | `POST /api/v1/x402/ws-pass/hour` |\n| 1 day | $10.00 | `POST /api/v1/x402/ws-pass/day` |\n\nBuying additional passes while one is active extends your remaining time additively. Connections close at slot expiry with code `4006 NO_ACTIVE_PASS`. See the [WebSocket docs](https://apiv2.laevitas.ch/websocket) for the full flow and reconnect best practices.\n\nAPI-key customers see no change — unlimited streaming continues to be included.\n\n## 1.25.2 (2026-05-04)\n\n### Fix payment headers on /macro and /instruments\n\n`/api/v1/macro/*` and `/api/v1/instruments[/*]` were returning HTTP 402 but without the `payment-required` response header that x402 clients (and x402scan discovery) need to know what asset, amount, network, and recipient wallet to pay. Both families now return the proper 402 challenge — same shape as `/perpetuals/*`, `/futures/*`, etc.\n\nWallet customers using x402scan or any standards-compliant x402 client can now discover and pay these endpoints automatically.\n\n## 1.25.1 (2026-05-03)\n\n### Macro — surface dated commodity futures alongside perpetuals\n\nFollow-up to v1.25.0. Two endpoints in the macro section had been hardcoded to perpetuals only, hiding dated futures (OKX gold weeklies `XAU-USD_UM-*`, Bybit XAUT dateds `XAUTUSDT-DDMMMYY`) that already exist in the metadata table.\n\n**Changes**\n\n- `GET /api/v1/macro/summary` — new optional `market_type` query param (default `perpetual`, accepts `future`). The previous behaviour is unchanged when the param is omitted. Pass `market_type=future` to rank dated commodity futures by 24h USD volume. Equity / forex / index return empty `top` arrays since no active dated futures exist in those classes.\n- `GET /api/v1/macro/venues` — now groups by `market_type`, so each (exchange, sub_exchange) splits into separate rows for `perpetual` / `future` / `spot`. New optional `market_type` query param scopes the response. Response shape gains a `market_type` field per row.\n\n**MCP**\n\n- `get_macro_summary` — new optional `market_type` arg, default `perpetual`.\n- `get_macro_venues` — new optional `market_type` arg + `market_type` field per row.\n\n**Backwards compatibility**\n\n- `/macro/summary` with no params returns the same data as v1.25.0.\n- `/macro/venues` response shape gains a new field per row but no fields removed; consumers reading the existing fields keep working.\n\n## 1.25.0 (2026-04-30)\n\n### Macro perpetuals — equity, commodity, FX, index\n\nA new top-level section exposes the non-crypto perpetual segment: equity perps (NVDA, TSLA, MSTR, AAPL, HOOD, COIN, GOOGL, …), commodity perps (GOLD, SILVER, OIL/CL, NATGAS, PALLADIUM, WHEAT, …), FX perps (EURUSD, GBPUSD, JPYUSD, …) and the small index segment. Coverage spans Hyperliquid (incl. HIP-3 sub-venues `xyz`/`flx`/`km`/`cash`/`vntl`/`hyna`), Kraken Futures (`PF_*`), Binance, Bybit, OKX, and Nado — ~390 active non-crypto perpetual contracts at launch.\n\nDiscovery is the new bit — once you have an `instrument_name` and `exchange`, all OHLC, ticker, trades, orderbook, liquidations, and funding data are served by the existing `/api/v1/perpetuals/*` endpoints exactly the same way as crypto perps. The two new filters on `/instruments` and `/perpetuals/catalog` (`asset_class`, `sub_exchange`) let you narrow to \"every NVDA perp across all exchanges\" or \"every Hyperliquid HIP-3 listing\" in one call.\n\n**New REST endpoints**\n\n* `GET /api/v1/macro/catalog` — paginated list of non-crypto perpetuals with full contract specs. Filters: `asset_class`, `market_type`, `exchange`, `sub_exchange`, `base_currency`, `instrument_name` (partial), `status`.\n* `GET /api/v1/macro/asset-classes` — counts and example tickers per supported class (equity / commodity / forex / index).\n* `GET /api/v1/macro/venues` — `(asset_class, exchange, sub_exchange)` breakdown with active instrument counts. Useful for \"which exchanges list NVDA perps?\".\n* `GET /api/v1/macro/summary` — top-N most-traded macro perpetuals over the last 24h per asset class, ranked by USD volume.\n\n**New filters on existing endpoints**\n\n* `GET /api/v1/instruments` — added `asset_class` and `sub_exchange` query params. Covers all market types (perpetual / future / spot / option) across crypto and non-crypto.\n* `GET /api/v1/perpetuals/catalog` — added `asset_class` and `sub_exchange` query params. Lets clients narrow the perpetuals catalog to, e.g., `?asset_class=equity` for the headline use case.\n\n**New MCP tools**\n\n* `get_macro_catalog` — discovery tool for non-crypto perp instruments and venues.\n* `get_macro_asset_classes` — high-level summary (counts + example tickers).\n* `get_macro_venues` — per-class venue breakdown including Hyperliquid HIP-3 sub-venues.\n* `get_macro_summary` — top-N volume leaders per asset class, last 24h.\n* `get_perpetuals_catalog` — gained optional `asset_class` and `sub_exchange` parameters so AI agents can narrow the existing perpetuals catalog without switching tool families.\n\n**WebSockets — works today, no schema changes**\n\nMacro perps publish on the existing `trades.perpetuals.{exchange}.{instrument}`, `ohlc.{ticker,vt}.perpetuals.{exchange}.{instrument}.{tf}`, `liquidations.perpetuals.{exchange}.{instrument}`, and `book.perpetuals.{exchange}.{instrument}` channels. Examples: `trades.perpetuals.kraken.PF_NVDAXUSD`, `ohlc.ticker.perpetuals.hyperliquid.xyz:NVDA-USD.1m`, `book.perpetuals.hyperliquid.flx:GOLD-USD`. Hyperliquid HIP-3 instrument names are colon-prefixed.\n\n**x402 coverage**\n\n`/api/v1/macro/*` is a paid surface. Pricing matches the existing derivatives endpoints (per-call x402 or prepaid credit bundle). API-key customers are unaffected.\n\n**Notes & limitations**\n\n* Equity / FX perps on some venues (Kraken `PF_*`, Hyperliquid `cash:*`) only tick during the underlying market's hours. 24/7 venues like Hyperliquid `xyz:*` and Binance USDT/USDC perps stream continuously.\n* The aggregated trade stream (`v2_futures_trades`) is currently sparse for non-crypto perps (~42 rows/24h aggregate) — OHLC and ticker history are dense and recommended for analysis.\n* Hyperliquid HIP-3 listings churn — many instruments are deployer-curated and may delist within hours/days. Default catalog filter is `status=active`; pass `status=all` for historical.\n\n## 1.24.0 (2026-04-30)\n\n### WebSocket streaming passes (preview)\n\nAdds the WebSocket pass surface that goes live in v1.25.3. Wallet customers will be able to buy a pre-paid time slot with a single x402 payment (USDC on Base mainnet) and connect to `/ws` or `/stream` with the returned credit token.\n\n| Pass | Price | Streaming |\n|---|---|---|\n| 1 hour | $0.50 | `POST /api/v1/x402/ws-pass/hour` |\n| 1 day | $10.00 | `POST /api/v1/x402/ws-pass/day` |\n\n**How it works**\n\n1. Buy a pass — single x402 payment, no metering or per-event charging.\n2. Use the returned `X-Credit-Token` header to connect to `wss://apiv2.laevitas.ch/ws` or `/stream`.\n3. Disconnect and reconnect freely within your slot. Buying additional passes while one is active extends your remaining time additively.\n4. Connections close at slot expiry with code `4006 NO_ACTIVE_PASS`. Buy another pass to resume.\n\n**Pricing alongside the API subscription**\n\n| Tier | Price | Streaming | Monthly equivalent (24/7) |\n|---|---|---|---|\n| WS hour pass | $0.50 | 1 hour | $360 |\n| WS day pass | $10.00 | 24 hours | $300 |\n| API subscription | $500/month | unlimited (REST + WS) | $500 |\n\nFor sustained heavy usage the API subscription remains the most cost-effective option (rate-limit-free, historical access, support included). Day passes are convenience pricing for short bursts, not a subscription replacement.\n\n**Service interruptions**\n\nPasses are non-refundable in USDC. If a service issue affects your pass, contact support@laevitas.ch — we may extend your pass or grant REST credits at our discretion.\n\nAPI-key customers are unaffected — unlimited streaming continues to be included.\n\n---\n\n## 1.23.1 (2026-04-29)\n\n### WebSocket — Playground supports wildcard subscriptions\n\nFollow-up to v1.23.0 that lets users actually exercise the new wildcard syntax from the [playground](/websocket).\n\n* The Market dropdown now includes `* — Any market (wildcard)` so you can build wildcard patterns step-by-step in the structured form.\n* The Pairs field accepts `*` literals — `*:BTCUSDT`, `binance:*`, `*:*` all work alongside the existing `exchange:instrument` form. Placeholder text updated.\n* New \"Raw channel pattern\" toggle (top-right of the Subscribe card) — flip it on to bypass the structured form and type a full pattern directly (`liquidations.perpetuals.*`, `book.perpetuals.*.BTCUSDT`, etc.). Useful for power users and copy-paste from the docs page above.\n* The JavaScript and Python code examples in the Code Examples tab now show a wildcard subscription alongside a concrete one in the same `subscribe` request, demonstrating that you can mix both freely.\n\nNo server-side changes. The wire protocol and channel-pattern semantics are unchanged from v1.23.0.\n\n---\n\n## 1.23.0 (2026-04-29)\n\n### WebSocket — Wildcard subscriptions\n\nYou can now use `*` as a wildcard in the `market`, `exchange`, or `instrument` position of any channel pattern. This lets a single subscription cover many channels at once — e.g. every liquidation across exchanges, or every order book for a given instrument across all venues.\n\n**Examples**\n\n```\ntrades.*                                ← every trade across every market/exchange/instrument\nliquidations.*                          ← every liquidation\nliquidations.perpetuals.*               ← every perp liquidation across exchanges\nbook.*                                  ← every L2 order-book snapshot\nbook.perpetuals.*.BTCUSDT               ← BTCUSDT perp book across all exchanges\ntrades.*.binance.BTCUSDT                ← every binance BTCUSDT trade across markets\ntrades.predictions.polymarket.*         ← every Polymarket prediction trade\nohlc.ticker.*.binance.BTCUSDT.1m        ← 1m ticker bars for binance BTCUSDT across markets\n```\n\n**Trailing-wildcard shorthand**\n\nA trailing `*` auto-pads remaining segments. `trades.*` is equivalent to `trades.*.*.*` (every segment below `trades` wildcarded). `liquidations.perpetuals.*` is equivalent to `liquidations.perpetuals.*.*`.\n\n**Wire format unchanged**\n\nEvents arriving from a wildcard subscription carry the **resolved concrete channel path** in the `channel` field, not the wildcard pattern you subscribed to:\n\n```json\n// You subscribed to: trades.predictions.polymarket.*\n// You receive:\n{\n  \"channel\": \"trades.predictions.polymarket.btc-updown-5m-1777389300-YES\",\n  \"data\": { ... }\n}\n```\n\nClient dispatch logic that already keys off the concrete channel name keeps working unchanged.\n\n**What's NOT allowed**\n\n* `*` in the channel-type position (pick `trades`, `ohlc`, `liquidations`, or `book`).\n* `*` in the OHLC `dataType` position — subscribe to `ohlc.ticker.*` or `ohlc.vt.*` explicitly.\n* `*` in the OHLC `timeframe` position — subscribe per timeframe.\n\nThese constraints prevent silent waste (a single `*` in `dataType`/`timeframe` would fire many events for the same instrument) and ambiguous fanout across channel types with different payload shapes.\n\n**Limits**\n\n* Each wildcard subscription counts as 1 against the 200-subscriptions-per-connection cap.\n* High-volume firehose subscriptions (e.g. `book.*`) need a fast consumer — the existing 2 MB outbound-buffer / 500-pending-packet slow-consumer protections (close codes `4003`) apply unchanged.\n* Other limits — inbound message rate (`4008`), 24h connection lifetime (`4004`), per-key/IP connection caps (`4005`) — unchanged.\n\n**Backward compatibility**\n\nFully backward-compatible. Existing concrete-channel subscriptions are a strict subset of the new wildcard syntax and behave identically. No client changes required to keep existing integrations working.\n\n---\n\n## 1.22.2 (2026-04-29)\n\n### WebSocket — Predictions discovery notice\n\nAdded a callout on the [/websocket](/websocket) playground reminding users that Polymarket prediction instruments are short-lived (sports/event markets can resolve within hours) and pointing them at the right discovery endpoints — `/api/v1/predictions/catalog` (filter by category or currency) and `/api/v1/predictions/categories` (browse available categories). Don't hard-code prediction instrument slugs in client integrations.\n\n---\n\n## 1.22.1 (2026-04-29)\n\n### WebSocket — Predictions L2 order book + evergreen examples\n\n**Predictions L2.** The Order Book channel now accepts `predictions` as a market:\n\n```\nbook.predictions.polymarket.{instrument}\n```\n\nPrediction snapshots route to the same `BookSnapshotEvent` shape as spot/perpetuals/futures — same fields, same pre-computed liquidity tiers, same imbalance ratios, same microprice. Routing is by `instrument_type: \"prediction\"` on the payload.\n\nSame exchange-list, payload, and snapshot-only semantics documented for the other markets in v1.22.0 — predictions are a 1-for-1 addition.\n\n**Stale example cleanup.** The Payload Examples section was using dated futures (`BTC-27MAR26`) and a near-term options expiry (`BTC-30JAN26-100000-C`) that would expire and look stale on the docs page. Replaced with evergreen instruments where possible:\n\n* \"Futures Trade Event\" renamed to \"Perpetuals Trade Event\" and uses `BTC-PERPETUAL` (no expiry).\n* \"OHLC Ticker Event\" and \"OHLC VT Event\" use `BTC-PERPETUAL`.\n* \"Options Trade Event\" uses a far-out 2027 expiry with a footnote pointing at `/options/catalog` for current expiries.\n\n**Channel-pattern cleanup.** The Operations section and code examples were teaching the legacy `trades.futures.binance.BTCUSDT` channel for a perp instrument. v1.17.0 introduced the perpetuals split with a one-version deprecation alias for `trades.futures.{exchange}.{perp_instrument}`. Examples now use `trades.perpetuals.binance.BTCUSDT` to match the new convention.\n\n---\n\n## 1.22.0 (2026-04-29)\n\n### WebSocket — L2 Order Book channel + playground fix\n\nA new top-level channel type for L2 order book snapshots, plus a fix for the v1.21.0 playground that was sending `trades.*` instead of `liquidations.*` when you picked Liquidations from the dropdown.\n\n#### Order Book channel\n\n```\nbook.{market}.{exchange}.{instrument}\n```\n\n`{market}` is `perpetuals`, `futures`, or `spot`. **Options have no L2 feed** and are explicitly rejected with a clear error. Predictions are also rejected (their book data ships via the prediction.ticker stream).\n\n**Exchange coverage:** binance, bybit, okx, hyperliquid, coinbase, kraken — every exchange that has perpetuals / futures / spot has L2.\n\n**Snapshot semantics:** every event is a complete snapshot. The full book is\npublished on every update—there are no deltas, no sequence numbers, and no\nsnapshot-on-subscribe contract. The next event always supersedes the previous\none.\n\n**Event payload**\n\n```json\n{\n  \"timestamp\": 1777464961535,\n  \"exchange\": \"bybit\",\n  \"instrument_name\": \"BTCUSDT\",\n  \"currency\": \"BTC\",\n  \"instrument_type\": \"perpetual\",\n  \"margin_type\": \"linear\",\n  \"multiplier\": 1,\n  \"depth\": 100,\n  \"bids\": [[89990, 1.5], [89989, 0.8], \"...\"],\n  \"asks\": [[89991, 0.6], [89992, 2.1], \"...\"],\n  \"bid_liquidity_10\": 1512918.4,\n  \"bid_liquidity_20\": 3587922.06,\n  \"bid_liquidity_50\": 4368371.83,\n  \"bid_liquidity_100\": 4368371.83,\n  \"ask_liquidity_10\": 1212726.78,\n  \"ask_liquidity_20\": 3469574.02,\n  \"ask_liquidity_50\": 3970438.56,\n  \"ask_liquidity_100\": 3970438.56,\n  \"imbalance_10\": 0.11,\n  \"imbalance_20\": 0.017,\n  \"imbalance_50\": 0.048,\n  \"imbalance_100\": 0.048,\n  \"microprice\": 89990.78\n}\n```\n\n* `bids` / `asks` — arrays of `[price, size]` tuples, sorted (asks ascending, bids descending). Up to 100 levels per side.\n* `*_liquidity_N` — cumulative size at the top N levels per side, useful for cascade detection without client-side recomputation.\n* `imbalance_N` — `(bid_liquidity_N - ask_liquidity_N) / (bid_liquidity_N + ask_liquidity_N)`, signed (-1..1).\n* `microprice` — liquidity-weighted mid; preferred over `(best_bid + best_ask) / 2` for HFT signals because it accounts for the size at top of book.\n\n#### Playground fix\n\nThe v1.21.0 playground at `/websocket` shipped a \"Liquidations\" option in the channel dropdown but was sending `trades.{market}.{exchange}.{instrument}` instead of `liquidations.{market}.{exchange}.{instrument}` when you submitted the form. Subscribers got trades, not liquidations. Fixed in v1.22.0 along with the new Order Book option.\n\n---\n\n## 1.21.0 (2026-04-29)\n\n### WebSocket — Liquidations channel\n\nA new top-level channel type for forced-liquidation events, alongside the existing `trades.*` and `ohlc.*` channels.\n\n**Channel pattern**\n\n```\nliquidations.{market}.{exchange}.{instrument}\n```\n\n`{market}` is `perpetuals` or `futures`. Liquidations are available on\nderivatives only—`spot`, `options`, and `predictions` are not valid here and\nthe gateway returns a clear error if you subscribe to them.\n\n**Exchange coverage:** binance, bybit, okx, kraken, nado.\n\n**Examples**\n\n```\nliquidations.perpetuals.binance.BTCUSDT\nliquidations.perpetuals.okx.UP-USDT-SWAP\nliquidations.perpetuals.bybit.ETHUSDT\nliquidations.futures.deribit.BTC-27MAR26   (rare — dated futures liquidations)\n```\n\n**Event payload**\n\n```json\n{\n  \"timestamp\": 1777461297250,\n  \"exchange\": \"binance\",\n  \"instrument_name\": \"BTCUSDT\",\n  \"currency\": \"BTC\",\n  \"instrument_type\": \"perpetual\",\n  \"margin_type\": \"linear\",\n  \"multiplier\": 1,\n  \"quote_currency\": \"USDT\",\n  \"direction\": \"buy\",\n  \"position_side\": \"short\",\n  \"category\": \"forced\",\n  \"price\": 90000,\n  \"amount\": 0.5,\n  \"amount_base\": 0.5,\n  \"amount_usd\": 45000,\n  \"mark_price\": 89990,\n  \"index_price\": 89980\n}\n```\n\n* `direction` — aggressor side of the order that filled the liquidation.\n* `position_side` — the side of the position that was liquidated.\n* `amount_usd` — USD-denominated size (helpful for cross-symbol comparisons / cascade detection).\n\n**Note on `raw_data`**\n\nThe venue's original payload is not included on the WebSocket. If you need it,\nfetch it from the corresponding REST endpoint (`/futures/liquidations`,\n`/perpetuals/liquidations`, `/derivatives/liquidations`).\n\n---\n\n## 1.20.0 (2026-04-29)\n\n### WebSocket — Mid-session re-auth, slow-consumer parity on `/stream`\n\nTwo operational improvements to the WS gateway. Existing well-behaved clients see no change in behavior; the new close-code paths only trigger on revoked keys or stuck consumers.\n\n**Mid-session re-auth**\n\nThe server now revalidates each authenticated connection's API key every 10 minutes. If a key has been revoked or rotated server-side, the connection closes with `4001` (auth failed) on the next check.\n\n* Applies to both `/ws` and `/stream`.\n* Existing reconnect logic for `4001` (surface to user, do not auto-retry until the key is fixed — see v1.18.0) is unchanged. The only difference is that a 4001 may now arrive mid-session, not just at connect.\n* No client change required for keys that are still valid.\n\n**Slow-consumer parity on `/stream`**\n\nSocket.IO `/stream` now disconnects clients that fall behind on outbound delivery, matching the behavior added to the native `/ws` transport in v1.19.0. The threshold is 500 pending packets queued to the underlying transport (roughly 0.5–1 s of data on a high-volume channel like `trades.spot.binance.BTCUSDT`).\n\n* Close code on the breach: `4003` (slow consumer) — same as native `/ws`.\n* Triggers only on truly stuck consumers; a healthy connection's queue depth hovers near zero between drain events.\n\n**Updated close-code reference for `/stream`**\n\n| Code | Reason | Client guidance |\n|---|---|---|\n| `4001` | Auth failed — including mid-session revocation | Surface to user; do not auto-retry until the key is fixed |\n| `4003` | Slow consumer — outbound buffer full | Reduce subscriptions or upgrade your network; reconnect after draining |\n\n(Existing `/ws` codes from v1.18.0 / v1.19.0 are unchanged.)\n\n---\n\n## 1.19.0 (2026-04-29)\n\n### WebSocket — Per-connection limits and new close codes\n\nThe WS gateway now enforces explicit limits on subscriptions, message rate, connection lifetime, and concurrent connections. Defaults are well above retail usage — most existing clients see no change. Hitting a cap closes the connection with a specific application close code so reconnect logic can react correctly.\n\n**Limits**\n\n| Cap | Value | Triggers close code |\n|---|---|---|\n| Subscriptions per connection | 200 | error response on the offending subscribe |\n| Inbound messages per second per connection | 20 | `4008` |\n| Max connection lifetime | 24 hours | `4004` |\n| Concurrent connections per API key | 5 | `4005` |\n| Concurrent connections per client IP | 20 | `4005` |\n| Per-recipient send buffer (slow consumer) on `/ws` | 2 MB | `4003` |\n\n**Close-code reference**\n\n| Code | Reason | Client guidance |\n|---|---|---|\n| `4003` | Slow consumer — outbound buffer full | Reduce subscriptions or upgrade your network; reconnect after draining |\n| `4004` | 24-hour lifetime cap reached | Reconnect immediately |\n| `4005` | Concurrent-connection cap reached (per API key or per IP) | Close idle connections before reconnecting |\n| `4008` | Inbound message rate exceeded | Slow down outgoing requests, reconnect with exponential backoff |\n\nThe slow-consumer check on `/stream` (Socket.IO) is not yet enforced — coming in a follow-up release.\n\n**Performance**\n\n* Disabled `permessage-deflate` compression on both transports. JSON tick streams are latency-sensitive; the per-message compression cost outweighs the bandwidth saving. Clients that need bandwidth wins can compress at their load balancer.\n* Broadcast fan-out on `/ws` now serializes each event once per channel rather than once per subscriber — invisible from the client side, but reduces tail latency on popular channels.\n\n**Documentation**\n\n* New \"Limits & Close Codes\" section on the [playground](/websocket) lists every cap and what each close code means.\n* Need higher caps for a specific use case? Email support@laevitas.ch.\n\n---\n\n## 1.18.0 (2026-04-29)\n\n### WebSocket — Authentication, heartbeats, and structured close codes\n\nA production-readiness pass on the WS gateway. The notable client-facing change is the removal of query-string authentication on both `/ws` and `/stream`.\n\n**Authentication**\n\n* **breaking:** `?apiKey=` query-string authentication is no longer accepted on either transport. Query strings end up in load-balancer access logs, browser history, and HTTP `Referer` headers, which is unsafe for credentials. Use one of:\n  * `apikey` header on the upgrade request (server-side clients with the `ws` library or `websockets` Python library)\n  * Socket.IO `auth: { apiKey }` payload (Socket.IO clients)\n  * First-message `{ \"id\": 0, \"method\": \"auth\", \"params\": { \"apiKey\": \"...\" } }` RPC (browser clients, since the browser WebSocket API doesn't allow custom headers)\n* Native `/ws` now closes the socket with code `4001` on auth failure. Previously failed auth was logged but the socket stayed open.\n* New 30-second grace window for native `/ws` clients that connect without a header. The client has that window to send the `auth` RPC; otherwise the server closes with `4001`.\n\n**Liveness / heartbeats**\n\n* Native `/ws` now tracks pongs per connection and terminates idle clients within ~75s of no response. Previously dead TCP connections (NAT timeout, network partition, paused tabs) could linger indefinitely.\n* Ping interval tightened to 25s on both transports so dead-client cleanup runs\n  before common network idle timeouts.\n* Socket.IO `/stream` ping/pong window tightened to ~35s total.\n\n**Close codes**\n\n| Code | Meaning | Client guidance |\n|---|---|---|\n| `1001` | Server going away (graceful shutdown) | Reconnect with backoff |\n| `1012` | Server restart | Reconnect with backoff |\n| `4001` | Authentication failed | Surface to user; do not auto-retry until the key is fixed |\n| `4002` | Idle timeout (server didn't get a pong) | Reconnect with backoff |\n\n**Documentation**\n\n* The [playground](/websocket) and embedded code examples now show the header and first-message auth flows.\n\n---\n\n## 1.17.0 (2026-04-28)\n\n### WebSocket — Spot, predictions, and the perpetuals split\n\nThis release brings the WS gateway in line with the REST and MCP surface. Spot, predictions, and a dedicated perpetuals namespace are all exposed for the first time. A small subscription-matcher fix prevents same-symbol cross-market events from leaking between subscriptions.\n\n**Spot**\n\n* New channels: `trades.spot.{exchange}.{instrument}`, `ohlc.ticker.spot.{exchange}.{instrument}.{tf}`, `ohlc.vt.spot.{exchange}.{instrument}.{tf}`. Covers binance, bybit, okx, hyperliquid, coinbase, kraken.\n* Spot ticker bars carry `last_price_*` (instead of `mark_price_*`), `quote_currency`, and 24h rolling stats. Spot trade events drop the derivatives-only fields (`mark_price`, `oi_change`, `maturity`, `basis`).\n* Closed `final`-state OHLC bars are now delivered. Previously only `live` (mid-formation) bars reached subscribers — `final` (closed) bars, which are the canonical close-of-period values consumers expect for backfill, were silently dropped.\n\n**Predictions**\n\n* New channels: `trades.predictions.polymarket.{instrument}`, `ohlc.ticker.predictions.polymarket.{instrument}.{tf}`, `ohlc.vt.predictions.polymarket.{instrument}.{tf}`.\n* Trade and bar events preserve the rich Polymarket metadata: `condition_id`, `token_id`, `category`, `event_slug`, `outcome`, `human_outcome`, `outcomes`, `sports_market_type`, probability OHLC, `complement_probability_close`.\n* Categories are open-ended (`sports`, `tennis`, `up-or-down`, `politics`, `weather`, `crypto`, `tech`, `world-elections`, `culture`, `cricket`, ...) — the gateway accepts any category as Polymarket adds them.\n* Quote/BBO data for prediction markets is delivered as aggregated `ohlc.ticker.predictions.*` bars only. There is no separate raw ticker channel — same model as futures, options, and spot.\n\n**Perpetuals split**\n\n* Perpetual swaps now have their own market namespace: `trades.perpetuals.{exchange}.{instrument}`, `ohlc.ticker.perpetuals.{exchange}.{instrument}.{tf}`, `ohlc.vt.perpetuals.{exchange}.{instrument}.{tf}`. This mirrors the long-standing REST split between `/futures` (dated) and `/perpetuals`.\n* The subscription matcher now discriminates events by market, so a single instrument name that exists on multiple markets (e.g. `binance:BTCUSDT` exists on both spot and perpetuals) is routed only to the correct subscription.\n* **Deprecation:** Perp events continue to fire on the legacy `trades.futures.*` / `ohlc.{ticker,vt}.futures.*` channels for one minor version where `maturity === \"PERPETUAL\"`. Existing clients keep working without changes; please migrate perpetual subscriptions to the new `perpetuals` market before the next minor release, when the legacy alias is removed.\n\n---\n\n## 1.16.0 (2026-04-27)\n\n### Analytics — Realized Volatility\n\nA new `/api/v1/analytics/*` section for derived cross-asset metrics, kicking off with realized volatility.\n\n- `GET /analytics/realized-volatility` — annualized realized volatility from precomputed metrics. Omit `start`/`end` for the latest snapshot across every `(frequency × window_days × estimator)` combination; pass `start`/`end` for a paginated time series.\n- Validates `frequency` (`daily`, `hourly`), `estimator` (`close_to_close`, `parkinson`, `garman_klass`), and `window_days` (`7`, `30`, `60`, `90`, `180`, `365`). Invalid values now return `400` instead of an empty array.\n- `sort_dir=ASC|DESC` honoured on the historical mode.\n- MCP: new `get_realized_volatility` tool.\n- x402 pay-per-request supported on `/analytics/*` (same model as futures, perps, options, spot, predictions, instruments).\n\nMore cross-asset metrics will land in this section over time (basis, term structure, IV/RV spread, correlation).\n\n### Instruments — Deduplication + response envelope\n\n- `/api/v1/instruments` was returning duplicate rows for the same contract. It now returns one row per `(exchange, instrument_name)` — latest snapshot wins. Pagination and `meta.total` count distinct contracts, not raw history rows.\n- `/api/v1/instruments/detail` previously returned a bare entity at the top level. It now returns the standard `{ data, meta }` envelope, consistent with every other v2 endpoint.\n- **Breaking:** `/api/v1/instruments` (list) moved `next_cursor` and `total` from top-level into `meta`. Old: `{ data, next_cursor, total }`. New: `{ data, meta: { next_cursor, total, count } }`. `count` is the number of contracts in the current page.\n- Anonymous requests to `/api/v1/instruments` now correctly return `402` (was `401`), so x402 wallet customers can pay and access the list endpoint.\n\n### Swagger UI\n\n- Tag ordering normalised: Instruments → Spot → Futures → Perpetuals → Options → Predictions → Analytics → MCP → OAuth.\n- \"Try it out\" on x402-protected GET endpoints no longer fails with `Request with GET/HEAD method cannot have body`.\n\n---\n\n## 1.15.0 (2026-04-27)\n\n### Time-series sort direction\n\n`sort_dir=ASC|DESC` is now honoured on every paginated time-series endpoint across futures, perpetuals, options, and spot — including carry, ohlcvt, open-interest, volume, ticker-history, reference, volatility, l2-orderbook, l2-raw, and vol-surface history. Cursor pagination walks forward in time for ASC, backward for DESC.\n\nDefault remains `ASC` (oldest first), so existing callers see identical responses. Snapshot endpoints are point-in-time and don't paginate. Don't switch `sort_dir` partway through a paginated scan — keep it constant for the duration.\n\n---\n\n## 1.14.0 (2026-04-08)\n\n### Derive options support\n\nDerive is now a supported exchange across all options and vol-surface endpoints. Coverage: BTC, ETH, SOL, HYPE, ADA options. The `exchange` enum in MCP tools and Swagger descriptions updated to match.\n\n---\n\n## 1.13.0 (2026-04-02)\n\n### Instruments metadata endpoints\n\nCross-market contract reference data — every instrument across spot, perpetual, future, and option markets, refreshed every 5 minutes.\n\n- `GET /instruments` — paginated list with filters: `exchange`, `market_type`, `base_currency`, `quote_currency`, `status`, `margin_type`, `option_type`, `expiry` range, `instrument_name` (partial match). Offset-based cursor pagination, `limit` 1–1000.\n- `GET /instruments/detail` — full instrument specification including raw exchange data.\n- MCP: new `get_instruments_metadata` tool.\n- x402 pay-per-request supported.\n\n---\n\n## 1.12.2 (2026-03-31)\n\n### Bullish options support\n\nBullish is now a supported exchange across all options and vol-surface endpoints. Coverage: BTC options only, USDC-quoted (e.g. `BTC-USDC-20260401-65800-P`). The `exchange` enum in MCP tools and Swagger descriptions updated to match.\n\n---\n\n## 1.12.1 (2026-03-19)\n\n### Options flow — time bucketing\n\n`GET /options/flow` now produces real time-bucketed data when you pass a `resolution` (it was previously ignored). Each response includes:\n\n- A new `buckets` array — per-bucket breakdown at the requested resolution: trade count, buy/sell premium, call/put premium, notional, block-trade stats, net OI change, average IV, average absolute delta.\n- `start`, `end`, `resolution` echoed in the summary so consumers know the aggregation window.\n- `top_n` now controls `notable_trades` only; `most_active_strikes` always returns the top 10 (previously both shared `top_n`).\n\nMCP `get_options_flow` updated with `resolution` and the new `buckets` field.\n\n---\n\n## 1.12.0 (2026-03-13)\n\n### Vol-surface — 10-delta wings\n\n10-delta call/put IV is now available on every vol-surface endpoint (by-expiry, by-tenor, history, time-series), along with derived `skew_10d` (`put_10d_iv - call_10d_iv`) and `butterfly_10d` (`(call_10d_iv + put_10d_iv) / 2 - atm_iv`). The `by-tenor` term structure interpolates 10-delta wings using the total-variance method.\n\nThe redundant `date` field on per-row data in by-expiry and by-tenor snapshot responses has been removed; date lives exclusively in `meta.date`.\n\n### MCP snapshot tools — bounded responses\n\nAll MCP snapshot tools (futures, perpetuals, options, spot) now accept a `limit` parameter (default 100) and return `total`, `count`, and `truncated` fields. Tool descriptions warn AI agents about context overflow when calling unfiltered snapshots on busy markets.\n\n---\n\n## 1.11.0 (2026-03-11)\n\n### Vol-surface — time-series mode\n\n`by-expiry` and `by-tenor` now accept `start`/`end` for paginated history instead of one call per data point. `limit` controls distinct time buckets (not total rows), so each page returns complete snapshots. MCP tools `get_vol_surface_by_expiry` and `get_vol_surface_by_tenor` updated with the new parameters.\n\nFully backward compatible — passing only `date` returns the same single-snapshot response as before.\n\n### Kraken support\n\nKraken is now a supported exchange across futures, perpetuals, and spot endpoints (and the corresponding MCP tools).\n\n### Nado support\n\nNado (perp DEX) is now a supported exchange on perpetuals endpoints only.\n\n### Predictions snapshot — keyword filter\n\n`GET /predictions/snapshot` and the `get_predictions_snapshot` MCP tool now support `keyword` (case-insensitive partial match on instrument name) and `instrument_name` (exact match) filters. The MCP tool also gained a `limit` parameter (default 100) so unfiltered snapshots of broad categories like \"politics\" don't overflow AI agent context windows.\n\n### MCP exchange enums\n\nThe `exchange` enum on every MCP tool now lists every supported exchange per product type (previously some tools only showed `deribit`/`binance`):\n\n- Futures: deribit, binance, okx, bybit, kraken\n- Perpetuals: deribit, binance, okx, bybit, hyperliquid, kraken, nado\n- Options + vol-surface: deribit, binance, okx, bybit, bullish, derive\n- Spot: binance, coinbase, bybit, okx, kraken\n\n---\n\n## 1.10.0 (2026-03-07)\n\n### Spot market data\n\nA complete spot module across Binance, Coinbase, Bybit, and OKX.\n\n- 10 REST endpoints under `/api/v1/spot/*`: catalog, metadata, ohlcvt, ticker, trades, volume, snapshot, level1, l2-orderbook, l2-orderbook-raw.\n- 7 MCP tools mirroring the REST surface (`get_spot_ohlcvt`, `get_spot_ticker`, `get_spot_trades`, `get_spot_volume`, `get_spot_snapshot`, `get_spot_l2_orderbook`, `get_spot_level1`), plus spot catalog and metadata in the discovery tool family.\n- x402 pay-per-request supported on `/api/v1/spot/*`.\n- Filtering catalog by `currency` / `quote_currency` no longer hits an aggregate alias collision.\n\n## 1.9.0 (2026-03-04)\n\n### x402scan Discovery Support\n* `GET /.well-known/x402` — machine-readable discovery endpoint listing all payable resources (v1 spec)\n* `GET /openapi.json` and `GET /.well-known/openapi.json` — OpenAPI spec with x402 payment extensions\n* Every payable operation in OpenAPI now includes `x-agentcash-auth`, `x-payment-info` (fixed pricing), and `402` response\n* MCP endpoint (`POST /api/v1/mcp`) now has Swagger decorators with JSON-RPC 2.0 requestBody schema\n\n---\n\n## 1.8.0 (2026-02-23)\n\n### New Product: Prediction Markets (Polymarket)\n* `GET /predictions/catalog` — list available prediction market instruments with optional filtering by exchange, category, event_slug, and keyword search\n* `GET /predictions/categories` — list all prediction market categories with instrument counts\n* `GET /predictions/metadata` — data availability metadata for a specific prediction instrument\n* `GET /predictions/ohlcvt` — OHLCVT candle data with probability-based prices (0.0–1.0), buy/sell volume, trade counts\n* `GET /predictions/ticker-history` — historical ticker data with probability OHLC, bid/ask spread, liquidity metrics\n* `GET /predictions/trades` — individual trades with price (probability), size, side, outcome, fee rate\n* `GET /predictions/orderbook-raw` — raw L2 orderbook snapshots with bid/ask arrays, depth liquidity (10/20/50), imbalance, microprice\n* `GET /predictions/snapshot` — cross-instrument snapshot at a single minute with ticker + OHLCVT data\n\n### New MCP Tools: Predictions\n* `get_predictions_catalog` — discover prediction instruments with category/keyword filtering\n* `get_predictions_categories` — list categories with counts\n* `get_predictions_metadata` — check data availability before querying\n* `get_predictions_ohlcvt` — probability candle data\n* `get_predictions_ticker_history` — market microstructure analysis\n* `get_predictions_trades` — individual trade history\n* `get_predictions_orderbook_raw` — raw L2 orderbook snapshots\n* `get_predictions_snapshot` — cross-instrument snapshots\n\n### E2E Tests\n* 26 E2E tests covering all prediction endpoints, cursor pagination, and edge cases\n\n---\n\n## 1.7.0 (2026-02-16)\n\n### New Endpoint: Options Flow\n* `GET /options/flow` — aggregated options flow summary bucketed by time interval\n* Returns per-bucket: trade counts (buy/sell, call/put), premium breakdowns, notional, block trade stats, net OI change, avg IV, avg delta\n* Configurable resolution (1m to 1M), max 7-day query window\n* MCP tool: `get_options_flow`\n\n### Enhanced: Options Trades — Currency-Level Filtering\n* `GET /options/trades` now supports querying by `currency` (e.g., `BTC`) to fetch trades across ALL options instruments in a single call\n* `instrument_name` is now optional when `currency` is provided (max 7-day window enforced)\n* New filter parameters: `min_premium_usd`, `min_notional`, `direction`, `strategy`, `block_only`, `opening_only`, `option_type`, `maturity`\n* Sortable by `timestamp`, `premium_usd`, `notional`, or `amount` with configurable `sort_dir` (ASC/DESC)\n* Offset-based cursor pagination for non-timestamp sorts\n* MCP tool `get_options_trades` updated with all new parameters\n* Backward compatible — existing instrument-level queries work unchanged\n\n### Documentation\n* Added `llms.txt` for LLM-friendly API reference\n* Updated Slate API documentation with new endpoints and parameters\n\n---\n\n## 1.6.0 (2026-02-16)\n\n### New: x402 Pay-Per-Request\n* USDC micropayments via HTTP 402 protocol — access derivatives data without an API key\n* Supported networks: Base mainnet (eip155:8453) + Sepolia testnet\n* Prepaid credit bundles: pay once for a configured number of calls and use the\n  returned credit token for subsequent requests.\n* Credit token JWT returned via `x-credit-token` header for subsequent fast-path access\n* Credit usage remains available across service restarts and instances.\n\n### New: x402 Payment for MCP\n* AI agents can now pay per tool call via x402 without needing an API key\n* Billing rules: `initialize` and `tools/list` are free; `tools/call` costs 1 credit per invocation\n* Credit tokens and prepaid bundles work identically to REST endpoints\n* 402 responses include both x402 headers and JSON-RPC error body for MCP client compatibility\n\n### New: OAuth 2.1 for MCP\n* OAuth 2.1 authorization flow for the MCP endpoint (`/api/v1/mcp`)\n* Custom `ApiKeyOAuthStrategy` — redirects to login page, exchanges API key for Bearer JWT\n* Bearer token validated in `ApiKeyGuard` for MCP routes only\n* All other endpoints continue to use API key headers\n\n### New Endpoint: Futures Carry\n* `GET /futures/carry` — carry/basis data (mark price minus index price) for dated futures\n* MCP tool: `get_futures_carry`\n\n### Improvements\n* Enriched volume responses: added `buy_volume`, `sell_volume`, `volume`, `buy_trades_count`, `sell_trades_count`, `trades_count` to futures, perpetuals, and options volume endpoints\n* Enriched ticker history: added OHLCVT trade-based fields to ticker snapshots\n* Enriched carry/funding: added OHLCVT trade-based fields to carry and funding responses\n* Improved MCP tool descriptions with more detailed return field lists\n* Updated public documentation pages for MCP and x402\n\n---\n\n## 1.5.0 (2026-02-10)\n\n### New Endpoints: L2 Orderbook Depth\n* `GET /futures/orderbook` - Aggregated L2 orderbook metrics (OHLC+avg) at 4 depth levels (10, 20, 50, 100)\n* `GET /futures/orderbook-raw` - Raw L2 orderbook snapshots with full 100-level bid/ask arrays (30-day retention)\n* `GET /perpetuals/orderbook` - Aggregated L2 orderbook metrics for perpetuals\n* `GET /perpetuals/orderbook-raw` - Raw L2 orderbook snapshots for perpetuals\n* Metrics include: bid/ask liquidity, order book imbalance, microprice, snapshot count\n* MCP tools: `get_futures_l2_orderbook`, `get_futures_l2_orderbook_raw`\n\n---\n\n## 1.4.0 (2026-02-09)\n\n### New: MCP Server (Model Context Protocol)\n* `POST /mcp` - Streamable HTTP transport for AI agent integration\n* Compatible with Claude Desktop, ChatGPT, and any MCP-compatible AI client\n* 20 tools across futures, options, and discovery:\n  - **Catalog & Discovery**: `get_futures_catalog`, `get_options_catalog`, `get_futures_metadata`, `get_options_metadata`\n  - **Futures Data**: `get_futures_ohlcvt`, `get_futures_ticker_history`, `get_futures_trades`, `get_futures_open_interest`, `get_futures_volume`, `get_futures_level1`, `get_futures_reference_price`, `get_futures_snapshot`\n  - **Options Data**: `get_options_ohlcvt`, `get_options_ticker_history`, `get_options_trades`, `get_options_open_interest`, `get_options_volatility`, `get_options_volume`, `get_options_level1`, `get_options_snapshot`\n* Token-optimized responses: redundant fields stripped, floating-point precision fixed, selective zero removal\n* Stateless mode with JSON responses enabled\n* Uses existing API key authentication (`apikey` / `x-api-key` header)\n\n---\n\n## 1.3.0 (2026-01-30)\n\n### New Endpoints: Volatility Surface\n* `GET /options/vol-surface/snapshot` - ATM IV, 25-delta skew, and 25-delta butterfly across all maturities at a single point in time\n* `GET /options/vol-surface/term-structure` - ATM IV, skew, and butterfly interpolated to fixed constant-maturity tenors (1d, 7d, 14d, 30d, 60d, 90d, 180d, 365d)\n* `GET /options/vol-surface/history` - Paginated time-series of vol surface metrics filtered by maturity\n\n### New Endpoints: Instrument Snapshots\n* `GET /futures/snapshot` - All futures instruments for a given exchange at a single minute\n* `GET /options/snapshot` - All options instruments for a given exchange and currency at a single minute\n* `GET /perpetuals/snapshot` - All perpetual instruments for a given exchange at a single minute\n\n### Improvements\n* Rate limit increased from 10 requests/60s to 240 requests/60s (20 requests per 5-second window)\n* All date fields standardized to UTC and ISO 8601 format\n* Fixed cursor pagination direction for correct forward chronological iteration\n\n---\n\n## 1.2.0 (2025-12-05)\n\n### New Exchange Support\n* **Hyperliquid** - Added Hyperliquid as a supported exchange for futures endpoints\n  - Historical data available for futures derivatives\n  - Full support across OHLCVT, reference prices, open interest, volume, trades, and level1 endpoints\n\n---\n\n## 1.1.0 (2025-11-23)\n\n### New Exchange Support\n* **Bybit** - Added Bybit as a supported exchange across all futures, perpetuals, and options endpoints\n  - Historical data available for all derivative types\n  - Full support across OHLCVT, reference prices, open interest, volume, trades, and level1 endpoints\n\n## 1.0.0 (2025-11-11)\n\n### Futures Endpoints\n* `GET /futures/ohlcvt` - Historical OHLC with volume and trade statistics\n* `GET /futures/reference-price` - Mark and index price data\n* `GET /futures/open-interest` - Open interest tracking\n* `GET /futures/volume` - Volume analysis with buy/sell breakdown\n* `GET /futures/trades` - Individual trade data\n* `GET /futures/level1` - Best bid/ask snapshots\n* `GET /futures/ticker-history` - Historical ticker snapshots\n\n### Perpetuals Endpoints\n* `GET /perpetuals/ohlcvt` - Historical OHLC with volume and trade statistics\n* `GET /perpetuals/reference-price` - Mark and index price data\n* `GET /perpetuals/open-interest` - Open interest tracking\n* `GET /perpetuals/volume` - Volume analysis with buy/sell breakdown\n* `GET /perpetuals/trades` - Individual trade data\n* `GET /perpetuals/level1` - Best bid/ask snapshots\n* `GET /perpetuals/carry` - Funding rates and carry metrics\n* `GET /perpetuals/ticker-history` - Historical ticker snapshots\n* `GET /perpetuals/catalog` - Available perpetual instruments\n\n### Options Endpoints\n* `GET /options/ohlcvt` - Options OHLC with Greeks and IV\n* `GET /options/reference-price` - Options reference prices\n* `GET /options/open-interest` - Options open interest data\n* `GET /options/volume` - Options volume statistics\n* `GET /options/trades` - Options trade flow\n* `GET /options/level1` - Options best bid/ask\n* `GET /options/volatility` - Implied volatility surface\n* `GET /options/ticker-history` - Options ticker history\n* `GET /options/catalog` - Available options instruments\n\n### Key Features\n* Real-time WebSocket streaming\n* Multiple exchange support (Binance, OKX, Deribit)\n* 1-minute to daily data resolutions\n* Cursor-based pagination for large datasets\n* Sub-50ms API response times\n* API key authentication with rate limiting\n\n### What's Next\n* Additional exchange integrations\n* Advanced Greeks calculations\n* Historical volatility metrics\n","lastUpdated":"2026-09-01T11:07:51.000Z"}