Skip to content

perps: [EPIC] Perps (margin) API — full SDK implementation tracker #387

Closed

Description

@TexasCoding

Perps (margin) API — full SDK implementation

Implements the Kalshi Perps API (perpetual futures / margin) in the SDK, mirroring the conventions of the existing prediction (event-contract) API. Source docs: https://docs.kalshi.com/margin

Surface (3 separate specs + FIX)

Spec Vendored to Host Auth Ops
perps_openapi.yaml (REST) specs/perps_openapi.yaml external-api.kalshi.com/trade-api/v2 (demo external-api.demo.kalshi.co) RSA-PSS (same signer) 34
perps_asyncapi.yaml (WS) specs/perps_asyncapi.yaml external-api-margin-ws.kalshi.com/trade-api/ws/v2/margin RSA-PSS apiKey 6 channels
perps_scm_openapi.yaml (Self-Clearing-Member "Klear") specs/perps_scm_openapi.yaml api.klear.kalshi.com/klear-api/v1 (demo demo-api.kalshi.co/klear-api/v1) session cookie + MFA (POST /log_in) 9
FIX — margin-fix-api.fix.elections.kalshi.com etc. FIX session deferred

Locked architecture decisions

  • Standalone PerpsClient / AsyncPerpsClient (not a namespace on KalshiClient). Own base URL, own PerpsConfig, separate env-var credentials. Reuse KalshiAuth (RSA-PSS) + SyncTransport/AsyncTransport + retry/error machinery unchanged. (Rationale: different host + Kalshi recommends separate API keys; KalshiConfig hard-fails on hosts outside its known set.)
  • New package layout kalshi/perps/{client,async_client}.py, kalshi/perps/models/<area>.py, kalshi/perps/resources/<area>.py, kalshi/perps/ws/… — mirroring the top-level layout. Exports flow kalshi/perps/__init__.py → kalshi/__init__.py.
  • Reuse DollarDecimal + FixedPointCount from kalshi/types.py: perps FixedPointDollars (string, ≤6 dp) and FixedPointCount (string "fp", 2 dp) have identical semantics. Prices/counts use them with validation_alias=AliasChoices(...) for API↔Python name mapping.
  • Timestamps: REST = RFC3339 date-time; WebSocket = Unix epoch milliseconds with _ms suffix (ts_ms, created_ts_ms) — a real parsing difference from the event-contract WS.
  • Request bodies = Pydantic models with model_config = {"extra": "forbid"}, serialized via model_dump(exclude_none=True, by_alias=True, mode="json"); serialization_alias for wire mismatches. POST/PUT/DELETE never retried.
  • Contract tests parameterized per-spec: perps REST validates against specs/perps_openapi.yaml, SCM against specs/perps_scm_openapi.yaml. Weekly spec-sync extended to fetch all three perps specs.

Shared-primitive ownership (avoid duplicate Pydantic defs)

The shared enums/value-objects — BookSide, SelfTradePreventionType, LastUpdateReason, OrderSource, MarginMarketStatus, ExchangeIndex, ExchangeInstance, PriceLevelDollarsCountFp, EmptyResponse, ErrorResponse — are defined once by the foundation issue in kalshi/perps/models/common.py. All resource issues import them and must not redefine. (Note: perps order side is bid/ask, not the prediction API's yes/no.)

Dependency graph

graph TD
  F[#388 foundation] --> EX[#389 exchange]
  F --> MK[#390 markets]
  F --> OR[#391 orders]
  F --> OG[#392 order groups]
  F --> PF[#393 positions/fills/trades]
  F --> BR[#394 balance/risk/fees]
  F --> FN[#395 funding]
  F --> TR[#396 transfers/subaccounts]
  F --> WF[#397 ws foundation]
  WF --> WC[#398 ws channels]
  F --> SA[#399 scm auth]
  SA --> SE[#400 scm endpoints]
  EX --> DOC[#401 docs/release]
  MK --> DOC
  OR --> DOC
  OG --> DOC
  PF --> DOC
  BR --> DOC
  FN --> DOC
  TR --> DOC
  WC --> DOC
  SE --> DOC
Loading

Implementation checklist

Foundation (do first)

REST resources (depend on #388, parallelizable)

WebSocket (after REST foundation)

SCM / Klear (new session+MFA auth)

Closeout

Out of scope (this milestone)

  • FIX API → tracked separately in perps: [EPIC] FIX API support (prediction + perps) — future #402 (covers both prediction and perps FIX gateways; large, orthogonal effort).
  • Perps WS channels unavailable upstream (market_positions, market_lifecycle_v2, multivariate*, communications) — documented, not implemented.
  • Batch order ops, RFQs/quotes, events/series/milestones on the margin exchange (not offered by the perps API).

Activity

  1. added this to the Perps API milestone on Jun 4, 2026
  2. added
    enhancementNew feature or request
    perpsPerps / margin (perpetual futures) API
    on Jun 4, 2026
  3. added 2 commits that reference this issue on Jun 5, 2026
  4. TexasCoding commented on Jun 5, 2026

    @TexasCoding
    OwnerAuthor

    ✅ Complete — shipped in v3.2.0 (published to PyPI + GitHub Release).

    The full Perps (margin) API surface landed across #388–401 and was hardened through the post-review follow-ups:

    • REST: PerpsClient / AsyncPerpsClient + PerpsConfig — exchange, markets, orders, order_groups, portfolio, margin, funding, transfers.
    • WebSocket: PerpsWebSocket with six typed channels (epoch-ms timestamps, sequence-gap + orderbook + backpressure machinery).
    • SCM: KlearClient / AsyncKlearClient — cookie-session + MFA settlement API.

    Post-merge hardening from the multi-LLM review (closed: #404–413, plus #405 by-design): MultiplierDecimal ratio fields, NullableList null-tolerance, typed list-response envelopes (perps + prediction), config/auth hardening (ws_base_url/password kwargs, host-allowlist split), Klear strict date validation, order-size guards, and WebSocket correctness fixes (stale-sid gate, _stop exception retrieval, error-ack raising, reconnect persistence). Docs + CHANGELOG finalized in #421.

    Closing as done. #402 remains for future API work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestperpsPerps / margin (perpetual futures) API

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions