Skip to content

Commit 88a849f

Browse files
authored
feat!: spec sync 3.22.0 → 3.23.0 (v6.0.0) — drop multivariate lookup-history, additive drift fixes (#466)
Syncs the SDK to upstream OpenAPI/AsyncAPI 3.22.0 → 3.23.0 (v6.0.0). Breaking: removed the multivariate lookup-history endpoint (lookup_history() + LookupPoint), deleted upstream in 3.23.0. Additive: subaccount-scoped API keys; subaccounts.transfer_position() (new POST /portfolio/subaccounts/positions/transfer); subaccounts.create(exchange_index=); new response fields on SubaccountTransfer, MarginOrder, MarginPosition/ MarginRiskPosition (is_portfolio), and the WS market_lifecycle_v2 payload (price_ranges). Defensive optional-ization of three fields the spec removed/relaxed. Closes #463 Closes #464 Closes #465
1 parent 00d126a commit 88a849f

42 files changed

Lines changed: 2319 additions & 2529 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,64 @@
22

33
All notable changes to kalshi-sdk will be documented in this file.
44

5+
## 6.0.0 — 2026-07-04
6+
7+
Syncs the upstream OpenAPI/AsyncAPI specs **3.22.0 → 3.23.0** (#463). The
8+
headline change is **breaking**: Kalshi removed the multivariate lookup-history
9+
endpoint from the spec, so the SDK removes the corresponding method and model.
10+
Every other change is additive and backward-compatible.
11+
12+
### Removed (breaking)
13+
14+
- **`lookup_history()`** on `client.multivariate_collections` (sync + async) and
15+
the **`LookupPoint`** model (no longer exported from `kalshi` /
16+
`kalshi.models`). Upstream removed the backing `GET
17+
/multivariate_event_collections/{collection_ticker}/lookup` operation
18+
(`GetMultivariateEventCollectionLookupHistory`) and the `LookupPoint` schema in
19+
3.23.0 — the endpoint now 404s. The `lookup_tickers()` sibling (the `PUT` on the
20+
same path) is unaffected.
21+
22+
### Added
23+
24+
- **`ApiKey.subaccount`**, **`CreateApiKeyRequest.subaccount`**,
25+
**`GenerateApiKeyRequest.subaccount`** (`int | None`) — when set, restricts the
26+
API key to a single subaccount. `api_keys.create()` / `generate()` (sync +
27+
async) accept a `subaccount` kwarg that threads into the body. The request
28+
models bound it to the spec's `0-63` range (`ge=0, le=63`) client-side; the
29+
response model stays permissive.
30+
- **`ApplySubaccountTransferRequest.exchange_index`** (`int | None`) — exchange
31+
shard to apply the transfer on (spec `ExchangeIndex`; defaults to 0).
32+
- **`SubaccountTransfer`** additive fields: `exchange_index` and `transfer_type`
33+
(`"cash"`/`"position"`, both required), plus the position-transfer-only
34+
`market_ticker` / `side` (`"yes"`/`"no"`) / `count` / `price_cents`.
35+
- **`MarginPosition.is_portfolio`** and **`MarginRiskPosition.is_portfolio`**
36+
(`bool`, required) — true when the position is hedged within a portfolio.
37+
- **`MarginOrder.order_reason`** (`"liquidation"`/`"take_profit_stop_loss"`,
38+
optional) — reason for a system-generated order.
39+
- **`MarketLifecyclePayload.price_ranges`** (WS `market_lifecycle_v2`) — valid
40+
price bands emitted alongside `price_level_structure`.
41+
- **`subaccounts.transfer_position(...)`** (sync + async) — new
42+
`POST /portfolio/subaccounts/positions/transfer` endpoint (spec 3.23.0): moves
43+
an open **position** (contracts) between subaccounts, distinct from the
44+
cash-only `transfer()`. Returns `ApplySubaccountPositionTransferResponse`
45+
(`position_transfer_id`). New models `ApplySubaccountPositionTransferRequest` /
46+
`ApplySubaccountPositionTransferResponse` are exported from `kalshi` /
47+
`kalshi.models`.
48+
- **`subaccounts.create(exchange_index=...)`**`POST /portfolio/subaccounts`
49+
gained an optional `CreateSubaccountRequest` body (spec 3.23.0); `create()`
50+
now accepts an optional `exchange_index` to target a specific exchange shard.
51+
New `CreateSubaccountRequest` model exported from `kalshi` / `kalshi.models`.
52+
53+
### Fixed
54+
55+
- **Defensive optional-ization of fields 3.23.0 removed/relaxed.** The drift
56+
suite is spec→SDK only, so a field the spec drops but the SDK still *requires*
57+
is a latent `ValidationError` if the server stops emitting it. Three such
58+
fields are now `... | None = None`:
59+
- `Market.fractional_trading_enabled` (removed from spec),
60+
- `MarketPosition.resting_orders_count` (removed from spec),
61+
- `MarginPosition.margin_used` (relaxed from required to optional).
62+
563
## 5.0.1 — 2026-06-27
664

765
Spec-drift catch-up (#460). Kalshi added fields to the `ExchangeStatus` schema

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ tests/
122122

123123
## API Reference
124124

125-
- OpenAPI spec: https://docs.kalshi.com/openapi.yaml (v3.22.0, 101 operations)
125+
- OpenAPI spec: https://docs.kalshi.com/openapi.yaml (v3.23.0, 101 operations)
126126
- AsyncAPI spec: https://docs.kalshi.com/asyncapi.yaml (13 WebSocket channels)
127127
- Base URL: https://api.elections.kalshi.com/trade-api/v2
128128
- Demo URL: https://demo-api.kalshi.co/trade-api/v2

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ A professional, spec-first Python SDK for the [Kalshi](https://kalshi.com) predi
1111
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
1212
[![Type checked: mypy strict](https://img.shields.io/badge/mypy-strict-blue.svg)](https://mypy.readthedocs.io/)
1313

14-
- **Full coverage** of the Kalshi REST API (101 operations across 19 resources, OpenAPI v3.22.0) and WebSocket API (12 typed `subscribe_*` channels + 2 escape-hatch).
14+
- **Full coverage** of the Kalshi REST API (101 operations across 19 resources, OpenAPI v3.23.0) and WebSocket API (12 typed `subscribe_*` channels + 2 escape-hatch).
1515
- **Perps (margin) API**: standalone `PerpsClient` / `AsyncPerpsClient` + `PerpsWebSocket` for the perpetual-futures exchange (34 REST operations, 6 WS channels), plus a `KlearClient` for the Self-Clearing-Member "Klear" settlement API (9 operations). See [Perps (margin) trading](#perps-margin-trading).
1616
- **FIX protocol**: an async-first FIX engine (FIXT.1.1 / FIX50SP2) for both products — order-entry, drop-copy, market-data, post-trade (prediction), and RFQ (prediction) sessions (plus order-group management over the order-entry session) with typed message models, sequence recovery, and order-book / settlement reassembly. `from kalshi import FixClient` / `MarginFixClient`. See [FIX protocol](#fix-protocol-low-latency-trading).
1717
- **V2 event-market orders**: `create_v2` / `amend_v2` / `decrease_v2` / `cancel_v2` plus batched variants on `/portfolio/events/orders/*` — the only order-write surface.

ROADMAP.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,27 @@
22

33
## Shipped
44

5+
- **v6.0.0 (2026-07-04)** — OpenAPI sync v3.22.0 → v3.23.0 (#463). **Breaking:**
6+
removed the multivariate lookup-history endpoint (`lookup_history()` +
7+
`LookupPoint`), deleted upstream. Additive: subaccount-scoped API keys
8+
(`api_keys.create/generate(subaccount=)`), subaccount **position** transfers
9+
(`subaccounts.transfer_position()` + models), `subaccounts.create(exchange_index=)`,
10+
and new response fields on `SubaccountTransfer`, `MarginOrder`,
11+
`MarginPosition` / `MarginRiskPosition` (`is_portfolio`), and the WS
12+
`market_lifecycle_v2` payload (`price_ranges`). Defensive optional-ization of
13+
three fields the spec removed/relaxed (#464, #465 folded in).
14+
- **v5.0.1 (2026-06-27)** — spec-drift catch-up (#460): additive `ExchangeStatus`
15+
fields (`intra_exchange_transfers_active`, `exchange_index_statuses` +
16+
`ExchangeIndexStatus`).
17+
- **v5.0.0 (2026-06-26)** — OpenAPI sync v3.21.0 → v3.22.0 (#454, #458).
18+
**Breaking:** removed the V1 order-write endpoints/models (use the `*_v2`
19+
family); added RFQ-scoped quote actions.
20+
- **v4.2.0 (2026-06-19)** — in-place spec-drift reconciliation (#451): additive
21+
fields the live OpenAPI/AsyncAPI specs gained after 4.1.0.
22+
- **v4.1.0 (2026-06-14)** — OpenAPI sync v3.20.0 → v3.21.0: additive new query
23+
params, response fields, and four new endpoints.
24+
- **v4.0.0 (2026-06-09)** — spec-drift reconciliation against OpenAPI 3.20.0
25+
(#443); one breaking change on the Self-Clearing-Member (Klear) surface.
526
- **v3.3.0 (2026-06-06)** — complete **FIX protocol** subsystem (FIXT.1.1 /
627
FIX50SP2) for both products: `FixClient` (prediction) + `MarginFixClient`
728
(margin) over a hand-rolled async session engine, with five session types

docs/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
A professional, spec-first Python SDK for the [Kalshi](https://kalshi.com) prediction
44
markets API.
55

6-
- **Full REST coverage** — 101 operations across 19 resources (OpenAPI v3.22.0),
6+
- **Full REST coverage** — 101 operations across 19 resources (OpenAPI v3.23.0),
77
every kwarg drift-tested against the spec.
88
- **V2 event-market orders** — new `create_v2` / `amend_v2` / `decrease_v2` /
99
`cancel_v2` family on `/portfolio/events/orders/*`. Legacy `/portfolio/orders`

docs/migration.md

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,31 @@
11
# Migration
22

3+
## v5 → v6.0.0
4+
5+
**Breaking: multivariate lookup-history is gone.** Kalshi removed the
6+
`GET /multivariate_event_collections/{ticker}/lookup` endpoint
7+
(`GetMultivariateEventCollectionLookupHistory`) and the `LookupPoint` schema from
8+
the OpenAPI spec in 3.23.0, so the SDK removed the matching method and model.
9+
10+
### Removed
11+
12+
| Removed (v5) | Replacement |
13+
| --------------------------------------------------- | ----------- |
14+
| `multivariate_collections.lookup_history(...)` (sync + async) | none — the endpoint was deleted upstream |
15+
| `LookupPoint` model (exported from `kalshi` / `kalshi.models`) | none |
16+
17+
Everything else in 6.0.0 is additive and needs no code changes:
18+
19+
- New optional/required response fields on `ApiKey`, `SubaccountTransfer`,
20+
`MarginPosition`, `MarginRiskPosition`, `MarginOrder`, and the WS
21+
`market_lifecycle_v2` payload.
22+
- New `subaccounts.transfer_position(...)` method (`POST
23+
/portfolio/subaccounts/positions/transfer`) for moving open positions between
24+
subaccounts.
25+
- `subaccounts.create()` gained an optional `exchange_index` argument.
26+
27+
See the [changelog](../CHANGELOG.md) for the full list.
28+
329
## v4 → v5.0.0
430

531
**Breaking: the V1 order-write API is gone.** Kalshi removed the V1 order
@@ -402,16 +428,14 @@ for position in client.portfolio.positions_all():
402428

403429
### Multivariate endpoints emit `DeprecationWarning`
404430

405-
Per #269, `multivariate.lookup_tickers`, `multivariate.lookup_history`,
406-
and `multivariate.create_market` (sync + async) carry
407-
`@typing_extensions.deprecated` decorators citing the spec's "should
408-
not be used for new integrations" guidance. Use RFQs instead. The
409-
endpoints still work; calls just emit a `DeprecationWarning` on first
410-
use.
431+
Per #269, `multivariate.lookup_tickers` and `multivariate.create_market`
432+
(sync + async) carry `@typing_extensions.deprecated` decorators citing
433+
the spec's "should not be used for new integrations" guidance. Use RFQs
434+
instead. The endpoints still work; calls just emit a `DeprecationWarning`
435+
on first use.
411436

412-
`multivariate.lookup_history` also now validates `lookback_seconds`
413-
locally against the spec enum `{10, 60, 300, 3600}` and raises
414-
`ValueError` for any other value before the round trip.
437+
(`multivariate.lookup_history`, also deprecated here in #269, was removed
438+
entirely in 6.0.0 — see the [v5 → v6.0.0](#v5--v600) section above.)
415439

416440
### `orders.list(event_ticker=...)` accepts lists
417441

docs/perps.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ Orders create/cancel/decrease/amend are POSTs/DELETEs and are **never retried**.
9999
- **Subaccounts** (since the v3.21.0 spec sync) — `MarginPosition` (the
100100
`portfolio.positions()` rows) carries a **required** `subaccount` (`int`)
101101
identifying which subaccount holds the position.
102+
- **Portfolio hedging** (since the v3.23.0 spec sync) — `MarginPosition` and
103+
`MarginRiskPosition` carry a **required** `is_portfolio` (`bool`), `True` when
104+
the position is hedged within a portfolio so its margin is computed at the
105+
portfolio level. `MarginOrder` gained an optional `order_reason`
106+
(`"liquidation"` / `"take_profit_stop_loss"`) identifying system-generated
107+
orders.
102108

103109
## Funding mechanics
104110

docs/reference.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,12 @@ every exception class.
6868

6969
::: kalshi.models.order_groups.UpdateOrderGroupLimitRequest
7070

71+
::: kalshi.models.subaccounts.CreateSubaccountRequest
72+
7173
::: kalshi.models.subaccounts.ApplySubaccountTransferRequest
7274

75+
::: kalshi.models.subaccounts.ApplySubaccountPositionTransferRequest
76+
7377
::: kalshi.models.subaccounts.UpdateSubaccountNettingRequest
7478

7579
## Response models

docs/resources/api-keys.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,16 @@ Auth required throughout (you need an existing key to manage keys).
1010
| Method | Endpoint |
1111
|---|---|
1212
| `list()` | `GET /api_keys` |
13-
| `create(*, name, public_key, scopes=None)` | `POST /api_keys` |
14-
| `generate(*, name, scopes=None)` | `POST /api_keys/generate` |
13+
| `create(*, name, public_key, scopes=None, subaccount=None)` | `POST /api_keys` |
14+
| `generate(*, name, scopes=None, subaccount=None)` | `POST /api_keys/generate` |
1515
| `delete(api_key)` | `DELETE /api_keys/{api_key}` |
1616

17+
!!! note "Subaccount-scoped keys (spec v3.23.0)"
18+
Pass `subaccount=<0-63>` to `create()` / `generate()` to restrict a key to a
19+
single subaccount. Omit it (the default) for an account-wide key. The value is
20+
bounded to `0-63` client-side; `ApiKey.subaccount` echoes it back on `list()`
21+
(`None` for account-wide keys).
22+
1723
## List
1824

1925
```python

docs/resources/multivariate.md

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,17 @@ Public listing, auth-required minting. Attribute name on the client:
99
`multivariate_collections`.
1010

1111
!!! warning "Deprecated methods"
12-
`create_market()`, `lookup_tickers()`, and `lookup_history()` are
13-
deprecated — "This endpoint predates RFQs and should not be used for new
14-
integrations." Calling them emits a `DeprecationWarning`. Use the
12+
`create_market()` and `lookup_tickers()` are deprecated — "This endpoint
13+
predates RFQs and should not be used for new integrations." Calling them
14+
emits a `DeprecationWarning`. Use the
1515
[Communications (RFQ/Quote)](communications.md) surface instead. `list()` /
1616
`list_all()` / `get()` remain supported.
1717

18+
!!! danger "Removed in 6.0.0"
19+
`lookup_history()` and the `LookupPoint` model were removed — Kalshi deleted
20+
the backing `GET /multivariate_event_collections/{ticker}/lookup` endpoint
21+
from the spec in 3.23.0.
22+
1823
## Quick reference
1924

2025
| Method | Endpoint | Auth |
@@ -23,7 +28,6 @@ Public listing, auth-required minting. Attribute name on the client:
2328
| `get(collection_ticker)` | `GET /multivariate_event_collections/{ticker}` | no |
2429
| `create_market(collection_ticker, *, selected_markets, with_market_payload=False)` | `POST /multivariate_event_collections/{ticker}` | yes |
2530
| `lookup_tickers(collection_ticker, *, selected_markets)` | `PUT /multivariate_event_collections/{ticker}/lookup` | yes |
26-
| `lookup_history(collection_ticker, *, lookback_seconds)` | `GET /multivariate_event_collections/{ticker}/lookup` (with `lookback_seconds` query param) | no |
2731

2832
## List collections
2933

@@ -77,17 +81,6 @@ if resp.market is not None:
7781
print(resp.market.yes_bid, resp.market.yes_ask)
7882
```
7983

80-
## Recent lookup history
81-
82-
```python
83-
history = client.multivariate_collections.lookup_history(
84-
"KXWEATHER-SPORTS-COMBO",
85-
lookback_seconds=3600,
86-
)
87-
for point in history:
88-
print(point.last_queried_ts, point.market_ticker, point.event_ticker)
89-
```
90-
9184
## Reference
9285

9386
::: kalshi.resources.multivariate.MultivariateCollectionsResource

0 commit comments

Comments
 (0)