Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,42 @@

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

## 8.0.0 — 2026-07-27

Reconciles upstream core OpenAPI / AsyncAPI content under version string
**3.26.0** (paths 93→92, 105→103 operations; 102 mapped) after Kalshi removed
the short-lived settlement-advance subaccount surface (Closes #489, #490).
**Breaking** for callers that adopted the v7.4.0 settlement-advance API.

### Removed (breaking)

- **`subaccounts.lock_settlement_advance()` / `unlock_settlement_advance()`**
(sync + async) and request/response models
`LockSubaccountForSettlementAdvanceRequest`,
`LockSubaccountForSettlementAdvanceResponse`,
`UnlockSubaccountForSettlementAdvanceRequest`. Upstream deleted
`PUT`/`DELETE` `/portfolio/subaccounts/settlement-advance-lock` and the
matching schemas from OpenAPI 3.26.0 content.
- **`SubaccountBalance.voluntarily_locked`**, **`settlement_advance`**, and
**`settlement_advance_state`** — also dropped from the upstream
`SubaccountBalance` schema. `list_balances()` responses no longer include
these fields.

### Added

- **WebSocket quote payloads** (AsyncAPI content): optional
`rfq_creator_id` and `subaccount` on `QuoteCreatedPayload` /
`QuoteAcceptedPayload`, and optional `subaccount` on
`QuoteExecutedPayload` (own subaccount only; never the counterparty's).

### Spec notes

- Core OpenAPI `info.version` still **3.26.0** (content-only change; paths
93→92, 103 operations / 102 mapped). Still unimplemented:
`POST /portfolio/intra_exchange_instance_transfer` (use
`PerpsClient.transfers.transfer_instance()` on the margin product).
- Perps OpenAPI / AsyncAPI / SCM specs unchanged for this release.

## 7.4.0 — 2026-07-26

Reconciles upstream core OpenAPI content under version string **3.26.0**
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ tests/

## API Reference

- OpenAPI spec: https://docs.kalshi.com/openapi.yaml (v3.26.0, 105 operations; 104 mapped in the core SDK — `POST /portfolio/intra_exchange_instance_transfer` is currently not available upstream)
- OpenAPI spec: https://docs.kalshi.com/openapi.yaml (v3.26.0, 103 operations; 102 mapped in the core SDK — `POST /portfolio/intra_exchange_instance_transfer` is currently not available upstream)
- AsyncAPI spec: https://docs.kalshi.com/asyncapi.yaml (13 WebSocket channels)
- Base URL: https://api.elections.kalshi.com/trade-api/v2
- Demo URL: https://demo-api.kalshi.co/trade-api/v2
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ A professional, spec-first Python SDK for the [Kalshi](https://kalshi.com) predi
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
[![Type checked: mypy strict](https://img.shields.io/badge/mypy-strict-blue.svg)](https://mypy.readthedocs.io/)

- **Full coverage** of the Kalshi REST API (104 operations across 19 resources, OpenAPI v3.26.0) and WebSocket API (12 typed `subscribe_*` channels + 2 escape-hatch).
- **Full coverage** of the Kalshi REST API (102 operations across 19 resources, OpenAPI v3.26.0) and WebSocket API (12 typed `subscribe_*` channels + 2 escape-hatch).
- **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 (11 operations). See [Perps (margin) trading](#perps-margin-trading).
- **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).
- **V2 event-market orders**: `create_v2` / `amend_v2` / `decrease_v2` / `cancel_v2` plus batched variants on `/portfolio/events/orders/*` — the only order-write surface.
Expand Down
6 changes: 6 additions & 0 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

## Shipped

- **v8.0.0 (2026-07-27)** — Spec-drift reconcile under OpenAPI 3.26.0
(#489 / #490). **Breaking:** removed the settlement-advance subaccount
surface added in v7.4.0 (`lock_settlement_advance` /
`unlock_settlement_advance` + models + `SubaccountBalance` advance fields)
after upstream deleted the endpoint. Additive: WS quote payload
`rfq_creator_id` / `subaccount` fields.
- **v7.4.0 (2026-07-26)** — OpenAPI 3.26.0 content reconcile (#486). Additive:
`subaccounts.lock_settlement_advance()` / `unlock_settlement_advance()`, and
`SubaccountBalance` settlement-advance fields (`voluntarily_locked`,
Expand Down
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
A professional, spec-first Python SDK for the [Kalshi](https://kalshi.com) prediction
markets API.

- **Full REST coverage** — 104 operations across 19 resources (OpenAPI v3.26.0),
- **Full REST coverage** — 102 operations across 19 resources (OpenAPI v3.26.0),
every kwarg drift-tested against the spec.
- **V2 event-market orders** — new `create_v2` / `amend_v2` / `decrease_v2` /
`cancel_v2` family on `/portfolio/events/orders/*`. Legacy `/portfolio/orders`
Expand Down
37 changes: 37 additions & 0 deletions docs/migration.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,42 @@
# Migration

## v7.4 → v8.0.0

Reconciles upstream core OpenAPI / AsyncAPI content under version string
**3.26.0** after Kalshi removed the settlement-advance subaccount surface
(Closes #489, #490). **Breaking** for callers that adopted the v7.4.0
settlement-advance API (methods, request models, and balance fields).

### Removed

- **`subaccounts.lock_settlement_advance()` / `unlock_settlement_advance()`**
(sync + async) and
`LockSubaccountForSettlementAdvanceRequest` /
`LockSubaccountForSettlementAdvanceResponse` /
`UnlockSubaccountForSettlementAdvanceRequest`.
- **`SubaccountBalance.voluntarily_locked`**, **`settlement_advance`**,
**`settlement_advance_state`**.

```python
# No longer available — the upstream endpoints 404:
# client.subaccounts.lock_settlement_advance(subaccount_number=1)
# client.subaccounts.unlock_settlement_advance(subaccount_number=1)

resp = client.subaccounts.list_balances()
for bal in resp.subaccount_balances:
print(bal.subaccount_number, bal.balance, bal.updated_ts)
# bal.voluntarily_locked / bal.settlement_advance removed
```

### Added (non-breaking)

- Optional **`rfq_creator_id`** / **`subaccount`** on WS
`QuoteCreatedPayload` / `QuoteAcceptedPayload`, and optional
**`subaccount`** on `QuoteExecutedPayload`.

See the [changelog](https://github.com/TexasCoding/kalshi-python-sdk/blob/main/CHANGELOG.md)
for the full list.

## v7.3 → v7.4.0

Reconciles upstream core OpenAPI content under version string **3.26.0** for
Expand Down
2 changes: 0 additions & 2 deletions docs/request-models.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,6 @@ exposed by each resource method stays in lockstep with the OpenAPI spec.
| `client.subaccounts.transfer` | `ApplySubaccountTransferRequest` |
| `client.subaccounts.transfer_position` | `ApplySubaccountPositionTransferRequest` |
| `client.subaccounts.update_netting` | `UpdateSubaccountNettingRequest` |
| `client.subaccounts.lock_settlement_advance` | `LockSubaccountForSettlementAdvanceRequest` |
| `client.subaccounts.unlock_settlement_advance` | `UnlockSubaccountForSettlementAdvanceRequest` |

All are importable from the top-level `kalshi` package.

Expand Down
39 changes: 4 additions & 35 deletions docs/resources/subaccounts.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ primary; `1`–`63` are numbered extras. Auth required throughout.
| `list_all_transfers(*, limit=None, max_pages=None)` | walks `list_transfers` |
| `update_netting(*, subaccount_number, enabled)` | `PUT /portfolio/subaccounts/netting` |
| `get_netting()` | `GET /portfolio/subaccounts/netting` |
| `lock_settlement_advance(*, subaccount_number, exchange_index=None)` | `PUT /portfolio/subaccounts/settlement-advance-lock` |
| `unlock_settlement_advance(*, subaccount_number, exchange_index=None)` | `DELETE /portfolio/subaccounts/settlement-advance-lock` |

## Create a subaccount

Expand Down Expand Up @@ -79,41 +77,12 @@ print(resp.position_transfer_id)
```python
resp = client.subaccounts.list_balances()
for bal in resp.subaccount_balances:
print(
bal.subaccount_number,
bal.balance,
bal.updated_ts,
bal.voluntarily_locked,
bal.settlement_advance,
bal.settlement_advance_state,
)
print(bal.subaccount_number, bal.balance, bal.updated_ts, bal.exchange_index)
```

`bal.balance` and `bal.settlement_advance` are `DollarDecimal` (dollars).
`bal.updated_ts` is Unix seconds (not ISO datetime). `bal.voluntarily_locked`
is whether the subaccount is locked for settlement-advance computation;
`bal.settlement_advance_state` is the optional CAS token (`UUID | None`).

## Settlement advance lock

Lock a subaccount before settlement-advance work (cancels resting orders and
prevents trading). Unlock is rejected while an outstanding settlement advance
remains.

```python
lock = client.subaccounts.lock_settlement_advance(
subaccount_number=1,
exchange_index=0, # optional; defaults to 0 server-side
)
print(lock.settlement_advance_state) # UUID CAS token

# After the advance is cleared:
client.subaccounts.unlock_settlement_advance(subaccount_number=1)
```

Both methods also accept a pre-built request model
(`LockSubaccountForSettlementAdvanceRequest` /
`UnlockSubaccountForSettlementAdvanceRequest`). Auth required.
`bal.balance` is `DollarDecimal` (dollars). `bal.updated_ts` is Unix seconds
(not ISO datetime). `bal.exchange_index` is the exchange shard the balance is
held on.

## List transfers

Expand Down
8 changes: 1 addition & 7 deletions kalshi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,6 @@
IncentiveProgramTypeLiteral,
IndexedBalance,
LiveData,
LockSubaccountForSettlementAdvanceRequest,
LockSubaccountForSettlementAdvanceResponse,
LookupTickersForMarketInMultivariateEventCollectionRequest,
LookupTickersResponse,
MaintenanceWindow,
Expand Down Expand Up @@ -166,7 +164,6 @@
TimeInForceLiteral,
TotalRestingOrderValue,
Trade,
UnlockSubaccountForSettlementAdvanceRequest,
UpdateOrderGroupLimitRequest,
UpdateSubaccountNettingRequest,
UserDataTimestamp,
Expand Down Expand Up @@ -314,8 +311,6 @@
"KlearClient",
"KlearConfig",
"LiveData",
"LockSubaccountForSettlementAdvanceRequest",
"LockSubaccountForSettlementAdvanceResponse",
"LookupTickersForMarketInMultivariateEventCollectionRequest",
"LookupTickersResponse",
"MaintenanceWindow",
Expand Down Expand Up @@ -376,7 +371,6 @@
"TimeInForceLiteral",
"TotalRestingOrderValue",
"Trade",
"UnlockSubaccountForSettlementAdvanceRequest",
"UpdateOrderGroupLimitRequest",
"UpdateSubaccountNettingRequest",
"UserDataTimestamp",
Expand All @@ -385,4 +379,4 @@
"Withdrawal",
]

__version__ = "7.4.0"
__version__ = "8.0.0"
18 changes: 1 addition & 17 deletions kalshi/_contract_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,10 +160,7 @@ class ContractEntry:
ContractEntry(
sdk_model="kalshi.models.subaccounts.SubaccountBalance",
spec_schema="SubaccountBalance",
notes=(
"balance + settlement_advance use DollarDecimal; updated_ts is Unix int; "
"settlement_advance_state is UUID | None"
),
notes="balance uses DollarDecimal; updated_ts is Unix int",
),
ContractEntry(
sdk_model="kalshi.models.subaccounts.SubaccountTransfer",
Expand All @@ -185,19 +182,6 @@ class ContractEntry:
sdk_model="kalshi.models.subaccounts.ApplySubaccountPositionTransferResponse",
spec_schema="ApplySubaccountPositionTransferResponse",
),
ContractEntry(
sdk_model="kalshi.models.subaccounts.LockSubaccountForSettlementAdvanceRequest",
spec_schema="LockSubaccountForSettlementAdvanceRequest",
),
ContractEntry(
sdk_model="kalshi.models.subaccounts.LockSubaccountForSettlementAdvanceResponse",
spec_schema="LockSubaccountForSettlementAdvanceResponse",
notes="settlement_advance_state is UUID",
),
ContractEntry(
sdk_model="kalshi.models.subaccounts.UnlockSubaccountForSettlementAdvanceRequest",
spec_schema="UnlockSubaccountForSettlementAdvanceRequest",
),
ContractEntry(
sdk_model="kalshi.models.subaccounts.CreateSubaccountRequest",
spec_schema="CreateSubaccountRequest",
Expand Down
6 changes: 0 additions & 6 deletions kalshi/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,12 +172,9 @@
CreateSubaccountResponse,
GetSubaccountBalancesResponse,
GetSubaccountNettingResponse,
LockSubaccountForSettlementAdvanceRequest,
LockSubaccountForSettlementAdvanceResponse,
SubaccountBalance,
SubaccountNettingConfig,
SubaccountTransfer,
UnlockSubaccountForSettlementAdvanceRequest,
UpdateSubaccountNettingRequest,
)

Expand Down Expand Up @@ -269,8 +266,6 @@
"IncentiveProgramTypeLiteral",
"IndexedBalance",
"LiveData",
"LockSubaccountForSettlementAdvanceRequest",
"LockSubaccountForSettlementAdvanceResponse",
"LookupTickersForMarketInMultivariateEventCollectionRequest",
"LookupTickersResponse",
"MaintenanceWindow",
Expand Down Expand Up @@ -323,7 +318,6 @@
"TimeInForceLiteral",
"TotalRestingOrderValue",
"Trade",
"UnlockSubaccountForSettlementAdvanceRequest",
"UpdateOrderGroupLimitRequest",
"UpdateSubaccountNettingRequest",
"UserDataTimestamp",
Expand Down
49 changes: 0 additions & 49 deletions kalshi/models/subaccounts.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,22 +105,13 @@ class SubaccountBalance(BaseModel):
``format: date-time`` and surface as ``datetime``; subaccount
timestamps follow the spec's int wire format. Callers wanting a
``datetime`` can ``datetime.fromtimestamp(obj.updated_ts, tz=timezone.utc)``.

Spec content under OpenAPI 3.26.0 (2026-07-25) added settlement-advance
fields: ``voluntarily_locked`` / ``settlement_advance`` (required) and
optional ``settlement_advance_state`` (CAS token from
:meth:`~kalshi.resources.subaccounts.SubaccountsResource.lock_settlement_advance`).
"""

subaccount_number: int
# Spec v3.22.0: exchange shard the balance is held on (required).
exchange_index: int
balance: DollarDecimal
updated_ts: int
# Settlement-advance surface (OpenAPI 3.26.0 content, 2026-07-25).
voluntarily_locked: bool
settlement_advance: DollarDecimal
settlement_advance_state: UUID | None = None

model_config = {"extra": "allow"}

Expand All @@ -133,46 +124,6 @@ class GetSubaccountBalancesResponse(BaseModel):
model_config = {"extra": "allow"}


class LockSubaccountForSettlementAdvanceRequest(BaseModel):
"""Body for PUT /portfolio/subaccounts/settlement-advance-lock.

Locks a subaccount for settlement-advance computation (cancels resting
orders and prevents trading). ``subaccount_number`` uses ``0`` for the
primary account; ``exchange_index`` defaults to ``0`` when omitted.
"""

subaccount_number: StrictInt = Field(ge=0)
exchange_index: StrictInt | None = Field(default=None, ge=0)

model_config = {"extra": "forbid"}


class LockSubaccountForSettlementAdvanceResponse(BaseModel):
"""Response from PUT /portfolio/subaccounts/settlement-advance-lock.

``settlement_advance_state`` is the new compare-and-swap token for
subsequent settlement-advance requests.
"""

settlement_advance_state: UUID

model_config = {"extra": "allow"}


class UnlockSubaccountForSettlementAdvanceRequest(BaseModel):
"""Body for DELETE /portfolio/subaccounts/settlement-advance-lock.

Unlock is rejected while the subaccount has an outstanding settlement
advance. Same ``subaccount_number`` / ``exchange_index`` semantics as
:class:`LockSubaccountForSettlementAdvanceRequest`.
"""

subaccount_number: StrictInt = Field(ge=0)
exchange_index: StrictInt | None = Field(default=None, ge=0)

model_config = {"extra": "forbid"}


class SubaccountTransfer(BaseModel):
"""A past **cash** transfer between subaccounts.

Expand Down
Loading
Loading