Skip to content

Releases: TexasCoding/kalshi-python-sdk

v7.0.0

Choose a tag to compare

@github-actions github-actions released this 10 Jul 14:35
5d476db

Syncs the upstream OpenAPI/AsyncAPI specs 3.23.0 → 3.24.0 (Closes #467, #470).
One breaking rename on the subaccounts surface, a soft-deprecation, three new
endpoints, and additive drift fixes. Kalshi changed spec content without always
bumping info.version, so this also absorbs in-place edits made under the same string.

Changed (breaking)

  • Position-transfer price is now fixed-point dollars, not integer cents. The
    price_cents field/kwarg (integer cents, 0-100) on
    ApplySubaccountPositionTransferRequest, SubaccountTransfer, and
    subaccounts.transfer_position() (sync + async) is renamed price and
    typed OrderPrice / DollarDecimal (fixed-point dollars, Decimal). Pass
    price=Decimal("0.50") where you previously passed price_cents=50. The old
    client-side cap (le=100 cents) is gone — OrderPrice guards only
    non-negativity and the $0.0001 tick, leaving the upper bound to the server
    (matches CreateOrderRequest). Upstream renamed the wire field price_cents
    price (FixedPointDollars) in 3.24.0.

Deprecated

  • exchange.announcements() (sync + async) now emits a DeprecationWarning.
    Kalshi removed GET /exchange/announcements and the Announcement schema from
    the spec in 3.24.0, so the live endpoint 404s. The method and the Announcement
    model are retained (soft-deprecated) pending confirmation the removal is
    permanent — upstream has transiently dropped endpoints as publishing glitches
    before (see #452). A future major release removes them once confirmed.

Added

  • communications.quotes.get_for_rfq(rfq_id, quote_id) (sync + async) —
    GET /communications/rfqs/{rfq_id}/quotes/{quote_id}, the RFQ-scoped
    get-a-quote (returns GetQuoteResponse, the same payload as the flat
    quotes.get).
  • klear.margin.active_obligations() (sync + async) —
    GET /margin/active_obligations, all currently-active settlement obligations
    (GetActiveMarginObligationsResponse; the plural sibling of the single-obligation
    active_obligation()).
  • klear.margin.settlement_estimate_by_asset_class() (sync + async) —
    GET /margin/settlement_estimate_by_asset_class, next-settlement estimates keyed
    by asset class (GetSettlementEstimateByAssetClassResponse +
    AssetClassSettlementEstimate).
  • SubaccountNettingConfig.exchange_index (int, required) — exchange index
    of the subaccount.
  • portfolio.balance() (sync + async) gains an optional exchange_index
    query param — target a specific exchange shard (defaults to 0 server-side).
  • ObligationEntry.asset_class (perps SCM / Klear; AssetClassLiteral =
    Literal["Crypto"], required) — asset class of the settlement obligation.

v6.0.0

Choose a tag to compare

@github-actions github-actions released this 04 Jul 15:18
88a849f

Syncs the upstream OpenAPI/AsyncAPI specs 3.22.0 → 3.23.0 (#463). The
headline change is breaking: Kalshi removed the multivariate lookup-history
endpoint from the spec, so the SDK removes the corresponding method and model.
Every other change is additive and backward-compatible.

Removed (breaking)

  • lookup_history() on client.multivariate_collections (sync + async) and
    the LookupPoint model (no longer exported from kalshi /
    kalshi.models). Upstream removed the backing GET /multivariate_event_collections/{collection_ticker}/lookup operation
    (GetMultivariateEventCollectionLookupHistory) and the LookupPoint schema in
    3.23.0 — the endpoint now 404s. The lookup_tickers() sibling (the PUT on the
    same path) is unaffected.

Added

  • ApiKey.subaccount, CreateApiKeyRequest.subaccount,
    GenerateApiKeyRequest.subaccount (int | None) — when set, restricts the
    API key to a single subaccount. api_keys.create() / generate() (sync +
    async) accept a subaccount kwarg that threads into the body. The request
    models bound it to the spec's 0-63 range (ge=0, le=63) client-side; the
    response model stays permissive.
  • ApplySubaccountTransferRequest.exchange_index (int | None) — exchange
    shard to apply the transfer on (spec ExchangeIndex; defaults to 0).
  • SubaccountTransfer additive fields: exchange_index and transfer_type
    ("cash"/"position", both required), plus the position-transfer-only
    market_ticker / side ("yes"/"no") / count / price_cents.
  • MarginPosition.is_portfolio and MarginRiskPosition.is_portfolio
    (bool, required) — true when the position is hedged within a portfolio.
  • MarginOrder.order_reason ("liquidation"/"take_profit_stop_loss",
    optional) — reason for a system-generated order.
  • MarketLifecyclePayload.price_ranges (WS market_lifecycle_v2) — valid
    price bands emitted alongside price_level_structure.
  • subaccounts.transfer_position(...) (sync + async) — new
    POST /portfolio/subaccounts/positions/transfer endpoint (spec 3.23.0): moves
    an open position (contracts) between subaccounts, distinct from the
    cash-only transfer(). Returns ApplySubaccountPositionTransferResponse
    (position_transfer_id). New models ApplySubaccountPositionTransferRequest /
    ApplySubaccountPositionTransferResponse are exported from kalshi /
    kalshi.models.
  • subaccounts.create(exchange_index=...)POST /portfolio/subaccounts
    gained an optional CreateSubaccountRequest body (spec 3.23.0); create()
    now accepts an optional exchange_index to target a specific exchange shard.
    New CreateSubaccountRequest model exported from kalshi / kalshi.models.

Fixed

  • Defensive optional-ization of fields 3.23.0 removed/relaxed. The drift
    suite is spec→SDK only, so a field the spec drops but the SDK still requires
    is a latent ValidationError if the server stops emitting it. Three such
    fields are now ... | None = None:
    • Market.fractional_trading_enabled (removed from spec),
    • MarketPosition.resting_orders_count (removed from spec),
    • MarginPosition.margin_used (relaxed from required to optional).

v5.0.1

Choose a tag to compare

@github-actions github-actions released this 27 Jun 15:36
16442c2

Spec-drift catch-up (#460). Kalshi added fields to the ExchangeStatus schema
in place — without bumping the OpenAPI version (still 3.22.0) — so the
nightly strict contract suite flagged additive drift the day after the 5.0.0
sync. All changes are additive and backward-compatible.

Fixed

  • ExchangeStatus additive drift. Added two optional fields that upstream
    introduced on GET /exchange/status:
    • intra_exchange_transfers_active: bool | None — whether intra-exchange
      transfers are currently permitted (omitted by older servers, hence optional).
    • exchange_index_statuses: list[ExchangeIndexStatus] — per-index (shard)
      status breakdown; defaults to [] when absent or null.

Added

  • ExchangeIndexStatus model (exported from kalshi and kalshi.models):
    per-exchange-index operational status with exchange_index, exchange_active,
    trading_active, and intra_exchange_transfers_active.

v5.0.0

Choose a tag to compare

@github-actions github-actions released this 26 Jun 18:36
a1c6bd0

Syncs the upstream OpenAPI spec 3.21.0 → 3.22.0 (#454, #458). The headline
change is breaking: Kalshi removed the V1 order-write endpoints from the
spec, so the SDK removes the V1 order methods and their models. Order writes now
go exclusively through the V2 /portfolio/events/orders family (the *_v2
methods, which have existed since 3.18.0). See docs/migration.md for the
V1 → V2 mapping.

Removed (breaking)

  • V1 order-write methods on client.orders (sync + async): create,
    cancel, batch_create, batch_cancel, amend, decrease. The underlying
    endpoints (POST/DELETE /portfolio/orders, /portfolio/orders/batched,
    /portfolio/orders/{id}/amend, /portfolio/orders/{id}/decrease) were
    removed from the spec in 3.22.0. Use the *_v2 equivalents instead.
  • V1 order models (no longer exported from kalshi / kalshi.models):
    CreateOrderRequest, AmendOrderRequest, AmendOrderResponse,
    DecreaseOrderRequest, BatchCreateOrdersRequest, BatchCreateOrdersResponse,
    BatchCreateOrdersResponseEntry, BatchCancelOrdersRequest,
    BatchCancelOrdersResponse, BatchCancelOrdersResponseEntry,
    BatchCancelOrdersRequestOrder, and the ActionLiteral (buy/sell) alias.
  • Dead quote filtersevent_ticker and market_ticker were removed from
    GET /communications/quotes upstream, so they are removed from
    client.communications.quotes.list / list_all and the
    communications.list_quotes / list_all_quotes facade methods.

Added

  • RFQ-scoped quote actions (spec 3.22.0) on client.communications.quotes
    (sync + async): accept_for_rfq(rfq_id, quote_id, ...),
    confirm_for_rfq(rfq_id, quote_id), delete_for_rfq(rfq_id, quote_id)
    backing PUT/DELETE /communications/rfqs/{rfq_id}/quotes/{quote_id}[/accept|/confirm].
  • cancel_v2 market_ticker query param — required when exchange_index
    is -1 (auto-route by ticker).
  • BatchCancelOrdersV2RequestOrder.market_ticker — same auto-route semantics
    for batch V2 cancels.
  • SubaccountBalance.exchange_index — the exchange shard a balance is held on.
  • Perps SCM (kalshi.perps.klear): new MarketSettlementEstimate model;
    SettlementEstimate.positions (per-market breakdown map); and
    GetSettlementEstimateResponse.prev_settlement_prices (market → last
    settlement price, centicents).

v4.2.0

Choose a tag to compare

@github-actions github-actions released this 19 Jun 21:59
6cef1d0

Reconciles in-place upstream spec drift detected by the nightly run (#451):
the live OpenAPI/AsyncAPI specs gained fields after 4.1.0 vendored them, under
the same 3.21.0 version string. All changes are additive — new response
fields on existing models. Also widens the cryptography dependency ceiling.

Added

  • Event.settlement_sources — the official settlement sources for an event
    (EventData.settlement_sources, openapi 3.21.0). Typed
    NullableList[SettlementSource], so a JSON null coerces to [] while the
    key-present contract holds (same nullable shape as Series.settlement_sources).
    Note: spec-required, so code that constructs Event directly (e.g. test
    mocks) must now include it.
  • WS MarketLifecyclePayload strike fieldsstrike_type, cap_strike,
    and custom_strike on market_lifecycle_v2 payloads (asyncapi). All optional;
    present only on metadata_updated frames. strike_type (between / greater
    / less) controls how floor_strike / cap_strike are interpreted;
    custom_strike carries structured strikes.

Changed

  • cryptography dependency ceiling widened <49<50 (#448) — permits
    cryptography 49.x. The SDK's RSA-PSS signing path uses only hashes /
    serialization / padding / rsa, none of which 49.0.0's removals affect.
  • Re-vendored specs/openapi.yaml (added EventData.settlement_sources) and
    specs/asyncapi.yaml (added the lifecycle strike fields; refreshed WS
    error-code docs). openapi.yaml was held at its known-good 104-operation
    state: the upstream publish transiently dropped CreateOrder /
    BatchCreateOrders / AmendOrder, an upstream glitch that was not imported.

v4.1.0

Choose a tag to compare

@github-actions github-actions released this 15 Jun 10:13
74abbf8

Spec sync from upstream OpenAPI v3.20.0 → v3.21.0 (plus AsyncAPI/perps). All
changes are additive — new query params, response fields, and four new
endpoints. Also closes the nightly spec-drift CI gap (failures now open a
tracking issue).

Added

  • client.communications.block_trade_proposals — new sub-resource for the
    block-trade-proposals API (openapi 3.21.0): list() / list_all()
    (GET /communications/block-trade-proposals), create()
    (POST /communications/block-trade-proposals), and accept()
    (POST /communications/block-trade-proposals/{id}/accept). New models
    BlockTradeProposal / GetBlockTradeProposalsResponse /
    ProposeBlockTradeRequest / ProposeBlockTradeResponse /
    AcceptBlockTradeProposalRequest (exported from kalshi).
  • AccountResource.volume_progress()GET /account/api_usage_level/volume_progress
    returns trailing-30-day trading-volume progress toward volume-based API usage
    tiers. New models AccountVolumeProgress / AccountApiUsageLevelVolumeProgress
    / AccountApiUsageLevelVolumeGoal.
  • events.list / list_all gain a tickers filter — comma-separated event
    tickers (GET /events?tickers=...).
  • communications quotes endpoints gain min_ts / max_ts — filter quotes
    by last-updated Unix timestamp on quotes.list / list_all (and the
    deprecated list_quotes / list_all_quotes forwarders).
  • Perps MarginMarket mark-price fieldssettlement_mark_price,
    liquidation_mark_price, and reference_price (each a nested TickerPrice
    of {price, ts_ms}); MarginPosition.subaccount (the holding subaccount
    number); and WS ErrorPayload.market_tickers (multi-market error frames).
    Note: MarginPosition.subaccount is spec-required, so code that constructs
    MarginPosition directly (e.g. test mocks) must now include it.

Changed

  • Re-vendored specs/openapi.yaml (3.20.0 → 3.21.0), specs/asyncapi.yaml,
    specs/perps_openapi.yaml, and specs/perps_scm_openapi.yaml.
  • Upstream narrowed the Settlement.market_result enumvoid was removed
    (now yes / no / scalar). No SDK change: Settlement.market_result is a
    plain str with extra="allow", so any value still parses; noted here for
    accuracy.
  • Nightly spec-drift CI now files a tracking issue on failure. The scheduled
    Spec Drift Detection run previously failed silently between the weekly
    Weekly Spec Sync runs; it now opens (and dedups) a single spec-drift issue
    so upstream drift is tracked the day it appears.

Fixed

  • Hardened the TestWsSpecDrift contract-test fixture (the class-scoped fixture
    is now a @staticmethod) so the strict nightly run reports real WebSocket
    drift instead of erroring the whole class under -W error::UserWarning.

v4.0.0

Choose a tag to compare

@github-actions github-actions released this 10 Jun 01:07
fad01c0

Spec-drift reconciliation against the latest upstream OpenAPI (3.20.0) and AsyncAPI
specs (closes #443). Includes one breaking change: the Self-Clearing-Member
"Klear" API migrated from cookie-session login to Bearer-token auth. Everything
else is additive.

Breaking

  • Klear (SCM) auth is now a Bearer token. Upstream removed POST /log_in and
    switched the Klear API to Authorization: Bearer <admin_user_id>:<access_token>.
    KlearClient / AsyncKlearClient now require admin_user_id and access_token
    at construction (or via from_env(), which reads KALSHI_KLEAR_ADMIN_USER_ID /
    KALSHI_KLEAR_ACCESS_TOKEN). Removed: the login() method, the
    is_authenticated property, the client.auth resource, and the LogInRequest /
    LogInResponse models. KlearAuth is now a Bearer-credential holder
    (KlearAuth(admin_user_id, access_token)). Generate a token at
    https://klearing.kalshi.com (the "Security" page).

Added

  • cfbenchmarks_value WebSocket channel — stream CF Benchmarks reference index
    values (e.g. BRTI) with trailing 60-second and final-minute quarter-hour
    averages via KalshiWebSocket.subscribe_cfbenchmarks_value(index_ids=[...]). New
    models CFBenchmarksValueMessage / CFBenchmarksValuePayload /
    CFBenchmarksAvgData / CFBenchmarksIndexListMessage /
    CFBenchmarksIndexListPayload (exported from kalshi.ws.models).
  • AccountResource.upgrade()POST /account/api_usage_level/upgrade to
    request a permanent Advanced API usage-level grant.
  • AccountApiLimits.grants — the per-exchange-lane usage-level grant list, plus
    a new ApiUsageLevelGrant model (exchange_instance / level / source /
    expires_ts), exported from kalshi.
  • MarginAccountResource.api_limits()GET /account/limits/perps for the
    Perps API tier limits (reuses AccountApiLimits).
  • Perps market notional/leverage fieldsMarginMarket gains
    leverage_estimates and volume/volume_24h/open_interest notional-value
    fields; MarginMarketCandlestick and the ticker WS payload gain notional-value
    fields, all tracking the spec.

Changed

  • Re-vendored specs/openapi.yaml, specs/asyncapi.yaml, specs/perps_openapi.yaml,
    specs/perps_asyncapi.yaml, and specs/perps_scm_openapi.yaml; the subaccount
    range documented in prose is now 1–63 (no validation change).

v3.3.0

Choose a tag to compare

@github-actions github-actions released this 06 Jun 16:06
bff73a1

Adds a complete FIX protocol subsystem (FIXT.1.1 / FIX50SP2) for both the
prediction and perps products. Additive release: no changes to the existing REST,
WebSocket, or Perps surfaces.

Added

  • FIX engine (kalshi.fix) — a hand-rolled, async-first FIX client for both
    products: FixClient (prediction) and MarginFixClient (margin, in
    kalshi.perps.fix), re-exported from the top-level kalshi package alongside
    FixConfig, FixEnvironment, and FixSessionType. Covers five session types —
    order entry (NR/RT), drop copy, market data, post-trade settlement (prediction),
    and RFQ (prediction), plus order-group management over the order-entry session —
    on a session state machine with
    RSA-PSS logon (reusing the REST key), heartbeat / test-request liveness,
    sequence tracking with gap-fill / resend on the retransmission sessions, and
    AWS-style full-jitter reconnect. (Epic #402.)
  • Typed FIX messages — Pydantic v2 models for every Kalshi FIX message across
    order entry, order groups, market data, RFQ/quoting, drop copy, and market
    settlement, with DollarDecimal / FixedPointCount money types (no float
    drift) and a central inbound dispatch via decode_app_message.
  • FixOrderBook — aggregated order-book reconstruction from market-data
    snapshots + incrementals; SettlementReassembler — paginated
    settlement-report reassembly.
  • FixSession.on_decode_error hook + decode_app_message_strict — surface a
    registered-but-malformed inbound message instead of silently dropping it (#432).
  • FIX documentation — new docs/fix.md guide, plus FIX coverage in the
    README, errors, authentication, configuration, environment-variables, and the
    API reference.
  • FIX dictionary drift testspecs/kalshi-fix-dictionary.xml checked in
    with a model↔dictionary drift test, the FIX analogue of the REST contract-drift
    suite (#437).

Fixed

  • Documentation accuracy pass: fcm.positions_all() is now documented (the FCM
    page previously stated it did not exist); the portfolio reads document their
    subaccount parameter; the markets.is_block_trade version note is corrected
    to SDK v3.1.0; the OrderPrice and MultiplierDecimal types are documented;
    and the docs landing page's WebSocket channel count is corrected to 11.

v3.2.0

Choose a tag to compare

@github-actions github-actions released this 05 Jun 19:25
eed032d

Adds full SDK support for the Kalshi Perps (margin) API — a separate
perpetual-futures exchange — as standalone clients alongside the existing
prediction-API surface. Additive release: no changes to KalshiClient.

Added

  • PerpsClient / AsyncPerpsClient — standalone clients for the perps
    exchange (external-api.kalshi.com / demo external-api.demo.kalshi.co,
    /trade-api/v2), with their own PerpsConfig and a separate KALSHI_PERPS_*
    credential namespace. They reuse the prediction-API RSA-PSS signer and HTTP
    transport unchanged. The constructors and from_env() also accept
    ws_base_url (set the WS endpoint independently from REST) and password
    (passphrase for an encrypted key), and read KALSHI_PERPS_WS_BASE_URL /
    KALSHI_PERPS_PRIVATE_KEY_PASSPHRASE from the environment; passing config=
    together with demo/base_url/ws_base_url is rejected. Resource families:
    exchange (status / enabled gate /
    risk parameters), markets (list / get / orderbook / candlesticks), orders
    (create / get / list / cancel / decrease / amend + FCM), order_groups,
    portfolio (positions / fills / trades), margin (balance / risk /
    notional risk limit / fee tiers), funding (rate estimate / historical /
    history), and transfers (intra-exchange-instance + margin subaccounts).
    Margin order side is bid / ask; prices are DollarDecimal
    (FixedPointDollars), counts FixedPointCount, and number/double ratios
    (leverage, funding rate, ROE, fee tiers) are MultiplierDecimal (exact
    Decimal, string-serialized) — consistent across the REST, WS, and exchange
    surfaces. Margin-account list responses tolerate a server-returned null.
  • PerpsWebSocket — the perps margin WebSocket
    (external-api-margin-ws.kalshi.com, /trade-api/ws/v2/margin) with six typed
    channels (subscribe_orderbook_delta, subscribe_ticker — carrying
    funding_rate + next_funding_time_ms, subscribe_trade, subscribe_fill,
    subscribe_user_orders, subscribe_order_group). Reuses the event-contract
    WS connection / sequence-gap / backpressure machinery; perps WS timestamps are
    Unix epoch milliseconds (*_ms fields).
  • KlearClient / AsyncKlearClient — the Self-Clearing-Member "Klear"
    settlement API (api.klear.kalshi.com / demo demo-api.kalshi.co,
    /klear-api/v1) with a third auth model: cookie-session + MFA via
    login(email=..., password=..., code=...). Resource margin covers reports,
    active/historical obligations, settlement estimate, settlement + guaranty-fund
    balances, settlement-balance history, and settlement-balance withdrawal.
    Klear money fields are integer centicents; the single real-money write
    (withdraw_settlement_balance) validates a positive amount at construction.
    Credentials and the session cookie are never logged or shown in repr().
  • docs/perps.md (+ mkdocs nav), README "Perps (margin) trading" section, and
    runnable examples/perps_create_order.py / perps_stream_ticker.py /
    perps_balance_risk.py.

Changed

  • Prediction-API list endpoints markets.candlesticks / bulk_candlesticks /
    bulk_orderbooks now validate a typed response envelope: a missing
    spec-required array key raises ValidationError (surfacing spec drift instead
    of silently returning []), while a null array coerces to [] (Kalshi's
    empty-as-null convention — the prior data.get(...) extraction would
    TypeError on a null array). The perps markets.list / markets.candlesticks
    / funding.historical_rates / funding.history responses use the same
    NullableList envelopes, so null-handling is consistent across both surfaces.
    The optional order_groups.list stays tolerant of a missing/null array.

Fixed

  • KalshiWebSocket._stop() now retrieves an already-finished receive-loop's
    exception, so a session torn down after a permanent close no longer logs
    asyncio's "Task exception was never retrieved" on garbage collection.

Internal

  • Vendored the three perps specs (specs/perps_openapi.yaml,
    perps_asyncapi.yaml, perps_scm_openapi.yaml); scripts/sync_spec.py and the
    weekly spec-sync workflow now fetch/diff/checksum them and fold their sha256
    into the drift fingerprint (preserving the contents: read + issues: write
    security model).
  • Parameterized the contract-drift harness per spec: TestPerps*Drift /
    TestPerpsScm*Drift validate the perps REST + SCM surfaces against their own
    specs, alongside the existing prediction-API drift suites.
  • README / docs/index.md banners note the perps surface (34 REST operations,
    6 WS channels, 10 SCM operations).

v3.1.0

Choose a tag to compare

@github-actions github-actions released this 04 Jun 00:49
cd9ae6f

OpenAPI + AsyncAPI spec sync from v3.19.0 → v3.20.0 (#385). Adds the
new GET /events/fee_changes endpoint plus three smaller additive
changes upstream re-published into 3.20.0 after the drift issue was
filed (the OpenAPI checksum in #385 is therefore stale; the AsyncAPI
checksum still matches).

Added

  • events.fee_changes() / fee_changes_all() (sync + async) for
    GET /events/fee_changes — the new paginated event-level fee-override
    feed (event_ticker, limit, cursor). Returns Page[EventFeeChange]
    (and an auto-paginating iterator). EventFeeChange exposes
    fee_type_override / fee_multiplier_override, both present-but-None
    when an override is cleared.
  • is_block_trade query param on markets.list_trades /
    list_all_trades (+ deprecated list_trades_all) and
    historical.trades / trades_all. Omit for all trades, True for
    only block trades, False for only non-block.
  • Trade.is_block_trade (bool) — new spec-required, non-nullable
    response field; a missing key raises so a schema regression surfaces.
  • WebSocket event_fee_update message on the existing
    market_lifecycle_v2 channel (EventFeeUpdateMessage /
    EventFeeUpdatePayload). subscribe_market_lifecycle() now yields
    MarketLifecycleMessage | EventFeeUpdateMessage. Channel count is
    unchanged (still 11) — this is a second message type on an existing
    channel. Behavioral note for existing subscribers: discriminate on
    .type before reading payload fields — an EventFeeUpdatePayload has no
    market_ticker, so naive access raises AttributeError. See the
    migration callout in docs/websockets.md.

Internal

  • specs/openapi.yaml (sha256
    b72a2aa138695d810f6ca85096bfe19e1b66ba5e9b2ed37753be284b5288d271)
    and specs/asyncapi.yaml (sha256
    2f72d0a3fd25fe331210ed300f03ad4c1fedcb561b3ab425046b2dca6f4683ec)
    snapshots bumped; kalshi/_generated/models.py regenerated.
  • Spec also relaxed CreateOrderV2Request.client_order_id and
    EventData.product_metadata from required to optional, and added
    ApiKeyScope / FeeType enums. No SDK-facade change: the V2 order
    keeps client_order_id required by design, Event.product_metadata
    already tolerated server omission, and API-key scopes stays str
    for forward-compat.
  • README + docs/index.md banners bumped to "99 operations … OpenAPI
    v3.20.0".