diff --git a/.github/workflows/spec-drift.yml b/.github/workflows/spec-drift.yml index 1f81ea1..96db254 100644 --- a/.github/workflows/spec-drift.yml +++ b/.github/workflows/spec-drift.yml @@ -7,6 +7,11 @@ on: - cron: "0 6 * * *" workflow_dispatch: +# Least privilege: the test job only needs read. The failure-reporting job +# below re-grants issues:write at job scope (it opens a tracking issue). +permissions: + contents: read + jobs: drift-check: runs-on: ubuntu-latest @@ -39,3 +44,110 @@ jobs: - name: Run contract tests (PR — warnings only) if: github.event_name != 'schedule' run: uv run pytest tests/test_contracts.py -v + + # When the scheduled strict run fails, open (and dedup) a single tracking + # issue. `needs` + `if: failure()` scopes this to a failed drift-check; the + # extra `github.event_name == 'schedule'` guard keeps it off PR runs (a PR + # failure already blocks the merge — no issue needed). Least privilege: + # issues:write lives only on this job; drift-check stays read-only. Actions + # are pinned to commit SHAs here (not @v6/@v7 tags like drift-check) because + # this job holds issues:write AND runs sync_spec.py against untrusted + # upstream — same threat model as spec-sync.yml (see its header comment). + report-failure: + needs: drift-check + if: failure() && github.event_name == 'schedule' + runs-on: ubuntu-latest + permissions: + contents: read + issues: write + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Install uv + uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 + + - name: Set up Python + run: uv python install 3.12 + + - name: Install dependencies + run: uv sync --dev + + # Re-fetch the same fresh spec drift-check saw, then re-run the strict + # suite to capture the failing tail for the issue body. continue-on-error + # so this step's (expected) failure doesn't abort the report. + - name: Reproduce failure output + id: repro + continue-on-error: true + run: | + set -uo pipefail + uv run python scripts/sync_spec.py || true + uv run pytest tests/test_contracts.py -v -W error::UserWarning \ + > /tmp/drift.log 2>&1 || true + # Keep the last 200 lines so the body stays inside GitHub's limits. + tail -n 200 /tmp/drift.log > /tmp/drift.tail + + - name: Ensure spec-drift label exists + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh label create spec-drift \ + --color 'e4e669' \ + --description 'Upstream OpenAPI/AsyncAPI spec changed since last sync' \ + --force \ + --repo "${GITHUB_REPOSITORY}" + + - name: Open or update nightly drift tracker issue + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + run: | + set -euo pipefail + + # Stable marker (NOT a content fingerprint): exactly one open tracker + # at a time. Re-runs append a dated comment instead of duplicating. + readonly MARKER='nightly-spec-drift-tracker' + today=$(date -u '+%Y-%m-%d') + + existing=$(gh issue list \ + --repo "${GITHUB_REPOSITORY}" \ + --state open \ + --label spec-drift \ + --limit 200 \ + --json number,body \ + --jq '[.[] | select(.body | contains("'"${MARKER}"'"))] | first | .number // empty') + + # Body / comment share the captured failing tail. printf (no unquoted + # heredoc) so upstream-sourced log text is never shell-expanded. + { + printf '## Nightly strict contract tests failed\n\n' + printf 'The scheduled `Spec Drift Detection` run promoted additive drift to an error.\n' + printf 'This means upstream OpenAPI/AsyncAPI changed and the SDK contract suite no longer matches.\n\n' + printf '**To resolve:** locally run `uv run python scripts/sync_spec.py` + `uv run python scripts/generate.py`, reconcile models/maps, and open a PR with `Closes #`.\n\n' + printf -- '- Failing run: %s\n\n' "${RUN_URL}" + printf '### Failing test output (last 200 lines)\n\n```\n' + cat /tmp/drift.tail + printf '\n```\n' + } > /tmp/body.md + + if [ -n "${existing}" ]; then + { + printf 'Still failing as of **%s** ([run](%s)).\n\n' "${today}" "${RUN_URL}" + printf '### Latest failing output (last 200 lines)\n\n```\n' + cat /tmp/drift.tail + printf '\n```\n' + } > /tmp/comment.md + echo "Tracker already open as #${existing}; appending dated comment." + gh issue comment "${existing}" \ + --repo "${GITHUB_REPOSITORY}" \ + --body-file /tmp/comment.md + exit 0 + fi + + # Hidden marker so the dedup query above matches future runs. + printf '\n\n' "${MARKER}" >> /tmp/body.md + + gh issue create \ + --repo "${GITHUB_REPOSITORY}" \ + --label spec-drift \ + --title "Nightly spec-drift: strict contract tests failing (since ${today})" \ + --body-file /tmp/body.md diff --git a/AGENTS.md b/AGENTS.md index 3885886..f41eaee 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,7 +1,7 @@ # GitNexus — Code Intelligence -This project is indexed by GitNexus as **kalshi-python-sdk** (13573 symbols, 29721 relationships, 300 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely. +This project is indexed by GitNexus as **kalshi-python-sdk** (13637 symbols, 29888 relationships, 300 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely. > If any GitNexus tool warns the index is stale, run `npx gitnexus analyze` in terminal first. diff --git a/CHANGELOG.md b/CHANGELOG.md index ffeafd5..4c5cec0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,58 @@ All notable changes to kalshi-sdk will be documented in this file. +## 4.1.0 — 2026-06-14 + +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 fields** — `settlement_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` enum** — `void` 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`. + ## 4.0.0 — 2026-06-09 Spec-drift reconciliation against the latest upstream OpenAPI (3.20.0) and AsyncAPI diff --git a/CLAUDE.md b/CLAUDE.md index 89c4ffe..dea90de 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -122,7 +122,7 @@ tests/ ## API Reference -- OpenAPI spec: https://docs.kalshi.com/openapi.yaml (v3.20.0, 99 operations) +- OpenAPI spec: https://docs.kalshi.com/openapi.yaml (v3.21.0, 104 operations) - 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 @@ -144,7 +144,7 @@ Reference issues from PRs via `Closes #N` so the issue closes on merge. # GitNexus — Code Intelligence -This project is indexed by GitNexus as **kalshi-python-sdk** (13573 symbols, 29721 relationships, 300 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely. +This project is indexed by GitNexus as **kalshi-python-sdk** (13637 symbols, 29888 relationships, 300 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely. > If any GitNexus tool warns the index is stale, run `npx gitnexus analyze` in terminal first. diff --git a/README.md b/README.md index 0f03357..798ae96 100644 --- a/README.md +++ b/README.md @@ -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 (99 operations across 19 resources, OpenAPI v3.20.0) and WebSocket API (12 typed `subscribe_*` channels + 2 escape-hatch). +- **Full coverage** of the Kalshi REST API (104 operations across 19 resources, OpenAPI v3.21.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 (9 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/*`. Legacy `/portfolio/orders` keeps working — deprecated no earlier than May 6, 2026. diff --git a/docs/index.md b/docs/index.md index ed10560..b5f9409 100644 --- a/docs/index.md +++ b/docs/index.md @@ -3,7 +3,7 @@ A professional, spec-first Python SDK for the [Kalshi](https://kalshi.com) prediction markets API. -- **Full REST coverage** — 99 operations across 19 resources (OpenAPI v3.20.0), +- **Full REST coverage** — 104 operations across 19 resources (OpenAPI v3.21.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` diff --git a/kalshi/__init__.py b/kalshi/__init__.py index e300d3a..fa4d955 100644 --- a/kalshi/__init__.py +++ b/kalshi/__init__.py @@ -26,9 +26,13 @@ from kalshi.fix import FixClient, FixConfig, FixEnvironment, FixSessionType from kalshi.models import ( RFQ, + AcceptBlockTradeProposalRequest, AcceptQuoteRequest, AccountApiLimits, + AccountApiUsageLevelVolumeGoal, + AccountApiUsageLevelVolumeProgress, AccountEndpointCosts, + AccountVolumeProgress, ActionLiteral, AmendOrderRequest, AmendOrderResponse, @@ -55,6 +59,7 @@ BatchCreateOrdersV2Response, BatchCreateOrdersV2ResponseEntry, BidAskDistribution, + BlockTradeProposal, BookSideLiteral, CancelOrderV2Response, Candlestick, @@ -90,6 +95,7 @@ GenerateApiKeyRequest, GenerateApiKeyResponse, GetApiKeysResponse, + GetBlockTradeProposalsResponse, GetCommunicationsIDResponse, GetFiltersBySportsResponse, GetGameStatsResponse, @@ -143,6 +149,8 @@ PlayByPlayPeriod, PositionsResponse, PriceDistribution, + ProposeBlockTradeRequest, + ProposeBlockTradeResponse, Quote, QuoteStatusLiteral, RateLimit, @@ -181,8 +189,10 @@ KlearConfig, ) from kalshi.resources.communications import ( + AsyncBlockTradeProposalsResource, AsyncQuotesResource, AsyncRFQsResource, + BlockTradeProposalsResource, QuotesResource, RFQsResource, ) @@ -190,9 +200,13 @@ __all__ = [ "RFQ", + "AcceptBlockTradeProposalRequest", "AcceptQuoteRequest", "AccountApiLimits", + "AccountApiUsageLevelVolumeGoal", + "AccountApiUsageLevelVolumeProgress", "AccountEndpointCosts", + "AccountVolumeProgress", "ActionLiteral", "AmendOrderRequest", "AmendOrderResponse", @@ -203,6 +217,7 @@ "ApiUsageLevelGrant", "ApplySubaccountTransferRequest", "AssociatedEvent", + "AsyncBlockTradeProposalsResource", "AsyncKalshiClient", "AsyncKlearClient", "AsyncPerpsClient", @@ -225,6 +240,8 @@ "BatchCreateOrdersV2Response", "BatchCreateOrdersV2ResponseEntry", "BidAskDistribution", + "BlockTradeProposal", + "BlockTradeProposalsResource", "BookSideLiteral", "CancelOrderV2Response", "Candlestick", @@ -264,6 +281,7 @@ "GenerateApiKeyRequest", "GenerateApiKeyResponse", "GetApiKeysResponse", + "GetBlockTradeProposalsResponse", "GetCommunicationsIDResponse", "GetFiltersBySportsResponse", "GetGameStatsResponse", @@ -344,6 +362,8 @@ "PlayByPlayPeriod", "PositionsResponse", "PriceDistribution", + "ProposeBlockTradeRequest", + "ProposeBlockTradeResponse", "Quote", "QuoteStatusLiteral", "QuotesResource", @@ -377,4 +397,4 @@ "Withdrawal", ] -__version__ = "4.0.0" +__version__ = "4.1.0" diff --git a/kalshi/_contract_map.py b/kalshi/_contract_map.py index 9c93668..38c97f9 100644 --- a/kalshi/_contract_map.py +++ b/kalshi/_contract_map.py @@ -147,6 +147,25 @@ class ContractEntry: sdk_model="kalshi.models.communications.AcceptQuoteRequest", spec_schema="AcceptQuoteRequest", ), + # Block trade proposals (openapi 3.21.0). The response item + the two + # request bodies get response-side drift coverage here, matching Quote/RFQ + # and CreateQuoteRequest/AcceptQuoteRequest. The list wrapper + # (GetBlockTradeProposalsResponse) and create response + # (ProposeBlockTradeResponse) are intentionally omitted, consistent with + # GetQuotesResponse / CreateQuoteResponse not being mapped. + ContractEntry( + sdk_model="kalshi.models.communications.BlockTradeProposal", + spec_schema="BlockTradeProposal", + notes="price_centi_cents/centicount are plain int (centi-cents/centicounts), not _fp.", + ), + ContractEntry( + sdk_model="kalshi.models.communications.ProposeBlockTradeRequest", + spec_schema="ProposeBlockTradeRequest", + ), + ContractEntry( + sdk_model="kalshi.models.communications.AcceptBlockTradeProposalRequest", + spec_schema="AcceptBlockTradeProposalRequest", + ), ContractEntry( sdk_model="kalshi.models.subaccounts.SubaccountBalance", spec_schema="SubaccountBalance", @@ -226,6 +245,28 @@ class ContractEntry: spec_schema="ApiUsageLevelGrant", notes="exchange_instance/level/source required; expires_ts nullable (None = permanent).", ), + ContractEntry( + sdk_model="kalshi.models.account.AccountVolumeProgress", + spec_schema="GetAccountApiUsageLevelVolumeProgressResponse", + notes="Wrapper: volume_progress list of cron-computed snapshots.", + ), + ContractEntry( + sdk_model="kalshi.models.account.AccountApiUsageLevelVolumeProgress", + spec_schema="AccountApiUsageLevelVolumeProgress", + notes=( + "computed_ts/trailing_30d_volume/goals all required. " + "trailing_30d_volume uses the trailing_30d_volume_fp alias " + "(FixedPointCount)." + ), + ), + ContractEntry( + sdk_model="kalshi.models.account.AccountApiUsageLevelVolumeGoal", + spec_schema="AccountApiUsageLevelVolumeGoal", + notes=( + "level/earn_volume_goal/keep_volume_goal all required; the two " + "goal fields use *_fp FixedPointCount aliases." + ), + ), ContractEntry( sdk_model="kalshi.models.structured_targets.StructuredTarget", spec_schema="StructuredTarget", diff --git a/kalshi/models/__init__.py b/kalshi/models/__init__.py index 09aa71b..9370281 100644 --- a/kalshi/models/__init__.py +++ b/kalshi/models/__init__.py @@ -2,7 +2,10 @@ from kalshi.models.account import ( AccountApiLimits, + AccountApiUsageLevelVolumeGoal, + AccountApiUsageLevelVolumeProgress, AccountEndpointCosts, + AccountVolumeProgress, ApiUsageLevelGrant, EndpointTokenCost, RateLimit, @@ -18,17 +21,22 @@ from kalshi.models.common import Page from kalshi.models.communications import ( RFQ, + AcceptBlockTradeProposalRequest, AcceptQuoteRequest, + BlockTradeProposal, CreateQuoteRequest, CreateQuoteResponse, CreateRFQRequest, CreateRFQResponse, + GetBlockTradeProposalsResponse, GetCommunicationsIDResponse, GetQuoteResponse, GetQuotesResponse, GetRFQResponse, GetRFQsResponse, MveSelectedLeg, + ProposeBlockTradeRequest, + ProposeBlockTradeResponse, Quote, QuoteStatusLiteral, RfqStatusLiteral, @@ -181,9 +189,13 @@ __all__ = [ "RFQ", + "AcceptBlockTradeProposalRequest", "AcceptQuoteRequest", "AccountApiLimits", + "AccountApiUsageLevelVolumeGoal", + "AccountApiUsageLevelVolumeProgress", "AccountEndpointCosts", + "AccountVolumeProgress", "ActionLiteral", "AmendOrderRequest", "AmendOrderResponse", @@ -210,6 +222,7 @@ "BatchCreateOrdersV2Response", "BatchCreateOrdersV2ResponseEntry", "BidAskDistribution", + "BlockTradeProposal", "BookSideLiteral", "CancelOrderV2Response", "Candlestick", @@ -245,6 +258,7 @@ "GenerateApiKeyRequest", "GenerateApiKeyResponse", "GetApiKeysResponse", + "GetBlockTradeProposalsResponse", "GetCommunicationsIDResponse", "GetFiltersBySportsResponse", "GetGameStatsResponse", @@ -298,6 +312,8 @@ "PlayByPlayPeriod", "PositionsResponse", "PriceDistribution", + "ProposeBlockTradeRequest", + "ProposeBlockTradeResponse", "Quote", "QuoteStatusLiteral", "RateLimit", diff --git a/kalshi/models/account.py b/kalshi/models/account.py index 54a66e3..a472bf0 100644 --- a/kalshi/models/account.py +++ b/kalshi/models/account.py @@ -2,9 +2,9 @@ from __future__ import annotations -from pydantic import BaseModel +from pydantic import AliasChoices, BaseModel, Field -from kalshi.types import NullableList +from kalshi.types import FixedPointCount, NullableList class RateLimit(BaseModel): @@ -80,3 +80,54 @@ class AccountApiLimits(BaseModel): grants: NullableList[ApiUsageLevelGrant] model_config = {"extra": "allow"} + + +class AccountApiUsageLevelVolumeGoal(BaseModel): + """A single volume goal for one API usage level. + + Spec ``AccountApiUsageLevelVolumeGoal``. ``earn_volume_goal`` is the + trailing-30-day contract volume needed to *earn* this ``level``; + ``keep_volume_goal`` is the (typically lower) volume needed to *keep* a + level already held. Both are fixed-point contract counts. + """ + + level: str + earn_volume_goal: FixedPointCount = Field( + validation_alias=AliasChoices("earn_volume_goal_fp", "earn_volume_goal"), + ) + keep_volume_goal: FixedPointCount = Field( + validation_alias=AliasChoices("keep_volume_goal_fp", "keep_volume_goal"), + ) + + model_config = {"extra": "allow"} + + +class AccountApiUsageLevelVolumeProgress(BaseModel): + """One cron-computed volume-progress snapshot for the predictions lane. + + Spec ``AccountApiUsageLevelVolumeProgress``. ``computed_ts`` is the Unix + timestamp (seconds) at which this snapshot was computed; ``trailing_30d_volume`` + is the trailing-30-day fixed-point contract volume ending at that time. + ``goals`` lists the per-level earn/keep volume thresholds. + """ + + computed_ts: int + trailing_30d_volume: FixedPointCount = Field( + validation_alias=AliasChoices("trailing_30d_volume_fp", "trailing_30d_volume"), + ) + goals: list[AccountApiUsageLevelVolumeGoal] + + model_config = {"extra": "allow"} + + +class AccountVolumeProgress(BaseModel): + """Response from GET /account/api_usage_level/volume_progress. + + Spec ``GetAccountApiUsageLevelVolumeProgressResponse``. Wraps the list of + latest cron-computed volume-progress snapshots toward volume-based API + usage tiers for the predictions (``event_contract``) lane. + """ + + volume_progress: list[AccountApiUsageLevelVolumeProgress] + + model_config = {"extra": "allow"} diff --git a/kalshi/models/communications.py b/kalshi/models/communications.py index 06bb0e1..b714284 100644 --- a/kalshi/models/communications.py +++ b/kalshi/models/communications.py @@ -225,3 +225,95 @@ class AcceptQuoteRequest(BaseModel): accepted_side: Literal["yes", "no"] model_config = {"extra": "forbid"} + + +# ── Block trade proposals (openapi 3.21.0) ───────────────────────────────── + + +class BlockTradeProposal(BaseModel): + """A block trade proposal — bilateral negotiated trade awaiting both sides. + + ``price_centi_cents`` and ``centicount`` are plain integers in the spec + (centi-cents and centicounts respectively), NOT FixedPointDollars/_fp + fixed-point wire fields, so they are not ``DollarDecimal``/``FixedPointCount``. + """ + + id: str + proposer_user_id: str + buyer_user_id: str + seller_user_id: str + market_ticker: str + price_centi_cents: int + centicount: int + maker_side: Literal["yes", "no"] + expiration_ts: AwareDatetime + status: str + created_ts: AwareDatetime + updated_ts: AwareDatetime + buyer_accepted: bool + seller_accepted: bool + # Optional fields. + buyer_subtrader_id: str | None = None + seller_subtrader_id: str | None = None + buyer_accepted_ts: AwareDatetime | None = None + seller_accepted_ts: AwareDatetime | None = None + executed_ts: AwareDatetime | None = None + buyer_order_id: str | None = None + seller_order_id: str | None = None + + model_config = {"extra": "allow"} + + +class GetBlockTradeProposalsResponse(BaseModel): + """Paginated list of block trade proposals.""" + + block_trade_proposals: list[BlockTradeProposal] + cursor: str | None = None + + model_config = {"extra": "allow"} + + +class ProposeBlockTradeRequest(BaseModel): + """Body for POST /communications/block-trade-proposals. + + ``price_centi_cents`` (centi-cents) and ``centicount`` (centicounts) are + plain integers per spec, both ``minimum: 1``. ``buyer_subtrader_id`` / + ``buyer_subaccount`` are mutually exclusive (same for the seller pair), but + the spec does not encode the exclusivity, so the SDK does not enforce it. + """ + + buyer_user_id: str + seller_user_id: str + market_ticker: str + price_centi_cents: StrictInt = Field(ge=1) + centicount: StrictInt = Field(ge=1) + maker_side: Literal["yes", "no"] + expiration_ts: AwareDatetime + buyer_subtrader_id: str | None = None + buyer_subaccount: StrictInt | None = Field(default=None, ge=0, le=63) + seller_subtrader_id: str | None = None + seller_subaccount: StrictInt | None = Field(default=None, ge=0, le=63) + + model_config = {"extra": "forbid"} + + +class ProposeBlockTradeResponse(BaseModel): + """Wraps the newly-created block trade proposal's id.""" + + block_trade_proposal_id: str + + model_config = {"extra": "allow"} + + +class AcceptBlockTradeProposalRequest(BaseModel): + """Body for POST /communications/block-trade-proposals/{id}/accept. + + Both fields are optional (spec requestBody ``required: false``); accept as + primary by sending an empty body. ``subtrader_id`` / ``subaccount`` are + mutually exclusive but the spec does not encode it, so it is not enforced. + """ + + subtrader_id: str | None = None + subaccount: StrictInt | None = Field(default=None, ge=0, le=63) + + model_config = {"extra": "forbid"} diff --git a/kalshi/perps/models/markets.py b/kalshi/perps/models/markets.py index 56664c1..3bd9bd0 100644 --- a/kalshi/perps/models/markets.py +++ b/kalshi/perps/models/markets.py @@ -31,6 +31,20 @@ """ +class TickerPrice(BaseModel): + """Spec ``TickerPrice`` — a reference/mark price point. + + ``price`` is a ``FixedPointDollars`` USD decimal string; ``ts_ms`` is the + source timestamp in epoch milliseconds (``int``). Used by the three + ``MarginMarket`` mark-price fields below. + """ + + price: DollarDecimal + ts_ms: int + + model_config = {"extra": "allow"} + + class MarginMarket(BaseModel): """Spec ``MarginMarket`` — a margin market with trading stats. @@ -83,6 +97,11 @@ class MarginMarket(BaseModel): "open_interest_notional_value_dollars", "open_interest_notional_value" ), ) + # Mark-price objects (spec ``$ref: TickerPrice``) — nested {price, ts_ms}, + # NOT bare price strings; absent from the spec ``required`` list, so optional. + settlement_mark_price: TickerPrice | None = None + liquidation_mark_price: TickerPrice | None = None + reference_price: TickerPrice | None = None model_config = {"extra": "allow", "populate_by_name": True} diff --git a/kalshi/perps/models/portfolio.py b/kalshi/perps/models/portfolio.py index afd7a56..355eeba 100644 --- a/kalshi/perps/models/portfolio.py +++ b/kalshi/perps/models/portfolio.py @@ -51,6 +51,7 @@ class MarginPosition(BaseModel): friendlier :attr:`return_on_equity`. """ + subaccount: int market_ticker: str position: FixedPointCount entry_price: DollarDecimal diff --git a/kalshi/resources/_base.py b/kalshi/resources/_base.py index 0961865..2bf3ef0 100644 --- a/kalshi/resources/_base.py +++ b/kalshi/resources/_base.py @@ -264,6 +264,29 @@ def _post_json( result: dict[str, Any] = self._load_json(response) return result + def _post_void( + self, + path: str, + *, + params: dict[str, Any] | None = None, + json: dict[str, Any] | None = None, + extra_headers: dict[str, str] | None = None, + ) -> None: + """POST that expects no response body (e.g. a 204, like accept). + + Mirrors the void semantics of :meth:`_put`/:meth:`_delete`: the + response is fired and discarded, so a bodyless 204 never reaches the + JSON parser. Error statuses still raise via the transport. + """ + self._transport.request( + "POST", + path, + params=params, + json=json, + headers={"Content-Type": "application/json"}, + extra_headers=extra_headers, + ) + def _put( self, path: str, @@ -514,6 +537,24 @@ async def _post_json( result: dict[str, Any] = self._load_json(response) return result + async def _post_void( + self, + path: str, + *, + params: dict[str, Any] | None = None, + json: dict[str, Any] | None = None, + extra_headers: dict[str, str] | None = None, + ) -> None: + """Async :meth:`SyncResource._post_void`.""" + await self._transport.request( + "POST", + path, + params=params, + json=json, + headers={"Content-Type": "application/json"}, + extra_headers=extra_headers, + ) + async def _put( self, path: str, diff --git a/kalshi/resources/account.py b/kalshi/resources/account.py index b05eabd..634a468 100644 --- a/kalshi/resources/account.py +++ b/kalshi/resources/account.py @@ -2,7 +2,11 @@ from __future__ import annotations -from kalshi.models.account import AccountApiLimits, AccountEndpointCosts +from kalshi.models.account import ( + AccountApiLimits, + AccountEndpointCosts, + AccountVolumeProgress, +) from kalshi.resources._base import AsyncResource, SyncResource @@ -22,6 +26,21 @@ def endpoint_costs( data = self._get("/account/endpoint_costs", extra_headers=extra_headers) return AccountEndpointCosts.model_validate(data) + def volume_progress( + self, *, extra_headers: dict[str, str] | None = None + ) -> AccountVolumeProgress: + """Latest cron-computed trading-volume progress toward API usage tiers. + + GET ``/account/api_usage_level/volume_progress``. Returns the + authenticated user's trailing-30-day fixed-point contract volume and the + per-level earn/keep goals for the predictions (``event_contract``) lane. + """ + self._require_auth() + data = self._get( + "/account/api_usage_level/volume_progress", extra_headers=extra_headers + ) + return AccountVolumeProgress.model_validate(data) + def upgrade(self, *, extra_headers: dict[str, str] | None = None) -> None: """Request a permanent Advanced API usage-level grant. @@ -52,6 +71,21 @@ async def endpoint_costs( data = await self._get("/account/endpoint_costs", extra_headers=extra_headers) return AccountEndpointCosts.model_validate(data) + async def volume_progress( + self, *, extra_headers: dict[str, str] | None = None + ) -> AccountVolumeProgress: + """Latest cron-computed trading-volume progress toward API usage tiers. + + GET ``/account/api_usage_level/volume_progress``. Returns the + authenticated user's trailing-30-day fixed-point contract volume and the + per-level earn/keep goals for the predictions (``event_contract``) lane. + """ + self._require_auth() + data = await self._get( + "/account/api_usage_level/volume_progress", extra_headers=extra_headers + ) + return AccountVolumeProgress.model_validate(data) + async def upgrade(self, *, extra_headers: dict[str, str] | None = None) -> None: """Request a permanent Advanced API usage-level grant. diff --git a/kalshi/resources/communications.py b/kalshi/resources/communications.py index 2794910..c5bf78c 100644 --- a/kalshi/resources/communications.py +++ b/kalshi/resources/communications.py @@ -13,6 +13,7 @@ from __future__ import annotations from collections.abc import AsyncIterator, Iterator +from datetime import datetime from decimal import Decimal from typing import Any, Literal, overload @@ -22,7 +23,9 @@ from kalshi.models.common import Page from kalshi.models.communications import ( RFQ, + AcceptBlockTradeProposalRequest, AcceptQuoteRequest, + BlockTradeProposal, CreateQuoteRequest, CreateQuoteResponse, CreateRFQRequest, @@ -30,6 +33,8 @@ GetCommunicationsIDResponse, GetQuoteResponse, GetRFQResponse, + ProposeBlockTradeRequest, + ProposeBlockTradeResponse, Quote, QuoteStatusLiteral, RfqStatusLiteral, @@ -104,6 +109,8 @@ def _list_quotes_params( *, cursor: str | None, limit: int | None, + min_ts: int | None, + max_ts: int | None, event_ticker: str | None, market_ticker: str | None, status: QuoteStatusLiteral | None, @@ -118,6 +125,8 @@ def _list_quotes_params( return _params( cursor=cursor, limit=limit, + min_ts=min_ts, + max_ts=max_ts, event_ticker=event_ticker, market_ticker=market_ticker, status=status, @@ -217,6 +226,99 @@ def _build_accept_quote_body( return request.model_dump(exclude_none=True, by_alias=True, mode="json") +def _list_block_trade_proposals_params( + *, + cursor: str | None, + limit: int | None, + market_ticker: str | None, + status: str | None, +) -> dict[str, Any]: + limit = _validate_limit(limit, hi=100) + return _params( + cursor=cursor, + limit=limit, + market_ticker=market_ticker, + status=status, + ) + + +def _build_propose_block_trade_body( + request: ProposeBlockTradeRequest | None, + *, + buyer_user_id: str | None, + seller_user_id: str | None, + market_ticker: str | None, + price_centi_cents: int | None, + centicount: int | None, + maker_side: Literal["yes", "no"] | None, + expiration_ts: Any, + buyer_subtrader_id: str | None, + buyer_subaccount: int | None, + seller_subtrader_id: str | None, + seller_subaccount: int | None, +) -> dict[str, Any]: + _check_request_exclusive( + request, + buyer_user_id=buyer_user_id, + seller_user_id=seller_user_id, + market_ticker=market_ticker, + price_centi_cents=price_centi_cents, + centicount=centicount, + maker_side=maker_side, + expiration_ts=expiration_ts, + buyer_subtrader_id=buyer_subtrader_id, + buyer_subaccount=buyer_subaccount, + seller_subtrader_id=seller_subtrader_id, + seller_subaccount=seller_subaccount, + ) + if request is None: + if ( + buyer_user_id is None + or seller_user_id is None + or market_ticker is None + or price_centi_cents is None + or centicount is None + or maker_side is None + or expiration_ts is None + ): + raise TypeError( + "create() requires `buyer_user_id`, `seller_user_id`, " + "`market_ticker`, `price_centi_cents`, `centicount`, " + "`maker_side`, and `expiration_ts` (or pass `request=...`)" + ) + request = ProposeBlockTradeRequest( + buyer_user_id=buyer_user_id, + seller_user_id=seller_user_id, + market_ticker=market_ticker, + price_centi_cents=price_centi_cents, + centicount=centicount, + maker_side=maker_side, + expiration_ts=expiration_ts, + buyer_subtrader_id=buyer_subtrader_id, + buyer_subaccount=buyer_subaccount, + seller_subtrader_id=seller_subtrader_id, + seller_subaccount=seller_subaccount, + ) + return request.model_dump(exclude_none=True, by_alias=True, mode="json") + + +def _build_accept_block_trade_proposal_body( + request: AcceptBlockTradeProposalRequest | None, + *, + subtrader_id: str | None, + subaccount: int | None, +) -> dict[str, Any]: + _check_request_exclusive(request, subtrader_id=subtrader_id, subaccount=subaccount) + if request is None: + request = AcceptBlockTradeProposalRequest( + subtrader_id=subtrader_id, + subaccount=subaccount, + ) + # Empty body is valid (spec requestBody required: false). model_dump yields + # {} when nothing is set, which still forces Content-Type: application/json. + return request.model_dump(exclude_none=True, by_alias=True, mode="json") + + # v3.0.0 deprecation messages shown by ``typing_extensions.deprecated`` at the # call site. Templated so each forwarder names its replacement explicitly. def _rfq_dep(new: str, old: str) -> str: @@ -374,6 +476,8 @@ def list( *, cursor: str | None = None, limit: int | None = None, + min_ts: int | None = None, + max_ts: int | None = None, event_ticker: str | None = None, market_ticker: str | None = None, status: QuoteStatusLiteral | None = None, @@ -395,6 +499,8 @@ def list( params = _list_quotes_params( cursor=cursor, limit=limit, + min_ts=min_ts, + max_ts=max_ts, event_ticker=event_ticker, market_ticker=market_ticker, status=status, @@ -413,6 +519,8 @@ def list_all( self, *, limit: int | None = None, + min_ts: int | None = None, + max_ts: int | None = None, event_ticker: str | None = None, market_ticker: str | None = None, status: QuoteStatusLiteral | None = None, @@ -436,6 +544,8 @@ def list_all( params = _list_quotes_params( cursor=None, limit=limit, + min_ts=min_ts, + max_ts=max_ts, event_ticker=event_ticker, market_ticker=market_ticker, status=status, @@ -553,6 +663,162 @@ def confirm(self, quote_id: str, *, extra_headers: dict[str, str] | None = None) ) +class BlockTradeProposalsResource(SyncResource): + """Sync block-trade-proposals sub-resource. + + ``client.communications.block_trade_proposals`` — backs the + ``/communications/block-trade-proposals`` endpoints (openapi 3.21.0). + """ + + def list( + self, + *, + cursor: str | None = None, + limit: int | None = None, + market_ticker: str | None = None, + status: str | None = None, + extra_headers: dict[str, str] | None = None, + ) -> Page[BlockTradeProposal]: + self._require_auth() + params = _list_block_trade_proposals_params( + cursor=cursor, + limit=limit, + market_ticker=market_ticker, + status=status, + ) + return self._list( + "/communications/block-trade-proposals", + BlockTradeProposal, + "block_trade_proposals", + params=params, + extra_headers=extra_headers, + ) + + def list_all( + self, + *, + limit: int | None = None, + market_ticker: str | None = None, + status: str | None = None, + max_pages: int | None = None, + extra_headers: dict[str, str] | None = None, + ) -> Iterator[BlockTradeProposal]: + self._require_auth() + _validate_max_pages(max_pages) + params = _list_block_trade_proposals_params( + cursor=None, + limit=limit, + market_ticker=market_ticker, + status=status, + ) + return self._list_all( + "/communications/block-trade-proposals", + BlockTradeProposal, + "block_trade_proposals", + params=params, + max_pages=max_pages, + extra_headers=extra_headers, + ) + + @overload + def create( + self, + *, + request: ProposeBlockTradeRequest, + extra_headers: dict[str, str] | None = None, + ) -> ProposeBlockTradeResponse: ... + @overload + def create( + self, + *, + buyer_user_id: str, + seller_user_id: str, + market_ticker: str, + price_centi_cents: int, + centicount: int, + maker_side: Literal["yes", "no"], + expiration_ts: datetime | str, + buyer_subtrader_id: str | None = ..., + buyer_subaccount: int | None = ..., + seller_subtrader_id: str | None = ..., + seller_subaccount: int | None = ..., + extra_headers: dict[str, str] | None = None, + ) -> ProposeBlockTradeResponse: ... + def create( + self, + *, + request: ProposeBlockTradeRequest | None = None, + buyer_user_id: str | None = None, + seller_user_id: str | None = None, + market_ticker: str | None = None, + price_centi_cents: int | None = None, + centicount: int | None = None, + maker_side: Literal["yes", "no"] | None = None, + expiration_ts: Any = None, + buyer_subtrader_id: str | None = None, + buyer_subaccount: int | None = None, + seller_subtrader_id: str | None = None, + seller_subaccount: int | None = None, + extra_headers: dict[str, str] | None = None, + ) -> ProposeBlockTradeResponse: + self._require_auth() + body = _build_propose_block_trade_body( + request, + buyer_user_id=buyer_user_id, + seller_user_id=seller_user_id, + market_ticker=market_ticker, + price_centi_cents=price_centi_cents, + centicount=centicount, + maker_side=maker_side, + expiration_ts=expiration_ts, + buyer_subtrader_id=buyer_subtrader_id, + buyer_subaccount=buyer_subaccount, + seller_subtrader_id=seller_subtrader_id, + seller_subaccount=seller_subaccount, + ) + data = self._post( + "/communications/block-trade-proposals", json=body, extra_headers=extra_headers + ) + return ProposeBlockTradeResponse.model_validate(data) + + @overload + def accept( + self, + block_trade_proposal_id: str, + *, + request: AcceptBlockTradeProposalRequest, + extra_headers: dict[str, str] | None = None, + ) -> None: ... + @overload + def accept( + self, + block_trade_proposal_id: str, + *, + subtrader_id: str | None = ..., + subaccount: int | None = ..., + extra_headers: dict[str, str] | None = None, + ) -> None: ... + def accept( + self, + block_trade_proposal_id: str, + *, + request: AcceptBlockTradeProposalRequest | None = None, + subtrader_id: str | None = None, + subaccount: int | None = None, + extra_headers: dict[str, str] | None = None, + ) -> None: + self._require_auth() + body = _build_accept_block_trade_proposal_body( + request, subtrader_id=subtrader_id, subaccount=subaccount + ) + self._post_void( + f"/communications/block-trade-proposals/" + f"{_seg(block_trade_proposal_id, name='block_trade_proposal_id')}/accept", + json=body, + extra_headers=extra_headers, + ) + + class CommunicationsResource(SyncResource): """Sync communications / RFQ API. @@ -571,11 +837,13 @@ class CommunicationsResource(SyncResource): rfqs: RFQsResource quotes: QuotesResource + block_trade_proposals: BlockTradeProposalsResource def __init__(self, transport: SyncTransport) -> None: super().__init__(transport) self.rfqs = RFQsResource(transport) self.quotes = QuotesResource(transport) + self.block_trade_proposals = BlockTradeProposalsResource(transport) def get_id(self, *, extra_headers: dict[str, str] | None = None) -> GetCommunicationsIDResponse: self._require_auth() @@ -683,6 +951,8 @@ def list_quotes( *, cursor: str | None = None, limit: int | None = None, + min_ts: int | None = None, + max_ts: int | None = None, event_ticker: str | None = None, market_ticker: str | None = None, status: QuoteStatusLiteral | None = None, @@ -698,6 +968,8 @@ def list_quotes( return self.quotes.list( cursor=cursor, limit=limit, + min_ts=min_ts, + max_ts=max_ts, event_ticker=event_ticker, market_ticker=market_ticker, status=status, @@ -715,6 +987,8 @@ def list_all_quotes( self, *, limit: int | None = None, + min_ts: int | None = None, + max_ts: int | None = None, event_ticker: str | None = None, market_ticker: str | None = None, status: QuoteStatusLiteral | None = None, @@ -730,6 +1004,8 @@ def list_all_quotes( """.. deprecated:: 3.0.0 Use :meth:`client.communications.quotes.list_all` instead.""" return self.quotes.list_all( limit=limit, + min_ts=min_ts, + max_ts=max_ts, event_ticker=event_ticker, market_ticker=market_ticker, status=status, @@ -938,6 +1214,8 @@ async def list( *, cursor: str | None = None, limit: int | None = None, + min_ts: int | None = None, + max_ts: int | None = None, event_ticker: str | None = None, market_ticker: str | None = None, status: QuoteStatusLiteral | None = None, @@ -959,6 +1237,8 @@ async def list( params = _list_quotes_params( cursor=cursor, limit=limit, + min_ts=min_ts, + max_ts=max_ts, event_ticker=event_ticker, market_ticker=market_ticker, status=status, @@ -977,6 +1257,8 @@ def list_all( self, *, limit: int | None = None, + min_ts: int | None = None, + max_ts: int | None = None, event_ticker: str | None = None, market_ticker: str | None = None, status: QuoteStatusLiteral | None = None, @@ -1001,6 +1283,8 @@ def list_all( params = _list_quotes_params( cursor=None, limit=limit, + min_ts=min_ts, + max_ts=max_ts, event_ticker=event_ticker, market_ticker=market_ticker, status=status, @@ -1122,6 +1406,163 @@ async def confirm( ) +class AsyncBlockTradeProposalsResource(AsyncResource): + """Async block-trade-proposals sub-resource. + + ``client.communications.block_trade_proposals`` — backs the + ``/communications/block-trade-proposals`` endpoints (openapi 3.21.0). + """ + + async def list( + self, + *, + cursor: str | None = None, + limit: int | None = None, + market_ticker: str | None = None, + status: str | None = None, + extra_headers: dict[str, str] | None = None, + ) -> Page[BlockTradeProposal]: + self._require_auth() + params = _list_block_trade_proposals_params( + cursor=cursor, + limit=limit, + market_ticker=market_ticker, + status=status, + ) + return await self._list( + "/communications/block-trade-proposals", + BlockTradeProposal, + "block_trade_proposals", + params=params, + extra_headers=extra_headers, + ) + + def list_all( + self, + *, + limit: int | None = None, + market_ticker: str | None = None, + status: str | None = None, + max_pages: int | None = None, + extra_headers: dict[str, str] | None = None, + ) -> AsyncIterator[BlockTradeProposal]: + """Returns an async iterator — use ``async for``.""" + self._require_auth() + _validate_max_pages(max_pages) + params = _list_block_trade_proposals_params( + cursor=None, + limit=limit, + market_ticker=market_ticker, + status=status, + ) + return self._list_all( + "/communications/block-trade-proposals", + BlockTradeProposal, + "block_trade_proposals", + params=params, + max_pages=max_pages, + extra_headers=extra_headers, + ) + + @overload + async def create( + self, + *, + request: ProposeBlockTradeRequest, + extra_headers: dict[str, str] | None = None, + ) -> ProposeBlockTradeResponse: ... + @overload + async def create( + self, + *, + buyer_user_id: str, + seller_user_id: str, + market_ticker: str, + price_centi_cents: int, + centicount: int, + maker_side: Literal["yes", "no"], + expiration_ts: datetime | str, + buyer_subtrader_id: str | None = ..., + buyer_subaccount: int | None = ..., + seller_subtrader_id: str | None = ..., + seller_subaccount: int | None = ..., + extra_headers: dict[str, str] | None = None, + ) -> ProposeBlockTradeResponse: ... + async def create( + self, + *, + request: ProposeBlockTradeRequest | None = None, + buyer_user_id: str | None = None, + seller_user_id: str | None = None, + market_ticker: str | None = None, + price_centi_cents: int | None = None, + centicount: int | None = None, + maker_side: Literal["yes", "no"] | None = None, + expiration_ts: Any = None, + buyer_subtrader_id: str | None = None, + buyer_subaccount: int | None = None, + seller_subtrader_id: str | None = None, + seller_subaccount: int | None = None, + extra_headers: dict[str, str] | None = None, + ) -> ProposeBlockTradeResponse: + self._require_auth() + body = _build_propose_block_trade_body( + request, + buyer_user_id=buyer_user_id, + seller_user_id=seller_user_id, + market_ticker=market_ticker, + price_centi_cents=price_centi_cents, + centicount=centicount, + maker_side=maker_side, + expiration_ts=expiration_ts, + buyer_subtrader_id=buyer_subtrader_id, + buyer_subaccount=buyer_subaccount, + seller_subtrader_id=seller_subtrader_id, + seller_subaccount=seller_subaccount, + ) + data = await self._post( + "/communications/block-trade-proposals", json=body, extra_headers=extra_headers + ) + return ProposeBlockTradeResponse.model_validate(data) + + @overload + async def accept( + self, + block_trade_proposal_id: str, + *, + request: AcceptBlockTradeProposalRequest, + extra_headers: dict[str, str] | None = None, + ) -> None: ... + @overload + async def accept( + self, + block_trade_proposal_id: str, + *, + subtrader_id: str | None = ..., + subaccount: int | None = ..., + extra_headers: dict[str, str] | None = None, + ) -> None: ... + async def accept( + self, + block_trade_proposal_id: str, + *, + request: AcceptBlockTradeProposalRequest | None = None, + subtrader_id: str | None = None, + subaccount: int | None = None, + extra_headers: dict[str, str] | None = None, + ) -> None: + self._require_auth() + body = _build_accept_block_trade_proposal_body( + request, subtrader_id=subtrader_id, subaccount=subaccount + ) + await self._post_void( + f"/communications/block-trade-proposals/" + f"{_seg(block_trade_proposal_id, name='block_trade_proposal_id')}/accept", + json=body, + extra_headers=extra_headers, + ) + + class AsyncCommunicationsResource(AsyncResource): """Async communications / RFQ API. @@ -1139,11 +1580,13 @@ class AsyncCommunicationsResource(AsyncResource): rfqs: AsyncRFQsResource quotes: AsyncQuotesResource + block_trade_proposals: AsyncBlockTradeProposalsResource def __init__(self, transport: AsyncTransport) -> None: super().__init__(transport) self.rfqs = AsyncRFQsResource(transport) self.quotes = AsyncQuotesResource(transport) + self.block_trade_proposals = AsyncBlockTradeProposalsResource(transport) async def get_id( self, *, extra_headers: dict[str, str] | None = None @@ -1255,6 +1698,8 @@ async def list_quotes( *, cursor: str | None = None, limit: int | None = None, + min_ts: int | None = None, + max_ts: int | None = None, event_ticker: str | None = None, market_ticker: str | None = None, status: QuoteStatusLiteral | None = None, @@ -1270,6 +1715,8 @@ async def list_quotes( return await self.quotes.list( cursor=cursor, limit=limit, + min_ts=min_ts, + max_ts=max_ts, event_ticker=event_ticker, market_ticker=market_ticker, status=status, @@ -1287,6 +1734,8 @@ def list_all_quotes( self, *, limit: int | None = None, + min_ts: int | None = None, + max_ts: int | None = None, event_ticker: str | None = None, market_ticker: str | None = None, status: QuoteStatusLiteral | None = None, @@ -1302,6 +1751,8 @@ def list_all_quotes( """.. deprecated:: 3.0.0 Use :meth:`client.communications.quotes.list_all` instead.""" return self.quotes.list_all( limit=limit, + min_ts=min_ts, + max_ts=max_ts, event_ticker=event_ticker, market_ticker=market_ticker, status=status, diff --git a/kalshi/resources/events.py b/kalshi/resources/events.py index 133ce56..cbef28a 100644 --- a/kalshi/resources/events.py +++ b/kalshi/resources/events.py @@ -2,6 +2,7 @@ from __future__ import annotations +import builtins from collections.abc import AsyncIterator, Iterator from typing import Any @@ -11,6 +12,7 @@ AsyncResource, SyncResource, _bool_param, + _join_tickers, _params, _seg, _validate_limit, @@ -24,6 +26,7 @@ def _list_events_params( *, status: EventStatusLiteral | None, series_ticker: str | None, + tickers: builtins.list[str] | str | None, with_nested_markets: bool | None, with_milestones: bool | None, min_close_ts: int | None, @@ -35,6 +38,7 @@ def _list_events_params( return _params( status=status, series_ticker=series_ticker, + tickers=_join_tickers(tickers), with_nested_markets=_bool_param(with_nested_markets), with_milestones=_bool_param(with_milestones), min_close_ts=min_close_ts, @@ -84,6 +88,7 @@ def list( *, status: EventStatusLiteral | None = None, series_ticker: str | None = None, + tickers: builtins.list[str] | str | None = None, with_nested_markets: bool | None = None, with_milestones: bool | None = None, min_close_ts: int | None = None, @@ -95,6 +100,7 @@ def list( params = _list_events_params( status=status, series_ticker=series_ticker, + tickers=tickers, with_nested_markets=with_nested_markets, with_milestones=with_milestones, min_close_ts=min_close_ts, @@ -109,6 +115,7 @@ def list_all( *, status: EventStatusLiteral | None = None, series_ticker: str | None = None, + tickers: builtins.list[str] | str | None = None, with_nested_markets: bool | None = None, with_milestones: bool | None = None, min_close_ts: int | None = None, @@ -121,6 +128,7 @@ def list_all( params = _list_events_params( status=status, series_ticker=series_ticker, + tickers=tickers, with_nested_markets=with_nested_markets, with_milestones=with_milestones, min_close_ts=min_close_ts, @@ -264,6 +272,7 @@ async def list( *, status: EventStatusLiteral | None = None, series_ticker: str | None = None, + tickers: builtins.list[str] | str | None = None, with_nested_markets: bool | None = None, with_milestones: bool | None = None, min_close_ts: int | None = None, @@ -275,6 +284,7 @@ async def list( params = _list_events_params( status=status, series_ticker=series_ticker, + tickers=tickers, with_nested_markets=with_nested_markets, with_milestones=with_milestones, min_close_ts=min_close_ts, @@ -291,6 +301,7 @@ def list_all( *, status: EventStatusLiteral | None = None, series_ticker: str | None = None, + tickers: builtins.list[str] | str | None = None, with_nested_markets: bool | None = None, with_milestones: bool | None = None, min_close_ts: int | None = None, @@ -303,6 +314,7 @@ def list_all( params = _list_events_params( status=status, series_ticker=series_ticker, + tickers=tickers, with_nested_markets=with_nested_markets, with_milestones=with_milestones, min_close_ts=min_close_ts, diff --git a/kalshi/ws/models/base.py b/kalshi/ws/models/base.py index 45344a6..d26b62f 100644 --- a/kalshi/ws/models/base.py +++ b/kalshi/ws/models/base.py @@ -17,6 +17,7 @@ class ErrorPayload(BaseModel): msg: str market_ticker: str | None = None market_id: str | None = None + market_tickers: list[str] | None = None model_config = {"extra": "allow", "populate_by_name": True} diff --git a/pyproject.toml b/pyproject.toml index b590260..6f8f850 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "kalshi-sdk" -version = "4.0.0" +version = "4.1.0" description = "A professional Python SDK for the Kalshi prediction markets and Perps (margin) APIs" readme = "README.md" license = { text = "MIT" } diff --git a/specs/asyncapi.yaml b/specs/asyncapi.yaml index 4e9cec0..3015a5d 100644 --- a/specs/asyncapi.yaml +++ b/specs/asyncapi.yaml @@ -74,6 +74,14 @@ info: | 21 | shard_key must be >= 0 and < shard_factor | Invalid shard_key | | 22 | shard_factor must be <= 100 | shard_factor too large | + + | 26 | Subscription market limit exceeded | Adding markets would exceed the + per-subscription market limit | + + | 27 | Too many requests | The subscription exceeded its command rate limit + | + + | 28 | Markets not found | Unknown tickers were not subscribed | contact: name: Kalshi Support url: https://kalshi.com @@ -1377,6 +1385,14 @@ components: | 25 | Subscription buffer overflow | The subscription's outbound buffer was exceeded | + + | 26 | Subscription market limit exceeded | Adding markets would exceed + the per-subscription market limit | + + | 27 | Too many requests | The subscription exceeded its command rate + limit | + + | 28 | Markets not found | Unknown tickers were not subscribed | contentType: application/json payload: $ref: '#/components/schemas/errorResponsePayload' @@ -2449,8 +2465,16 @@ components: - 25: Subscription buffer overflow - The subscription's outbound buffer was exceeded + + - 26: Subscription market limit exceeded - Adding markets would + exceed the per-subscription market limit + + - 27: Too many requests - The subscription exceeded its command + rate limit + + - 28: Markets not found - Unknown tickers were not subscribed minimum: 1 - maximum: 25 + maximum: 28 msg: type: string description: Human-readable error message @@ -2460,6 +2484,11 @@ components: market_ticker: type: string description: Market ticker if error is market-specific (optional) + market_tickers: + type: array + items: + type: string + description: Market tickers if error is market-specific (optional) listSubscriptionsCommandPayload: type: object required: @@ -3950,3 +3979,12 @@ x-error-codes: - code: 25 name: Subscription buffer overflow description: The subscription's outbound buffer was exceeded + - code: 26 + name: Subscription market limit exceeded + description: Adding markets would exceed the per-subscription market limit + - code: 27 + name: Too many requests + description: The subscription exceeded its command rate limit + - code: 28 + name: Markets not found + description: Unknown tickers were not subscribed diff --git a/specs/openapi.yaml b/specs/openapi.yaml index 12ec60b..8486382 100644 --- a/specs/openapi.yaml +++ b/specs/openapi.yaml @@ -1,10 +1,9 @@ openapi: 3.0.0 info: title: Kalshi Trade API Manual Endpoints - version: 3.20.0 - description: >- - Manually defined OpenAPI spec for endpoints being migrated to spec-first - approach + version: 3.21.0 + description: Manually defined OpenAPI spec for endpoints being migrated to spec-first approach + servers: - url: https://external-api.kalshi.com/trade-api/v2 description: Production Trade API server @@ -14,6 +13,7 @@ servers: description: Demo Trade API server - url: https://demo-api.kalshi.co/trade-api/v2 description: Demo shared API server, also supported + paths: /exchange/status: get: @@ -47,6 +47,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ExchangeStatus' + /exchange/announcements: get: operationId: GetExchangeAnnouncements @@ -63,6 +64,7 @@ paths: $ref: '#/components/schemas/GetExchangeAnnouncementsResponse' '500': description: Internal server error + /series/fee_changes: get: operationId: GetSeriesFeeChanges @@ -94,6 +96,7 @@ paths: $ref: '#/components/responses/BadRequestError' '500': $ref: '#/components/responses/InternalServerError' + /exchange/schedule: get: operationId: GetExchangeSchedule @@ -110,6 +113,7 @@ paths: $ref: '#/components/schemas/GetExchangeScheduleResponse' '500': description: Internal server error + /exchange/user_data_timestamp: get: operationId: GetUserDataTimestamp @@ -126,19 +130,14 @@ paths: $ref: '#/components/schemas/GetUserDataTimestampResponse' '500': description: Internal server error + /series/{series_ticker}/markets/{ticker}/candlesticks: get: operationId: GetMarketCandlesticks summary: Get Market Candlesticks - description: > - Time period length of each candlestick in minutes. Valid values: 1 (1 - minute), 60 (1 hour), 1440 (1 day). - - Candlesticks for markets that settled before the historical cutoff are - only available via `GET /historical/markets/{ticker}/candlesticks`. See - [Historical - Data](https://docs.kalshi.com/getting_started/historical_data) for - details. + description: | + Time period length of each candlestick in minutes. Valid values: 1 (1 minute), 60 (1 hour), 1440 (1 day). + Candlesticks for markets that settled before the historical cutoff are only available via `GET /historical/markets/{ticker}/candlesticks`. See [Historical Data](https://docs.kalshi.com/getting_started/historical_data) for details. tags: - market parameters: @@ -157,49 +156,34 @@ paths: - name: start_ts in: query required: true - description: >- - Start timestamp (Unix timestamp). Candlesticks will include those - ending on or after this time. + description: Start timestamp (Unix timestamp). Candlesticks will include those ending on or after this time. schema: type: integer format: int64 - name: end_ts in: query required: true - description: >- - End timestamp (Unix timestamp). Candlesticks will include those - ending on or before this time. + description: End timestamp (Unix timestamp). Candlesticks will include those ending on or before this time. schema: type: integer format: int64 - name: period_interval in: query required: true - description: >- - Time period length of each candlestick in minutes. Valid values are - 1 (1 minute), 60 (1 hour), or 1440 (1 day). + description: Time period length of each candlestick in minutes. Valid values are 1 (1 minute), 60 (1 hour), or 1440 (1 day). schema: type: integer - enum: - - 1 - - 60 - - 1440 + enum: [1, 60, 1440] x-oapi-codegen-extra-tags: - validate: required,oneof=1 60 1440 + validate: "required,oneof=1 60 1440" - name: include_latest_before_start in: query required: false - description: > - If true, prepends the latest candlestick available before the - start_ts. This synthetic candlestick is created by: - + description: | + If true, prepends the latest candlestick available before the start_ts. This synthetic candlestick is created by: 1. Finding the most recent real candlestick before start_ts - - 2. Projecting it forward to the first period boundary (calculated as - the next period interval after start_ts) - - 3. Setting all OHLC prices to null, and `previous_price` to the - close price from the real candlestick + 2. Projecting it forward to the first period boundary (calculated as the next period interval after start_ts) + 3. Setting all OHLC prices to null, and `previous_price` to the close price from the real candlestick schema: type: boolean default: false @@ -216,21 +200,13 @@ paths: description: Not found '500': description: Internal server error + /markets/trades: get: operationId: GetTrades summary: Get Trades - description: > - Endpoint for getting all trades for all markets. A trade represents a - completed transaction between two users on a specific market. Each trade - includes the market ticker, price, quantity, and timestamp information. - Block trades are included in the response by default and identified by - the `is_block_trade` field; use the `is_block_trade` query parameter to - filter by block / non-block. This endpoint returns a paginated response. - Use the 'limit' parameter to control page size (1-1000, defaults to - 100). The response includes a 'cursor' field - pass this value in the - 'cursor' parameter of your next request to get the next page. An empty - cursor indicates no more pages are available. + description: | + Endpoint for getting all trades for all markets. A trade represents a completed transaction between two users on a specific market. Each trade includes the market ticker, price, quantity, and timestamp information. Block trades are included in the response by default and identified by the `is_block_trade` field; use the `is_block_trade` query parameter to filter by block / non-block. This endpoint returns a paginated response. Use the 'limit' parameter to control page size (1-1000, defaults to 100). The response includes a 'cursor' field - pass this value in the 'cursor' parameter of your next request to get the next page. An empty cursor indicates no more pages are available. tags: - market parameters: @@ -251,6 +227,7 @@ paths: description: Bad request '500': description: Internal server error + /markets/{ticker}/orderbook: get: operationId: GetMarketOrderbook @@ -266,9 +243,7 @@ paths: - $ref: '#/components/parameters/TickerPath' - name: depth in: query - description: >- - Depth of the orderbook to retrieve (0 or negative means all levels, - 1-100 for specific depth) + description: Depth of the orderbook to retrieve (0 or negative means all levels, 1-100 for specific depth) required: false schema: type: integer @@ -290,20 +265,12 @@ paths: $ref: '#/components/responses/NotFoundError' '500': $ref: '#/components/responses/InternalServerError' + /markets/orderbooks: get: operationId: GetMarketOrderbooks summary: Get Multiple Market Orderbooks - description: >- - Endpoint for getting the current order books for multiple markets in a - single request. The order book shows all active bid orders for both yes - and no sides of a binary market. It returns yes bids and no bids only - (no asks are returned). This is because in binary markets, a bid for yes - at price X is equivalent to an ask for no at price (100-X). For example, - a yes bid at 7¢ is the same as a no ask at 93¢, with identical contract - sizes. Each side shows price levels with their corresponding quantities - and order counts, organized from best to worst prices. Returns one - orderbook per requested market ticker. + description: 'Endpoint for getting the current order books for multiple markets in a single request. The order book shows all active bid orders for both yes and no sides of a binary market. It returns yes bids and no bids only (no asks are returned). This is because in binary markets, a bid for yes at price X is equivalent to an ask for no at price (100-X). For example, a yes bid at 7¢ is the same as a no ask at 93¢, with identical contract sizes. Each side shows price levels with their corresponding quantities and order counts, organized from best to worst prices. Returns one orderbook per requested market ticker.' tags: - market security: @@ -339,6 +306,7 @@ paths: $ref: '#/components/responses/UnauthorizedError' '500': $ref: '#/components/responses/InternalServerError' + /series/{series_ticker}: get: operationId: GetSeries @@ -360,9 +328,7 @@ paths: type: boolean default: false x-go-type-skip-optional-pointer: true - description: >- - If true, includes the total volume traded across all events in this - series. + description: If true, includes the total volume traded across all events in this series. responses: '200': description: Series retrieved successfully @@ -374,6 +340,7 @@ paths: $ref: '#/components/responses/BadRequestError' '500': $ref: '#/components/responses/InternalServerError' + /series: get: operationId: GetSeriesList @@ -408,15 +375,11 @@ paths: type: boolean default: false x-go-type-skip-optional-pointer: true - description: >- - If true, includes the total volume traded across all events in each - series. + description: If true, includes the total volume traded across all events in each series. - name: min_updated_ts in: query required: false - description: >- - Filter series with metadata updated after this Unix timestamp (in - seconds). Use this to efficiently poll for changes. + description: Filter series with metadata updated after this Unix timestamp (in seconds). Use this to efficiently poll for changes. schema: type: integer format: int64 @@ -431,24 +394,25 @@ paths: $ref: '#/components/responses/BadRequestError' '500': $ref: '#/components/responses/InternalServerError' + /markets: get: operationId: GetMarkets summary: Get Markets - description: > - Filter by market status. Possible values: `unopened`, `open`, `closed`, - `settled`. Leave empty to return markets with any status. - - Only one `status` filter may be supplied at a time. - - Timestamp filters will be mutually exclusive from other timestamp filters and certain status filters. - - | Compatible Timestamp Filters | Additional Status Filters| Extra Notes | - |------------------------------|--------------------------|-------------| - | min_created_ts, max_created_ts | `unopened`, `open`, *empty* | | - | min_close_ts, max_close_ts | `closed`, *empty* | | - | min_settled_ts, max_settled_ts | `settled`, *empty* | | - | min_updated_ts | *empty* | Incompatible with all filters besides `mve_filter=exclude` | - - Markets that settled before the historical cutoff are only available via `GET /historical/markets`. See [Historical Data](https://docs.kalshi.com/getting_started/historical_data) for details. + description: | + Filter by market status. Possible values: `unopened`, `open`, `closed`, `settled`. Leave empty to return markets with any status. + - Only one `status` filter may be supplied at a time. + - Timestamp filters will be mutually exclusive from other timestamp filters and certain status filters. + + | Compatible Timestamp Filters | Additional Status Filters| Extra Notes | + |------------------------------|--------------------------|-------------| + | min_created_ts, max_created_ts | `unopened`, `open`, *empty* | | + | min_close_ts, max_close_ts | `closed`, *empty* | | + | min_settled_ts, max_settled_ts | `settled`, *empty* | | + | min_updated_ts | *empty* | Incompatible with all filters besides `mve_filter=exclude`. May be combined with `series_ticker`, which requires `mve_filter=exclude` | + + Markets that settled before the historical cutoff are only available via `GET /historical/markets`. See [Historical Data](https://docs.kalshi.com/getting_started/historical_data) for details. + tags: - market parameters: @@ -479,6 +443,7 @@ paths: description: Unauthorized '500': description: Internal server error + /markets/{ticker}: get: operationId: GetMarket @@ -501,22 +466,18 @@ paths: description: Not found '500': description: Internal server error + /markets/candlesticks: get: operationId: BatchGetMarketCandlesticks summary: Batch Get Market Candlesticks - description: > + description: | Endpoint for retrieving candlestick data for multiple markets. - - Accepts up to 100 market tickers per request - - Returns up to 10,000 candlesticks total across all markets - - Returns candlesticks grouped by market_id - - - Optionally includes a synthetic initial candlestick for price - continuity (see `include_latest_before_start` parameter) + - Optionally includes a synthetic initial candlestick for price continuity (see `include_latest_before_start` parameter) tags: - market parameters: @@ -551,17 +512,11 @@ paths: - name: include_latest_before_start in: query required: false - description: > - If true, prepends the latest candlestick available before the - start_ts. This synthetic candlestick is created by: - + description: | + If true, prepends the latest candlestick available before the start_ts. This synthetic candlestick is created by: 1. Finding the most recent real candlestick before start_ts - - 2. Projecting it forward to the first period boundary (calculated as - the next period interval after start_ts) - - 3. Setting all OHLC prices to null, and `previous_price` to the - close price from the real candlestick + 2. Projecting it forward to the first period boundary (calculated as the next period interval after start_ts) + 3. Setting all OHLC prices to null, and `previous_price` to the close price from the real candlestick schema: type: boolean default: false @@ -578,6 +533,7 @@ paths: description: Unauthorized '500': description: Internal server error + /series/{series_ticker}/events/{ticker}/candlesticks: get: operationId: GetMarketCandlesticksByEvent @@ -606,7 +562,7 @@ paths: type: integer format: int64 x-oapi-codegen-extra-tags: - validate: required + validate: "required" - name: end_ts in: query required: true @@ -615,22 +571,17 @@ paths: type: integer format: int64 x-oapi-codegen-extra-tags: - validate: required + validate: "required" - name: period_interval in: query required: true - description: >- - Specifies the length of each candlestick period, in minutes. Must be - one minute, one hour, or one day. + description: Specifies the length of each candlestick period, in minutes. Must be one minute, one hour, or one day. schema: type: integer format: int32 - enum: - - 1 - - 60 - - 1440 + enum: [1, 60, 1440] x-oapi-codegen-extra-tags: - validate: required,oneof=1 60 1440 + validate: "required,oneof=1 60 1440" responses: '200': description: Event candlesticks retrieved successfully @@ -644,27 +595,22 @@ paths: description: Unauthorized '500': description: Internal server error + /events: get: operationId: GetEvents summary: Get Events - description: > + description: | Get all events. This endpoint excludes multivariate events. - - To retrieve multivariate events, use the GET /events/multivariate - endpoint. - - All events are accessible through this endpoint, even if their - associated markets are older than the historical cutoff. + To retrieve multivariate events, use the GET /events/multivariate endpoint. + All events are accessible through this endpoint, even if their associated markets are older than the historical cutoff. tags: - events parameters: - name: limit in: query required: false - description: >- - Parameter to specify the number of results per page. Defaults to - 200. Maximum value is 200. + description: Parameter to specify the number of results per page. Defaults to 200. Maximum value is 200. schema: type: integer minimum: 1 @@ -673,21 +619,13 @@ paths: - name: cursor in: query required: false - description: >- - Parameter to specify the pagination cursor. Use the cursor value - returned from the previous response to get the next page of results. - Leave empty for the first page. + description: Parameter to specify the pagination cursor. Use the cursor value returned from the previous response to get the next page of results. Leave empty for the first page. schema: type: string - name: with_nested_markets in: query required: false - description: >- - Parameter to specify if nested markets should be included in the - response. When true, each event will include a 'markets' field - containing a list of Market objects associated with that event. - Historical markets settled before the historical cutoff will not be - included. + description: Parameter to specify if nested markets should be included in the response. When true, each event will include a 'markets' field containing a list of Market objects associated with that event. Historical markets settled before the historical cutoff will not be included. schema: type: boolean default: false @@ -703,32 +641,23 @@ paths: - name: status in: query required: false - description: >- - Filter by event status. Possible values are 'unopened', 'open', - 'closed', 'settled'. Leave empty to return events with any status. + description: Filter by event status. Possible values are 'unopened', 'open', 'closed', 'settled'. Leave empty to return events with any status. schema: type: string - enum: - - unopened - - open - - closed - - settled + enum: ['unopened', 'open', 'closed', 'settled'] - $ref: '#/components/parameters/SeriesTickerQuery' + - $ref: '#/components/parameters/EventTickersQuery' - name: min_close_ts in: query required: false - description: >- - Filter events with at least one market with close timestamp greater - than this Unix timestamp (in seconds). + description: Filter events with at least one market with close timestamp greater than this Unix timestamp (in seconds). schema: type: integer format: int64 - name: min_updated_ts in: query required: false - description: >- - Filter events with metadata updated after this Unix timestamp (in - seconds). Use this to efficiently poll for changes. + description: Filter events with metadata updated after this Unix timestamp (in seconds). Use this to efficiently poll for changes. schema: type: integer format: int64 @@ -745,14 +674,12 @@ paths: description: Unauthorized '500': description: Internal server error + /events/multivariate: get: operationId: GetMultivariateEvents summary: Get Multivariate Events - description: >- - Retrieve multivariate (combo) events. These are dynamically created - events from multivariate event collections. Supports filtering by series - and collection ticker. + description: 'Retrieve multivariate (combo) events. These are dynamically created events from multivariate event collections. Supports filtering by series and collection ticker.' tags: - events parameters: @@ -768,28 +695,20 @@ paths: - name: cursor in: query required: false - description: >- - Pagination cursor. Use the cursor value returned from the previous - response to get the next page of results. + description: Pagination cursor. Use the cursor value returned from the previous response to get the next page of results. schema: type: string - $ref: '#/components/parameters/SeriesTickerQuery' - name: collection_ticker in: query required: false - description: >- - Filter events by collection ticker. Returns only multivariate events - belonging to the specified collection. Cannot be used together with - series_ticker. + description: Filter events by collection ticker. Returns only multivariate events belonging to the specified collection. Cannot be used together with series_ticker. schema: type: string - name: with_nested_markets in: query required: false - description: >- - Parameter to specify if nested markets should be included in the - response. When true, each event will include a 'markets' field - containing a list of Market objects associated with that event. + description: Parameter to specify if nested markets should be included in the response. When true, each event will include a 'markets' field containing a list of Market objects associated with that event. schema: type: boolean default: false @@ -806,14 +725,13 @@ paths: description: Unauthorized '500': description: Internal server error + /events/fee_changes: get: operationId: GetEventFeeChanges summary: Get Event Fee Changes - description: > - Event fees are an override layered on top of the parent series' fee - structure. If `fee_type_override` and `fee_multiplier_override` are - null, that indicates the override is cleared. + description: | + Event fees are an override layered on top of the parent series' fee structure. If `fee_type_override` and `fee_multiplier_override` are null, that indicates the override is cleared. tags: - events parameters: @@ -836,20 +754,15 @@ paths: $ref: '#/components/responses/BadRequestError' '500': $ref: '#/components/responses/InternalServerError' + /events/{event_ticker}: get: operationId: GetEvent summary: Get Event - description: > - Endpoint for getting data about an event by its ticker. An event - represents a real-world occurrence that can be traded on, such as an - election, sports game, or economic indicator release. - - Events contain one or more markets where users can place trades on - different outcomes. - - All events are accessible through this endpoint, even if their - associated markets are older than the historical cutoff. + description: | + Endpoint for getting data about an event by its ticker. An event represents a real-world occurrence that can be traded on, such as an election, sports game, or economic indicator release. + Events contain one or more markets where users can place trades on different outcomes. + All events are accessible through this endpoint, even if their associated markets are older than the historical cutoff. tags: - events parameters: @@ -862,11 +775,7 @@ paths: - name: with_nested_markets in: query required: false - description: >- - If true, markets are included within the event object. If false - (default), markets are returned as a separate top-level field in the - response. Historical markets settled before the historical cutoff - will not be included. + description: If true, markets are included within the event object. If false (default), markets are returned as a separate top-level field in the response. Historical markets settled before the historical cutoff will not be included. schema: type: boolean default: false @@ -880,12 +789,13 @@ paths: $ref: '#/components/schemas/GetEventResponse' '400': description: Bad request - '401': - description: Unauthorized '404': description: Event not found + '401': + description: Unauthorized '500': description: Internal server error + /events/{event_ticker}/metadata: get: operationId: GetEventMetadata @@ -909,19 +819,18 @@ paths: $ref: '#/components/schemas/GetEventMetadataResponse' '400': description: Bad request - '401': - description: Unauthorized '404': description: Event not found + '401': + description: Unauthorized '500': description: Internal server error + /series/{series_ticker}/events/{ticker}/forecast_percentile_history: get: operationId: GetEventForecastPercentilesHistory summary: Get Event Forecast Percentile History - description: >- - Endpoint for getting the historical raw and formatted forecast numbers - for an event at specific percentiles. + description: Endpoint for getting the historical raw and formatted forecast numbers for an event at specific percentiles. tags: - events security: @@ -972,44 +881,32 @@ paths: - name: period_interval in: query required: true - description: >- - Specifies the length of each forecast period, in minutes. 0 for - 5-second intervals, or 1, 60, or 1440 for minute-based intervals. + description: Specifies the length of each forecast period, in minutes. 0 for 5-second intervals, or 1, 60, or 1440 for minute-based intervals. schema: type: integer format: int32 - enum: - - 0 - - 1 - - 60 - - 1440 + enum: [0, 1, 60, 1440] responses: '200': description: Event forecast percentile history retrieved successfully content: application/json: schema: - $ref: >- - #/components/schemas/GetEventForecastPercentilesHistoryResponse + $ref: '#/components/schemas/GetEventForecastPercentilesHistoryResponse' '400': description: Bad request '401': description: Unauthorized '500': description: Internal server error + /portfolio/orders: get: operationId: GetOrders summary: Get Orders - description: > - Restricts the response to orders that have a certain status: resting, - canceled, or executed. - - Orders that have been canceled or fully executed before the historical - cutoff are only available via `GET /historical/orders`. Resting orders - will always be available through this endpoint. See [Historical - Data](https://docs.kalshi.com/getting_started/historical_data) for - details. + description: | + Restricts the response to orders that have a certain status: resting, canceled, or executed. + Orders that have been canceled or fully executed before the historical cutoff are only available via `GET /historical/orders`. Resting orders will always be available through this endpoint. See [Historical Data](https://docs.kalshi.com/getting_started/historical_data) for details. tags: - orders security: @@ -1038,18 +935,15 @@ paths: $ref: '#/components/responses/UnauthorizedError' '500': $ref: '#/components/responses/InternalServerError' + post: operationId: CreateOrder summary: Create Order description: ' Endpoint for submitting orders in a market. Each user is limited to 200 000 open orders at a time.' x-mint: - content: > + content: | - - **Rate limit:** 100 tokens per request. See `GET - /trade-api/v2/account/endpoint_costs` for current non-default endpoint - costs. - + **Rate limit:** 100 tokens per request. See `GET /trade-api/v2/account/endpoint_costs` for current non-default endpoint costs. tags: - orders @@ -1080,19 +974,16 @@ paths: $ref: '#/components/responses/RateLimitError' '500': $ref: '#/components/responses/InternalServerError' + /portfolio/orders/{order_id}: get: operationId: GetOrder summary: Get Order description: ' Endpoint for getting a single order.' x-mint: - content: > + content: | - - **Rate limit:** 2 tokens per request. See `GET - /trade-api/v2/account/endpoint_costs` for current non-default endpoint - costs. - + **Rate limit:** 2 tokens per request. See `GET /trade-api/v2/account/endpoint_costs` for current non-default endpoint costs. tags: - orders @@ -1115,18 +1006,15 @@ paths: $ref: '#/components/responses/NotFoundError' '500': $ref: '#/components/responses/InternalServerError' + delete: operationId: CancelOrder summary: Cancel Order description: ' Endpoint for canceling orders. The value for the orderId should match the id field of the order you want to decrease. Commonly, DELETE-type endpoints return 204 status with no body content on success. But we can''t completely delete the order, as it may be partially filled already. Instead, the DeleteOrder endpoint reduce the order completely, essentially zeroing the remaining resting contracts on it. The zeroed order is returned on the response payload as a form of validation for the client.' x-mint: - content: > + content: | - - **Rate limit:** 2 tokens per request. See `GET - /trade-api/v2/account/endpoint_costs` for current non-default endpoint - costs. - + **Rate limit:** 2 tokens per request. See `GET /trade-api/v2/account/endpoint_costs` for current non-default endpoint costs. tags: - orders @@ -1151,23 +1039,16 @@ paths: $ref: '#/components/responses/NotFoundError' '500': $ref: '#/components/responses/InternalServerError' + /portfolio/orders/batched: post: operationId: BatchCreateOrders summary: Batch Create Orders - description: >- - Endpoint for submitting a batch of orders. The maximum batch size scales - with your tier's write budget — see [Rate Limits and - Tiers](/getting_started/rate_limits). + description: 'Endpoint for submitting a batch of orders. The maximum batch size scales with your tier''s write budget — see [Rate Limits and Tiers](/getting_started/rate_limits).' x-mint: - content: > + content: | - - **Rate limit:** 10 tokens per order in the batch — billed per item, so - total cost for a batch of N orders is N × 10. See `GET - /trade-api/v2/account/endpoint_costs` for current non-default endpoint - costs. - + **Rate limit:** 10 tokens per order in the batch — billed per item, so total cost for a batch of N orders is N × 10. See `GET /trade-api/v2/account/endpoint_costs` for current non-default endpoint costs. tags: - orders @@ -1196,22 +1077,15 @@ paths: $ref: '#/components/responses/ForbiddenError' '500': $ref: '#/components/responses/InternalServerError' + delete: operationId: BatchCancelOrders summary: Batch Cancel Orders - description: >- - Endpoint for cancelling a batch of orders. The maximum batch size scales - with your tier's write budget — see [Rate Limits and - Tiers](/getting_started/rate_limits). + description: 'Endpoint for cancelling a batch of orders. The maximum batch size scales with your tier''s write budget — see [Rate Limits and Tiers](/getting_started/rate_limits).' x-mint: - content: > + content: | - - **Rate limit:** 2 tokens per order in the batch — billed per item, so - total cost for a batch of N cancels is N × 2. See `GET - /trade-api/v2/account/endpoint_costs` for current non-default endpoint - costs. - + **Rate limit:** 2 tokens per order in the batch — billed per item, so total cost for a batch of N cancels is N × 2. See `GET /trade-api/v2/account/endpoint_costs` for current non-default endpoint costs. tags: - orders @@ -1240,20 +1114,16 @@ paths: $ref: '#/components/responses/ForbiddenError' '500': $ref: '#/components/responses/InternalServerError' + /portfolio/orders/{order_id}/amend: post: operationId: AmendOrder summary: Amend Order description: ' Endpoint for amending the max number of fillable contracts and/or price in an existing order. Max fillable contracts is `remaining_count` + `fill_count`.' x-mint: - content: > + content: | - - Amending a resting order preserves queue position only when the - amendment decreases size. All other amendments — like increasing size - or changing price forfeit queue position and place the order at the - back of the queue. - + Amending a resting order preserves queue position only when the amendment decreases size. All other amendments — like increasing size or changing price forfeit queue position and place the order at the back of the queue. tags: - orders @@ -1284,19 +1154,16 @@ paths: $ref: '#/components/responses/NotFoundError' '500': $ref: '#/components/responses/InternalServerError' + /portfolio/orders/{order_id}/decrease: post: operationId: DecreaseOrder summary: Decrease Order description: ' Endpoint for decreasing the number of contracts in an existing order. This is the only kind of edit available on order quantity. Cancelling an order is equivalent to decreasing an order amount to zero.' x-mint: - content: > + content: | - - **Rate limit:** 100 tokens per request. See `GET - /trade-api/v2/account/endpoint_costs` for current non-default endpoint - costs. - + **Rate limit:** 100 tokens per request. See `GET /trade-api/v2/account/endpoint_costs` for current non-default endpoint costs. tags: - orders @@ -1327,6 +1194,7 @@ paths: $ref: '#/components/responses/NotFoundError' '500': $ref: '#/components/responses/InternalServerError' + /portfolio/orders/queue_positions: get: operationId: GetOrderQueuePositions @@ -1363,6 +1231,7 @@ paths: $ref: '#/components/responses/UnauthorizedError' '500': $ref: '#/components/responses/InternalServerError' + /portfolio/orders/{order_id}/queue_position: get: operationId: GetOrderQueuePosition @@ -1389,16 +1258,12 @@ paths: $ref: '#/components/responses/NotFoundError' '500': $ref: '#/components/responses/InternalServerError' + /portfolio/events/orders: post: operationId: CreateOrderV2 summary: Create Order (V2) - description: >- - Endpoint for submitting event-market orders using the V2 - request/response shape (single-book `bid`/`ask` side and fixed-point - dollar prices). The legacy `/portfolio/orders` endpoint will be - deprecated no earlier than May 6, 2026 — clients should migrate to this - path. + description: 'Endpoint for submitting event-market orders using the V2 request/response shape (single-book `bid`/`ask` side and fixed-point dollar prices). The legacy `/portfolio/orders` endpoint will be deprecated no earlier than May 6, 2026 — clients should migrate to this path.' tags: - orders security: @@ -1428,24 +1293,16 @@ paths: $ref: '#/components/responses/RateLimitError' '500': $ref: '#/components/responses/InternalServerError' + /portfolio/events/orders/batched: post: operationId: BatchCreateOrdersV2 summary: Batch Create Orders (V2) - description: >- - Endpoint for submitting a batch of event-market orders using the V2 - request/response shape. The maximum batch size scales with your tier's - write budget — see [Rate Limits and - Tiers](/getting_started/rate_limits). + description: 'Endpoint for submitting a batch of event-market orders using the V2 request/response shape. The maximum batch size scales with your tier''s write budget — see [Rate Limits and Tiers](/getting_started/rate_limits).' x-mint: - content: > + content: | - - **Rate limit:** 10 tokens per order in the batch — billed per item, so - total cost for a batch of N orders is N × 10. See `GET - /trade-api/v2/account/endpoint_costs` for current non-default endpoint - costs. - + **Rate limit:** 10 tokens per order in the batch — billed per item, so total cost for a batch of N orders is N × 10. See `GET /trade-api/v2/account/endpoint_costs` for current non-default endpoint costs. tags: - orders @@ -1474,22 +1331,15 @@ paths: $ref: '#/components/responses/ForbiddenError' '500': $ref: '#/components/responses/InternalServerError' + delete: operationId: BatchCancelOrdersV2 summary: Batch Cancel Orders (V2) - description: >- - Endpoint for cancelling a batch of event-market orders using the V2 - response shape. The maximum batch size scales with your tier's write - budget — see [Rate Limits and Tiers](/getting_started/rate_limits). + description: 'Endpoint for cancelling a batch of event-market orders using the V2 response shape. The maximum batch size scales with your tier''s write budget — see [Rate Limits and Tiers](/getting_started/rate_limits).' x-mint: - content: > + content: | - - **Rate limit:** 2 tokens per order in the batch — billed per item, so - total cost for a batch of N cancels is N × 2. See `GET - /trade-api/v2/account/endpoint_costs` for current non-default endpoint - costs. - + **Rate limit:** 2 tokens per order in the batch — billed per item, so total cost for a batch of N cancels is N × 2. See `GET /trade-api/v2/account/endpoint_costs` for current non-default endpoint costs. tags: - orders @@ -1518,22 +1368,16 @@ paths: $ref: '#/components/responses/ForbiddenError' '500': $ref: '#/components/responses/InternalServerError' + /portfolio/events/orders/{order_id}: delete: operationId: CancelOrderV2 summary: Cancel Order (V2) - description: >- - Endpoint for cancelling event-market orders using the V2 response shape. - Returns `{order_id, client_order_id, reduced_by}` rather than a full - order object. + description: 'Endpoint for cancelling event-market orders using the V2 response shape. Returns `{order_id, client_order_id, reduced_by}` rather than a full order object.' x-mint: - content: > + content: | - - **Rate limit:** 2 tokens per request. See `GET - /trade-api/v2/account/endpoint_costs` for current non-default endpoint - costs. - + **Rate limit:** 2 tokens per request. See `GET /trade-api/v2/account/endpoint_costs` for current non-default endpoint costs. tags: - orders @@ -1558,25 +1402,16 @@ paths: $ref: '#/components/responses/NotFoundError' '500': $ref: '#/components/responses/InternalServerError' + /portfolio/events/orders/{order_id}/amend: post: operationId: AmendOrderV2 summary: Amend Order (V2) - description: >- - Endpoint for amending the price and/or max fillable count of an existing - event-market order using the V2 request/response shape. The request - `count` is the updated total/max fillable count, equal to already filled - count plus desired resting remaining count. This behavior matches the v1 - amend endpoints; only the request/response shape differs. + description: 'Endpoint for amending the price and/or max fillable count of an existing event-market order using the V2 request/response shape. The request `count` is the updated total/max fillable count, equal to already filled count plus desired resting remaining count. This behavior matches the v1 amend endpoints; only the request/response shape differs.' x-mint: - content: > + content: | - - Amending a resting order preserves queue position only when the - amendment decreases size. All other amendments — like increasing size - or changing price forfeit queue position and place the order at the - back of the queue. - + Amending a resting order preserves queue position only when the amendment decreases size. All other amendments — like increasing size or changing price forfeit queue position and place the order at the back of the queue. tags: - orders @@ -1608,14 +1443,12 @@ paths: $ref: '#/components/responses/NotFoundError' '500': $ref: '#/components/responses/InternalServerError' + /portfolio/events/orders/{order_id}/decrease: post: operationId: DecreaseOrderV2 summary: Decrease Order (V2) - description: >- - Endpoint for decreasing the remaining count of an existing event-market - order using the V2 request/response shape. Exactly one of `reduce_by` or - `reduce_to` must be provided. + description: 'Endpoint for decreasing the remaining count of an existing event-market order using the V2 request/response shape. Exactly one of `reduce_by` or `reduce_to` must be provided.' tags: - orders security: @@ -1646,6 +1479,7 @@ paths: $ref: '#/components/responses/NotFoundError' '500': $ref: '#/components/responses/InternalServerError' + /portfolio/order_groups: get: operationId: GetOrderGroups @@ -1672,6 +1506,7 @@ paths: $ref: '#/components/responses/UnauthorizedError' '500': $ref: '#/components/responses/InternalServerError' + /portfolio/order_groups/create: post: operationId: CreateOrderGroup @@ -1702,6 +1537,7 @@ paths: $ref: '#/components/responses/UnauthorizedError' '500': $ref: '#/components/responses/InternalServerError' + /portfolio/order_groups/{order_group_id}: get: operationId: GetOrderGroup @@ -1756,6 +1592,7 @@ paths: $ref: '#/components/responses/NotFoundError' '500': $ref: '#/components/responses/InternalServerError' + /portfolio/order_groups/{order_group_id}/reset: put: operationId: ResetOrderGroup @@ -1790,6 +1627,7 @@ paths: $ref: '#/components/responses/NotFoundError' '500': $ref: '#/components/responses/InternalServerError' + /portfolio/order_groups/{order_group_id}/trigger: put: operationId: TriggerOrderGroup @@ -1824,6 +1662,7 @@ paths: $ref: '#/components/responses/NotFoundError' '500': $ref: '#/components/responses/InternalServerError' + /portfolio/order_groups/{order_group_id}/limit: put: operationId: UpdateOrderGroupLimit @@ -1859,11 +1698,13 @@ paths: $ref: '#/components/responses/NotFoundError' '500': $ref: '#/components/responses/InternalServerError' + + # Portfolio endpoints /portfolio/balance: get: operationId: GetBalance summary: Get Balance - description: ' Endpoint for getting the balance and portfolio value of a member. Both values are returned in cents.' + description: "Endpoint for getting the balance and portfolio value of a member. Both values are returned in cents. This endpoint also accepts API keys with the 'read::portfolio_balance' scope." tags: - portfolio security: @@ -1883,15 +1724,12 @@ paths: $ref: '#/components/responses/UnauthorizedError' '500': $ref: '#/components/responses/InternalServerError' + /portfolio/subaccounts: post: operationId: CreateSubaccount summary: Create Subaccount - description: >- - Creates a new subaccount for the authenticated user. This endpoint is - currently only available to institutions and market makers. Subaccounts - are numbered sequentially starting from 1. Maximum 63 numbered - subaccounts per user (64 including the primary account). + description: 'Creates a new subaccount for the authenticated user. This endpoint is currently only available to institutions and market makers. Subaccounts are numbered sequentially starting from 1. Maximum 63 numbered subaccounts per user (64 including the primary account).' tags: - portfolio security: @@ -1911,13 +1749,12 @@ paths: $ref: '#/components/responses/UnauthorizedError' '500': $ref: '#/components/responses/InternalServerError' + /portfolio/subaccounts/transfer: post: operationId: ApplySubaccountTransfer summary: Transfer Between Subaccounts - description: >- - Transfers funds between the authenticated user's subaccounts. Use 0 for - the primary account, or 1-63 for numbered subaccounts. + description: 'Transfers funds between the authenticated user''s subaccounts. Use 0 for the primary account, or 1-63 for numbered subaccounts.' tags: - portfolio security: @@ -1943,11 +1780,12 @@ paths: $ref: '#/components/responses/UnauthorizedError' '500': $ref: '#/components/responses/InternalServerError' + /portfolio/subaccounts/balances: get: operationId: GetSubaccountBalances summary: Get All Subaccount Balances - description: Gets balances for all subaccounts including the primary account. + description: 'Gets balances for all subaccounts including the primary account.' tags: - portfolio security: @@ -1965,13 +1803,12 @@ paths: $ref: '#/components/responses/UnauthorizedError' '500': $ref: '#/components/responses/InternalServerError' + /portfolio/subaccounts/transfers: get: operationId: GetSubaccountTransfers summary: Get Subaccount Transfers - description: >- - Gets a paginated list of all transfers between subaccounts for the - authenticated user. + description: 'Gets a paginated list of all transfers between subaccounts for the authenticated user.' tags: - portfolio security: @@ -1992,13 +1829,12 @@ paths: $ref: '#/components/responses/UnauthorizedError' '500': $ref: '#/components/responses/InternalServerError' + /portfolio/subaccounts/netting: put: operationId: UpdateSubaccountNetting summary: Update Subaccount Netting - description: >- - Updates the netting enabled setting for a specific subaccount. Use 0 for - the primary account, or 1-63 for numbered subaccounts. + description: 'Updates the netting enabled setting for a specific subaccount. Use 0 for the primary account, or 1-63 for numbered subaccounts.' tags: - portfolio security: @@ -2023,7 +1859,7 @@ paths: get: operationId: GetSubaccountNetting summary: Get Subaccount Netting - description: Gets the netting enabled settings for all subaccounts. + description: 'Gets the netting enabled settings for all subaccounts.' tags: - portfolio security: @@ -2041,14 +1877,12 @@ paths: $ref: '#/components/responses/UnauthorizedError' '500': $ref: '#/components/responses/InternalServerError' + /portfolio/positions: get: operationId: GetPositions summary: Get Positions - description: >- - Restricts the positions to those with any of following fields with - non-zero values, as a comma separated list. The following values are - accepted: position, total_traded + description: 'Restricts the positions to those with any of following fields with non-zero values, as a comma separated list. The following values are accepted: position, total_traded' tags: - portfolio security: @@ -2075,6 +1909,7 @@ paths: $ref: '#/components/responses/UnauthorizedError' '500': $ref: '#/components/responses/InternalServerError' + /portfolio/settlements: get: operationId: GetSettlements @@ -2107,11 +1942,12 @@ paths: $ref: '#/components/responses/UnauthorizedError' '500': $ref: '#/components/responses/InternalServerError' + /portfolio/deposits: get: operationId: GetDeposits summary: Get Deposits - description: Endpoint for getting the member's deposit history. + description: 'Endpoint for getting the member''s deposit history.' tags: - portfolio security: @@ -2134,11 +1970,12 @@ paths: $ref: '#/components/responses/UnauthorizedError' '500': $ref: '#/components/responses/InternalServerError' + /portfolio/withdrawals: get: operationId: GetWithdrawals summary: Get Withdrawals - description: Endpoint for getting the member's withdrawal history. + description: 'Endpoint for getting the member''s withdrawal history.' tags: - portfolio security: @@ -2161,6 +1998,7 @@ paths: $ref: '#/components/responses/UnauthorizedError' '500': $ref: '#/components/responses/InternalServerError' + /portfolio/summary/total_resting_order_value: get: operationId: GetPortfolioRestingOrderTotalValue @@ -2178,24 +2016,19 @@ paths: content: application/json: schema: - $ref: >- - #/components/schemas/GetPortfolioRestingOrderTotalValueResponse + $ref: '#/components/schemas/GetPortfolioRestingOrderTotalValueResponse' '401': $ref: '#/components/responses/UnauthorizedError' '500': $ref: '#/components/responses/InternalServerError' + /portfolio/fills: get: operationId: GetFills summary: Get Fills - description: > - Endpoint for getting all fills for the member. A fill is when a trade - you have is matched. - - Fills that occurred before the historical cutoff are only available via - `GET /historical/fills`. See [Historical - Data](https://docs.kalshi.com/getting_started/historical_data) for - details. + description: | + Endpoint for getting all fills for the member. A fill is when a trade you have is matched. + Fills that occurred before the historical cutoff are only available via `GET /historical/fills`. See [Historical Data](https://docs.kalshi.com/getting_started/historical_data) for details. tags: - portfolio security: @@ -2223,6 +2056,7 @@ paths: description: Unauthorized '500': description: Internal server error + /communications/id: get: operationId: GetCommunicationsID @@ -2245,6 +2079,117 @@ paths: $ref: '#/components/responses/UnauthorizedError' '500': $ref: '#/components/responses/InternalServerError' + + /communications/block-trade-proposals: + get: + operationId: GetBlockTradeProposals + summary: Get Block Trade Proposals + description: ' Endpoint for getting block trade proposals visible to the authenticated user.' + tags: + - communications + security: + - kalshiAccessKey: [] + kalshiAccessSignature: [] + kalshiAccessTimestamp: [] + parameters: + - $ref: '#/components/parameters/CursorQuery' + - $ref: '#/components/parameters/MarketTickerQuery' + - name: limit + in: query + description: Parameter to specify the number of results per page. Defaults to 100. + schema: + type: integer + format: int32 + minimum: 1 + maximum: 100 + default: 100 + - name: status + in: query + description: Filter block trade proposals by status + schema: + type: string + responses: + '200': + description: Block trade proposals retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/GetBlockTradeProposalsResponse' + '400': + $ref: '#/components/responses/BadRequestError' + '401': + $ref: '#/components/responses/UnauthorizedError' + '500': + $ref: '#/components/responses/InternalServerError' + + post: + operationId: ProposeBlockTrade + summary: Propose Block Trade + description: ' Endpoint for creating a block trade proposal.' + tags: + - communications + security: + - kalshiAccessKey: [] + kalshiAccessSignature: [] + kalshiAccessTimestamp: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ProposeBlockTradeRequest' + responses: + '201': + description: Block trade proposal created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/ProposeBlockTradeResponse' + '400': + $ref: '#/components/responses/BadRequestError' + '401': + $ref: '#/components/responses/UnauthorizedError' + '403': + $ref: '#/components/responses/ForbiddenError' + '500': + $ref: '#/components/responses/InternalServerError' + + /communications/block-trade-proposals/{block_trade_proposal_id}/accept: + post: + operationId: AcceptBlockTradeProposal + summary: Accept Block Trade Proposal + description: ' Endpoint for accepting a block trade proposal.' + tags: + - communications + security: + - kalshiAccessKey: [] + kalshiAccessSignature: [] + kalshiAccessTimestamp: [] + parameters: + - name: block_trade_proposal_id + in: path + required: true + description: Block trade proposal ID + schema: + type: string + requestBody: + required: false + content: + application/json: + schema: + $ref: '#/components/schemas/AcceptBlockTradeProposalRequest' + responses: + '204': + description: Block trade proposal accepted successfully + '400': + $ref: '#/components/responses/BadRequestError' + '401': + $ref: '#/components/responses/UnauthorizedError' + '404': + $ref: '#/components/responses/NotFoundError' + '500': + $ref: '#/components/responses/InternalServerError' + /communications/rfqs: get: operationId: GetRFQs @@ -2263,9 +2208,7 @@ paths: - $ref: '#/components/parameters/SubaccountQuery' - name: limit in: query - description: >- - Parameter to specify the number of results per page. Defaults to - 100. + description: Parameter to specify the number of results per page. Defaults to 100. schema: type: integer format: int32 @@ -2290,7 +2233,7 @@ paths: $ref: '#/components/schemas/UserFilter' x-go-type-skip-optional-pointer: true x-oapi-codegen-extra-tags: - validate: omitempty,oneof=self + validate: "omitempty,oneof=self" responses: '200': description: RFQs retrieved successfully @@ -2302,6 +2245,7 @@ paths: $ref: '#/components/responses/UnauthorizedError' '500': $ref: '#/components/responses/InternalServerError' + post: operationId: CreateRFQ summary: Create RFQ @@ -2333,6 +2277,7 @@ paths: $ref: '#/components/responses/ConflictError' '500': $ref: '#/components/responses/InternalServerError' + /communications/rfqs/{rfq_id}: get: operationId: GetRFQ @@ -2359,6 +2304,7 @@ paths: $ref: '#/components/responses/NotFoundError' '500': $ref: '#/components/responses/InternalServerError' + delete: operationId: DeleteRFQ summary: Delete RFQ @@ -2380,6 +2326,7 @@ paths: $ref: '#/components/responses/NotFoundError' '500': $ref: '#/components/responses/InternalServerError' + /communications/quotes: get: operationId: GetQuotes @@ -2395,18 +2342,28 @@ paths: - $ref: '#/components/parameters/CursorQuery' - $ref: '#/components/parameters/SingleEventTickerQuery' - $ref: '#/components/parameters/MarketTickerQuery' - - name: limit + - name: min_ts in: query - description: >- - Parameter to specify the number of results per page. Defaults to - 500. + description: Restricts the response to quotes last updated after a timestamp, formatted as a Unix Timestamp schema: type: integer - format: int32 - minimum: 1 - maximum: 500 - default: 500 - - name: status + format: int64 + - name: max_ts + in: query + description: Restricts the response to quotes last updated before a timestamp, formatted as a Unix Timestamp + schema: + type: integer + format: int64 + - name: limit + in: query + description: Parameter to specify the number of results per page. Defaults to 500. + schema: + type: integer + format: int32 + minimum: 1 + maximum: 500 + default: 500 + - name: status in: query description: Filter quotes by status schema: @@ -2427,18 +2384,16 @@ paths: $ref: '#/components/schemas/UserFilter' x-go-type-skip-optional-pointer: true x-oapi-codegen-extra-tags: - validate: omitempty,oneof=self + validate: "omitempty,oneof=self" - name: rfq_user_filter in: query required: false - description: >- - Filter for quotes responding to RFQs created by the authenticated - user. + description: Filter for quotes responding to RFQs created by the authenticated user. schema: $ref: '#/components/schemas/UserFilter' x-go-type-skip-optional-pointer: true x-oapi-codegen-extra-tags: - validate: omitempty,oneof=self + validate: "omitempty,oneof=self" - name: rfq_creator_user_id in: query description: Filter quotes by RFQ creator user ID @@ -2469,18 +2424,15 @@ paths: $ref: '#/components/responses/UnauthorizedError' '500': $ref: '#/components/responses/InternalServerError' + post: operationId: CreateQuote summary: Create Quote description: ' Endpoint for creating a quote in response to an RFQ' x-mint: - content: > + content: | - - **Rate limit:** 2 tokens per request. See `GET - /trade-api/v2/account/endpoint_costs` for current non-default endpoint - costs. - + **Rate limit:** 2 tokens per request. See `GET /trade-api/v2/account/endpoint_costs` for current non-default endpoint costs. tags: - communications @@ -2507,6 +2459,7 @@ paths: $ref: '#/components/responses/UnauthorizedError' '500': $ref: '#/components/responses/InternalServerError' + /communications/quotes/{quote_id}: get: operationId: GetQuote @@ -2533,18 +2486,15 @@ paths: $ref: '#/components/responses/NotFoundError' '500': $ref: '#/components/responses/InternalServerError' + delete: operationId: DeleteQuote summary: Delete Quote description: ' Endpoint for deleting a quote, which means it can no longer be accepted.' x-mint: - content: > + content: | - - **Rate limit:** 2 tokens per request. See `GET - /trade-api/v2/account/endpoint_costs` for current non-default endpoint - costs. - + **Rate limit:** 2 tokens per request. See `GET /trade-api/v2/account/endpoint_costs` for current non-default endpoint costs. tags: - communications @@ -2563,6 +2513,7 @@ paths: $ref: '#/components/responses/NotFoundError' '500': $ref: '#/components/responses/InternalServerError' + /communications/quotes/{quote_id}/accept: put: operationId: AcceptQuote @@ -2593,6 +2544,7 @@ paths: $ref: '#/components/responses/NotFoundError' '500': $ref: '#/components/responses/InternalServerError' + /communications/quotes/{quote_id}/confirm: put: operationId: ConfirmQuote @@ -2621,6 +2573,8 @@ paths: $ref: '#/components/responses/NotFoundError' '500': $ref: '#/components/responses/InternalServerError' + + # Multivariate Event Collections endpoints /api_keys: get: operationId: GetApiKeys @@ -2643,6 +2597,7 @@ paths: description: Unauthorized '500': description: Internal server error + post: operationId: CreateApiKey summary: Create API Key @@ -2674,6 +2629,7 @@ paths: description: Forbidden - insufficient API usage level '500': description: Internal server error + /api_keys/generate: post: operationId: GenerateApiKey @@ -2704,6 +2660,7 @@ paths: description: Unauthorized '500': description: Internal server error + /api_keys/{api_key}: delete: operationId: DeleteApiKey @@ -2733,10 +2690,11 @@ paths: description: API key not found '500': description: Internal server error + /account/limits: get: operationId: GetAccountApiLimits - summary: Get Account API Limits + summary: Get Account API Limits description: ' Endpoint to retrieve the API tier limits associated with the authenticated user.' tags: - account @@ -2755,23 +2713,16 @@ paths: description: Unauthorized '500': description: Internal server error + /account/api_usage_level/upgrade: post: operationId: UpgradeAccountApiUsageLevel summary: Upgrade Account API Usage Level - description: >- - Grants a permanent Advanced API usage-level grant. Currently only the - Predictions exchange instance is supported. Criteria: at least 1 of the - user's last 100 Predictions orders was created via API. Use Get Account - API Limits to inspect the resulting usage tier and grants. + description: 'Grants a permanent Advanced API usage-level grant. Currently only the Predictions exchange instance is supported. Criteria: at least 1 of the user''s last 100 Predictions orders was created via API. Use Get Account API Limits to inspect the resulting usage tier and grants.' x-mint: - content: > + content: | - - **Rate limit:** 30 tokens per request. See `GET - /trade-api/v2/account/endpoint_costs` for current non-default endpoint - costs. - + **Rate limit:** 30 tokens per request. See `GET /trade-api/v2/account/endpoint_costs` for current non-default endpoint costs. tags: - account @@ -2785,22 +2736,40 @@ paths: '401': description: Unauthorized '403': - description: >- - No API-created order was found in the user's latest 100 Predictions - orders + description: No API-created order was found in the user's latest 100 Predictions orders '429': - description: >- - Rate limit exceeded. This endpoint costs 30 tokens and uses the - Predictions Write bucket. + description: Rate limit exceeded. This endpoint costs 30 tokens and uses the Predictions Write bucket. + '500': + description: Internal server error + + /account/api_usage_level/volume_progress: + get: + operationId: GetAccountApiUsageLevelVolumeProgress + summary: Get Account API Usage Level Volume Progress + description: 'Returns the authenticated user''s latest cron-computed trading volume progress toward volume-based API usage tiers for the predictions (event_contract) lane. Volume figures are reported as fixed-point contract counts.' + tags: + - account + security: + - kalshiAccessKey: [] + kalshiAccessSignature: [] + kalshiAccessTimestamp: [] + responses: + '200': + description: Account API usage level volume progress retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/GetAccountApiUsageLevelVolumeProgressResponse' + '401': + description: Unauthorized '500': description: Internal server error + /account/endpoint_costs: get: operationId: GetAccountEndpointCosts summary: List Non-Default Endpoint Costs - description: >- - Lists API v2 endpoints whose configured token cost differs from the - default cost. Endpoints that use the default cost are omitted. + description: 'Lists API v2 endpoints whose configured token cost differs from the default cost. Endpoints that use the default cost are omitted.' tags: - account responses: @@ -2812,16 +2781,15 @@ paths: $ref: '#/components/schemas/GetAccountEndpointCostsResponse' '500': description: Internal server error + /search/tags_by_categories: get: operationId: GetTagsForSeriesCategories summary: Get Tags for Series Categories - description: > + description: | Retrieve tags organized by series categories. - - This endpoint returns a mapping of series categories to their associated - tags, which can be used for filtering and search functionality. + This endpoint returns a mapping of series categories to their associated tags, which can be used for filtering and search functionality. tags: - search responses: @@ -2835,17 +2803,15 @@ paths: description: Unauthorized '500': description: Internal server error + /search/filters_by_sport: get: operationId: GetFiltersForSports summary: Get Filters for Sports - description: > + description: | Retrieve available filters organized by sport. - - This endpoint returns filtering options available for each sport, - including scopes and competitions. It also provides an ordered list of - sports for display purposes. + This endpoint returns filtering options available for each sport, including scopes and competitions. It also provides an ordered list of sports for display purposes. tags: - search responses: @@ -2859,6 +2825,7 @@ paths: description: Unauthorized '500': description: Internal server error + /live_data/milestone/{milestone_id}: get: operationId: GetLiveDataByMilestone @@ -2877,11 +2844,9 @@ paths: in: query required: false description: >- - When true, includes player-level statistics in the live data - response. Supported for Pro Football, Pro Basketball, and College - Men's Basketball milestones that have player ID mappings configured. - Has no effect for other sports or milestones without player - mappings. + When true, includes player-level statistics in the live data response. + Supported for Pro Football, Pro Basketball, and College Men's Basketball milestones that have player ID mappings configured. + Has no effect for other sports or milestones without player mappings. schema: type: boolean default: false @@ -2896,14 +2861,12 @@ paths: description: Live data not found '500': description: Internal server error + /live_data/{type}/milestone/{milestone_id}: get: operationId: GetLiveData summary: Get Live Data (with type) - description: >- - Get live data for a specific milestone. This is the legacy endpoint that - requires a type path parameter. Prefer using - `/live_data/milestone/{milestone_id}` instead. + description: Get live data for a specific milestone. This is the legacy endpoint that requires a type path parameter. Prefer using `/live_data/milestone/{milestone_id}` instead. tags: - live-data parameters: @@ -2923,11 +2886,9 @@ paths: in: query required: false description: >- - When true, includes player-level statistics in the live data - response. Supported for Pro Football, Pro Basketball, and College - Men's Basketball milestones that have player ID mappings configured. - Has no effect for other sports or milestones without player - mappings. + When true, includes player-level statistics in the live data response. + Supported for Pro Football, Pro Basketball, and College Men's Basketball milestones that have player ID mappings configured. + Has no effect for other sports or milestones without player mappings. schema: type: boolean default: false @@ -2942,6 +2903,7 @@ paths: description: Live data not found '500': description: Internal server error + /live_data/batch: get: operationId: GetLiveDatas @@ -2965,11 +2927,9 @@ paths: in: query required: false description: >- - When true, includes player-level statistics in the live data - response. Supported for Pro Football, Pro Basketball, and College - Men's Basketball milestones that have player ID mappings configured. - Has no effect for other sports or milestones without player - mappings. + When true, includes player-level statistics in the live data response. + Supported for Pro Football, Pro Basketball, and College Men's Basketball milestones that have player ID mappings configured. + Has no effect for other sports or milestones without player mappings. schema: type: boolean default: false @@ -2982,16 +2942,15 @@ paths: $ref: '#/components/schemas/GetLiveDatasResponse' '500': description: Internal server error + /live_data/milestone/{milestone_id}/game_stats: get: operationId: GetGameStats summary: Get Game Stats description: >- - Get play-by-play game statistics for a specific milestone. Supported - sports: Pro Football, College Football, Pro Basketball, College Men's - Basketball, College Women's Basketball, WNBA, Soccer, Pro Hockey, and - Pro Baseball. Returns null for unsupported milestone types or milestones - without a Sportradar ID. + Get play-by-play game statistics for a specific milestone. + Supported sports: Pro Football, College Football, Pro Basketball, College Men's Basketball, College Women's Basketball, WNBA, Soccer, Pro Hockey, and Pro Baseball. + Returns null for unsupported milestone types or milestones without a Sportradar ID. tags: - live-data parameters: @@ -3012,6 +2971,8 @@ paths: description: Game stats not found '500': description: Internal server error + + /structured_targets: get: operationId: GetStructuredTargets @@ -3022,9 +2983,7 @@ paths: parameters: - name: ids in: query - description: >- - Filter by specific structured target IDs. Pass multiple IDs by - repeating the parameter (e.g. `?ids=uuid1&ids=uuid2`). + description: Filter by specific structured target IDs. Pass multiple IDs by repeating the parameter (e.g. `?ids=uuid1&ids=uuid2`). required: false schema: type: array @@ -3042,9 +3001,7 @@ paths: example: basketball_player - name: competition in: query - description: >- - Filter by competition. Matches against the league, conference, - division, or tour in the structured target details. + description: 'Filter by competition. Matches against the league, conference, division, or tour in the structured target details.' required: false schema: type: string @@ -3076,6 +3033,7 @@ paths: description: Unauthorized '500': description: Internal server error + /structured_targets/{structured_target_id}: get: operationId: GetStructuredTarget @@ -3103,6 +3061,7 @@ paths: description: Not found '500': description: Internal server error + /milestones/{milestone_id}: get: operationId: GetMilestone @@ -3132,6 +3091,7 @@ paths: description: Not Found '500': description: Internal Server Error + /milestones: get: operationId: GetMilestones @@ -3157,18 +3117,14 @@ paths: format: date-time - name: category in: query - description: >- - Filter by milestone category. E.g. Sports, Elections, Esports, - Crypto. + description: 'Filter by milestone category. E.g. Sports, Elections, Esports, Crypto.' required: false schema: type: string example: Sports - name: competition in: query - description: >- - Filter by competition. E.g. Pro Football, Pro Basketball (M), Pro - Baseball, Pro Hockey, College Football. + description: 'Filter by competition. E.g. Pro Football, Pro Basketball (M), Pro Baseball, Pro Hockey, College Football.' required: false schema: type: string @@ -3181,10 +3137,7 @@ paths: type: string - name: type in: query - description: >- - Filter by milestone type. E.g. football_game, basketball_game, - soccer_tournament_multi_leg, baseball_game, hockey_match, - political_race. + description: 'Filter by milestone type. E.g. football_game, basketball_game, soccer_tournament_multi_leg, baseball_game, hockey_match, political_race.' required: false schema: type: string @@ -3197,18 +3150,14 @@ paths: type: string - name: cursor in: query - description: >- - Pagination cursor. Use the cursor value returned from the previous - response to get the next page of results + description: Pagination cursor. Use the cursor value returned from the previous response to get the next page of results required: false schema: type: string - name: min_updated_ts in: query required: false - description: >- - Filter milestones with metadata updated after this Unix timestamp - (in seconds). Use this to efficiently poll for changes. + description: Filter milestones with metadata updated after this Unix timestamp (in seconds). Use this to efficiently poll for changes. schema: type: integer format: int64 @@ -3225,6 +3174,8 @@ paths: description: Unauthorized '500': description: Internal Server Error + + # Communications endpoints /multivariate_event_collections/{collection_ticker}: get: operationId: GetMultivariateEventCollection @@ -3255,10 +3206,7 @@ paths: post: operationId: CreateMarketInMultivariateEventCollection summary: Create Market In Multivariate Event Collection - description: >- - Endpoint for creating an individual market in a multivariate event - collection. This endpoint must be hit at least once before trading or - looking up a market. Users are limited to 5000 creations per week. + description: 'Endpoint for creating an individual market in a multivariate event collection. This endpoint must be hit at least once before trading or looking up a market. Users are limited to 5000 creations per week.' tags: - multivariate security: @@ -3277,16 +3225,14 @@ paths: content: application/json: schema: - $ref: >- - #/components/schemas/CreateMarketInMultivariateEventCollectionRequest + $ref: '#/components/schemas/CreateMarketInMultivariateEventCollectionRequest' responses: '200': description: Market created successfully content: application/json: schema: - $ref: >- - #/components/schemas/CreateMarketInMultivariateEventCollectionResponse + $ref: '#/components/schemas/CreateMarketInMultivariateEventCollectionResponse' '400': $ref: '#/components/responses/BadRequestError' '401': @@ -3295,6 +3241,7 @@ paths: $ref: '#/components/responses/RateLimitError' '500': $ref: '#/components/responses/InternalServerError' + /multivariate_event_collections: get: operationId: GetMultivariateEventCollections @@ -3305,15 +3252,10 @@ paths: parameters: - name: status in: query - description: >- - Only return collections of a certain status. Can be unopened, open, - or closed. + description: Only return collections of a certain status. Can be unopened, open, or closed. schema: type: string - enum: - - unopened - - open - - closed + enum: [unopened, open, closed] - name: associated_event_ticker in: query description: Only return collections associated with a particular event ticker. @@ -3334,11 +3276,7 @@ paths: maximum: 200 - name: cursor in: query - description: >- - The Cursor represents a pointer to the next page of records in the - pagination. This optional parameter, when filled, should be filled - with the cursor string returned in a previous request to this - end-point. + description: The Cursor represents a pointer to the next page of records in the pagination. This optional parameter, when filled, should be filled with the cursor string returned in a previous request to this end-point. schema: type: string responses: @@ -3352,33 +3290,21 @@ paths: $ref: '#/components/responses/BadRequestError' '500': $ref: '#/components/responses/InternalServerError' + /multivariate_event_collections/{collection_ticker}/lookup: put: operationId: LookupTickersForMarketInMultivariateEventCollection summary: Lookup Tickers For Market In Multivariate Event Collection deprecated: true - description: >- - DEPRECATED: This endpoint predates RFQs and should not be used for new - integrations. Endpoint for looking up an individual market in a - multivariate event collection. If - CreateMarketInMultivariateEventCollection has never been hit with that - variable combination before, this will return a 404. + description: 'DEPRECATED: This endpoint predates RFQs and should not be used for new integrations. Endpoint for looking up an individual market in a multivariate event collection. If CreateMarketInMultivariateEventCollection has never been hit with that variable combination before, this will return a 404.' x-mint: - content: > + content: | - - This endpoint is deprecated and predates RFQs. Do not use it for new - integrations. - + This endpoint is deprecated and predates RFQs. Do not use it for new integrations. - - - **Rate limit:** 2 tokens per request. See `GET - /trade-api/v2/account/endpoint_costs` for current non-default endpoint - costs. - + **Rate limit:** 2 tokens per request. See `GET /trade-api/v2/account/endpoint_costs` for current non-default endpoint costs. tags: - multivariate @@ -3398,16 +3324,14 @@ paths: content: application/json: schema: - $ref: >- - #/components/schemas/LookupTickersForMarketInMultivariateEventCollectionRequest + $ref: '#/components/schemas/LookupTickersForMarketInMultivariateEventCollectionRequest' responses: '200': description: Market looked up successfully content: application/json: schema: - $ref: >- - #/components/schemas/LookupTickersForMarketInMultivariateEventCollectionResponse + $ref: '#/components/schemas/LookupTickersForMarketInMultivariateEventCollectionResponse' '400': $ref: '#/components/responses/BadRequestError' '401': @@ -3420,17 +3344,11 @@ paths: operationId: GetMultivariateEventCollectionLookupHistory summary: Get Multivariate Event Collection Lookup History deprecated: true - description: >- - DEPRECATED: This endpoint predates RFQs and should not be used for new - integrations. Endpoint for retrieving which markets in an event - collection were recently looked up. + description: 'DEPRECATED: This endpoint predates RFQs and should not be used for new integrations. Endpoint for retrieving which markets in an event collection were recently looked up.' x-mint: - content: > + content: | - - This endpoint is deprecated and predates RFQs. Do not use it for new - integrations. - + This endpoint is deprecated and predates RFQs. Do not use it for new integrations. tags: - multivariate @@ -3444,29 +3362,23 @@ paths: - name: lookback_seconds in: query required: true - description: >- - Number of seconds to look back for lookup history. Must be one of - 10, 60, 300, or 3600. + description: Number of seconds to look back for lookup history. Must be one of 10, 60, 300, or 3600. schema: type: integer format: int32 - enum: - - 10 - - 60 - - 300 - - 3600 + enum: [10, 60, 300, 3600] responses: '200': description: Lookup history retrieved successfully content: application/json: schema: - $ref: >- - #/components/schemas/GetMultivariateEventCollectionLookupHistoryResponse + $ref: '#/components/schemas/GetMultivariateEventCollectionLookupHistoryResponse' '400': $ref: '#/components/responses/BadRequestError' '500': $ref: '#/components/responses/InternalServerError' + /incentive_programs: get: operationId: GetIncentivePrograms @@ -3478,29 +3390,17 @@ paths: - name: status in: query required: false - description: >- - Status filter. Can be "all", "active", "upcoming", "closed", or - "paid_out". Default is "all". + description: 'Status filter. Can be "all", "active", "upcoming", "closed", or "paid_out". Default is "all".' schema: type: string - enum: - - all - - active - - upcoming - - closed - - paid_out + enum: [all, active, upcoming, closed, paid_out] - name: type in: query required: false - description: >- - Type filter. Can be "all", "liquidity", or "volume". Default is - "all". + description: 'Type filter. Can be "all", "liquidity", or "volume". Default is "all".' schema: type: string - enum: - - all - - liquidity - - volume + enum: [all, liquidity, volume] - name: incentive_description in: query required: false @@ -3540,15 +3440,14 @@ paths: application/json: schema: $ref: '#/components/schemas/ErrorResponse' + /fcm/orders: get: operationId: GetFCMOrders summary: Get FCM Orders - description: > + description: | Endpoint for FCM members to get orders filtered by subtrader ID. - - This endpoint requires FCM member access level and allows filtering - orders by subtrader ID. + This endpoint requires FCM member access level and allows filtering orders by subtrader ID. tags: - fcm security: @@ -3559,9 +3458,7 @@ paths: - name: subtrader_id in: query required: true - description: >- - Restricts the response to orders for a specific subtrader (FCM - members only) + description: Restricts the response to orders for a specific subtrader (FCM members only) schema: type: string - $ref: '#/components/parameters/CursorQuery' @@ -3569,17 +3466,13 @@ paths: - $ref: '#/components/parameters/TickerQuery' - name: min_ts in: query - description: >- - Restricts the response to orders after a timestamp, formatted as a - Unix Timestamp + description: Restricts the response to orders after a timestamp, formatted as a Unix Timestamp schema: type: integer format: int64 - name: max_ts in: query - description: >- - Restricts the response to orders before a timestamp, formatted as a - Unix Timestamp + description: Restricts the response to orders before a timestamp, formatted as a Unix Timestamp schema: type: integer format: int64 @@ -3588,10 +3481,7 @@ paths: description: Restricts the response to orders that have a certain status schema: type: string - enum: - - resting - - canceled - - executed + enum: [resting, canceled, executed] - name: limit in: query description: Parameter to specify the number of results per page. Defaults to 100 @@ -3614,16 +3504,14 @@ paths: description: Not found '500': description: Internal server error + /fcm/positions: get: operationId: GetFCMPositions summary: Get FCM Positions - description: > - Endpoint for FCM members to get market positions filtered by subtrader - ID. - - This endpoint requires FCM member access level and allows filtering - positions by subtrader ID. + description: | + Endpoint for FCM members to get market positions filtered by subtrader ID. + This endpoint requires FCM member access level and allows filtering positions by subtrader ID. tags: - fcm security: @@ -3634,9 +3522,7 @@ paths: - name: subtrader_id in: query required: true - description: >- - Restricts the response to positions for a specific subtrader (FCM - members only) + description: Restricts the response to positions for a specific subtrader (FCM members only) schema: type: string - name: ticker @@ -3653,9 +3539,7 @@ paths: x-go-type-skip-optional-pointer: true - name: count_filter in: query - description: >- - Restricts the positions to those with any of following fields with - non-zero values, as a comma separated list + description: Restricts the positions to those with any of following fields with non-zero values, as a comma separated list schema: type: string - name: settlement_status @@ -3663,10 +3547,7 @@ paths: description: Settlement status of the markets to return. Defaults to unsettled schema: type: string - enum: - - all - - unsettled - - settled + enum: [all, unsettled, settled] - name: limit in: query description: Parameter to specify the number of results per page. Defaults to 100 @@ -3676,9 +3557,7 @@ paths: maximum: 1000 - name: cursor in: query - description: >- - The Cursor represents a pointer to the next page of records in the - pagination + description: The Cursor represents a pointer to the next page of records in the pagination schema: type: string responses: @@ -3696,27 +3575,18 @@ paths: description: Not found '500': description: Internal server error + /historical/cutoff: get: operationId: GetHistoricalCutoff summary: Get Historical Cutoff Timestamps - description: > - Returns the cutoff timestamps that define the boundary between **live** - and **historical** data. - + description: | + Returns the cutoff timestamps that define the boundary between **live** and **historical** data. ## Cutoff fields - - - `market_settled_ts` : Markets that **settled** before this timestamp, - and their candlesticks, must be accessed via `GET /historical/markets` - and `GET /historical/markets/{ticker}/candlesticks`. - - - `trades_created_ts` : Trades that were **filled** before this - timestamp must be accessed via `GET /historical/fills`. - - - `orders_updated_ts` : Orders that were **canceled or fully executed** - before this timestamp must be accessed via `GET /historical/orders`. - Resting (active) orders are always available in `GET /portfolio/orders`. + - `market_settled_ts` : Markets that **settled** before this timestamp, and their candlesticks, must be accessed via `GET /historical/markets` and `GET /historical/markets/{ticker}/candlesticks`. + - `trades_created_ts` : Trades that were **filled** before this timestamp must be accessed via `GET /historical/fills`. + - `orders_updated_ts` : Orders that were **canceled or fully executed** before this timestamp must be accessed via `GET /historical/orders`. Resting (active) orders are always available in `GET /portfolio/orders`. tags: - historical responses: @@ -3728,6 +3598,7 @@ paths: $ref: '#/components/schemas/GetHistoricalCutoffResponse' '500': description: Internal server error + /historical/markets/{ticker}/candlesticks: get: operationId: GetMarketCandlesticksHistorical @@ -3745,35 +3616,26 @@ paths: - name: start_ts in: query required: true - description: >- - Start timestamp (Unix timestamp). Candlesticks will include those - ending on or after this time. + description: Start timestamp (Unix timestamp). Candlesticks will include those ending on or after this time. schema: type: integer format: int64 - name: end_ts in: query required: true - description: >- - End timestamp (Unix timestamp). Candlesticks will include those - ending on or before this time. + description: End timestamp (Unix timestamp). Candlesticks will include those ending on or before this time. schema: type: integer format: int64 - name: period_interval in: query required: true - description: >- - Time period length of each candlestick in minutes. Valid values are - 1 (1 minute), 60 (1 hour), or 1440 (1 day). + description: Time period length of each candlestick in minutes. Valid values are 1 (1 minute), 60 (1 hour), or 1440 (1 day). schema: type: integer - enum: - - 1 - - 60 - - 1440 + enum: [1, 60, 1440] x-oapi-codegen-extra-tags: - validate: required,oneof=1 60 1440 + validate: "required,oneof=1 60 1440" responses: '200': description: Candlesticks retrieved successfully @@ -3787,6 +3649,7 @@ paths: description: Not found '500': description: Internal server error + /historical/fills: get: operationId: GetFillsHistorical @@ -3818,11 +3681,12 @@ paths: $ref: '#/components/responses/NotFoundError' '500': description: Internal server error + /historical/orders: get: operationId: GetHistoricalOrders summary: Get Historical Orders - description: ' Endpoint for getting orders that have been archived to the historical database.' + description: ' Endpoint for getting orders that have been archived to the historical database.' tags: - historical security: @@ -3847,6 +3711,7 @@ paths: $ref: '#/components/responses/UnauthorizedError' '500': $ref: '#/components/responses/InternalServerError' + /historical/trades: get: operationId: GetTradesHistorical @@ -3874,13 +3739,13 @@ paths: $ref: '#/components/responses/NotFoundError' '500': $ref: '#/components/responses/InternalServerError' + /historical/markets: get: operationId: GetHistoricalMarkets summary: Get Historical Markets - description: > - Endpoint for getting markets that have been archived to the historical - database. Filters are mutually exclusive. + description: | + Endpoint for getting markets that have been archived to the historical database. Filters are mutually exclusive. tags: - historical parameters: @@ -3901,6 +3766,7 @@ paths: $ref: '#/components/responses/BadRequestError' '500': $ref: '#/components/responses/InternalServerError' + /historical/markets/{ticker}: get: operationId: GetHistoricalMarket @@ -3921,6 +3787,7 @@ paths: $ref: '#/components/responses/NotFoundError' '500': $ref: '#/components/responses/InternalServerError' + components: securitySchemes: kalshiAccessKey: @@ -3938,6 +3805,7 @@ components: in: header name: KALSHI-ACCESS-TIMESTAMP description: Request timestamp in milliseconds + responses: BadRequestError: description: Bad request - invalid input @@ -3976,13 +3844,12 @@ components: schema: $ref: '#/components/schemas/ErrorResponse' RateLimitError: - description: >- - Rate limit exceeded. The default cost is 10 tokens per request. Use GET - /trade-api/v2/account/endpoint_costs to list non-default endpoint costs. + description: 'Rate limit exceeded. The default cost is 10 tokens per request. Use GET /trade-api/v2/account/endpoint_costs to list non-default endpoint costs.' content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' + parameters: LimitQuery: name: limit @@ -3995,7 +3862,8 @@ components: maximum: 1000 default: 100 x-oapi-codegen-extra-tags: - validate: omitempty,min=1,max=1000 + validate: "omitempty,min=1,max=1000" + WithdrawalLimitQuery: name: limit in: query @@ -4007,7 +3875,8 @@ components: maximum: 500 default: 100 x-oapi-codegen-extra-tags: - validate: omitempty,min=1,max=500 + validate: "omitempty,min=1,max=500" + MarketLimitQuery: name: limit in: query @@ -4020,22 +3889,22 @@ components: default: 100 x-oapi-codegen-extra-tags: validate: omitempty,gte=0,lte=1000 + CursorQuery: name: cursor in: query - description: >- - Pagination cursor. Use the cursor value returned from the previous - response to get the next page of results. Leave empty for the first - page. + description: Pagination cursor. Use the cursor value returned from the previous response to get the next page of results. Leave empty for the first page. schema: type: string x-go-type-skip-optional-pointer: true + StatusQuery: name: status in: query description: Filter by status. Possible values depend on the endpoint. schema: type: string + OrderGroupIdPath: name: order_group_id in: path @@ -4043,6 +3912,7 @@ components: description: Order group ID schema: type: string + RfqIdPath: name: rfq_id in: path @@ -4050,6 +3920,7 @@ components: description: RFQ ID schema: type: string + QuoteIdPath: name: quote_id in: path @@ -4057,6 +3928,7 @@ components: description: Quote ID schema: type: string + MarketTickerQuery: name: market_ticker in: query @@ -4064,6 +3936,7 @@ components: schema: type: string x-go-type-skip-optional-pointer: true + TickerQuery: name: ticker in: query @@ -4071,15 +3944,15 @@ components: schema: type: string x-go-type-skip-optional-pointer: true + IsBlockTradeQuery: name: is_block_trade in: query - description: > - Filter trades by whether they are block trades. Omit to return all - trades. Set to `true` to return only block trades. Set to `false` to - return only non-block trades. + description: | + Filter trades by whether they are block trades. Omit to return all trades. Set to `true` to return only block trades. Set to `false` to return only non-block trades. schema: type: boolean + SingleEventTickerQuery: name: event_ticker in: query @@ -4087,6 +3960,7 @@ components: schema: type: string x-go-type-skip-optional-pointer: true + MultipleEventTickerQuery: name: event_ticker in: query @@ -4094,15 +3968,14 @@ components: schema: type: string x-go-type-skip-optional-pointer: true + PositionsCursorQuery: name: cursor in: query - description: >- - The Cursor represents a pointer to the next page of records in the - pagination. Use the value returned from the previous response to get the - next page. + description: The Cursor represents a pointer to the next page of records in the pagination. Use the value returned from the previous response to get the next page. schema: type: string + PositionsLimitQuery: name: limit in: query @@ -4113,15 +3986,14 @@ components: minimum: 1 maximum: 1000 default: 100 + CountFilterQuery: name: count_filter in: query - description: >- - Restricts the positions to those with any of following fields with - non-zero values, as a comma separated list. The following values are - accepted - position, total_traded + description: Restricts the positions to those with any of following fields with non-zero values, as a comma separated list. The following values are accepted - position, total_traded schema: type: string + OrderIdQuery: name: order_id in: query @@ -4129,6 +4001,7 @@ components: schema: type: string x-go-type-skip-optional-pointer: true + MinTsQuery: name: min_ts in: query @@ -4136,6 +4009,7 @@ components: schema: type: integer format: int64 + MaxTsQuery: name: max_ts in: query @@ -4143,26 +4017,28 @@ components: schema: type: integer format: int64 + SubaccountQuery: name: subaccount in: query - description: >- - Subaccount number (0 for primary, 1-63 for subaccounts). If omitted, - defaults to all subaccounts. + description: Subaccount number (0 for primary, 1-63 for subaccounts). If omitted, defaults to all subaccounts. schema: type: integer + SubaccountQueryDefaultPrimary: name: subaccount in: query description: Subaccount number (0 for primary, 1-63 for subaccounts). Defaults to 0. schema: type: integer + ExchangeIndexQuery: name: exchange_index in: query schema: $ref: '#/components/schemas/ExchangeIndex' x-go-type-skip-optional-pointer: true + OrderIdPath: name: order_id in: path @@ -4170,6 +4046,7 @@ components: description: Order ID schema: type: string + TickerPath: name: ticker in: path @@ -4177,6 +4054,7 @@ components: description: Market ticker schema: type: string + SeriesTickerQuery: name: series_ticker in: query @@ -4184,6 +4062,7 @@ components: schema: type: string x-go-type-skip-optional-pointer: true + MinCreatedTsQuery: name: min_created_ts in: query @@ -4191,6 +4070,7 @@ components: schema: type: integer format: int64 + MaxCreatedTsQuery: name: max_created_ts in: query @@ -4198,15 +4078,15 @@ components: schema: type: integer format: int64 + MinUpdatedTsQuery: name: min_updated_ts in: query - description: >- - Return markets with metadata updated later than this Unix timestamp. - Tracks non-trading changes only. Incompatible with any other filters. + description: Return markets with metadata updated later than this Unix timestamp. Tracks non-trading changes only. Incompatible with any other filters except mve_filter=exclude. May be combined with series_ticker, which requires mve_filter=exclude. schema: type: integer format: int64 + MaxCloseTsQuery: name: max_close_ts in: query @@ -4214,6 +4094,7 @@ components: schema: type: integer format: int64 + MinCloseTsQuery: name: min_close_ts in: query @@ -4221,6 +4102,7 @@ components: schema: type: integer format: int64 + MinSettledTsQuery: name: min_settled_ts in: query @@ -4228,6 +4110,7 @@ components: schema: type: integer format: int64 + MaxSettledTsQuery: name: max_settled_ts in: query @@ -4235,86 +4118,73 @@ components: schema: type: integer format: int64 + MarketStatusQuery: name: status in: query description: Filter by market status. Leave empty to return markets with any status. schema: type: string - enum: - - unopened - - open - - paused - - closed - - settled + enum: [unopened, open, paused, closed, settled] + TickersQuery: name: tickers in: query - description: >- - Filter by specific market tickers. Comma-separated list of market - tickers to retrieve. + description: Filter by specific market tickers. Comma-separated list of market tickers to retrieve. + schema: + type: string + + EventTickersQuery: + name: tickers + in: query + description: Filter by specific event tickers. Comma-separated list of event tickers to retrieve. schema: type: string + MveFilterQuery: name: mve_filter in: query - description: >- - Filter by multivariate events (combos). 'only' returns only multivariate - events, 'exclude' excludes multivariate events. + description: Filter by multivariate events (combos). 'only' returns only multivariate events, 'exclude' excludes multivariate events. schema: type: string - enum: - - only - - exclude + enum: ['only', 'exclude'] + MveHistoricalFilterQuery: name: mve_filter in: query - description: >- - Filter by multivariate events (combos). By default, MVE markets are - included. + description: Filter by multivariate events (combos). By default, MVE markets are included. schema: type: string - enum: - - exclude + enum: ['exclude'] nullable: true default: null + schemas: + # Common schemas FixedPointDollars: type: string - description: >- - US dollar amount as a fixed-point decimal string with up to 6 decimal - places of precision. This is the maximum supported precision; valid - quote intervals for a given market are constrained by that market's - price level structure. - example: '0.5600' + description: US dollar amount as a fixed-point decimal string with up to 6 decimal places of precision. This is the maximum supported precision; valid quote intervals for a given market are constrained by that market's price level structure. + example: "0.5600" + FixedPointCount: type: string - description: >- - Fixed-point contract count string (2 decimals, e.g., "10.00"; referred - to as "fp" in field names). Requests accept 0–2 decimal places (e.g., - "10", "10.0", "10.00"); responses always emit 2 decimals. Fractional - contract values (e.g., "2.50") are supported on markets with fractional - trading enabled; the minimum granularity is 0.01 contracts. Integer - contract count fields are legacy and will be deprecated; when both - integer and fp fields are provided, they must match. - example: '10.00' + description: Fixed-point contract count string (2 decimals, e.g., "10.00"; referred to as "fp" in field names). Requests accept 0–2 decimal places (e.g., "10", "10.0", "10.00"); responses always emit 2 decimals. Fractional contract values (e.g., "2.50") are supported on markets with fractional trading enabled; the minimum granularity is 0.01 contracts. Integer contract count fields are legacy and will be deprecated; when both integer and fp fields are provided, they must match. + example: "10.00" + ExchangeIndex: type: integer - description: >- - Identifier for an exchange shard. Defaults to 0 if unspecified. Note: - currently only 0 supported. + description: "Identifier for an exchange shard. Defaults to 0 if unspecified. Note: currently only 0 supported." example: 0 + FeeType: type: string - enum: - - quadratic - - quadratic_with_maker_fees - - flat + enum: [quadratic, quadratic_with_maker_fees, flat] x-enum-varnames: - FeeTypeQuadratic - FeeTypeQuadraticWithMakerFees - FeeTypeFlat description: Fee type for a series or scheduled fee override. + GetMarketCandlesticksHistoricalResponse: type: object required: @@ -4329,6 +4199,7 @@ components: description: Array of candlestick data points for the specified time range. items: $ref: '#/components/schemas/MarketCandlestickHistorical' + MarketCandlestickHistorical: type: object required: @@ -4345,29 +4216,20 @@ components: description: Unix timestamp for the inclusive end of the candlestick period. yes_bid: $ref: '#/components/schemas/BidAskDistributionHistorical' - description: >- - Open, high, low, close (OHLC) data for YES buy offers on the market - during the candlestick period. + description: Open, high, low, close (OHLC) data for YES buy offers on the market during the candlestick period. yes_ask: $ref: '#/components/schemas/BidAskDistributionHistorical' - description: >- - Open, high, low, close (OHLC) data for YES sell offers on the market - during the candlestick period. + description: Open, high, low, close (OHLC) data for YES sell offers on the market during the candlestick period. price: $ref: '#/components/schemas/PriceDistributionHistorical' - description: >- - Open, high, low, close (OHLC) and more data for trade YES contract - prices on the market during the candlestick period. + description: Open, high, low, close (OHLC) and more data for trade YES contract prices on the market during the candlestick period. volume: $ref: '#/components/schemas/FixedPointCount' - description: >- - String representation of the number of contracts bought on the - market during the candlestick period. + description: String representation of the number of contracts bought on the market during the candlestick period. open_interest: $ref: '#/components/schemas/FixedPointCount' - description: >- - String representation of the number of contracts bought on the - market by end of the candlestick period (end_period_ts). + description: String representation of the number of contracts bought on the market by end of the candlestick period (end_period_ts). + BidAskDistributionHistorical: type: object required: @@ -4378,24 +4240,17 @@ components: properties: open: $ref: '#/components/schemas/FixedPointDollars' - description: >- - Offer price on the market at the start of the candlestick period (in - dollars). + description: Offer price on the market at the start of the candlestick period (in dollars). low: $ref: '#/components/schemas/FixedPointDollars' - description: >- - Lowest offer price on the market during the candlestick period (in - dollars). + description: Lowest offer price on the market during the candlestick period (in dollars). high: $ref: '#/components/schemas/FixedPointDollars' - description: >- - Highest offer price on the market during the candlestick period (in - dollars). + description: Highest offer price on the market during the candlestick period (in dollars). close: $ref: '#/components/schemas/FixedPointDollars' - description: >- - Offer price on the market at the end of the candlestick period (in - dollars). + description: Offer price on the market at the end of the candlestick period (in dollars). + PriceDistributionHistorical: type: object required: @@ -4410,44 +4265,33 @@ components: allOf: - $ref: '#/components/schemas/FixedPointDollars' nullable: true - description: >- - Price of the first trade during the candlestick period (in dollars). - Null if no trades occurred. + description: Price of the first trade during the candlestick period (in dollars). Null if no trades occurred. low: allOf: - $ref: '#/components/schemas/FixedPointDollars' nullable: true - description: >- - Lowest trade price during the candlestick period (in dollars). Null - if no trades occurred. + description: Lowest trade price during the candlestick period (in dollars). Null if no trades occurred. high: allOf: - $ref: '#/components/schemas/FixedPointDollars' nullable: true - description: >- - Highest trade price during the candlestick period (in dollars). Null - if no trades occurred. + description: Highest trade price during the candlestick period (in dollars). Null if no trades occurred. close: allOf: - $ref: '#/components/schemas/FixedPointDollars' nullable: true - description: >- - Price of the last trade during the candlestick period (in dollars). - Null if no trades occurred. + description: Price of the last trade during the candlestick period (in dollars). Null if no trades occurred. mean: allOf: - $ref: '#/components/schemas/FixedPointDollars' nullable: true - description: >- - Volume-weighted average price during the candlestick period (in - dollars). Null if no trades occurred. + description: Volume-weighted average price during the candlestick period (in dollars). Null if no trades occurred. previous: allOf: - $ref: '#/components/schemas/FixedPointDollars' nullable: true - description: >- - Close price from the previous candlestick period (in dollars). Null - if this is the first candlestick or no prior trade exists. + description: Close price from the previous candlestick period (in dollars). Null if this is the first candlestick or no prior trade exists. + ErrorResponse: type: object properties: @@ -4463,64 +4307,40 @@ components: service: type: string description: The name of the service that generated the error + SelfTradePreventionType: type: string - enum: - - taker_at_cross - - maker - description: > - The self-trade prevention type for orders. `taker_at_cross` cancels the - taker order when it would trade against another order from the same - user; execution stops and any partial fills already matched are - executed. `maker` cancels the resting maker order and continues - matching. + enum: ['taker_at_cross', 'maker'] + description: | + The self-trade prevention type for orders. `taker_at_cross` cancels the taker order when it would trade against another order from the same user; execution stops and any partial fills already matched are executed. `maker` cancels the resting maker order and continues matching. + BookSide: type: string - enum: - - bid - - ask - description: >- - Side of the book for an order or trade. For event markets, this refers - to the YES leg only: `bid` means buy YES, `ask` means sell YES. (Selling - YES is economically equivalent to buying NO at `1 - price`, but this - endpoint quotes everything from the YES side.) + enum: ['bid', 'ask'] + description: 'Side of the book for an order or trade. For event markets, this refers to the YES leg only: `bid` means buy YES, `ask` means sell YES. (Selling YES is economically equivalent to buying NO at `1 - price`, but this endpoint quotes everything from the YES side.)' + OrderStatus: type: string - enum: - - resting - - canceled - - executed + enum: ['resting', 'canceled', 'executed'] description: The status of an order + ExchangeInstance: type: string - enum: - - event_contract - - margined + enum: ['event_contract', 'margined'] description: The exchange instance type + UserFilter: type: string - enum: - - self - x-enum-varnames: - - UserFilterSelf - description: >- - Omit or leave empty to return all results. Use `self` to filter by the - authenticated user. + enum: ['self'] + x-enum-varnames: ['UserFilterSelf'] + description: Omit or leave empty to return all results. Use `self` to filter by the authenticated user. + ApiKeyScope: type: string - enum: - - read - - write - - write::transfer - x-enum-varnames: - - ApiKeyScopeRead - - ApiKeyScopeWrite - - ApiKeyScopeWriteTransfer - description: >- - Scope granted to an API key. Parent scopes grant broad access; for - example, `read` grants all read endpoints and `write` grants all write - endpoints. Child scopes such as `write::transfer` grant only their - specific endpoint group and can be granted without the parent scope. + enum: ['read', 'write', 'read::block_trade_accept', 'read::portfolio_balance', 'write::transfer', 'write::block_trade_accept'] + x-enum-varnames: ['ApiKeyScopeRead', 'ApiKeyScopeWrite', 'ApiKeyScopeReadBlockTradeAccept', 'ApiKeyScopeReadPortfolioBalance', 'ApiKeyScopeWriteTransfer', 'ApiKeyScopeWriteBlockTradeAccept'] + description: Scope granted to an API key. Parent scopes grant broad access; for example, `read` grants all read endpoints and `write` grants all write endpoints. Child scopes such as `read::block_trade_accept`, `read::portfolio_balance`, `write::transfer`, and `write::block_trade_accept` grant only their specific endpoint group and can be granted without the parent scope. + ApiKey: type: object required: @@ -4539,6 +4359,7 @@ components: description: List of scopes granted to this API key. items: $ref: '#/components/schemas/ApiKeyScope' + GetApiKeysResponse: type: object required: @@ -4549,6 +4370,7 @@ components: description: List of all API keys associated with the user items: $ref: '#/components/schemas/ApiKey' + CreateApiKeyRequest: type: object required: @@ -4560,18 +4382,13 @@ components: description: Name for the API key. This helps identify the key's purpose public_key: type: string - description: >- - RSA public key in PEM format. This will be used to verify signatures - on API requests + description: RSA public key in PEM format. This will be used to verify signatures on API requests scopes: type: array - description: >- - List of scopes to grant to the API key. If the broad `write` parent - scope is included, `read` must also be included. Child write scopes - may be granted without the broad parent scope. Defaults to full - access (`read`, `write`) if not provided. + description: List of scopes to grant to the API key. If the broad `write` parent scope is included, `read` must also be included. Child scopes may be granted without the broad parent scope. Defaults to full access (`read`, `write`) if not provided. items: $ref: '#/components/schemas/ApiKeyScope' + CreateApiKeyResponse: type: object required: @@ -4580,6 +4397,7 @@ components: api_key_id: type: string description: Unique identifier for the newly created API key + GenerateApiKeyRequest: type: object required: @@ -4590,13 +4408,10 @@ components: description: Name for the API key. This helps identify the key's purpose scopes: type: array - description: >- - List of scopes to grant to the API key. If the broad `write` parent - scope is included, `read` must also be included. Child write scopes - may be granted without the broad parent scope. Defaults to full - access (`read`, `write`) if not provided. + description: List of scopes to grant to the API key. If the broad `write` parent scope is included, `read` must also be included. Child scopes may be granted without the broad parent scope. Defaults to full access (`read`, `write`) if not provided. items: $ref: '#/components/schemas/ApiKeyScope' + GenerateApiKeyResponse: type: object required: @@ -4608,9 +4423,8 @@ components: description: Unique identifier for the newly generated API key private_key: type: string - description: >- - RSA private key in PEM format. This must be stored securely and - cannot be retrieved again after this response + description: RSA private key in PEM format. This must be stored securely and cannot be retrieved again after this response + GetTagsForSeriesCategoriesResponse: type: object required: @@ -4623,6 +4437,7 @@ components: type: array items: type: string + ScopeList: type: object required: @@ -4633,6 +4448,7 @@ components: description: List of scopes items: type: string + SportFilterDetails: type: object required: @@ -4649,6 +4465,7 @@ components: description: Mapping of competitions to their scope lists additionalProperties: $ref: '#/components/schemas/ScopeList' + GetFiltersBySportsResponse: type: object required: @@ -4665,6 +4482,7 @@ components: description: Ordered list of sports for display items: type: string + BucketLimit: type: object description: | @@ -4688,6 +4506,7 @@ components: headroom that idle clients accumulate and can spend in a single pulse (e.g. write buckets at non-Basic tiers hold two seconds of budget). + GetAccountApiLimitsResponse: type: object required: @@ -4705,12 +4524,10 @@ components: $ref: '#/components/schemas/BucketLimit' grants: type: array - description: >- - The caller's active API usage level grants across exchange lanes, - where each grant applies to its exchange_instance and usage_tier - reflects the effective tier for the lane reported by this endpoint. + description: The caller's active API usage level grants across exchange lanes, where each grant applies to its exchange_instance and usage_tier reflects the effective tier for the lane reported by this endpoint. items: $ref: '#/components/schemas/ApiUsageLevelGrant' + ApiUsageLevelGrant: type: object required: @@ -4727,50 +4544,87 @@ components: type: integer format: int64 nullable: true - description: >- - Unix timestamp (seconds) when the grant expires. Absent for - permanent grants. + description: Unix timestamp (seconds) when the grant expires. Absent for permanent grants. source: type: string - description: >- - How the grant was created: "volume" (earned from trading volume) or - "manual" (assigned by Kalshi). - EndpointTokenCost: + description: 'How the grant was created: "volume" (earned from trading volume) or "manual" (assigned by Kalshi).' + + GetAccountApiUsageLevelVolumeProgressResponse: type: object required: - - method - - path - - cost + - volume_progress properties: - method: - type: string - description: HTTP method for the endpoint. - path: - type: string - description: API route path for the endpoint. - cost: - type: integer - description: >- - Configured token cost for an endpoint whose cost differs from the - default cost. - GetAccountEndpointCostsResponse: + volume_progress: + type: array + description: Latest cron-computed trading volume progress toward volume-based API usage tiers for the predictions (event_contract) lane. + items: + $ref: '#/components/schemas/AccountApiUsageLevelVolumeProgress' + + AccountApiUsageLevelVolumeProgress: type: object required: - - default_cost - - endpoint_costs + - computed_ts + - trailing_30d_volume_fp + - goals + properties: + computed_ts: + type: integer + format: int64 + description: 'Unix timestamp (seconds) when this progress was computed; trailing_30d_volume_fp covers the trailing 30 days ending at this time.' + trailing_30d_volume_fp: + $ref: '#/components/schemas/FixedPointCount' + goals: + type: array + items: + $ref: '#/components/schemas/AccountApiUsageLevelVolumeGoal' + + AccountApiUsageLevelVolumeGoal: + type: object + required: + - level + - earn_volume_goal_fp + - keep_volume_goal_fp + properties: + level: + type: string + description: API usage level for this volume goal. + earn_volume_goal_fp: + $ref: '#/components/schemas/FixedPointCount' + keep_volume_goal_fp: + $ref: '#/components/schemas/FixedPointCount' + + EndpointTokenCost: + type: object + required: + - method + - path + - cost + properties: + method: + type: string + description: HTTP method for the endpoint. + path: + type: string + description: API route path for the endpoint. + cost: + type: integer + description: Configured token cost for an endpoint whose cost differs from the default cost. + + GetAccountEndpointCostsResponse: + type: object + required: + - default_cost + - endpoint_costs properties: default_cost: type: integer - description: >- - Default token cost applied to endpoints that are not listed in - `endpoint_costs`. This is currently 10. + description: Default token cost applied to endpoints that are not listed in `endpoint_costs`. This is currently 10. endpoint_costs: type: array - description: >- - API v2 endpoints whose configured token cost differs from - `default_cost`. Endpoints that use the default cost are omitted. + description: API v2 endpoints whose configured token cost differs from `default_cost`. Endpoints that use the default cost are omitted. items: $ref: '#/components/schemas/EndpointTokenCost' + ExchangeStatus: type: object required: @@ -4779,23 +4633,16 @@ components: properties: exchange_active: type: boolean - description: >- - False if the core Kalshi exchange is no longer taking any state - changes at all. This includes but is not limited to trading, new - users, and transfers. True unless we are under maintenance. + description: False if the core Kalshi exchange is no longer taking any state changes at all. This includes but is not limited to trading, new users, and transfers. True unless we are under maintenance. trading_active: type: boolean - description: >- - True if we are currently permitting trading on the exchange. This is - true during trading hours and false outside exchange hours. Kalshi - reserves the right to pause at any time in case issues are detected. + description: True if we are currently permitting trading on the exchange. This is true during trading hours and false outside exchange hours. Kalshi reserves the right to pause at any time in case issues are detected. exchange_estimated_resume_time: type: string format: date-time - description: >- - Estimated downtime for the current exchange maintenance window. - However, this is not guaranteed and can be extended. + description: Estimated downtime for the current exchange maintenance window. However, this is not guaranteed and can be extended. nullable: true + GetExchangeAnnouncementsResponse: type: object required: @@ -4806,6 +4653,7 @@ components: description: A list of exchange-wide announcements. items: $ref: '#/components/schemas/Announcement' + Announcement: type: object required: @@ -4816,10 +4664,7 @@ components: properties: type: type: string - enum: - - info - - warning - - error + enum: [info, warning, error] description: The type of the announcement. message: type: string @@ -4830,10 +4675,9 @@ components: description: The time the announcement was delivered. status: type: string - enum: - - active - - inactive + enum: [active, inactive] description: The current status of this announcement. + GetExchangeScheduleResponse: type: object required: @@ -4841,6 +4685,7 @@ components: properties: schedule: $ref: '#/components/schemas/Schedule' + Schedule: type: object required: @@ -4849,18 +4694,15 @@ components: properties: standard_hours: type: array - description: >- - The standard operating hours of the exchange. All times are - expressed in ET. Outside of these times trading will be unavailable. + description: The standard operating hours of the exchange. All times are expressed in ET. Outside of these times trading will be unavailable. items: $ref: '#/components/schemas/WeeklySchedule' maintenance_windows: type: array - description: >- - Scheduled maintenance windows, during which the exchange may be - unavailable. + description: Scheduled maintenance windows, during which the exchange may be unavailable. items: $ref: '#/components/schemas/MaintenanceWindow' + WeeklySchedule: type: object required: @@ -4881,9 +4723,7 @@ components: end_time: type: string format: date-time - description: >- - End date and time for when this weekly schedule is no longer - effective. + description: End date and time for when this weekly schedule is no longer effective. monday: type: array description: Trading hours for Monday. May contain multiple sessions. @@ -4919,6 +4759,7 @@ components: description: Trading hours for Sunday. May contain multiple sessions. items: $ref: '#/components/schemas/DailySchedule' + DailySchedule: type: object required: @@ -4931,6 +4772,7 @@ components: close_time: type: string description: Closing time in ET (Eastern Time) format HH:MM. + MaintenanceWindow: type: object required: @@ -4945,6 +4787,7 @@ components: type: string format: date-time description: End date and time of the maintenance window. + GetHistoricalCutoffResponse: type: object required: @@ -4955,25 +4798,19 @@ components: market_settled_ts: type: string format: date-time - description: > - Cutoff based on **market settlement time**. Markets and their - candlesticks that settled before this timestamp must be accessed via - `GET /historical/markets` and `GET - /historical/markets/{ticker}/candlesticks`. + description: | + Cutoff based on **market settlement time**. Markets and their candlesticks that settled before this timestamp must be accessed via `GET /historical/markets` and `GET /historical/markets/{ticker}/candlesticks`. trades_created_ts: type: string format: date-time - description: > - Cutoff based on **trade fill time**. Fills that occurred before this - timestamp must be accessed via `GET /historical/fills`. + description: | + Cutoff based on **trade fill time**. Fills that occurred before this timestamp must be accessed via `GET /historical/fills`. orders_updated_ts: type: string format: date-time - description: > - Cutoff based on **order cancellation or execution time**. Orders - canceled or fully executed before this timestamp must be accessed - via `GET /historical/orders`. Resting (active) orders are always - available in `GET /portfolio/orders`. + description: | + Cutoff based on **order cancellation or execution time**. Orders canceled or fully executed before this timestamp must be accessed via `GET /historical/orders`. Resting (active) orders are always available in `GET /portfolio/orders`. + GetUserDataTimestampResponse: type: object required: @@ -4983,6 +4820,7 @@ components: type: string format: date-time description: Timestamp when user data was last updated. + GetMarketCandlesticksResponse: type: object required: @@ -4997,6 +4835,7 @@ components: description: Array of candlestick data points for the specified time range. items: $ref: '#/components/schemas/MarketCandlestick' + GetEventCandlesticksResponse: type: object required: @@ -5011,9 +4850,7 @@ components: type: string market_candlesticks: type: array - description: >- - Array of market candlestick arrays, one for each market in the - event. + description: Array of market candlestick arrays, one for each market in the event. items: type: array items: @@ -5021,9 +4858,8 @@ components: adjusted_end_ts: type: integer format: int64 - description: >- - Adjusted end timestamp if the requested candlesticks would be larger - than maxAggregateCandidates. + description: Adjusted end timestamp if the requested candlesticks would be larger than maxAggregateCandidates. + BatchGetMarketCandlesticksResponse: type: object required: @@ -5034,6 +4870,7 @@ components: description: Array of market candlestick data, one entry per requested market. items: $ref: '#/components/schemas/MarketCandlesticksResponse' + MarketCandlesticksResponse: type: object required: @@ -5045,11 +4882,10 @@ components: description: Market ticker string (e.g., 'INXD-24JAN01'). candlesticks: type: array - description: >- - Array of candlestick data points for the market. Includes an initial - data point at the start timestamp when available. + description: Array of candlestick data points for the market. Includes an initial data point at the start timestamp when available. items: $ref: '#/components/schemas/MarketCandlestick' + MarketCandlestick: type: object required: @@ -5066,29 +4902,20 @@ components: description: Unix timestamp for the inclusive end of the candlestick period. yes_bid: $ref: '#/components/schemas/BidAskDistribution' - description: >- - Open, high, low, close (OHLC) data for YES buy offers on the market - during the candlestick period. + description: Open, high, low, close (OHLC) data for YES buy offers on the market during the candlestick period. yes_ask: $ref: '#/components/schemas/BidAskDistribution' - description: >- - Open, high, low, close (OHLC) data for YES sell offers on the market - during the candlestick period. + description: Open, high, low, close (OHLC) data for YES sell offers on the market during the candlestick period. price: $ref: '#/components/schemas/PriceDistribution' - description: >- - Open, high, low, close (OHLC) and more data for trade YES contract - prices on the market during the candlestick period. + description: Open, high, low, close (OHLC) and more data for trade YES contract prices on the market during the candlestick period. volume_fp: $ref: '#/components/schemas/FixedPointCount' - description: >- - String representation of the number of contracts bought on the - market during the candlestick period. + description: String representation of the number of contracts bought on the market during the candlestick period. open_interest_fp: $ref: '#/components/schemas/FixedPointCount' - description: >- - String representation of the number of contracts bought on the - market by end of the candlestick period (end_period_ts). + description: String representation of the number of contracts bought on the market by end of the candlestick period (end_period_ts). + BidAskDistribution: type: object required: @@ -5099,81 +4926,54 @@ components: properties: open_dollars: $ref: '#/components/schemas/FixedPointDollars' - description: >- - Offer price on the market at the start of the candlestick period (in - dollars). + description: Offer price on the market at the start of the candlestick period (in dollars). low_dollars: $ref: '#/components/schemas/FixedPointDollars' - description: >- - Lowest offer price on the market during the candlestick period (in - dollars). + description: Lowest offer price on the market during the candlestick period (in dollars). high_dollars: $ref: '#/components/schemas/FixedPointDollars' - description: >- - Highest offer price on the market during the candlestick period (in - dollars). + description: Highest offer price on the market during the candlestick period (in dollars). close_dollars: $ref: '#/components/schemas/FixedPointDollars' - description: >- - Offer price on the market at the end of the candlestick period (in - dollars). + description: Offer price on the market at the end of the candlestick period (in dollars). + PriceDistribution: type: object properties: open_dollars: $ref: '#/components/schemas/FixedPointDollars' nullable: true - description: >- - First traded YES contract price on the market during the candlestick - period (in dollars). May be null if there was no trade during the - period. + description: First traded YES contract price on the market during the candlestick period (in dollars). May be null if there was no trade during the period. low_dollars: $ref: '#/components/schemas/FixedPointDollars' nullable: true - description: >- - Lowest traded YES contract price on the market during the - candlestick period (in dollars). May be null if there was no trade - during the period. + description: Lowest traded YES contract price on the market during the candlestick period (in dollars). May be null if there was no trade during the period. high_dollars: $ref: '#/components/schemas/FixedPointDollars' nullable: true - description: >- - Highest traded YES contract price on the market during the - candlestick period (in dollars). May be null if there was no trade - during the period. + description: Highest traded YES contract price on the market during the candlestick period (in dollars). May be null if there was no trade during the period. close_dollars: $ref: '#/components/schemas/FixedPointDollars' nullable: true - description: >- - Last traded YES contract price on the market during the candlestick - period (in dollars). May be null if there was no trade during the - period. + description: Last traded YES contract price on the market during the candlestick period (in dollars). May be null if there was no trade during the period. mean_dollars: $ref: '#/components/schemas/FixedPointDollars' nullable: true - description: >- - Mean traded YES contract price on the market during the candlestick - period (in dollars). May be null if there was no trade during the - period. + description: Mean traded YES contract price on the market during the candlestick period (in dollars). May be null if there was no trade during the period. previous_dollars: $ref: '#/components/schemas/FixedPointDollars' nullable: true - description: >- - Last traded YES contract price on the market before the candlestick - period (in dollars). May be null if there were no trades before the - period. + description: Last traded YES contract price on the market before the candlestick period (in dollars). May be null if there were no trades before the period. min_dollars: $ref: '#/components/schemas/FixedPointDollars' nullable: true - description: >- - Minimum close price of any market during the candlestick period (in - dollars). + description: Minimum close price of any market during the candlestick period (in dollars). max_dollars: $ref: '#/components/schemas/FixedPointDollars' nullable: true - description: >- - Maximum close price of any market during the candlestick period (in - dollars). + description: Maximum close price of any market during the candlestick period (in dollars). + + # Live Data schemas LiveData: type: object required: @@ -5191,6 +4991,7 @@ components: milestone_id: type: string description: Milestone ID + GetLiveDataResponse: type: object required: @@ -5198,6 +4999,7 @@ components: properties: live_data: $ref: '#/components/schemas/LiveData' + GetLiveDatasResponse: type: object required: @@ -5207,11 +5009,13 @@ components: type: array items: $ref: '#/components/schemas/LiveData' + GetGameStatsResponse: type: object properties: pbp: $ref: '#/components/schemas/PlayByPlay' + PlayByPlay: type: object description: Play-by-play data organized by period. @@ -5226,6 +5030,7 @@ components: items: type: object additionalProperties: true + IndexedBalance: type: object required: @@ -5236,6 +5041,7 @@ components: $ref: '#/components/schemas/ExchangeIndex' balance: $ref: '#/components/schemas/FixedPointDollars' + GetBalanceResponse: type: object required: @@ -5247,20 +5053,14 @@ components: balance: type: integer format: int64 - description: >- - Member's available balance in cents. This represents the amount - available for trading. + description: Member's available balance in cents. This represents the amount available for trading. balance_dollars: $ref: '#/components/schemas/FixedPointDollars' - description: >- - Member's available balance as a fixed-point dollar string. This - represents the amount available for trading. + description: Member's available balance as a fixed-point dollar string. This represents the amount available for trading. portfolio_value: type: integer format: int64 - description: >- - Member's portfolio value in cents. This is the current value of all - positions held. + description: Member's portfolio value in cents. This is the current value of all positions held. updated_ts: type: integer format: int64 @@ -5270,6 +5070,7 @@ components: items: $ref: '#/components/schemas/IndexedBalance' description: Balance broken down per exchange index. + CreateSubaccountResponse: type: object required: @@ -5278,6 +5079,7 @@ components: subaccount_number: type: integer description: The sequential number assigned to this subaccount (1-63). + ApplySubaccountTransferRequest: type: object required: @@ -5291,24 +5093,22 @@ components: format: uuid description: Unique client-provided transfer ID for idempotency. x-oapi-codegen-extra-tags: - validate: required + validate: "required" from_subaccount: type: integer - description: >- - Source subaccount number (0 for primary, 1-63 for numbered - subaccounts). + description: Source subaccount number (0 for primary, 1-63 for numbered subaccounts). to_subaccount: type: integer - description: >- - Destination subaccount number (0 for primary, 1-63 for numbered - subaccounts). + description: Destination subaccount number (0 for primary, 1-63 for numbered subaccounts). amount_cents: type: integer format: int64 description: Amount to transfer in cents. + ApplySubaccountTransferResponse: type: object description: Empty response indicating successful transfer. + GetSubaccountBalancesResponse: type: object required: @@ -5318,6 +5118,7 @@ components: type: array items: $ref: '#/components/schemas/SubaccountBalance' + SubaccountBalance: type: object required: @@ -5335,6 +5136,7 @@ components: type: integer format: int64 description: Unix timestamp of last balance update. + GetSubaccountTransfersResponse: type: object required: @@ -5347,6 +5149,7 @@ components: cursor: type: string description: Cursor for the next page of results. + SubaccountTransfer: type: object required: @@ -5373,6 +5176,7 @@ components: type: integer format: int64 description: Unix timestamp when the transfer was created. + UpdateSubaccountNettingRequest: type: object required: @@ -5385,6 +5189,7 @@ components: enabled: type: boolean description: Whether netting is enabled for this subaccount. + GetSubaccountNettingResponse: type: object required: @@ -5394,6 +5199,7 @@ components: type: array items: $ref: '#/components/schemas/SubaccountNettingConfig' + SubaccountNettingConfig: type: object required: @@ -5406,6 +5212,8 @@ components: enabled: type: boolean description: Whether netting is enabled for this subaccount. + + # Portfolio schemas (specific to portfolio endpoints, not shared with IB) GetSettlementsResponse: type: object required: @@ -5417,6 +5225,7 @@ components: $ref: '#/components/schemas/Settlement' cursor: type: string + Settlement: type: object required: @@ -5439,49 +5248,36 @@ components: description: The event ticker symbol of the market that was settled. market_result: type: string - enum: - - 'yes' - - 'no' - - scalar - - void - description: >- - The outcome of the market settlement. 'yes' = market resolved to - YES, 'no' = market resolved to NO, 'scalar' = scalar market settled - at a specific value, 'void' = market was voided/cancelled and all - positions returned at original cost. + enum: ['yes', 'no', 'scalar'] + description: The outcome of the market settlement. 'yes' = market resolved to YES, 'no' = market resolved to NO, 'scalar' = scalar market settled at a specific value. yes_count_fp: $ref: '#/components/schemas/FixedPointCount' - description: >- - String representation of the number of YES contracts owned at the - time of settlement. + description: String representation of the number of YES contracts owned at the time of settlement. yes_total_cost_dollars: $ref: '#/components/schemas/FixedPointDollars' description: Total cost basis of all YES contracts in fixed-point dollars. no_count_fp: $ref: '#/components/schemas/FixedPointCount' - description: >- - String representation of the number of NO contracts owned at the - time of settlement. + description: String representation of the number of NO contracts owned at the time of settlement. no_total_cost_dollars: $ref: '#/components/schemas/FixedPointDollars' description: Total cost basis of all NO contracts in fixed-point dollars. revenue: type: integer - description: >- - Total revenue earned from this settlement in cents (winning - contracts pay out 100 cents each). + description: Total revenue earned from this settlement in cents (winning contracts pay out 100 cents each). settled_time: type: string format: date-time description: Timestamp when the market was settled and payouts were processed. fee_cost: $ref: '#/components/schemas/FixedPointDollars' - example: '0.3400' + example: "0.3400" description: Total fees paid in fixed point dollars. value: type: integer nullable: true description: Payout of a single yes contract in cents. + GetPortfolioRestingOrderTotalValueResponse: type: object required: @@ -5490,6 +5286,7 @@ components: total_resting_order_value: type: integer description: Total value of resting orders in cents + GetDepositsResponse: type: object required: @@ -5501,6 +5298,7 @@ components: $ref: '#/components/schemas/Deposit' cursor: type: string + Deposit: type: object required: @@ -5521,9 +5319,7 @@ components: - applied - failed - returned - description: >- - Current status of the deposit. 'applied' means funds are reflected - in balance. + description: Current status of the deposit. 'applied' means funds are reflected in balance. type: type: string enum: @@ -5549,9 +5345,8 @@ components: type: integer format: int64 nullable: true - description: >- - Unix timestamp of when the deposit was finalized (applied, failed, - or returned). + description: Unix timestamp of when the deposit was finalized (applied, failed, or returned). + GetWithdrawalsResponse: type: object required: @@ -5563,6 +5358,7 @@ components: $ref: '#/components/schemas/Withdrawal' cursor: type: string + Withdrawal: type: object required: @@ -5583,9 +5379,7 @@ components: - applied - failed - returned - description: >- - Current status of the withdrawal. 'applied' means funds have been - deducted from balance. + description: Current status of the withdrawal. 'applied' means funds have been deducted from balance. type: type: string enum: @@ -5611,9 +5405,9 @@ components: type: integer format: int64 nullable: true - description: >- - Unix timestamp of when the withdrawal was finalized (applied, - failed, or returned). + description: Unix timestamp of when the withdrawal was finalized (applied, failed, or returned). + + # FCM schemas Order: type: object required: @@ -5648,62 +5442,34 @@ components: type: string side: type: string - enum: - - 'yes' - - 'no' + enum: ['yes', 'no'] deprecated: true - description: > - Deprecated. Use `outcome_side` (or `book_side`) instead. See [Order - direction](/getting_started/order_direction). This field will not be - removed before May 14, 2026. + description: | + Deprecated. Use `outcome_side` (or `book_side`) instead. See [Order direction](/getting_started/order_direction). This field will not be removed before May 14, 2026. action: type: string - enum: - - buy - - sell + enum: [buy, sell] deprecated: true - description: > - Deprecated. Use `outcome_side` (or `book_side`) instead. See [Order - direction](/getting_started/order_direction). This field will not be - removed before May 14, 2026. + description: | + Deprecated. Use `outcome_side` (or `book_side`) instead. See [Order direction](/getting_started/order_direction). This field will not be removed before May 14, 2026. outcome_side: type: string - enum: - - 'yes' - - 'no' - description: > - The outcome side this order is positioned for. buy-yes and sell-no - produce 'yes'; buy-no and sell-yes produce 'no'. - - - `outcome_side` describes directional exposure only; it does not - change the order's price. An order at price `p` with - `outcome_side=no` is matched by an order at the same price `p` with - `outcome_side=yes` — both parties trade at the same price, just on - opposite directions. + enum: ['yes', 'no'] + description: | + The outcome side this order is positioned for. buy-yes and sell-no produce 'yes'; buy-no and sell-yes produce 'no'. + `outcome_side` describes directional exposure only; it does not change the order's price. An order at price `p` with `outcome_side=no` is matched by an order at the same price `p` with `outcome_side=yes` — both parties trade at the same price, just on opposite directions. - `outcome_side` and `book_side` will become the canonical way to - determine order direction. The legacy `action`, `side`, and `is_yes` - fields will be deprecated in a future release — please migrate to - these new fields. + `outcome_side` and `book_side` will become the canonical way to determine order direction. The legacy `action`, `side`, and `is_yes` fields will be deprecated in a future release — please migrate to these new fields. book_side: $ref: '#/components/schemas/BookSide' - description: > - Same directional bit as outcome_side in book vocabulary. 'bid' is - equivalent to outcome_side 'yes'; 'ask' is equivalent to - outcome_side 'no'. - + description: | + Same directional bit as outcome_side in book vocabulary. 'bid' is equivalent to outcome_side 'yes'; 'ask' is equivalent to outcome_side 'no'. - `outcome_side` and `book_side` will become the canonical way to - determine order direction. The legacy `action`, `side`, and `is_yes` - fields will be deprecated in a future release — please migrate to - these new fields. + `outcome_side` and `book_side` will become the canonical way to determine order direction. The legacy `action`, `side`, and `is_yes` fields will be deprecated in a future release — please migrate to these new fields. type: type: string - enum: - - limit - - market + enum: [limit, market] status: $ref: '#/components/schemas/OrderStatus' yes_price_dollars: @@ -5714,17 +5480,13 @@ components: description: The no price for this order in fixed-point dollars fill_count_fp: $ref: '#/components/schemas/FixedPointCount' - description: >- - String representation of the number of contracts that have been - filled + description: String representation of the number of contracts that have been filled remaining_count_fp: $ref: '#/components/schemas/FixedPointCount' description: String representation of the remaining contracts for this order initial_count_fp: $ref: '#/components/schemas/FixedPointCount' - description: >- - String representation of the initial size of the order (contract - units) + description: String representation of the initial size of the order (contract units) taker_fill_cost_dollars: $ref: '#/components/schemas/FixedPointDollars' description: The cost of filled taker orders in dollars @@ -5762,9 +5524,7 @@ components: description: The order group this order is part of cancel_order_on_pause: type: boolean - description: >- - If this flag is set to true, the order will be canceled if the order - is open and trading on the exchange is paused for any reason. + description: If this flag is set to true, the order will be canceled if the order is open and trading on the exchange is paused for any reason. subaccount_number: type: integer nullable: true @@ -5774,6 +5534,7 @@ components: allOf: - $ref: '#/components/schemas/ExchangeIndex' x-go-type-skip-optional-pointer: true + Milestone: type: object required: @@ -5793,14 +5554,11 @@ components: description: Unique identifier for the milestone. category: type: string - description: Category of the milestone. E.g. Sports, Elections, Esports, Crypto. + description: 'Category of the milestone. E.g. Sports, Elections, Esports, Crypto.' example: Sports type: type: string - description: >- - Type of the milestone. E.g. football_game, basketball_game, - soccer_tournament_multi_leg, baseball_game, hockey_match, - golf_tournament, political_race. + description: 'Type of the milestone. E.g. football_game, basketball_game, soccer_tournament_multi_leg, baseball_game, hockey_match, golf_tournament, political_race.' example: football_game start_date: type: string @@ -5839,13 +5597,12 @@ components: type: array items: type: string - description: >- - List of event tickers directly related to the outcome of this - milestone. + description: List of event tickers directly related to the outcome of this milestone. last_updated_ts: type: string format: date-time description: Last time this structured target was updated. + GetMilestoneResponse: type: object required: @@ -5854,6 +5611,7 @@ components: milestone: $ref: '#/components/schemas/Milestone' description: The milestone data. + GetMilestonesResponse: type: object required: @@ -5867,6 +5625,7 @@ components: cursor: type: string description: Cursor for pagination. + GetOrdersResponse: type: object required: @@ -5879,6 +5638,7 @@ components: $ref: '#/components/schemas/Order' cursor: type: string + GetOrderQueuePositionResponse: type: object required: @@ -5887,6 +5647,7 @@ components: queue_position_fp: $ref: '#/components/schemas/FixedPointCount' description: The number of preceding shares before the order in the queue. + OrderQueuePosition: type: object required: @@ -5903,6 +5664,7 @@ components: queue_position_fp: $ref: '#/components/schemas/FixedPointCount' description: The number of preceding shares before the order in the queue. + GetOrderQueuePositionsResponse: type: object required: @@ -5913,6 +5675,7 @@ components: description: Queue positions for all matching orders items: $ref: '#/components/schemas/OrderQueuePosition' + MarketPosition: type: object required: @@ -5934,9 +5697,7 @@ components: description: Total spent on this market in dollars position_fp: $ref: '#/components/schemas/FixedPointCount' - description: >- - String representation of the number of contracts bought in this - market. Negative means NO contracts and positive means YES contracts + description: String representation of the number of contracts bought in this market. Negative means NO contracts and positive means YES contracts market_exposure_dollars: $ref: '#/components/schemas/FixedPointDollars' description: Cost of the aggregate market position in dollars @@ -5946,7 +5707,7 @@ components: resting_orders_count: type: integer format: int32 - description: '[DEPRECATED] Aggregate size of resting orders in contract units' + description: "[DEPRECATED] Aggregate size of resting orders in contract units" deprecated: true fees_paid_dollars: $ref: '#/components/schemas/FixedPointDollars' @@ -5955,6 +5716,7 @@ components: type: string format: date-time description: Last time the position is updated + EventPosition: type: object required: @@ -5973,9 +5735,7 @@ components: description: Total spent on this event in dollars total_cost_shares_fp: $ref: '#/components/schemas/FixedPointCount' - description: >- - String representation of the total number of shares traded on this - event (including both YES and NO contracts) + description: String representation of the total number of shares traded on this event (including both YES and NO contracts) event_exposure_dollars: $ref: '#/components/schemas/FixedPointDollars' description: Cost of the aggregate event position in dollars @@ -5985,6 +5745,7 @@ components: fees_paid_dollars: $ref: '#/components/schemas/FixedPointDollars' description: Fees paid on fill orders, in dollars + GetPositionsResponse: type: object required: @@ -5993,12 +5754,7 @@ components: properties: cursor: type: string - description: >- - The Cursor represents a pointer to the next page of records in the - pagination. Use the value returned here in the cursor query - parameter for this end-point to get the next page containing limit - records. An empty value of this field indicates there is no next - page. + description: The Cursor represents a pointer to the next page of records in the pagination. Use the value returned here in the cursor query parameter for this end-point to get the next page containing limit records. An empty value of this field indicates there is no next page. market_positions: type: array items: @@ -6009,6 +5765,7 @@ components: items: $ref: '#/components/schemas/EventPosition' description: List of event positions + Trade: type: object required: @@ -6031,9 +5788,7 @@ components: description: Unique identifier for the market count_fp: $ref: '#/components/schemas/FixedPointCount' - description: >- - String representation of the number of contracts bought or sold in - this trade + description: String representation of the number of contracts bought or sold in this trade yes_price_dollars: $ref: '#/components/schemas/FixedPointDollars' description: Yes price for this trade in dollars @@ -6042,63 +5797,35 @@ components: description: No price for this trade in dollars taker_side: type: string - enum: - - 'yes' - - 'no' - x-enum-varnames: - - TradeTakerSideYes - - TradeTakerSideNo + enum: ['yes', 'no'] + x-enum-varnames: ['TradeTakerSideYes', 'TradeTakerSideNo'] deprecated: true - description: > - Deprecated. Use `taker_outcome_side` (or `taker_book_side`) instead. - See [Order direction](/getting_started/order_direction). This field - will not be removed before May 14, 2026. + description: | + Deprecated. Use `taker_outcome_side` (or `taker_book_side`) instead. See [Order direction](/getting_started/order_direction). This field will not be removed before May 14, 2026. taker_outcome_side: type: string - enum: - - 'yes' - - 'no' - x-enum-varnames: - - TradeTakerOutcomeSideYes - - TradeTakerOutcomeSideNo - description: > - The outcome side the taker is positioned for. buy-yes and sell-no - produce 'yes'; buy-no and sell-yes produce 'no'. - - - `taker_outcome_side` describes directional exposure only; it does - not change the trade's price. A trade at price `p` with - `taker_outcome_side=no` is matched against the maker at the same - price `p` with the opposite direction — both parties trade at the - same price. - - - `taker_outcome_side` and `taker_book_side` will become the canonical - way to determine trade direction. The legacy `taker_side` field will - be deprecated in a future release — please migrate to these new - fields. + enum: ['yes', 'no'] + x-enum-varnames: ['TradeTakerOutcomeSideYes', 'TradeTakerOutcomeSideNo'] + description: | + The outcome side the taker is positioned for. buy-yes and sell-no produce 'yes'; buy-no and sell-yes produce 'no'. + + `taker_outcome_side` describes directional exposure only; it does not change the trade's price. A trade at price `p` with `taker_outcome_side=no` is matched against the maker at the same price `p` with the opposite direction — both parties trade at the same price. + + `taker_outcome_side` and `taker_book_side` will become the canonical way to determine trade direction. The legacy `taker_side` field will be deprecated in a future release — please migrate to these new fields. taker_book_side: $ref: '#/components/schemas/BookSide' - description: > - Same directional bit as taker_outcome_side in book vocabulary. 'bid' - is equivalent to taker_outcome_side 'yes'; 'ask' is equivalent to - taker_outcome_side 'no'. - + description: | + Same directional bit as taker_outcome_side in book vocabulary. 'bid' is equivalent to taker_outcome_side 'yes'; 'ask' is equivalent to taker_outcome_side 'no'. - `taker_outcome_side` and `taker_book_side` will become the canonical - way to determine trade direction. The legacy `taker_side` field will - be deprecated in a future release — please migrate to these new - fields. + `taker_outcome_side` and `taker_book_side` will become the canonical way to determine trade direction. The legacy `taker_side` field will be deprecated in a future release — please migrate to these new fields. created_time: type: string format: date-time description: Timestamp when this trade was executed is_block_trade: type: boolean - description: >- - True if this trade was matched off-book as a block trade (e.g. via - RFQ / negotiated block proposal); false for trades that filled on - the standard order book. + description: True if this trade was matched off-book as a block trade (e.g. via RFQ / negotiated block proposal); false for trades that filled on the standard order book. + GetIncentiveProgramsResponse: type: object required: @@ -6111,6 +5838,7 @@ components: next_cursor: type: string description: Cursor for pagination to get the next page of results + IncentiveProgram: type: object required: @@ -6129,19 +5857,13 @@ components: description: Unique identifier for the incentive program market_id: type: string - description: >- - The unique identifier of the market associated with this incentive - program + description: The unique identifier of the market associated with this incentive program market_ticker: type: string - description: >- - The ticker symbol of the market associated with this incentive - program + description: The ticker symbol of the market associated with this incentive program incentive_type: type: string - enum: - - liquidity - - volume + enum: ['liquidity', 'volume'] description: Type of incentive program incentive_description: type: string @@ -6169,9 +5891,8 @@ components: target_size_fp: $ref: '#/components/schemas/FixedPointCount' nullable: true - description: >- - String representation of the target size for the incentive program - (optional) + description: String representation of the target size for the incentive program (optional) + GetTradesResponse: type: object required: @@ -6184,6 +5905,7 @@ components: $ref: '#/components/schemas/Trade' cursor: type: string + Fill: type: object required: @@ -6219,62 +5941,34 @@ components: description: Unique identifier for the market (legacy field name, same as ticker) side: type: string - enum: - - 'yes' - - 'no' + enum: ['yes', 'no'] deprecated: true - description: > - Deprecated. Use `outcome_side` (or `book_side`) instead. See [Order - direction](/getting_started/order_direction). This field will not be - removed before May 14, 2026. + description: | + Deprecated. Use `outcome_side` (or `book_side`) instead. See [Order direction](/getting_started/order_direction). This field will not be removed before May 14, 2026. action: type: string - enum: - - buy - - sell + enum: ['buy', 'sell'] deprecated: true - description: > - Deprecated. Use `outcome_side` (or `book_side`) instead. See [Order - direction](/getting_started/order_direction). This field will not be - removed before May 14, 2026. + description: | + Deprecated. Use `outcome_side` (or `book_side`) instead. See [Order direction](/getting_started/order_direction). This field will not be removed before May 14, 2026. outcome_side: type: string - enum: - - 'yes' - - 'no' - description: > - The outcome side this fill positioned the user for. buy-yes and - sell-no produce 'yes'; buy-no and sell-yes produce 'no'. - - - `outcome_side` describes directional exposure only; it does not - change the fill's price. A fill at price `p` with `outcome_side=no` - is matched against an order at the same price `p` with - `outcome_side=yes` — both parties trade at the same price, just on - opposite directions. + enum: ['yes', 'no'] + description: | + The outcome side this fill positioned the user for. buy-yes and sell-no produce 'yes'; buy-no and sell-yes produce 'no'. + `outcome_side` describes directional exposure only; it does not change the fill's price. A fill at price `p` with `outcome_side=no` is matched against an order at the same price `p` with `outcome_side=yes` — both parties trade at the same price, just on opposite directions. - `outcome_side` and `book_side` will become the canonical way to - determine fill direction. The legacy `action` and `side` fields will - be deprecated in a future release — please migrate to these new - fields. + `outcome_side` and `book_side` will become the canonical way to determine fill direction. The legacy `action` and `side` fields will be deprecated in a future release — please migrate to these new fields. book_side: $ref: '#/components/schemas/BookSide' - description: > - Same directional bit as outcome_side in book vocabulary. 'bid' is - equivalent to outcome_side 'yes'; 'ask' is equivalent to - outcome_side 'no'. - + description: | + Same directional bit as outcome_side in book vocabulary. 'bid' is equivalent to outcome_side 'yes'; 'ask' is equivalent to outcome_side 'no'. - `outcome_side` and `book_side` will become the canonical way to - determine fill direction. The legacy `action` and `side` fields will - be deprecated in a future release — please migrate to these new - fields. + `outcome_side` and `book_side` will become the canonical way to determine fill direction. The legacy `action` and `side` fields will be deprecated in a future release — please migrate to these new fields. count_fp: $ref: '#/components/schemas/FixedPointCount' - description: >- - String representation of the number of contracts bought or sold in - this fill + description: String representation of the number of contracts bought or sold in this fill yes_price_dollars: $ref: '#/components/schemas/FixedPointDollars' description: Fill price for the yes side in fixed-point dollars @@ -6283,9 +5977,7 @@ components: description: Fill price for the no side in fixed-point dollars is_taker: type: boolean - description: >- - If true, this fill was a taker (removed liquidity from the order - book) + description: If true, this fill was a taker (removed liquidity from the order book) created_time: type: string format: date-time @@ -6297,13 +5989,12 @@ components: type: integer nullable: true x-omitempty: true - description: >- - Subaccount number (0 for primary, 1-63 for subaccounts). Present for - direct users. + description: Subaccount number (0 for primary, 1-63 for subaccounts). Present for direct users. ts: type: integer format: int64 description: Unix timestamp when this fill was executed (legacy field name) + GetFillsResponse: type: object required: @@ -6316,6 +6007,8 @@ components: $ref: '#/components/schemas/Fill' cursor: type: string + + # Structured Target schemas StructuredTarget: type: object properties: @@ -6330,14 +6023,10 @@ components: description: Type of the structured target. details: type: object - description: >- - Additional details about the structured target. Contains flexible - JSON data specific to the target type. + description: Additional details about the structured target. Contains flexible JSON data specific to the target type. source_id: type: string - description: >- - External source identifier for the structured target, if available - (e.g., third-party data provider ID). + description: External source identifier for the structured target, if available (e.g., third-party data provider ID). source_ids: type: object additionalProperties: @@ -6347,6 +6036,7 @@ components: type: string format: date-time description: Timestamp when this structured target was last updated. + GetStructuredTargetsResponse: type: object properties: @@ -6356,17 +6046,19 @@ components: $ref: '#/components/schemas/StructuredTarget' cursor: type: string - description: >- - Pagination cursor for the next page. Empty if there are no more - results. + description: Pagination cursor for the next page. Empty if there are no more results. + GetStructuredTargetResponse: type: object properties: structured_target: $ref: '#/components/schemas/StructuredTarget' + + # Order Group schemas EmptyResponse: type: object description: An empty response body + IntraExchangeInstanceTransferRequest: type: object required: @@ -6394,6 +6086,7 @@ components: default: 0 x-go-type-skip-optional-pointer: true description: Destination exchange shard index (default 0) + IntraExchangeInstanceTransferResponse: type: object required: @@ -6402,6 +6095,7 @@ components: transfer_id: type: string description: The ID of the transfer that was created + OrderGroup: type: object required: @@ -6414,9 +6108,7 @@ components: x-go-type-skip-optional-pointer: true contracts_limit_fp: $ref: '#/components/schemas/FixedPointCount' - description: >- - String representation of the current maximum contracts allowed over - a rolling 15-second window. + description: String representation of the current maximum contracts allowed over a rolling 15-second window. x-go-type-skip-optional-pointer: true is_auto_cancel_enabled: type: boolean @@ -6426,6 +6118,7 @@ components: allOf: - $ref: '#/components/schemas/ExchangeIndex' x-go-type-skip-optional-pointer: true + GetOrderGroupsResponse: type: object properties: @@ -6434,6 +6127,7 @@ components: items: $ref: '#/components/schemas/OrderGroup' x-go-type-skip-optional-pointer: true + GetOrderGroupResponse: type: object required: @@ -6445,9 +6139,7 @@ components: description: Whether auto-cancel is enabled for this order group contracts_limit_fp: $ref: '#/components/schemas/FixedPointCount' - description: >- - String representation of the current maximum contracts allowed over - a rolling 15-second window. + description: String representation of the current maximum contracts allowed over a rolling 15-second window. x-go-type-skip-optional-pointer: true orders: type: array @@ -6459,42 +6151,34 @@ components: allOf: - $ref: '#/components/schemas/ExchangeIndex' x-go-type-skip-optional-pointer: true + CreateOrderGroupRequest: type: object properties: subaccount: type: integer minimum: 0 - description: >- - Optional subaccount number to use for this order group (0 for - primary, 1-63 for subaccounts) + description: Optional subaccount number to use for this order group (0 for primary, 1-63 for subaccounts) default: 0 x-go-type-skip-optional-pointer: true contracts_limit: type: integer format: int64 minimum: 1 - description: >- - Specifies the maximum number of contracts that can be matched within - this group over a rolling 15-second window. Whole contracts only. - Provide contracts_limit or contracts_limit_fp; if both provided they - must match. + description: Specifies the maximum number of contracts that can be matched within this group over a rolling 15-second window. Whole contracts only. Provide contracts_limit or contracts_limit_fp; if both provided they must match. x-go-type-skip-optional-pointer: true x-oapi-codegen-extra-tags: validate: omitempty,gte=1 contracts_limit_fp: $ref: '#/components/schemas/FixedPointCount' nullable: true - description: >- - String representation of the maximum number of contracts that can be - matched within this group over a rolling 15-second window. Provide - contracts_limit or contracts_limit_fp; if both provided they must - match. + description: String representation of the maximum number of contracts that can be matched within this group over a rolling 15-second window. Provide contracts_limit or contracts_limit_fp; if both provided they must match. exchange_index: allOf: - $ref: '#/components/schemas/ExchangeIndex' default: 0 x-go-type-skip-optional-pointer: true + UpdateOrderGroupLimitRequest: type: object properties: @@ -6502,50 +6186,246 @@ components: type: integer format: int64 minimum: 1 - description: >- - New maximum number of contracts that can be matched within this - group over a rolling 15-second window. Whole contracts only. Provide - contracts_limit or contracts_limit_fp; if both provided they must - match. + description: New maximum number of contracts that can be matched within this group over a rolling 15-second window. Whole contracts only. Provide contracts_limit or contracts_limit_fp; if both provided they must match. + x-go-type-skip-optional-pointer: true + x-oapi-codegen-extra-tags: + validate: omitempty,gte=1 + contracts_limit_fp: + $ref: '#/components/schemas/FixedPointCount' + nullable: true + description: String representation of the new maximum number of contracts that can be matched within this group over a rolling 15-second window. Provide contracts_limit or contracts_limit_fp; if both provided they must match. + + CreateOrderGroupResponse: + type: object + required: + - order_group_id + - subaccount + properties: + order_group_id: + type: string + description: The unique identifier for the created order group + subaccount: + type: integer + minimum: 0 + description: Subaccount number that owns the created order group (0 for primary, 1-63 for subaccounts). + x-go-type-skip-optional-pointer: true + exchange_index: + allOf: + - $ref: '#/components/schemas/ExchangeIndex' + x-go-type-skip-optional-pointer: true + + GetCommunicationsIDResponse: + type: object + required: + - communications_id + properties: + communications_id: + type: string + description: A public communications ID which is used to identify the user + + BlockTradeProposal: + type: object + required: + - id + - proposer_user_id + - buyer_user_id + - seller_user_id + - market_ticker + - price_centi_cents + - centicount + - maker_side + - expiration_ts + - status + - created_ts + - updated_ts + - buyer_accepted + - seller_accepted + properties: + id: + type: string + description: Unique identifier for the block trade proposal + proposer_user_id: + type: string + description: User ID of the proposal creator + buyer_user_id: + type: string + description: User ID of the buyer. Empty when the authenticated user is not the buyer. + buyer_subtrader_id: + type: string + description: Subtrader ID of the buyer. Empty when the authenticated user is not the buyer. + x-go-type-skip-optional-pointer: true + seller_user_id: + type: string + description: User ID of the seller. Empty when the authenticated user is not the seller. + seller_subtrader_id: + type: string + description: Subtrader ID of the seller. Empty when the authenticated user is not the seller. + x-go-type-skip-optional-pointer: true + market_ticker: + type: string + description: The ticker of the market for this block trade + price_centi_cents: + type: integer + format: int64 + description: Price in centi-cents + centicount: + type: integer + format: int64 + description: Number of contracts in centicounts + maker_side: + type: string + description: The maker side of the trade + enum: ['yes', 'no'] + expiration_ts: + type: string + format: date-time + description: Expiration time of the proposal + status: + type: string + description: Current status of the proposal + created_ts: + type: string + format: date-time + description: Timestamp when the proposal was created + updated_ts: + type: string + format: date-time + description: Timestamp when the proposal was last updated + buyer_accepted: + type: boolean + description: Whether the buyer has accepted the proposal + seller_accepted: + type: boolean + description: Whether the seller has accepted the proposal + buyer_accepted_ts: + type: string + format: date-time + description: Timestamp when the buyer accepted + seller_accepted_ts: + type: string + format: date-time + description: Timestamp when the seller accepted + executed_ts: + type: string + format: date-time + description: Timestamp when the proposal was executed + buyer_order_id: + type: string + description: Order ID for the buyer after the proposal is executed + x-go-type-skip-optional-pointer: true + seller_order_id: + type: string + description: Order ID for the seller after the proposal is executed x-go-type-skip-optional-pointer: true + + GetBlockTradeProposalsResponse: + type: object + required: + - block_trade_proposals + properties: + block_trade_proposals: + type: array + items: + $ref: '#/components/schemas/BlockTradeProposal' + description: List of block trade proposals + cursor: + type: string + description: Cursor for pagination to get the next page of results + x-go-type-skip-optional-pointer: true + + ProposeBlockTradeRequest: + type: object + required: + - buyer_user_id + - seller_user_id + - market_ticker + - price_centi_cents + - centicount + - maker_side + - expiration_ts + properties: + buyer_user_id: + type: string + description: User ID of the buyer + x-oapi-codegen-extra-tags: + validate: required + buyer_subtrader_id: + type: string + description: Subtrader ID of the buyer. Provide either this or buyer_subaccount, not both. + x-go-type-skip-optional-pointer: true + buyer_subaccount: + type: integer + minimum: 0 + maximum: 63 + description: User-managed subaccount number of the buyer (0 for primary, 1-63 for numbered subaccounts). Provide either this or buyer_subtrader_id, not both. + seller_user_id: + type: string + description: User ID of the seller + x-oapi-codegen-extra-tags: + validate: required + seller_subtrader_id: + type: string + description: Subtrader ID of the seller. Provide either this or seller_subaccount, not both. + x-go-type-skip-optional-pointer: true + seller_subaccount: + type: integer + minimum: 0 + maximum: 63 + description: User-managed subaccount number of the seller (0 for primary, 1-63 for numbered subaccounts). Provide either this or seller_subtrader_id, not both. + market_ticker: + type: string + description: The ticker of the market for this block trade + x-oapi-codegen-extra-tags: + validate: required + price_centi_cents: + type: integer + format: int64 + minimum: 1 + description: Price in centi-cents + x-oapi-codegen-extra-tags: + validate: required,gt=0 + centicount: + type: integer + format: int64 + minimum: 1 + description: Number of contracts in centicounts + x-oapi-codegen-extra-tags: + validate: required,gt=0 + maker_side: + type: string + description: The maker side of the trade + enum: ['yes', 'no'] + x-oapi-codegen-extra-tags: + validate: required,oneof=yes no + expiration_ts: + type: string + format: date-time + description: Expiration time of the proposal x-oapi-codegen-extra-tags: - validate: omitempty,gte=1 - contracts_limit_fp: - $ref: '#/components/schemas/FixedPointCount' - nullable: true - description: >- - String representation of the new maximum number of contracts that - can be matched within this group over a rolling 15-second window. - Provide contracts_limit or contracts_limit_fp; if both provided they - must match. - CreateOrderGroupResponse: + validate: required + + ProposeBlockTradeResponse: type: object required: - - order_group_id - - subaccount + - block_trade_proposal_id properties: - order_group_id: + block_trade_proposal_id: type: string - description: The unique identifier for the created order group - subaccount: - type: integer - minimum: 0 - description: >- - Subaccount number that owns the created order group (0 for primary, - 1-63 for subaccounts). - x-go-type-skip-optional-pointer: true - exchange_index: - allOf: - - $ref: '#/components/schemas/ExchangeIndex' - x-go-type-skip-optional-pointer: true - GetCommunicationsIDResponse: + description: The ID of the newly created block trade proposal + + AcceptBlockTradeProposalRequest: type: object - required: - - communications_id properties: - communications_id: + subtrader_id: type: string - description: A public communications ID which is used to identify the user + description: Subtrader ID to accept as. Provide either this or subaccount, not both. + x-go-type-skip-optional-pointer: true + subaccount: + type: integer + minimum: 0 + maximum: 63 + description: User-managed subaccount number to accept as (0 for primary, 1-63 for numbered subaccounts). Provide either this or subtrader_id, not both. + RFQ: type: object required: @@ -6567,18 +6447,14 @@ components: description: The ticker of the market this RFQ is for contracts_fp: $ref: '#/components/schemas/FixedPointCount' - description: >- - String representation of the number of contracts requested in the - RFQ + description: String representation of the number of contracts requested in the RFQ target_cost_dollars: $ref: '#/components/schemas/FixedPointDollars' description: Total value of the RFQ in dollars status: type: string description: Current status of the RFQ (open, closed) - enum: - - open - - closed + enum: [open, closed] created_ts: type: string format: date-time @@ -6607,9 +6483,7 @@ components: x-go-type-skip-optional-pointer: true creator_subaccount: type: integer - description: >- - Subaccount number of the RFQ creator (visible when the caller is the - RFQ creator) + description: Subaccount number of the RFQ creator (visible when the caller is the RFQ creator) cancelled_ts: type: string format: date-time @@ -6618,6 +6492,7 @@ components: type: string format: date-time description: Timestamp when the RFQ was last updated + GetRFQsResponse: type: object required: @@ -6632,6 +6507,7 @@ components: type: string description: Cursor for pagination to get the next page of results x-go-type-skip-optional-pointer: true + GetRFQResponse: type: object required: @@ -6640,6 +6516,7 @@ components: rfq: $ref: '#/components/schemas/RFQ' description: The details of the requested RFQ + CreateRFQRequest: type: object required: @@ -6651,23 +6528,16 @@ components: description: The ticker of the market for which to create an RFQ contracts: type: integer - description: >- - Whole-contract count for the RFQ. Use contracts_fp for partial - contract values; if both are provided, they must match. + description: Whole-contract count for the RFQ. Use contracts_fp for partial contract values; if both are provided, they must match. x-go-type-skip-optional-pointer: true contracts_fp: $ref: '#/components/schemas/FixedPointCount' nullable: true - description: >- - Fixed-point number of contracts for the RFQ. Supports partial - contracts in 0.01-contract increments; if contracts is also - provided, both values must match. + description: Fixed-point number of contracts for the RFQ. Supports partial contracts in 0.01-contract increments; if contracts is also provided, both values must match. target_cost_centi_cents: type: integer format: int64 - description: >- - DEPRECATED: The target cost for the RFQ in centi-cents. Use - target_cost_dollars instead. + description: 'DEPRECATED: The target cost for the RFQ in centi-cents. Use target_cost_dollars instead.' deprecated: true x-go-type-skip-optional-pointer: true target_cost_dollars: @@ -6688,10 +6558,9 @@ components: x-go-type-skip-optional-pointer: true subaccount: type: integer - description: >- - The subaccount number to create the RFQ for (direct members only; 0 - for primary, 1-63 for subaccounts) + description: The subaccount number to create the RFQ for (direct members only; 0 for primary, 1-63 for subaccounts) x-go-type-skip-optional-pointer: true + CreateRFQResponse: type: object required: @@ -6700,6 +6569,7 @@ components: id: type: string description: The ID of the newly created RFQ + Quote: type: object required: @@ -6751,18 +6621,11 @@ components: status: type: string description: Current status of the quote - enum: - - open - - accepted - - confirmed - - executed - - cancelled + enum: [open, accepted, confirmed, executed, cancelled] accepted_side: type: string description: The side that was accepted (yes or no) - enum: - - 'yes' - - 'no' + enum: ['yes', 'no'] accepted_ts: type: string format: date-time @@ -6784,9 +6647,7 @@ components: description: Whether to rest the remainder of the quote after execution post_only: type: boolean - description: >- - Whether the quote creator's order is post-only (visible when the - caller is the quote creator) + description: Whether the quote creator's order is post-only (visible when the caller is the quote creator) cancellation_reason: type: string description: Reason for quote cancellation if cancelled @@ -6812,20 +6673,17 @@ components: x-go-type-skip-optional-pointer: true creator_subaccount: type: integer - description: >- - Subaccount number of the quote creator (visible when the caller is - the quote creator) + description: Subaccount number of the quote creator (visible when the caller is the quote creator) rfq_creator_subaccount: type: integer - description: >- - Subaccount number of the RFQ creator (visible when the caller is the - RFQ creator) + description: Subaccount number of the RFQ creator (visible when the caller is the RFQ creator) yes_contracts_fp: $ref: '#/components/schemas/FixedPointCount' description: Number of YES contracts offered in the quote (fixed-point) no_contracts_fp: $ref: '#/components/schemas/FixedPointCount' description: Number of NO contracts offered in the quote (fixed-point) + GetQuotesResponse: type: object required: @@ -6840,6 +6698,7 @@ components: type: string description: Cursor for pagination to get the next page of results x-go-type-skip-optional-pointer: true + GetQuoteResponse: type: object required: @@ -6848,6 +6707,7 @@ components: quote: $ref: '#/components/schemas/Quote' description: The details of the requested quote + CreateQuoteRequest: type: object required: @@ -6872,14 +6732,11 @@ components: description: Whether to rest the remainder of the quote after execution post_only: type: boolean - description: >- - If true, the quote creator's resting order will be cancelled rather - than crossed if it would take liquidity. Defaults to false. + description: If true, the quote creator's resting order will be cancelled rather than crossed if it would take liquidity. Defaults to false. subaccount: type: integer - description: >- - Optional subaccount number to place the quote under (0 for primary, - 1-63 for subaccounts) + description: Optional subaccount number to place the quote under (0 for primary, 1-63 for subaccounts) + CreateQuoteResponse: type: object required: @@ -6888,6 +6745,7 @@ components: id: type: string description: The ID of the newly created quote + AcceptQuoteRequest: type: object required: @@ -6896,9 +6754,9 @@ components: accepted_side: type: string description: The side of the quote to accept (yes or no) - enum: - - 'yes' - - 'no' + enum: ['yes', 'no'] + + # Order schemas GetOrderResponse: type: object required: @@ -6906,6 +6764,7 @@ components: properties: order: $ref: '#/components/schemas/Order' + CreateOrderRequest: type: object required: @@ -6922,33 +6781,25 @@ components: x-go-type-skip-optional-pointer: true side: type: string - enum: - - 'yes' - - 'no' + enum: ['yes', 'no'] x-oapi-codegen-extra-tags: validate: required,oneof=yes no action: type: string - enum: - - buy - - sell + enum: ['buy', 'sell'] x-oapi-codegen-extra-tags: validate: required,oneof=buy sell count: type: integer minimum: 1 - description: >- - Order quantity in contracts (whole contracts only). Provide count or - count_fp; if both provided they must match. + description: Order quantity in contracts (whole contracts only). Provide count or count_fp; if both provided they must match. x-go-type-skip-optional-pointer: true x-oapi-codegen-extra-tags: validate: omitempty,gte=1 count_fp: $ref: '#/components/schemas/FixedPointCount' nullable: true - description: >- - String representation of the order quantity in contracts. Provide - count or count_fp; if both provided they must match. + description: String representation of the order quantity in contracts. Provide count or count_fp; if both provided they must match. yes_price: type: integer minimum: 1 @@ -6968,50 +6819,33 @@ components: expiration_ts: type: integer format: int64 - description: > - Optional Unix timestamp in seconds for when the order expires. To - place - + description: | + Optional Unix timestamp in seconds for when the order expires. To place an expiring order, set `time_in_force` to `good_till_canceled` and - - provide this `expiration_ts`. `GTT` is an internal execution type - and is - + provide this `expiration_ts`. `GTT` is an internal execution type and is not a valid API value for `time_in_force`. The `immediate_or_cancel` - time-in-force value cannot be combined with `expiration_ts`. time_in_force: type: string - description: > - Specifies how long the order remains active. Use - `good_till_canceled` - + description: | + Specifies how long the order remains active. Use `good_till_canceled` with `expiration_ts` for an order that should rest until a specific - expiration time; without `expiration_ts`, `good_till_canceled` is a - true good-till-canceled order. `GTT` is not a valid API value. - enum: - - fill_or_kill - - good_till_canceled - - immediate_or_cancel + enum: ['fill_or_kill', 'good_till_canceled', 'immediate_or_cancel'] x-oapi-codegen-extra-tags: - validate: >- - omitempty,oneof=fill_or_kill good_till_canceled - immediate_or_cancel + validate: omitempty,oneof=fill_or_kill good_till_canceled immediate_or_cancel x-go-type-skip-optional-pointer: true buy_max_cost: type: integer - description: >- - Maximum cost in cents. When specified, the order will automatically - have Fill-or-Kill (FoK) behavior. + description: Maximum cost in cents. When specified, the order will automatically have Fill-or-Kill (FoK) behavior. post_only: type: boolean reduce_only: type: boolean sell_position_floor: type: integer - description: 'Deprecated: Use reduce_only instead. Only accepts value of 0.' + description: "Deprecated: Use reduce_only instead. Only accepts value of 0." self_trade_prevention_type: allOf: - $ref: '#/components/schemas/SelfTradePreventionType' @@ -7024,22 +6858,19 @@ components: x-go-type-skip-optional-pointer: true cancel_order_on_pause: type: boolean - description: >- - If this flag is set to true, the order will be canceled if the order - is open and trading on the exchange is paused for any reason. + description: If this flag is set to true, the order will be canceled if the order is open and trading on the exchange is paused for any reason. subaccount: type: integer minimum: 0 default: 0 - description: >- - The subaccount number to use for this order. 0 is the primary - subaccount. + description: The subaccount number to use for this order. 0 is the primary subaccount. x-go-type-skip-optional-pointer: true exchange_index: allOf: - $ref: '#/components/schemas/ExchangeIndex' default: 0 x-go-type-skip-optional-pointer: true + CreateOrderResponse: type: object required: @@ -7047,6 +6878,7 @@ components: properties: order: $ref: '#/components/schemas/Order' + BatchCreateOrdersRequest: type: object required: @@ -7058,6 +6890,7 @@ components: validate: required,dive items: $ref: '#/components/schemas/CreateOrderRequest' + BatchCreateOrdersResponse: type: object required: @@ -7067,6 +6900,7 @@ components: type: array items: $ref: '#/components/schemas/BatchCreateOrdersIndividualResponse' + BatchCreateOrdersIndividualResponse: type: object properties: @@ -7075,12 +6909,13 @@ components: nullable: true order: allOf: - - $ref: '#/components/schemas/Order' + - $ref: '#/components/schemas/Order' nullable: true error: allOf: - - $ref: '#/components/schemas/ErrorResponse' + - $ref: '#/components/schemas/ErrorResponse' nullable: true + BatchCancelOrdersRequest: type: object properties: @@ -7094,9 +6929,8 @@ components: type: array items: $ref: '#/components/schemas/BatchCancelOrdersRequestOrder' - description: >- - An array of orders to cancel, each optionally specifying a - subaccount + description: An array of orders to cancel, each optionally specifying a subaccount + BatchCancelOrdersRequestOrder: type: object required: @@ -7109,15 +6943,14 @@ components: type: integer minimum: 0 default: 0 - description: >- - Optional subaccount number to use for this cancellation (0 for - primary, 1-63 for subaccounts) + description: Optional subaccount number to use for this cancellation (0 for primary, 1-63 for subaccounts) x-go-type-skip-optional-pointer: true exchange_index: allOf: - $ref: '#/components/schemas/ExchangeIndex' default: 0 x-go-type-skip-optional-pointer: true + BatchCancelOrdersResponse: type: object required: @@ -7127,6 +6960,7 @@ components: type: array items: $ref: '#/components/schemas/BatchCancelOrdersIndividualResponse' + BatchCancelOrdersIndividualResponse: type: object required: @@ -7135,22 +6969,19 @@ components: properties: order_id: type: string - description: >- - The order ID to identify which order had an error during batch - cancellation + description: The order ID to identify which order had an error during batch cancellation order: allOf: - $ref: '#/components/schemas/Order' nullable: true reduced_by_fp: $ref: '#/components/schemas/FixedPointCount' - description: >- - String representation of the number of contracts that were - successfully canceled from this order + description: String representation of the number of contracts that were successfully canceled from this order error: allOf: - $ref: '#/components/schemas/ErrorResponse' nullable: true + CancelOrderResponse: type: object required: @@ -7161,9 +6992,8 @@ components: $ref: '#/components/schemas/Order' reduced_by_fp: $ref: '#/components/schemas/FixedPointCount' - description: >- - String representation of the number of contracts that were - successfully canceled from this order + description: String representation of the number of contracts that were successfully canceled from this order + AmendOrderRequest: type: object required: @@ -7174,9 +7004,7 @@ components: subaccount: type: integer minimum: 0 - description: >- - Optional subaccount number to use for this amendment (0 for primary, - 1-63 for subaccounts) + description: Optional subaccount number to use for this amendment (0 for primary, 1-63 for subaccounts) default: 0 x-go-type-skip-optional-pointer: true ticker: @@ -7184,15 +7012,11 @@ components: description: Market ticker side: type: string - enum: - - 'yes' - - 'no' + enum: ["yes", "no"] description: Side of the order action: type: string - enum: - - buy - - sell + enum: ["buy", "sell"] description: Action of the order client_order_id: type: string @@ -7214,35 +7038,24 @@ components: description: Updated no price for the order in cents yes_price_dollars: $ref: '#/components/schemas/FixedPointDollars' - description: >- - Updated yes price for the order in fixed-point dollars. Exactly one - of yes_price, no_price, yes_price_dollars, and no_price_dollars must - be passed. + description: Updated yes price for the order in fixed-point dollars. Exactly one of yes_price, no_price, yes_price_dollars, and no_price_dollars must be passed. no_price_dollars: $ref: '#/components/schemas/FixedPointDollars' - description: >- - Updated no price for the order in fixed-point dollars. Exactly one - of yes_price, no_price, yes_price_dollars, and no_price_dollars must - be passed. + description: Updated no price for the order in fixed-point dollars. Exactly one of yes_price, no_price, yes_price_dollars, and no_price_dollars must be passed. count: type: integer minimum: 1 - description: >- - Updated quantity for the order (whole contracts only). If updating - quantity, provide count or count_fp; if both provided they must - match. + description: Updated quantity for the order (whole contracts only). If updating quantity, provide count or count_fp; if both provided they must match. count_fp: $ref: '#/components/schemas/FixedPointCount' nullable: true - description: >- - String representation of the updated quantity for the order. If - updating quantity, provide count or count_fp; if both provided they - must match. + description: String representation of the updated quantity for the order. If updating quantity, provide count or count_fp; if both provided they must match. exchange_index: allOf: - $ref: '#/components/schemas/ExchangeIndex' default: 0 x-go-type-skip-optional-pointer: true + AmendOrderResponse: type: object required: @@ -7255,54 +7068,38 @@ components: order: $ref: '#/components/schemas/Order' description: The order after amendment + DecreaseOrderRequest: type: object properties: subaccount: type: integer minimum: 0 - description: >- - Optional subaccount number to use for this decrease (0 for primary, - 1-63 for subaccounts) + description: Optional subaccount number to use for this decrease (0 for primary, 1-63 for subaccounts) default: 0 x-go-type-skip-optional-pointer: true reduce_by: type: integer minimum: 1 - description: >- - Number of contracts to reduce by (whole contracts only). Reduce-by - may be provided via reduce_by or reduce_by_fp; if both provided they - must match. Exactly one of reduce_by(/reduce_by_fp) or - reduce_to(/reduce_to_fp) must be provided. + description: Number of contracts to reduce by (whole contracts only). Reduce-by may be provided via reduce_by or reduce_by_fp; if both provided they must match. Exactly one of reduce_by(/reduce_by_fp) or reduce_to(/reduce_to_fp) must be provided. reduce_by_fp: $ref: '#/components/schemas/FixedPointCount' nullable: true - description: >- - String representation of the number of contracts to reduce by. - Reduce-by may be provided via reduce_by or reduce_by_fp; if both - provided they must match. Exactly one of reduce_by(/reduce_by_fp) or - reduce_to(/reduce_to_fp) must be provided. + description: String representation of the number of contracts to reduce by. Reduce-by may be provided via reduce_by or reduce_by_fp; if both provided they must match. Exactly one of reduce_by(/reduce_by_fp) or reduce_to(/reduce_to_fp) must be provided. reduce_to: type: integer minimum: 0 - description: >- - Number of contracts to reduce to (whole contracts only). Reduce-to - may be provided via reduce_to or reduce_to_fp; if both provided they - must match. Exactly one of reduce_by(/reduce_by_fp) or - reduce_to(/reduce_to_fp) must be provided. + description: Number of contracts to reduce to (whole contracts only). Reduce-to may be provided via reduce_to or reduce_to_fp; if both provided they must match. Exactly one of reduce_by(/reduce_by_fp) or reduce_to(/reduce_to_fp) must be provided. reduce_to_fp: $ref: '#/components/schemas/FixedPointCount' nullable: true - description: >- - String representation of the number of contracts to reduce to. - Reduce-to may be provided via reduce_to or reduce_to_fp; if both - provided they must match. Exactly one of reduce_by(/reduce_by_fp) or - reduce_to(/reduce_to_fp) must be provided. + description: String representation of the number of contracts to reduce to. Reduce-to may be provided via reduce_to or reduce_to_fp; if both provided they must match. Exactly one of reduce_by(/reduce_by_fp) or reduce_to(/reduce_to_fp) must be provided. exchange_index: allOf: - $ref: '#/components/schemas/ExchangeIndex' default: 0 x-go-type-skip-optional-pointer: true + DecreaseOrderResponse: type: object required: @@ -7310,6 +7107,7 @@ components: properties: order: $ref: '#/components/schemas/Order' + CreateOrderV2Request: type: object required: @@ -7323,8 +7121,8 @@ components: ticker: HIGHNY-24JAN01-T60 client_order_id: 8c35ecb3-328f-4f52-8c7c-0f4b9862f8d1 side: bid - count: '10.00' - price: '0.5600' + count: "10.00" + price: "0.5600" time_in_force: good_till_canceled self_trade_prevention_type: taker_at_cross post_only: false @@ -7354,37 +7152,21 @@ components: expiration_time: type: integer format: int64 - description: > - Optional Unix timestamp in seconds for when the order expires. To - place - + description: | + Optional Unix timestamp in seconds for when the order expires. To place an expiring order, set `time_in_force` to `good_till_canceled` and - - provide this `expiration_time`. `GTT` is an internal execution type - and - + provide this `expiration_time`. `GTT` is an internal execution type and is not a valid API value for `time_in_force`. The - `immediate_or_cancel` time-in-force value cannot be combined with - `expiration_time`. time_in_force: type: string - description: > - Specifies how long the order remains active. Use - `good_till_canceled` - - with `expiration_time` for an order that should rest until a - specific - - expiration time; without `expiration_time`, `good_till_canceled` is - a - + description: | + Specifies how long the order remains active. Use `good_till_canceled` + with `expiration_time` for an order that should rest until a specific + expiration time; without `expiration_time`, `good_till_canceled` is a true good-till-canceled order. `GTT` is not a valid API value. - enum: - - fill_or_kill - - good_till_canceled - - immediate_or_cancel + enum: ['fill_or_kill', 'good_till_canceled', 'immediate_or_cancel'] x-oapi-codegen-extra-tags: validate: required,oneof=fill_or_kill good_till_canceled immediate_or_cancel x-go-type-skip-optional-pointer: true @@ -7398,21 +7180,15 @@ components: x-go-type-skip-optional-pointer: true cancel_order_on_pause: type: boolean - description: >- - If this flag is set to true, the order will be canceled if the order - is open and trading on the exchange is paused for any reason. + description: If this flag is set to true, the order will be canceled if the order is open and trading on the exchange is paused for any reason. reduce_only: type: boolean - description: >- - Specifies whether the order place count should be capped by the - member's current position. + description: Specifies whether the order place count should be capped by the member's current position. subaccount: type: integer minimum: 0 default: 0 - description: >- - The subaccount number to use for this order. 0 is the primary - subaccount. + description: The subaccount number to use for this order. 0 is the primary subaccount. x-go-type-skip-optional-pointer: true order_group_id: type: string @@ -7423,6 +7199,7 @@ components: - $ref: '#/components/schemas/ExchangeIndex' default: 0 x-go-type-skip-optional-pointer: true + CreateOrderV2Response: type: object required: @@ -7433,8 +7210,8 @@ components: example: order_id: 3b23c1c7-f4ef-4f0d-8b9a-9e53c61f1a0d client_order_id: 8c35ecb3-328f-4f52-8c7c-0f4b9862f8d1 - fill_count: '0.00' - remaining_count: '10.00' + fill_count: "0.00" + remaining_count: "10.00" ts_ms: 1715793600123 properties: order_id: @@ -7446,25 +7223,18 @@ components: description: Number of contracts filled immediately upon placement. remaining_count: $ref: '#/components/schemas/FixedPointCount' - description: >- - Number of contracts remaining after placement. For IOC orders, this - reflects the final state after unfilled contracts are canceled. + description: Number of contracts remaining after placement. For IOC orders, this reflects the final state after unfilled contracts are canceled. average_fill_price: $ref: '#/components/schemas/FixedPointDollars' - description: >- - Volume-weighted average fill price. Only present when fill_count > - 0. + description: Volume-weighted average fill price. Only present when fill_count > 0. average_fee_paid: $ref: '#/components/schemas/FixedPointDollars' - description: >- - Volume-weighted average fee paid per contract for fills resulting - from this request. Only present when fill_count > 0. + description: Volume-weighted average fee paid per contract for fills resulting from this request. Only present when fill_count > 0. ts_ms: type: integer format: int64 - description: >- - Matching engine timestamp at which the order was processed, as Unix - epoch milliseconds. + description: Matching engine timestamp at which the order was processed, as Unix epoch milliseconds. + CancelOrderV2Response: type: object required: @@ -7474,7 +7244,7 @@ components: example: order_id: 3b23c1c7-f4ef-4f0d-8b9a-9e53c61f1a0d client_order_id: 8c35ecb3-328f-4f52-8c7c-0f4b9862f8d1 - reduced_by: '10.00' + reduced_by: "10.00" ts_ms: 1715793660456 properties: order_id: @@ -7483,38 +7253,32 @@ components: type: string reduced_by: $ref: '#/components/schemas/FixedPointCount' - description: >- - Number of contracts that were canceled (i.e. the remaining count at - time of cancellation). + description: Number of contracts that were canceled (i.e. the remaining count at time of cancellation). ts_ms: type: integer format: int64 - description: >- - Matching engine timestamp at which the cancellation was processed, - as Unix epoch milliseconds. + description: Matching engine timestamp at which the cancellation was processed, as Unix epoch milliseconds. + DecreaseOrderV2Request: type: object example: - reduce_by: '2.00' + reduce_by: "2.00" exchange_index: 0 properties: reduce_by: $ref: '#/components/schemas/FixedPointCount' nullable: true - description: >- - String representation of the number of contracts to reduce by. - Exactly one of `reduce_by` or `reduce_to` must be provided. + description: String representation of the number of contracts to reduce by. Exactly one of `reduce_by` or `reduce_to` must be provided. reduce_to: $ref: '#/components/schemas/FixedPointCount' nullable: true - description: >- - String representation of the number of contracts to reduce to. - Exactly one of `reduce_by` or `reduce_to` must be provided. + description: String representation of the number of contracts to reduce to. Exactly one of `reduce_by` or `reduce_to` must be provided. exchange_index: allOf: - $ref: '#/components/schemas/ExchangeIndex' default: 0 x-go-type-skip-optional-pointer: true + DecreaseOrderV2Response: type: object required: @@ -7524,7 +7288,7 @@ components: example: order_id: 3b23c1c7-f4ef-4f0d-8b9a-9e53c61f1a0d client_order_id: 8c35ecb3-328f-4f52-8c7c-0f4b9862f8d1 - remaining_count: '8.00' + remaining_count: "8.00" ts_ms: 1715793680789 properties: order_id: @@ -7537,9 +7301,8 @@ components: ts_ms: type: integer format: int64 - description: >- - Matching engine timestamp at which the decrease was processed, as - Unix epoch milliseconds. + description: Matching engine timestamp at which the decrease was processed, as Unix epoch milliseconds. + AmendOrderV2Request: type: object required: @@ -7550,8 +7313,8 @@ components: example: ticker: HIGHNY-24JAN01-T60 side: bid - price: '0.5700' - count: '8.00' + price: "0.5700" + count: "8.00" client_order_id: 8c35ecb3-328f-4f52-8c7c-0f4b9862f8d1 updated_client_order_id: 2a0e3fc9-b593-4aa3-96e5-82f7f7566c2a exchange_index: 0 @@ -7572,10 +7335,7 @@ components: x-go-type-skip-optional-pointer: true count: $ref: '#/components/schemas/FixedPointCount' - description: >- - Updated total/max fillable count for the order. Set this to the - order's already filled count plus the desired resting remaining - count after the amend. + description: Updated total/max fillable count for the order. Set this to the order's already filled count plus the desired resting remaining count after the amend. x-go-type-skip-optional-pointer: true client_order_id: type: string @@ -7590,6 +7350,7 @@ components: - $ref: '#/components/schemas/ExchangeIndex' default: 0 x-go-type-skip-optional-pointer: true + AmendOrderV2Response: type: object required: @@ -7598,8 +7359,8 @@ components: example: order_id: 3b23c1c7-f4ef-4f0d-8b9a-9e53c61f1a0d client_order_id: 2a0e3fc9-b593-4aa3-96e5-82f7f7566c2a - remaining_count: '8.00' - fill_count: '0.00' + remaining_count: "8.00" + fill_count: "0.00" ts_ms: 1715793690123 properties: order_id: @@ -7610,38 +7371,27 @@ components: $ref: '#/components/schemas/FixedPointCount' nullable: true x-omitempty: false - description: >- - Number of resting contracts remaining after the amend. This is the - actual post-amend resting quantity, not the request's total/max - fillable count. Only present when the amend caused a fill or changed - the resting size. + description: Number of resting contracts remaining after the amend. This is the actual post-amend resting quantity, not the request's total/max fillable count. Only present when the amend caused a fill or changed the resting size. fill_count: $ref: '#/components/schemas/FixedPointCount' nullable: true x-omitempty: false - description: >- - Number of contracts filled as a result of the amend crossing the - book. Only present when fills occurred or remaining size changed. + description: Number of contracts filled as a result of the amend crossing the book. Only present when fills occurred or remaining size changed. average_fill_price: $ref: '#/components/schemas/FixedPointDollars' nullable: true x-omitempty: false - description: >- - Volume-weighted average fill price for fills resulting from the - amend. Only present when fills occurred. + description: Volume-weighted average fill price for fills resulting from the amend. Only present when fills occurred. average_fee_paid: $ref: '#/components/schemas/FixedPointDollars' nullable: true x-omitempty: false - description: >- - Volume-weighted average fee paid per contract for fills resulting - from the amend. Only present when fills occurred. + description: Volume-weighted average fee paid per contract for fills resulting from the amend. Only present when fills occurred. ts_ms: type: integer format: int64 - description: >- - Matching engine timestamp at which the amend was processed, as Unix - epoch milliseconds. + description: Matching engine timestamp at which the amend was processed, as Unix epoch milliseconds. + BatchCreateOrdersV2Request: type: object required: @@ -7651,16 +7401,16 @@ components: - ticker: HIGHNY-24JAN01-T60 client_order_id: 8c35ecb3-328f-4f52-8c7c-0f4b9862f8d1 side: bid - count: '10.00' - price: '0.5600' + count: "10.00" + price: "0.5600" time_in_force: good_till_canceled self_trade_prevention_type: taker_at_cross exchange_index: 0 - ticker: HIGHNY-24JAN01-T60 client_order_id: 2a0e3fc9-b593-4aa3-96e5-82f7f7566c2a side: ask - count: '5.00' - price: '0.5800' + count: "5.00" + price: "0.5800" time_in_force: immediate_or_cancel self_trade_prevention_type: maker exchange_index: 0 @@ -7671,6 +7421,7 @@ components: validate: required,dive items: $ref: '#/components/schemas/CreateOrderV2Request' + BatchCreateOrdersV2Response: type: object required: @@ -7679,15 +7430,15 @@ components: orders: - order_id: 3b23c1c7-f4ef-4f0d-8b9a-9e53c61f1a0d client_order_id: 8c35ecb3-328f-4f52-8c7c-0f4b9862f8d1 - fill_count: '0.00' - remaining_count: '10.00' + fill_count: "0.00" + remaining_count: "10.00" ts_ms: 1715793600123 - order_id: a6d6010d-6d5f-40a1-a7e7-5501386bb621 client_order_id: 2a0e3fc9-b593-4aa3-96e5-82f7f7566c2a - fill_count: '5.00' - remaining_count: '0.00' - average_fill_price: '0.5800' - average_fee_paid: '0.0012' + fill_count: "5.00" + remaining_count: "0.00" + average_fill_price: "0.5800" + average_fee_paid: "0.0012" ts_ms: 1715793600456 properties: orders: @@ -7714,28 +7465,23 @@ components: $ref: '#/components/schemas/FixedPointDollars' nullable: true x-omitempty: false - description: >- - Volume-weighted average fill price. Only present when - fill_count > 0. + description: Volume-weighted average fill price. Only present when fill_count > 0. average_fee_paid: $ref: '#/components/schemas/FixedPointDollars' nullable: true x-omitempty: false - description: >- - Volume-weighted average fee paid per contract. Only present - when fill_count > 0. + description: Volume-weighted average fee paid per contract. Only present when fill_count > 0. ts_ms: type: integer format: int64 nullable: true x-omitempty: false - description: >- - Matching engine timestamp at which the order was processed, as - Unix epoch milliseconds. Absent when the request errored. + description: Matching engine timestamp at which the order was processed, as Unix epoch milliseconds. Absent when the request errored. error: allOf: - $ref: '#/components/schemas/ErrorResponse' nullable: true + BatchCancelOrdersV2Request: type: object required: @@ -7753,9 +7499,7 @@ components: type: array x-oapi-codegen-extra-tags: validate: required,dive - description: >- - An array of orders to cancel, each optionally specifying a - subaccount. + description: An array of orders to cancel, each optionally specifying a subaccount. items: type: object required: @@ -7768,15 +7512,14 @@ components: type: integer minimum: 0 default: 0 - description: >- - Optional subaccount number to use for this cancellation (0 for - primary, 1-63 for subaccounts). + description: Optional subaccount number to use for this cancellation (0 for primary, 1-63 for subaccounts). x-go-type-skip-optional-pointer: true exchange_index: allOf: - $ref: '#/components/schemas/ExchangeIndex' default: 0 x-go-type-skip-optional-pointer: true + BatchCancelOrdersV2Response: type: object required: @@ -7785,11 +7528,11 @@ components: orders: - order_id: 3b23c1c7-f4ef-4f0d-8b9a-9e53c61f1a0d client_order_id: 8c35ecb3-328f-4f52-8c7c-0f4b9862f8d1 - reduced_by: '10.00' + reduced_by: "10.00" ts_ms: 1715793660456 - order_id: a6d6010d-6d5f-40a1-a7e7-5501386bb621 client_order_id: 2a0e3fc9-b593-4aa3-96e5-82f7f7566c2a - reduced_by: '5.00' + reduced_by: "5.00" ts_ms: 1715793660789 properties: orders: @@ -7802,30 +7545,25 @@ components: properties: order_id: type: string - description: >- - The order ID identifying which order this entry corresponds - to. + description: The order ID identifying which order this entry corresponds to. client_order_id: type: string nullable: true reduced_by: $ref: '#/components/schemas/FixedPointCount' - description: >- - Number of contracts that were canceled (i.e. the remaining - count at time of cancellation). Zero if the cancel errored. + description: Number of contracts that were canceled (i.e. the remaining count at time of cancellation). Zero if the cancel errored. ts_ms: type: integer format: int64 nullable: true x-omitempty: false - description: >- - Matching engine timestamp at which the cancellation was - processed, as Unix epoch milliseconds. Absent when the cancel - errored. + description: Matching engine timestamp at which the cancellation was processed, as Unix epoch milliseconds. Absent when the cancel errored. error: allOf: - $ref: '#/components/schemas/ErrorResponse' nullable: true + + # Multivariate Event Collection schemas AssociatedEvent: type: object required: @@ -7843,21 +7581,18 @@ components: type: integer format: int32 nullable: true - description: >- - Maximum number of markets from this event (inclusive). Null means no - limit. + description: Maximum number of markets from this event (inclusive). Null means no limit. size_min: type: integer format: int32 nullable: true - description: >- - Minimum number of markets from this event (inclusive). Null means no - limit. + description: Minimum number of markets from this event (inclusive). Null means no limit. active_quoters: type: array items: type: string description: List of active quoters for this event. + MultivariateEventCollection: type: object required: @@ -7881,9 +7616,7 @@ components: description: Unique identifier for the collection. series_ticker: type: string - description: >- - Series associated with the collection. Events produced in the - collection will be associated with this series. + description: Series associated with the collection. Events produced in the collection will be associated with this series. title: type: string description: Title of the collection. @@ -7893,15 +7626,11 @@ components: open_date: type: string format: date-time - description: >- - The open date of the collection. Before this time, the collection - cannot be interacted with. + description: The open date of the collection. Before this time, the collection cannot be interacted with. close_date: type: string format: date-time - description: >- - The close date of the collection. After this time, the collection - cannot be interacted with. + description: The close date of the collection. After this time, the collection cannot be interacted with. associated_events: type: array items: @@ -7911,44 +7640,28 @@ components: type: array items: type: string - description: >- - [DEPRECATED - Use associated_events instead] A list of events - associated with the collection. Markets in these events can be - passed as inputs to the Lookup and Create endpoints. + description: '[DEPRECATED - Use associated_events instead] A list of events associated with the collection. Markets in these events can be passed as inputs to the Lookup and Create endpoints.' is_ordered: type: boolean - description: >- - Whether the collection is ordered. If true, the order of markets - passed into Lookup/Create affects the output. If false, the order - does not matter. + description: Whether the collection is ordered. If true, the order of markets passed into Lookup/Create affects the output. If false, the order does not matter. is_single_market_per_event: type: boolean - description: >- - [DEPRECATED - Use associated_events instead] Whether the collection - accepts multiple markets from the same event passed into - Lookup/Create. + description: '[DEPRECATED - Use associated_events instead] Whether the collection accepts multiple markets from the same event passed into Lookup/Create.' is_all_yes: type: boolean - description: >- - [DEPRECATED - Use associated_events instead] Whether the collection - requires that only the market side of 'yes' may be used. + description: '[DEPRECATED - Use associated_events instead] Whether the collection requires that only the market side of ''yes'' may be used.' size_min: type: integer format: int32 - description: >- - The minimum number of markets that must be passed into Lookup/Create - (inclusive). + description: The minimum number of markets that must be passed into Lookup/Create (inclusive). size_max: type: integer format: int32 - description: >- - The maximum number of markets that must be passed into Lookup/Create - (inclusive). + description: The maximum number of markets that must be passed into Lookup/Create (inclusive). functional_description: type: string - description: >- - A functional description of the collection describing how inputs - affect the output. + description: A functional description of the collection describing how inputs affect the output. + GetMultivariateEventCollectionResponse: type: object required: @@ -7957,6 +7670,7 @@ components: multivariate_contract: $ref: '#/components/schemas/MultivariateEventCollection' description: The multivariate event collection. + GetMultivariateEventCollectionsResponse: type: object required: @@ -7969,13 +7683,9 @@ components: description: List of multivariate event collections. cursor: type: string - description: >- - The Cursor represents a pointer to the next page of records in the - pagination. Use the value returned here in the cursor query - parameter for this end-point to get the next page containing limit - records. An empty value of this field indicates there is no next - page. + description: The Cursor represents a pointer to the next page of records in the pagination. Use the value returned here in the cursor query parameter for this end-point to get the next page containing limit records. An empty value of this field indicates there is no next page. x-go-type-skip-optional-pointer: true + TickerPair: type: object required: @@ -7991,10 +7701,11 @@ components: description: Event ticker identifier. side: type: string - enum: - - 'yes' - - 'no' + enum: ['yes', 'no'] description: Side of the market (yes or no). + x-oapi-codegen-extra-tags: + validate: required,oneof=yes no + LookupTickersForMarketInMultivariateEventCollectionRequest: type: object required: @@ -8004,9 +7715,8 @@ components: type: array items: $ref: '#/components/schemas/TickerPair' - description: >- - List of selected markets that act as parameters to determine which - market is produced. + description: List of selected markets that act as parameters to determine which market is produced. + LookupTickersForMarketInMultivariateEventCollectionResponse: type: object required: @@ -8019,6 +7729,7 @@ components: market_ticker: type: string description: Market ticker for the looked up market. + LookupPoint: type: object required: @@ -8042,6 +7753,7 @@ components: type: string format: date-time description: Timestamp when this lookup was last queried. + GetMultivariateEventCollectionLookupHistoryResponse: type: object required: @@ -8052,6 +7764,7 @@ components: items: $ref: '#/components/schemas/LookupPoint' description: List of recent lookup points in the collection. + CreateMarketInMultivariateEventCollectionRequest: type: object required: @@ -8061,12 +7774,13 @@ components: type: array items: $ref: '#/components/schemas/TickerPair' - description: >- - List of selected markets that act as parameters to determine which - market is created. + description: List of selected markets that act as parameters to determine which market is created. + x-oapi-codegen-extra-tags: + validate: required,dive with_market_payload: type: boolean description: Whether to include the market payload in the response. + CreateMarketInMultivariateEventCollectionResponse: type: object required: @@ -8082,20 +7796,16 @@ components: market: $ref: '#/components/schemas/Market' description: Market payload of the created market. + # Market Orderbook schemas PriceLevelDollarsCountFp: type: array minItems: 2 maxItems: 2 - example: - - '0.1500' - - '100.00' + example: ["0.1500", "100.00"] items: type: string - description: >- - Price level in dollars represented as [dollars_string, fp] where - dollars_string is like "0.1500" and fp is a FixedPointCount string - (fixed-point contract count). The second element is the contract - quantity (not price). + description: Price level in dollars represented as [dollars_string, fp] where dollars_string is like "0.1500" and fp is a FixedPointCount string (fixed-point contract count). The second element is the contract quantity (not price). + OrderbookCountFp: type: object required: @@ -8110,9 +7820,8 @@ components: type: array items: $ref: '#/components/schemas/PriceLevelDollarsCountFp' - description: >- - Orderbook with fixed-point contract counts (fp) in all dollar price - levels. + description: Orderbook with fixed-point contract counts (fp) in all dollar price levels. + GetMarketOrderbooksResponse: type: object required: @@ -8122,6 +7831,7 @@ components: type: array items: $ref: '#/components/schemas/MarketOrderbookFp' + MarketOrderbookFp: type: object required: @@ -8132,6 +7842,7 @@ components: type: string orderbook_fp: $ref: '#/components/schemas/OrderbookCountFp' + GetMarketOrderbookResponse: type: object required: @@ -8140,6 +7851,7 @@ components: orderbook_fp: $ref: '#/components/schemas/OrderbookCountFp' description: Orderbook with fixed-point contract counts (fp) in all price levels. + GetEventsResponse: type: object required: @@ -8158,9 +7870,8 @@ components: $ref: '#/components/schemas/Milestone' cursor: type: string - description: >- - Pagination cursor for the next page. Empty if there are no more - results. + description: Pagination cursor for the next page. Empty if there are no more results. + GetMultivariateEventsResponse: type: object required: @@ -8174,9 +7885,8 @@ components: $ref: '#/components/schemas/EventData' cursor: type: string - description: >- - Pagination cursor for the next page. Empty if there are no more - results. + description: Pagination cursor for the next page. Empty if there are no more results. + EventFeeChange: type: object required: @@ -8201,21 +7911,17 @@ components: - $ref: '#/components/schemas/FeeType' nullable: true example: quadratic - description: >- - New fee type override for the event. When null, the event clears any - prior override and falls back to the parent series' fee structure. + description: New fee type override for the event. When null, the event clears any prior override and falls back to the parent series' fee structure. fee_multiplier_override: type: number format: double nullable: true - description: >- - New fee multiplier override for the event. When null, the event - clears any prior override and falls back to the parent series' fee - multiplier. + description: New fee multiplier override for the event. When null, the event clears any prior override and falls back to the parent series' fee multiplier. scheduled_ts: type: string format: date-time description: Timestamp when this fee change is scheduled to take effect + GetEventFeeChangesResponse: type: object required: @@ -8228,9 +7934,8 @@ components: $ref: '#/components/schemas/EventFeeChange' cursor: type: string - description: >- - Pagination cursor for the next page. Empty if there are no more - results. + description: Pagination cursor for the next page. Empty if there are no more results. + GetEventResponse: type: object required: @@ -8242,13 +7947,10 @@ components: description: Data for the event. markets: type: array - description: >- - Data for the markets in this event. This field is deprecated in - favour of the "markets" field inside the event. Which will be filled - with the same value if you use the query parameter - "with_nested_markets=true". + description: Data for the markets in this event. This field is deprecated in favour of the "markets" field inside the event. Which will be filled with the same value if you use the query parameter "with_nested_markets=true". items: $ref: '#/components/schemas/Market' + MarketMetadata: type: object required: @@ -8265,6 +7967,7 @@ components: color_code: type: string description: The color code for the market. + GetEventMetadataResponse: type: object required: @@ -8300,6 +8003,7 @@ components: x-omitempty: true description: Event scope, based on the competition. x-go-type-skip-optional-pointer: true + GetEventForecastPercentilesHistoryResponse: type: object required: @@ -8310,6 +8014,7 @@ components: description: Array of forecast percentile data points over time. items: $ref: '#/components/schemas/ForecastPercentilesPoint' + ForecastPercentilesPoint: type: object required: @@ -8334,6 +8039,7 @@ components: description: Array of forecast values at different percentiles. items: $ref: '#/components/schemas/PercentilePoint' + PercentilePoint: type: object required: @@ -8355,6 +8061,7 @@ components: formatted_forecast: type: string description: The human-readable formatted forecast value. + EventData: type: object required: @@ -8380,14 +8087,10 @@ components: description: Full title of the event. collateral_return_type: type: string - description: >- - Specifies how collateral is returned when markets settle (e.g., - 'binary' for standard yes/no markets). + description: Specifies how collateral is returned when markets settle (e.g., 'binary' for standard yes/no markets). mutually_exclusive: type: boolean - description: >- - If true, only one market in this event can resolve to 'yes'. If - false, multiple markets can resolve to 'yes'. + description: If true, only one market in this event can resolve to 'yes'. If false, multiple markets can resolve to 'yes'. category: type: string description: Event category (deprecated, use series-level category instead). @@ -8398,23 +8101,16 @@ components: format: date-time nullable: true x-omitempty: true - description: >- - The specific date this event is based on. Only filled when the event - uses a date strike (mutually exclusive with strike_period). + description: The specific date this event is based on. Only filled when the event uses a date strike (mutually exclusive with strike_period). strike_period: type: string nullable: true x-omitempty: true - description: >- - The time period this event covers (e.g., 'week', 'month'). Only - filled when the event uses a period strike (mutually exclusive with - strike_date). + description: The time period this event covers (e.g., 'week', 'month'). Only filled when the event uses a period strike (mutually exclusive with strike_date). markets: type: array x-omitempty: true - description: >- - Array of markets associated with this event. Only populated when - 'with_nested_markets=true' is specified in the request. + description: Array of markets associated with this event. Only populated when 'with_nested_markets=true' is specified in the request. items: $ref: '#/components/schemas/Market' x-go-type-skip-optional-pointer: true @@ -8435,21 +8131,18 @@ components: type: string nullable: true x-omitempty: true - description: >- - Fee type override for this event. When present, takes precedence - over the series-level fee for this event's markets. + description: Fee type override for this event. When present, takes precedence over the series-level fee for this event's markets. fee_multiplier_override: type: number format: double nullable: true x-omitempty: true - description: >- - Fee multiplier override for this event. Paired with - fee_type_override. + description: Fee multiplier override for this event. Paired with fee_type_override. exchange_index: allOf: - $ref: '#/components/schemas/ExchangeIndex' x-go-type-skip-optional-pointer: true + Series: type: object required: @@ -8470,16 +8163,10 @@ components: description: Ticker that identifies this series. frequency: type: string - description: >- - Description of the frequency of the series. There is no fixed value - set here, but will be something human-readable like weekly, daily, - one-off. + description: Description of the frequency of the series. There is no fixed value set here, but will be something human-readable like weekly, daily, one-off. title: type: string - description: >- - Title describing the series. For full context use you should use - this field with the title field of the events belonging to this - series. + description: Title describing the series. For full context use you should use this field with the title field of the events belonging to this series. category: type: string description: Category specifies the category which this series belongs to. @@ -8488,28 +8175,19 @@ components: nullable: true items: type: string - description: >- - Tags specifies the subjects that this series relates to, multiple - series from different categories can have the same tags. + description: Tags specifies the subjects that this series relates to, multiple series from different categories can have the same tags. settlement_sources: type: array nullable: true items: $ref: '#/components/schemas/SettlementSource' - description: >- - SettlementSources specifies the official sources used for the - determination of markets within the series. Methodology is defined - in the rulebook. + description: SettlementSources specifies the official sources used for the determination of markets within the series. Methodology is defined in the rulebook. contract_url: type: string - description: >- - ContractUrl provides a direct link to the original filing of the - contract which underlies the series. + description: ContractUrl provides a direct link to the original filing of the contract which underlies the series. contract_terms_url: type: string - description: >- - ContractTermsUrl is the URL to the current terms of the contract - underlying the series. + description: ContractTermsUrl is the URL to the current terms of the contract underlying the series. product_metadata: type: object nullable: true @@ -8518,36 +8196,24 @@ components: fee_type: allOf: - $ref: '#/components/schemas/FeeType' - description: >- - FeeType is a string representing the series' fee structure. Fee - structures can be found at - https://kalshi.com/docs/kalshi-fee-schedule.pdf. 'quadratic' is - described by the General Trading Fees Table, - 'quadratic_with_maker_fees' is described by the General Trading Fees - Table with maker fees described in the Maker Fees section, 'flat' is - described by the Specific Trading Fees Table. + description: "FeeType is a string representing the series' fee structure. Fee structures can be found at https://kalshi.com/docs/kalshi-fee-schedule.pdf. 'quadratic' is described by the General Trading Fees Table, 'quadratic_with_maker_fees' is described by the General Trading Fees Table with maker fees described in the Maker Fees section, 'flat' is described by the Specific Trading Fees Table." fee_multiplier: type: number format: double - description: >- - FeeMultiplier is a floating point multiplier applied to the fee - calculations. + description: FeeMultiplier is a floating point multiplier applied to the fee calculations. additional_prohibitions: type: array items: type: string - description: >- - AdditionalProhibitions is a list of additional trading prohibitions - for this series. + description: AdditionalProhibitions is a list of additional trading prohibitions for this series. volume_fp: $ref: '#/components/schemas/FixedPointCount' - description: >- - String representation of the total number of contracts traded across - all events in this series. + description: String representation of the total number of contracts traded across all events in this series. last_updated_ts: type: string format: date-time description: Timestamp of when this series' metadata was last updated. + SeriesFeeChange: type: object required: @@ -8575,6 +8241,7 @@ components: type: string format: date-time description: Timestamp when this fee change is scheduled to take effect + GetSeriesResponse: type: object required: @@ -8582,6 +8249,7 @@ components: properties: series: $ref: '#/components/schemas/Series' + GetSeriesListResponse: type: object required: @@ -8591,6 +8259,7 @@ components: type: array items: $ref: '#/components/schemas/Series' + GetSeriesFeeChangesResponse: type: object required: @@ -8600,6 +8269,7 @@ components: type: array items: $ref: '#/components/schemas/SeriesFeeChange' + SettlementSource: type: object properties: @@ -8611,6 +8281,7 @@ components: type: string description: URL to the settlement source x-go-type-skip-optional-pointer: true + GetMarketsResponse: type: object required: @@ -8623,6 +8294,7 @@ components: $ref: '#/components/schemas/Market' cursor: type: string + GetMarketResponse: type: object required: @@ -8630,6 +8302,7 @@ components: properties: market: $ref: '#/components/schemas/Market' + MveSelectedLeg: type: object properties: @@ -8649,9 +8322,8 @@ components: $ref: '#/components/schemas/FixedPointDollars' nullable: true x-omitempty: true - description: >- - The settlement value of the YES/LONG side of the contract in - dollars. Only filled after determination + description: The settlement value of the YES/LONG side of the contract in dollars. Only filled after determination + PriceRange: type: object required: @@ -8668,6 +8340,7 @@ components: step: type: string description: Price step/tick size for this range in dollars + Market: type: object required: @@ -8713,9 +8386,7 @@ components: type: string market_type: type: string - enum: - - binary - - scalar + enum: [binary, scalar] description: Identifies the type of market title: type: string @@ -8764,20 +8435,11 @@ components: description: The amount of time after determination that the market settles status: type: string - enum: - - initialized - - inactive - - active - - closed - - determined - - disputed - - amended - - finalized + enum: [initialized, inactive, active, closed, determined, disputed, amended, finalized] description: The current status of the market in its lifecycle. response_price_units: type: string - enum: - - usd_cent + enum: [usd_cent] deprecated: true description: 'DEPRECATED: Use price_level_structure and price_ranges instead.' x-go-type-skip-optional-pointer: true @@ -8786,17 +8448,13 @@ components: description: Price for the highest YES buy offer on this market in dollars yes_bid_size_fp: $ref: '#/components/schemas/FixedPointCount' - description: >- - Total contract size of orders to buy YES at the best bid price - (fixed-point count string). + description: Total contract size of orders to buy YES at the best bid price (fixed-point count string). yes_ask_dollars: $ref: '#/components/schemas/FixedPointDollars' description: Price for the lowest YES sell offer on this market in dollars yes_ask_size_fp: $ref: '#/components/schemas/FixedPointCount' - description: >- - Total contract size of orders to sell YES at the best ask price - (fixed-point count string). + description: Total contract size of orders to sell YES at the best ask price (fixed-point count string). no_bid_dollars: $ref: '#/components/schemas/FixedPointDollars' description: Price for the highest NO buy offer on this market in dollars @@ -8814,63 +8472,45 @@ components: description: String representation of the 24h market volume in contracts result: type: string - enum: - - 'yes' - - 'no' - - scalar - - '' + enum: ['yes', 'no', 'scalar', ''] can_close_early: type: boolean fractional_trading_enabled: type: boolean deprecated: true description: >- - Deprecated. This flag is always `true` and carries no information. - Will be removed after a pre-announcement with the removal date. + Deprecated. This flag is always `true` and carries no information. Will be removed + after a pre-announcement with the removal date. open_interest_fp: $ref: '#/components/schemas/FixedPointCount' - description: >- - String representation of the number of contracts bought on this - market disconsidering netting + description: String representation of the number of contracts bought on this market disconsidering netting notional_value_dollars: $ref: '#/components/schemas/FixedPointDollars' description: The total value of a single contract at settlement in dollars previous_yes_bid_dollars: $ref: '#/components/schemas/FixedPointDollars' - description: >- - Price for the highest YES buy offer on this market a day ago in - dollars + description: Price for the highest YES buy offer on this market a day ago in dollars previous_yes_ask_dollars: $ref: '#/components/schemas/FixedPointDollars' - description: >- - Price for the lowest YES sell offer on this market a day ago in - dollars + description: Price for the lowest YES sell offer on this market a day ago in dollars previous_price_dollars: $ref: '#/components/schemas/FixedPointDollars' - description: >- - Price for the last traded YES contract on this market a day ago in - dollars + description: Price for the last traded YES contract on this market a day ago in dollars liquidity_dollars: $ref: '#/components/schemas/FixedPointDollars' deprecated: true - description: >- - DEPRECATED: This field is deprecated and will always return - "0.0000". + description: 'DEPRECATED: This field is deprecated and will always return "0.0000".' settlement_value_dollars: $ref: '#/components/schemas/FixedPointDollars' nullable: true x-omitempty: true - description: >- - The settlement value of the YES/LONG side of the contract in - dollars. Only filled after determination + description: The settlement value of the YES/LONG side of the contract in dollars. Only filled after determination settlement_ts: type: string format: date-time nullable: true x-omitempty: true - description: >- - Timestamp when the market was settled. Only filled for settled - markets + description: Timestamp when the market was settled. Only filled for settled markets expiration_value: type: string description: The value that was considered for the settlement @@ -8878,9 +8518,7 @@ components: type: string format: date-time nullable: true - description: >- - The recorded datetime when the underlying event occurred, if - available + description: The recorded datetime when the underlying event occurred, if available fee_waiver_expiration_time: type: string format: date-time @@ -8895,15 +8533,7 @@ components: x-go-type-skip-optional-pointer: true strike_type: type: string - enum: - - greater - - greater_or_equal - - less - - less_or_equal - - between - - functional - - custom - - structured + enum: [greater, greater_or_equal, less, less_or_equal, between, functional, custom, structured] x-omitempty: true description: Strike type defines how the market strike is defined and evaluated x-go-type-skip-optional-pointer: true @@ -8952,9 +8582,7 @@ components: x-omitempty: true price_level_structure: type: string - description: >- - Price level structure for this market, defining price ranges and - tick sizes + description: Price level structure for this market, defining price ranges and tick sizes price_ranges: type: array description: Valid price ranges for orders on this market @@ -8963,14 +8591,13 @@ components: is_provisional: type: boolean x-omitempty: true - description: >- - If true, the market may be removed after determination if there is - no activity on it + description: If true, the market may be removed after determination if there is no activity on it x-go-type-skip-optional-pointer: true exchange_index: allOf: - $ref: '#/components/schemas/ExchangeIndex' x-go-type-skip-optional-pointer: true + tags: - name: api-keys description: API key management endpoints diff --git a/specs/perps_openapi.yaml b/specs/perps_openapi.yaml index 1168e3c..8aa062d 100644 --- a/specs/perps_openapi.yaml +++ b/specs/perps_openapi.yaml @@ -2,14 +2,14 @@ openapi: 3.0.0 info: title: Kalshi Trade API Manual Endpoints version: 0.0.1 - description: Manually defined OpenAPI spec for endpoints being migrated to spec-first approach - + description: >- + Manually defined OpenAPI spec for endpoints being migrated to spec-first + approach servers: - url: https://external-api.kalshi.com/trade-api/v2 description: Production perps REST API server - url: https://external-api.demo.kalshi.co/trade-api/v2 description: Demo perps REST API server - paths: /account/limits/perps: get: @@ -33,12 +33,11 @@ paths: description: Unauthorized '500': description: Internal server error - /margin/exchange/status: get: operationId: GetMarginExchangeStatus summary: Get Exchange Status - description: 'Endpoint for getting the margin exchange status.' + description: Endpoint for getting the margin exchange status. tags: - exchange responses: @@ -66,12 +65,13 @@ paths: application/json: schema: $ref: '#/components/schemas/ExchangeStatus' - /margin/risk_parameters: get: operationId: GetMarginRiskParameters summary: Get Risk Parameters - description: 'Returns system-wide margin risk parameters including liquidation thresholds and per-market initial margin multipliers.' + description: >- + Returns system-wide margin risk parameters including liquidation + thresholds and per-market initial margin multipliers. tags: - risk responses: @@ -81,12 +81,11 @@ paths: application/json: schema: $ref: '#/components/schemas/GetMarginRiskParametersResponse' - /margin/orders: get: operationId: GetMarginOrders summary: Get Orders - description: 'Endpoint for listing margin orders with optional filtering.' + description: Endpoint for listing margin orders with optional filtering. tags: - orders security: @@ -147,14 +146,15 @@ paths: $ref: '#/components/responses/RateLimitError' '500': $ref: '#/components/responses/InternalServerError' - /margin/fcm/orders: get: operationId: GetMarginFCMOrders summary: Get FCM Orders - description: | + description: > Endpoint for FCM members to get margin orders filtered by subtrader ID. - This endpoint requires FCM member access level and allows filtering margin orders by subtrader ID. + + This endpoint requires FCM member access level and allows filtering + margin orders by subtrader ID. tags: - fcm security: @@ -165,7 +165,9 @@ paths: - name: subtrader_id in: query required: true - description: Restricts the response to margin orders for a specific subtrader (FCM members only) + description: >- + Restricts the response to margin orders for a specific subtrader + (FCM members only) schema: type: string - $ref: '#/components/parameters/TickerQuery' @@ -187,7 +189,6 @@ paths: $ref: '#/components/responses/UnauthorizedError' '500': $ref: '#/components/responses/InternalServerError' - /margin/orders/{order_id}: get: operationId: GetMarginOrder @@ -214,11 +215,12 @@ paths: $ref: '#/components/responses/NotFoundError' '500': $ref: '#/components/responses/InternalServerError' - delete: operationId: CancelMarginOrder summary: Cancel Order - description: Endpoint for canceling an order. Cancels all remaining resting contracts and returns the canceled order details. + description: >- + Endpoint for canceling an order. Cancels all remaining resting contracts + and returns the canceled order details. tags: - orders security: @@ -241,12 +243,14 @@ paths: $ref: '#/components/responses/NotFoundError' '500': $ref: '#/components/responses/InternalServerError' - /margin/orders/{order_id}/decrease: post: operationId: DecreaseMarginOrder summary: Decrease Order - description: Endpoint for decreasing the number of contracts in an existing order. Exactly one of `reduce_by` or `reduce_to` must be provided. Canceling an order is equivalent to decreasing to zero. + description: >- + Endpoint for decreasing the number of contracts in an existing order. + Exactly one of `reduce_by` or `reduce_to` must be provided. Canceling an + order is equivalent to decreasing to zero. tags: - orders security: @@ -277,16 +281,22 @@ paths: $ref: '#/components/responses/NotFoundError' '500': $ref: '#/components/responses/InternalServerError' - /margin/orders/{order_id}/amend: post: operationId: AmendMarginOrder summary: Amend Order - description: Endpoint for amending the price and/or max number of fillable contracts in an existing margin order. + description: >- + Endpoint for amending the price and/or max number of fillable contracts + in an existing margin order. x-mint: - content: | + content: > - Amending a resting order preserves queue position only when the amendment decreases size. All other amendments — like increasing size or changing price forfeit queue position and place the order at the back of the queue. + + Amending a resting order preserves queue position only when the + amendment decreases size. All other amendments — like increasing size + or changing price forfeit queue position and place the order at the + back of the queue. + tags: - orders @@ -318,7 +328,6 @@ paths: $ref: '#/components/responses/NotFoundError' '500': $ref: '#/components/responses/InternalServerError' - /margin/markets: get: operationId: GetMarginMarkets @@ -347,12 +356,13 @@ paths: $ref: '#/components/responses/RateLimitError' '500': $ref: '#/components/responses/InternalServerError' - /margin/markets/{ticker}: get: operationId: GetMarginMarket summary: Get Market - description: Endpoint for fetching a margin market with trading stats (price, volume, open interest). + description: >- + Endpoint for fetching a margin market with trading stats (price, volume, + open interest). tags: - market parameters: @@ -377,7 +387,6 @@ paths: $ref: '#/components/responses/RateLimitError' '500': $ref: '#/components/responses/InternalServerError' - /margin/markets/{ticker}/orderbook: get: operationId: GetMarginMarketOrderbook @@ -402,7 +411,9 @@ paths: default: 0 - name: aggregation_tick_size in: query - description: Tick size in dollars for aggregating price levels (e.g., 0.10 for 10 cent buckets) + description: >- + Tick size in dollars for aggregating price levels (e.g., 0.10 for 10 + cent buckets) required: false schema: type: string @@ -421,7 +432,6 @@ paths: $ref: '#/components/responses/RateLimitError' '500': $ref: '#/components/responses/InternalServerError' - /margin/markets/{ticker}/candlesticks: get: operationId: GetMarginMarketCandlesticks @@ -439,34 +449,49 @@ paths: - name: start_ts in: query required: true - description: Start timestamp (Unix timestamp). Candlesticks will include those ending on or after this time. + description: >- + Start timestamp (Unix timestamp). Candlesticks will include those + ending on or after this time. schema: type: integer format: int64 - name: end_ts in: query required: true - description: End timestamp (Unix timestamp). Candlesticks will include those ending on or before this time. + description: >- + End timestamp (Unix timestamp). Candlesticks will include those + ending on or before this time. schema: type: integer format: int64 - name: period_interval in: query required: true - description: Time period length of each candlestick in minutes. Valid values are 1 (1 minute), 60 (1 hour), or 1440 (1 day). + description: >- + Time period length of each candlestick in minutes. Valid values are + 1 (1 minute), 60 (1 hour), or 1440 (1 day). schema: type: integer - enum: [1, 60, 1440] + enum: + - 1 + - 60 + - 1440 x-oapi-codegen-extra-tags: - validate: "required,oneof=1 60 1440" + validate: required,oneof=1 60 1440 - name: include_latest_before_start in: query required: false - description: | - If true, prepends the latest candlestick available before the start_ts. This synthetic candlestick is created by: + description: > + If true, prepends the latest candlestick available before the + start_ts. This synthetic candlestick is created by: + 1. Finding the most recent real candlestick before start_ts - 2. Projecting it forward to the first period boundary (calculated as the next period interval after start_ts) - 3. Setting all OHLC prices to null, and `price.previous` to the close price from the real candlestick + + 2. Projecting it forward to the first period boundary (calculated as + the next period interval after start_ts) + + 3. Setting all OHLC prices to null, and `price.previous` to the + close price from the real candlestick schema: type: boolean default: false @@ -483,7 +508,6 @@ paths: $ref: '#/components/responses/NotFoundError' '500': $ref: '#/components/responses/InternalServerError' - /margin/fills: get: operationId: GetMarginFills @@ -547,12 +571,11 @@ paths: $ref: '#/components/responses/UnauthorizedError' '500': $ref: '#/components/responses/InternalServerError' - /margin/positions: get: operationId: GetMarginPositions summary: Get Positions - description: 'Endpoint for retrieving the authenticated user''s margin positions.' + description: Endpoint for retrieving the authenticated user's margin positions. tags: - portfolio security: @@ -586,12 +609,14 @@ paths: $ref: '#/components/responses/UnauthorizedError' '500': $ref: '#/components/responses/InternalServerError' - /margin/trades: get: operationId: GetMarginTrades summary: Get Trades - description: 'Endpoint for retrieving public margin trades for a given market ticker. Returns a paginated response. Use the cursor value from the previous response to get the next page.' + description: >- + Endpoint for retrieving public margin trades for a given market ticker. + Returns a paginated response. Use the cursor value from the previous + response to get the next page. tags: - market parameters: @@ -643,12 +668,13 @@ paths: $ref: '#/components/responses/BadRequestError' '500': $ref: '#/components/responses/InternalServerError' - /margin/enabled: get: operationId: GetMarginEnabled summary: Get Enabled Status - description: Endpoint for checking if margin trading is enabled for the authenticated user. + description: >- + Endpoint for checking if margin trading is enabled for the authenticated + user. tags: - exchange security: @@ -666,12 +692,13 @@ paths: $ref: '#/components/responses/UnauthorizedError' '500': $ref: '#/components/responses/InternalServerError' - /margin/notional_risk_limit: get: operationId: GetMarginNotionalRiskLimit summary: Get Notional Risk Limit - description: 'Endpoint for retrieving the notional value risk limit for the authenticated margin user.' + description: >- + Endpoint for retrieving the notional value risk limit for the + authenticated margin user. tags: - risk security: @@ -689,16 +716,24 @@ paths: $ref: '#/components/responses/UnauthorizedError' '500': $ref: '#/components/responses/InternalServerError' - /margin/balance: get: operationId: GetMarginBalance summary: Get Balance - description: 'Endpoint for retrieving the balance breakdown for the authenticated direct margin user. Returns cash balance (aggregate and per-subaccount), position value, total balance, and maintenance margin requirement.' + description: >- + Endpoint for retrieving the balance breakdown for the authenticated + direct margin user. Returns cash balance (aggregate and per-subaccount), + position value, total balance, and maintenance margin requirement. x-mint: - content: | + content: > - **Rate limit:** 5 tokens per request, or 50 tokens when `compute_available_balance=true` (the available-balance computation scans all resting orders). See `GET /trade-api/v2/account/endpoint_costs` for current non-default endpoint costs. + + **Rate limit:** 5 tokens per request, or 50 tokens when + `compute_available_balance=true` (the available-balance computation + scans all resting orders). See `GET + /trade-api/v2/account/endpoint_costs` for current non-default endpoint + costs. + tags: - portfolio @@ -714,7 +749,10 @@ paths: type: boolean default: false x-go-type-skip-optional-pointer: true - description: 'When true, computes available_balance per subaccount at an increased rate limit cost. Available balance is 0 when the flag is false or omitted.' + description: >- + When true, computes available_balance per subaccount at an increased + rate limit cost. Available balance is 0 when the flag is false or + omitted. responses: '200': description: Margin balance retrieved successfully @@ -730,12 +768,15 @@ paths: $ref: '#/components/responses/RateLimitError' '500': $ref: '#/components/responses/InternalServerError' - /margin/risk: get: operationId: GetMarginRisk summary: Get Risk - description: 'Endpoint for retrieving leverage and liquidation price data for the authenticated direct margin user. Returns account-level leverage plus per-position leverage and liquidation prices, grouped by subaccount and market.' + description: >- + Endpoint for retrieving leverage and liquidation price data for the + authenticated direct margin user. Returns account-level leverage plus + per-position leverage and liquidation prices, grouped by subaccount and + market. tags: - risk security: @@ -755,12 +796,14 @@ paths: $ref: '#/components/responses/ForbiddenError' '500': $ref: '#/components/responses/InternalServerError' - /margin/fee_tiers: get: operationId: GetMarginFeeTiers summary: Get Fee Tiers - description: 'Endpoint for retrieving the margin fee tiers for the authenticated direct margin user. Returns a map of margin market tickers to their fee tier strings.' + description: >- + Endpoint for retrieving the margin fee tiers for the authenticated + direct margin user. Returns a map of margin market tickers to their fee + tier strings. tags: - fees security: @@ -778,12 +821,15 @@ paths: $ref: '#/components/responses/UnauthorizedError' '500': $ref: '#/components/responses/InternalServerError' - /margin/funding_history: get: operationId: GetMarginFundingHistory summary: Get Funding History - description: 'Endpoint for retrieving the authenticated user''s historical margin funding payments joined with funding rates for a specific market, or across all markets when ticker is empty, over an inclusive UTC date range.' + description: >- + Endpoint for retrieving the authenticated user's historical margin + funding payments joined with funding rates for a specific market, or + across all markets when ticker is empty, over an inclusive UTC date + range. tags: - funding security: @@ -794,14 +840,18 @@ paths: - name: ticker in: query required: false - description: Market ticker for funding history. Leave empty to query across all markets. + description: >- + Market ticker for funding history. Leave empty to query across all + markets. schema: type: string x-go-type-skip-optional-pointer: true - name: start_date in: query required: true - description: Inclusive UTC start date for funding history range (YYYY-MM-DD format) + description: >- + Inclusive UTC start date for funding history range (YYYY-MM-DD + format) schema: type: string format: date @@ -834,12 +884,13 @@ paths: $ref: '#/components/responses/ForbiddenError' '500': $ref: '#/components/responses/InternalServerError' - /margin/funding_rates/historical: get: operationId: GetMarginHistoricalFundingRates summary: Get Historical Funding Rates - description: Endpoint for retrieving historical margin funding rates for a market, or across all markets when ticker is empty. + description: >- + Endpoint for retrieving historical margin funding rates for a market, or + across all markets when ticker is empty. tags: - funding parameters: @@ -853,14 +904,18 @@ paths: - name: start_ts in: query required: false - description: Start timestamp (Unix timestamp in seconds). If omitted, defaults to the earliest available data. + description: >- + Start timestamp (Unix timestamp in seconds). If omitted, defaults to + the earliest available data. schema: type: integer format: int64 - name: end_ts in: query required: false - description: End timestamp (Unix timestamp in seconds). If omitted, defaults to the current time. + description: >- + End timestamp (Unix timestamp in seconds). If omitted, defaults to + the current time. schema: type: integer format: int64 @@ -875,13 +930,16 @@ paths: $ref: '#/components/responses/BadRequestError' '500': $ref: '#/components/responses/InternalServerError' - /margin/funding_rates/estimate: get: operationId: GetMarginFundingRateEstimate summary: Get Funding Rate Estimate - description: | - Returns the estimated funding rate for the current, in-progress funding period. The value is a time-weighted average of the premium index computed over `[last_funding_time, now)`, so it continues to move as new data accumulates through the window and is only finalized at `next_funding_time`. + description: > + Returns the estimated funding rate for the current, in-progress funding + period. The value is a time-weighted average of the premium index + computed over `[last_funding_time, now)`, so it continues to move as new + data accumulates through the window and is only finalized at + `next_funding_time`. tags: - funding parameters: @@ -905,7 +963,6 @@ paths: $ref: '#/components/responses/BadRequestError' '500': $ref: '#/components/responses/InternalServerError' - /portfolio/intra_exchange_instance_transfer: post: operationId: IntraExchangeInstanceTransfer @@ -938,12 +995,14 @@ paths: $ref: '#/components/responses/ForbiddenError' '500': $ref: '#/components/responses/InternalServerError' - /portfolio/margin/subaccounts: post: operationId: CreateMarginSubaccount summary: Create Subaccount - description: 'Creates a new subaccount for the authenticated user in the margin exchange. Subaccounts are numbered sequentially starting from 1. Maximum 63 numbered subaccounts per user (64 including the primary account).' + description: >- + Creates a new subaccount for the authenticated user in the margin + exchange. Subaccounts are numbered sequentially starting from 1. Maximum + 63 numbered subaccounts per user (64 including the primary account). tags: - portfolio security: @@ -965,12 +1024,13 @@ paths: $ref: '#/components/responses/ForbiddenError' '500': $ref: '#/components/responses/InternalServerError' - /portfolio/margin/subaccounts/transfer: post: operationId: ApplyMarginSubaccountTransfer summary: Transfer Between Subaccounts - description: 'Transfers funds between the authenticated user''s margin subaccounts. Use 0 for the primary account, or 1-63 for numbered subaccounts.' + description: >- + Transfers funds between the authenticated user's margin subaccounts. Use + 0 for the primary account, or 1-63 for numbered subaccounts. tags: - portfolio security: @@ -996,12 +1056,13 @@ paths: $ref: '#/components/responses/UnauthorizedError' '500': $ref: '#/components/responses/InternalServerError' - /margin/order_groups: get: operationId: GetMarginOrderGroups summary: Get Order Groups - description: 'Retrieves all order groups for the authenticated user on the margin exchange.' + description: >- + Retrieves all order groups for the authenticated user on the margin + exchange. tags: - order-groups security: @@ -1023,12 +1084,14 @@ paths: $ref: '#/components/responses/UnauthorizedError' '500': $ref: '#/components/responses/InternalServerError' - /margin/order_groups/create: post: operationId: CreateMarginOrderGroup summary: Create Order Group - description: 'Creates a new order group on the margin exchange with a contracts limit measured over a rolling window. When the limit is hit, all orders in the group are cancelled and no new orders can be placed until reset.' + description: >- + Creates a new order group on the margin exchange with a contracts limit + measured over a rolling window. When the limit is hit, all orders in the + group are cancelled and no new orders can be placed until reset. tags: - order-groups security: @@ -1054,12 +1117,13 @@ paths: $ref: '#/components/responses/UnauthorizedError' '500': $ref: '#/components/responses/InternalServerError' - /margin/order_groups/{order_group_id}: get: operationId: GetMarginOrderGroup summary: Get Order Group - description: 'Retrieves details for a single order group on the margin exchange including all order IDs and auto-cancel status.' + description: >- + Retrieves details for a single order group on the margin exchange + including all order IDs and auto-cancel status. tags: - order-groups security: @@ -1085,7 +1149,9 @@ paths: delete: operationId: DeleteMarginOrderGroup summary: Delete Order Group - description: 'Deletes an order group on the margin exchange and cancels all orders within it.' + description: >- + Deletes an order group on the margin exchange and cancels all orders + within it. tags: - order-groups security: @@ -1108,12 +1174,14 @@ paths: $ref: '#/components/responses/NotFoundError' '500': $ref: '#/components/responses/InternalServerError' - /margin/order_groups/{order_group_id}/reset: put: operationId: ResetMarginOrderGroup summary: Reset Order Group - description: 'Resets the order group matched contracts counter to zero on the margin exchange, allowing new orders to be placed again after the limit was hit.' + description: >- + Resets the order group matched contracts counter to zero on the margin + exchange, allowing new orders to be placed again after the limit was + hit. tags: - order-groups security: @@ -1142,12 +1210,13 @@ paths: $ref: '#/components/responses/NotFoundError' '500': $ref: '#/components/responses/InternalServerError' - /margin/order_groups/{order_group_id}/trigger: put: operationId: TriggerMarginOrderGroup summary: Trigger Order Group - description: 'Triggers the order group on the margin exchange, canceling all orders in the group and preventing new orders until the group is reset.' + description: >- + Triggers the order group on the margin exchange, canceling all orders in + the group and preventing new orders until the group is reset. tags: - order-groups security: @@ -1176,12 +1245,14 @@ paths: $ref: '#/components/responses/NotFoundError' '500': $ref: '#/components/responses/InternalServerError' - /margin/order_groups/{order_group_id}/limit: put: operationId: UpdateMarginOrderGroupLimit summary: Update Order Group Limit - description: 'Updates the order group contracts limit on the margin exchange. If the updated limit would immediately trigger the group, all orders in the group are canceled and the group is triggered.' + description: >- + Updates the order group contracts limit on the margin exchange. If the + updated limit would immediately trigger the group, all orders in the + group are canceled and the group is triggered. tags: - order-groups security: @@ -1212,7 +1283,6 @@ paths: $ref: '#/components/responses/NotFoundError' '500': $ref: '#/components/responses/InternalServerError' - components: securitySchemes: kalshiAccessKey: @@ -1262,7 +1332,9 @@ components: schema: $ref: '#/components/schemas/ErrorResponse' RateLimitError: - description: 'Rate limit exceeded. The default cost is 10 tokens per request. Use GET /trade-api/v2/account/endpoint_costs to list non-default endpoint costs.' + description: >- + Rate limit exceeded. The default cost is 10 tokens per request. Use GET + /trade-api/v2/account/endpoint_costs to list non-default endpoint costs. content: application/json: schema: @@ -1287,13 +1359,17 @@ components: format: uuid description: Unique client-provided transfer ID for idempotency. x-oapi-codegen-extra-tags: - validate: "required" + validate: required from_subaccount: type: integer - description: Source subaccount number (0 for primary, 1-63 for numbered subaccounts). + description: >- + Source subaccount number (0 for primary, 1-63 for numbered + subaccounts). to_subaccount: type: integer - description: Destination subaccount number (0 for primary, 1-63 for numbered subaccounts). + description: >- + Destination subaccount number (0 for primary, 1-63 for numbered + subaccounts). amount_cents: type: integer format: int64 @@ -1307,21 +1383,31 @@ components: subaccount: type: integer minimum: 0 - description: Optional subaccount number to use for this order group (0 for primary, 1-63 for subaccounts) + description: >- + Optional subaccount number to use for this order group (0 for + primary, 1-63 for subaccounts) default: 0 x-go-type-skip-optional-pointer: true contracts_limit: type: integer format: int64 minimum: 1 - description: Specifies the maximum number of contracts that can be matched within this group over a rolling 15-second window. Whole contracts only. Provide contracts_limit or contracts_limit_fp; if both provided they must match. + description: >- + Specifies the maximum number of contracts that can be matched within + this group over a rolling 15-second window. Whole contracts only. + Provide contracts_limit or contracts_limit_fp; if both provided they + must match. x-go-type-skip-optional-pointer: true x-oapi-codegen-extra-tags: validate: omitempty,gte=1 contracts_limit_fp: $ref: '#/components/schemas/FixedPointCount' nullable: true - description: String representation of the maximum number of contracts that can be matched within this group over a rolling 15-second window. Provide contracts_limit or contracts_limit_fp; if both provided they must match. + description: >- + String representation of the maximum number of contracts that can be + matched within this group over a rolling 15-second window. Provide + contracts_limit or contracts_limit_fp; if both provided they must + match. exchange_index: allOf: - $ref: '#/components/schemas/ExchangeIndex' @@ -1339,7 +1425,9 @@ components: subaccount: type: integer minimum: 0 - description: Subaccount number that owns the created order group (0 for primary, 1-63 for subaccounts). + description: >- + Subaccount number that owns the created order group (0 for primary, + 1-63 for subaccounts). x-go-type-skip-optional-pointer: true exchange_index: allOf: @@ -1353,7 +1441,6 @@ components: subaccount_number: type: integer description: The sequential number assigned to this subaccount (1-63). - # Order Group schemas EmptyResponse: type: object description: An empty response body @@ -1374,11 +1461,15 @@ components: description: The name of the service that generated the error ExchangeIndex: type: integer - description: "Identifier for an exchange shard. Defaults to 0 if unspecified. Note: currently only 0 supported." + description: >- + Identifier for an exchange shard. Defaults to 0 if unspecified. Note: + currently only 0 supported. example: 0 ExchangeInstance: type: string - enum: ['event_contract', 'margined'] + enum: + - event_contract + - margined description: The exchange instance type BucketLimit: type: object @@ -1420,7 +1511,10 @@ components: $ref: '#/components/schemas/BucketLimit' grants: type: array - description: The caller's active API usage level grants across exchange lanes, where each grant applies to its exchange_instance and usage_tier reflects the effective tier for the lane reported by this endpoint. + description: >- + The caller's active API usage level grants across exchange lanes, + where each grant applies to its exchange_instance and usage_tier + reflects the effective tier for the lane reported by this endpoint. items: $ref: '#/components/schemas/ApiUsageLevelGrant' ApiUsageLevelGrant: @@ -1439,19 +1533,33 @@ components: type: integer format: int64 nullable: true - description: Unix timestamp (seconds) when the grant expires. Absent for permanent grants. + description: >- + Unix timestamp (seconds) when the grant expires. Absent for + permanent grants. source: type: string - description: 'How the grant was created: "volume" (earned from trading volume) or "manual" (assigned by Kalshi).' + description: >- + How the grant was created: "volume" (earned from trading volume) or + "manual" (assigned by Kalshi). FixedPointCount: type: string - description: Fixed-point contract count string (2 decimals, e.g., "10.00"; referred to as "fp" in field names). Requests accept 0–2 decimal places (e.g., "10", "10.0", "10.00"); responses always emit 2 decimals. Fractional contract values (e.g., "2.50") are supported on markets with fractional trading enabled; the minimum granularity is 0.01 contracts. Integer contract count fields are legacy and will be deprecated; when both integer and fp fields are provided, they must match. - example: "10.00" - # Common schemas + description: >- + Fixed-point contract count string (2 decimals, e.g., "10.00"; referred + to as "fp" in field names). Requests accept 0–2 decimal places (e.g., + "10", "10.0", "10.00"); responses always emit 2 decimals. Fractional + contract values (e.g., "2.50") are supported on markets with fractional + trading enabled; the minimum granularity is 0.01 contracts. Integer + contract count fields are legacy and will be deprecated; when both + integer and fp fields are provided, they must match. + example: '10.00' FixedPointDollars: type: string - description: US dollar amount as a fixed-point decimal string with up to 6 decimal places of precision. This is the maximum supported precision; valid quote intervals for a given market are constrained by that market's price level structure. - example: "0.5600" + description: >- + US dollar amount as a fixed-point decimal string with up to 6 decimal + places of precision. This is the maximum supported precision; valid + quote intervals for a given market are constrained by that market's + price level structure. + example: '0.5600' GetOrderGroupResponse: type: object required: @@ -1463,7 +1571,9 @@ components: description: Whether auto-cancel is enabled for this order group contracts_limit_fp: $ref: '#/components/schemas/FixedPointCount' - description: String representation of the current maximum contracts allowed over a rolling 15-second window. + description: >- + String representation of the current maximum contracts allowed over + a rolling 15-second window. x-go-type-skip-optional-pointer: true orders: type: array @@ -1530,7 +1640,9 @@ components: x-go-type-skip-optional-pointer: true contracts_limit_fp: $ref: '#/components/schemas/FixedPointCount' - description: String representation of the current maximum contracts allowed over a rolling 15-second window. + description: >- + String representation of the current maximum contracts allowed over + a rolling 15-second window. x-go-type-skip-optional-pointer: true is_auto_cancel_enabled: type: boolean @@ -1540,20 +1652,31 @@ components: allOf: - $ref: '#/components/schemas/ExchangeIndex' x-go-type-skip-optional-pointer: true - # Market Orderbook schemas PriceLevelDollarsCountFp: type: array minItems: 2 maxItems: 2 - example: ["0.1500", "100.00"] + example: + - '0.1500' + - '100.00' items: type: string - description: Price level in dollars represented as [dollars_string, fp] where dollars_string is like "0.1500" and fp is a FixedPointCount string (fixed-point contract count). The second element is the contract quantity (not price). + description: >- + Price level in dollars represented as [dollars_string, fp] where + dollars_string is like "0.1500" and fp is a FixedPointCount string + (fixed-point contract count). The second element is the contract + quantity (not price). SelfTradePreventionType: type: string - enum: ['taker_at_cross', 'maker'] - description: | - The self-trade prevention type for orders. `taker_at_cross` cancels the taker order when it would trade against another order from the same user; execution stops and any partial fills already matched are executed. `maker` cancels the resting maker order and continues matching. + enum: + - taker_at_cross + - maker + description: > + The self-trade prevention type for orders. `taker_at_cross` cancels the + taker order when it would trade against another order from the same + user; execution stops and any partial fills already matched are + executed. `maker` cancels the resting maker order and continues + matching. UpdateOrderGroupLimitRequest: type: object properties: @@ -1561,14 +1684,22 @@ components: type: integer format: int64 minimum: 1 - description: New maximum number of contracts that can be matched within this group over a rolling 15-second window. Whole contracts only. Provide contracts_limit or contracts_limit_fp; if both provided they must match. + description: >- + New maximum number of contracts that can be matched within this + group over a rolling 15-second window. Whole contracts only. Provide + contracts_limit or contracts_limit_fp; if both provided they must + match. x-go-type-skip-optional-pointer: true x-oapi-codegen-extra-tags: validate: omitempty,gte=1 contracts_limit_fp: $ref: '#/components/schemas/FixedPointCount' nullable: true - description: String representation of the new maximum number of contracts that can be matched within this group over a rolling 15-second window. Provide contracts_limit or contracts_limit_fp; if both provided they must match. + description: >- + String representation of the new maximum number of contracts that + can be matched within this group over a rolling 15-second window. + Provide contracts_limit or contracts_limit_fp; if both provided they + must match. ExchangeStatus: type: object required: @@ -1577,11 +1708,14 @@ components: properties: exchange_active: type: boolean - description: False if the exchange is no longer taking any state changes at all. True unless under maintenance. + description: >- + False if the exchange is no longer taking any state changes at all. + True unless under maintenance. trading_active: type: boolean - description: True if trading is currently permitted on the exchange. False outside exchange hours or during pauses. - + description: >- + True if trading is currently permitted on the exchange. False + outside exchange hours or during pauses. GetMarginRiskParametersResponse: type: object required: @@ -1602,7 +1736,10 @@ components: additionalProperties: type: number format: double - description: Map of market ticker to initial margin multiplier. The initial margin requirement is the maintenance margin multiplied by this value. + description: >- + Map of market ticker to initial margin multiplier. The initial + margin requirement is the maintenance margin multiplied by this + value. CreateMarginOrderRequest: type: object required: @@ -1637,7 +1774,10 @@ components: format: int64 time_in_force: type: string - enum: ['fill_or_kill', 'good_till_canceled', 'immediate_or_cancel'] + enum: + - fill_or_kill + - good_till_canceled + - immediate_or_cancel x-oapi-codegen-extra-tags: validate: required,oneof=fill_or_kill good_till_canceled immediate_or_cancel x-go-type-skip-optional-pointer: true @@ -1651,21 +1791,28 @@ components: x-go-type-skip-optional-pointer: true cancel_order_on_pause: type: boolean - description: If this flag is set to true, the order will be canceled if the order is open and trading on the exchange is paused for any reason. + description: >- + If this flag is set to true, the order will be canceled if the order + is open and trading on the exchange is paused for any reason. reduce_only: type: boolean - description: Specifies whether the order place count should be capped by the member's current position. Orders with reduce_only set to true will be rejected unless time_in_force is immediate_or_cancel or fill_or_kill. + description: >- + Specifies whether the order place count should be capped by the + member's current position. Orders with reduce_only set to true will + be rejected unless time_in_force is immediate_or_cancel or + fill_or_kill. subaccount: type: integer minimum: 0 default: 0 - description: The subaccount number to use for this margin order. 0 is the primary subaccount. + description: >- + The subaccount number to use for this margin order. 0 is the primary + subaccount. x-go-type-skip-optional-pointer: true order_group_id: type: string description: The order group this order is part of x-go-type-skip-optional-pointer: true - CreateMarginOrderResponse: type: object required: @@ -1682,14 +1829,19 @@ components: description: Number of contracts filled immediately upon placement. remaining_count: $ref: '#/components/schemas/FixedPointCount' - description: Number of contracts remaining after placement. For IOC orders, this reflects the final state after unfilled contracts are canceled. + description: >- + Number of contracts remaining after placement. For IOC orders, this + reflects the final state after unfilled contracts are canceled. average_fill_price: $ref: '#/components/schemas/FixedPointDollars' - description: Volume-weighted average fill price. Only present when fill_count > 0. + description: >- + Volume-weighted average fill price. Only present when fill_count > + 0. average_fee_paid: $ref: '#/components/schemas/FixedPointDollars' - description: Volume-weighted average fee paid per contract for fills resulting from this request. Only present when fill_count > 0. - + description: >- + Volume-weighted average fee paid per contract for fills resulting + from this request. Only present when fill_count > 0. GetMarginOrderResponse: type: object required: @@ -1697,7 +1849,6 @@ components: properties: order: $ref: '#/components/schemas/MarginOrder' - GetMarginOrdersResponse: type: object required: @@ -1710,7 +1861,6 @@ components: $ref: '#/components/schemas/MarginOrder' cursor: type: string - MarginOrder: type: object required: @@ -1767,14 +1917,17 @@ components: x-omitempty: false cancel_order_on_pause: type: boolean - description: If this flag is set to true, the order will be canceled if the order is open and trading on the exchange is paused for any reason. + description: >- + If this flag is set to true, the order will be canceled if the order + is open and trading on the exchange is paused for any reason. order_group_id: type: string description: The order group this order is part of order_source: $ref: '#/components/schemas/OrderSource' - description: The source of the order. Indicates whether the order was placed by the user or by the system on behalf of the user. - + description: >- + The source of the order. Indicates whether the order was placed by + the user or by the system on behalf of the user. CancelMarginOrderResponse: type: object required: @@ -1787,20 +1940,24 @@ components: type: string reduced_by: $ref: '#/components/schemas/FixedPointCount' - description: Number of contracts that were canceled (i.e. the remaining count at time of cancellation). - + description: >- + Number of contracts that were canceled (i.e. the remaining count at + time of cancellation). DecreaseMarginOrderRequest: type: object properties: reduce_by: $ref: '#/components/schemas/FixedPointCount' nullable: true - description: String representation of the number of contracts to reduce by. Exactly one of `reduce_by` or `reduce_to` must be provided. + description: >- + String representation of the number of contracts to reduce by. + Exactly one of `reduce_by` or `reduce_to` must be provided. reduce_to: $ref: '#/components/schemas/FixedPointCount' nullable: true - description: String representation of the number of contracts to reduce to. Exactly one of `reduce_by` or `reduce_to` must be provided. - + description: >- + String representation of the number of contracts to reduce to. + Exactly one of `reduce_by` or `reduce_to` must be provided. DecreaseMarginOrderResponse: type: object required: @@ -1814,7 +1971,6 @@ components: remaining_count: $ref: '#/components/schemas/FixedPointCount' description: Number of contracts remaining after the decrease. - AmendMarginOrderRequest: type: object required: @@ -1849,7 +2005,6 @@ components: type: string description: The new client-specified order ID after amendment x-go-type-skip-optional-pointer: true - AmendMarginOrderResponse: type: object required: @@ -1863,23 +2018,30 @@ components: $ref: '#/components/schemas/FixedPointCount' nullable: true x-omitempty: false - description: Number of contracts remaining after the amend. Only present when the amend caused a fill or changed the resting size. + description: >- + Number of contracts remaining after the amend. Only present when the + amend caused a fill or changed the resting size. fill_count: $ref: '#/components/schemas/FixedPointCount' nullable: true x-omitempty: false - description: Number of contracts filled as a result of the amend crossing the book. Only present when fills occurred or remaining size changed. + description: >- + Number of contracts filled as a result of the amend crossing the + book. Only present when fills occurred or remaining size changed. average_fill_price: $ref: '#/components/schemas/FixedPointDollars' nullable: true x-omitempty: false - description: Volume-weighted average fill price for fills resulting from the amend. Only present when fills occurred. + description: >- + Volume-weighted average fill price for fills resulting from the + amend. Only present when fills occurred. average_fee_paid: $ref: '#/components/schemas/FixedPointDollars' nullable: true x-omitempty: false - description: Volume-weighted average fee paid per contract for fills resulting from the amend. Only present when fills occurred. - + description: >- + Volume-weighted average fee paid per contract for fills resulting + from the amend. Only present when fills occurred. MarginOrderbookCount: type: object required: @@ -1888,15 +2050,18 @@ components: properties: bids: type: array - description: Bid price levels, ordered from best bid downward. Each level is [price, quantity]. + description: >- + Bid price levels, ordered from best bid downward. Each level is + [price, quantity]. items: $ref: '#/components/schemas/PriceLevelDollarsCountFp' asks: type: array - description: Ask price levels, ordered from best ask upward. Each level is [price, quantity]. + description: >- + Ask price levels, ordered from best ask upward. Each level is + [price, quantity]. items: $ref: '#/components/schemas/PriceLevelDollarsCountFp' - MarginOrderbookResponse: type: object required: @@ -1904,7 +2069,6 @@ components: properties: orderbook: $ref: '#/components/schemas/MarginOrderbookCount' - MarginMarket: type: object required: @@ -1933,8 +2097,9 @@ components: type: number format: double description: > - Leverage estimate (1 / margin_rate) evaluated at a small retail-sized notional position. - Actual leverage may be lower for larger positions as the liquidation margin rate grows with size. + Leverage estimate (1 / margin_rate) evaluated at a small + retail-sized notional position. Actual leverage may be lower for + larger positions as the liquidation margin rate grows with size. Null when margin config or price data is unavailable. leverage_estimates: type: object @@ -1942,10 +2107,10 @@ components: type: number format: double description: > - Leverage estimates (1 / margin_rate) keyed by notional position size in dollars - ("1000", "10000", "100000", "1000000"). Leverage decreases at larger notionals as - the liquidation margin rate grows with size. - Null when margin config or price data is unavailable. + Leverage estimates (1 / margin_rate) keyed by notional position size + in dollars ("1000", "10000", "100000", "1000000"). Leverage + decreases at larger notionals as the liquidation margin rate grows + with size. Null when margin config or price data is unavailable. price: $ref: '#/components/schemas/FixedPointDollars' description: Last trade price in dollars. @@ -1966,28 +2131,63 @@ components: description: One sided trade volume in the last 24 hours. volume_24h_notional_value_dollars: $ref: '#/components/schemas/FixedPointDollars' - description: Total notional value of one sided trade volume in the last 24 hours in dollars. + description: >- + Total notional value of one sided trade volume in the last 24 hours + in dollars. bid: $ref: '#/components/schemas/FixedPointDollars' description: Best bid price in dollars. ask: $ref: '#/components/schemas/FixedPointDollars' description: Best ask price in dollars. - + settlement_mark_price: + $ref: '#/components/schemas/TickerPrice' + description: Mark price used for settlement and funding. + liquidation_mark_price: + $ref: '#/components/schemas/TickerPrice' + description: Mark price used for liquidation. + reference_price: + $ref: '#/components/schemas/TickerPrice' + description: Underlying reference price, scaled per contract. + TickerPrice: + type: object + required: + - price + - ts_ms + properties: + price: + $ref: '#/components/schemas/FixedPointDollars' + description: Price in dollars. + ts_ms: + type: integer + format: int64 + description: Source timestamp in epoch milliseconds. MarginMarketStatus: type: string - enum: [inactive, active, closed] + enum: + - inactive + - active + - closed description: The status of a margin market - OrderSource: type: string - enum: ['user', 'system'] - description: The source of the order. 'user' indicates a user-placed order, 'system' indicates a system-generated liquidation order. - + enum: + - user + - system + description: >- + The source of the order. 'user' indicates a user-placed order, 'system' + indicates a system-generated liquidation order. LastUpdateReason: type: string - enum: ['', 'Decrease', 'Amend', 'MarginCancel', 'SelfTradeCancel', 'ExpiryCancel', 'Trade', 'PostOnlyCrossCancel'] - + enum: + - '' + - Decrease + - Amend + - MarginCancel + - SelfTradeCancel + - ExpiryCancel + - Trade + - PostOnlyCrossCancel MarginMarketResponse: type: object required: @@ -1995,7 +2195,6 @@ components: properties: market: $ref: '#/components/schemas/MarginMarket' - GetMarginMarketsResponse: type: object required: @@ -2005,7 +2204,6 @@ components: type: array items: $ref: '#/components/schemas/MarginMarket' - GetMarginFillsResponse: type: object required: @@ -2018,7 +2216,6 @@ components: $ref: '#/components/schemas/MarginFill' cursor: type: string - MarginFill: type: object required: @@ -2059,16 +2256,19 @@ components: description: Fill price in fixed-point dollars entry_price: type: string - description: Position entry price used to compute incremental realized PnL for this fill + description: >- + Position entry price used to compute incremental realized PnL for + this fill fees: type: string description: Fees paid on filled contracts, in dollars realized_pnl: type: string - description: Incremental realized PnL contributed by this fill, in fixed-point dollars + description: >- + Incremental realized PnL contributed by this fill, in fixed-point + dollars order_source: $ref: '#/components/schemas/OrderSource' - GetMarginPositionsResponse: type: object required: @@ -2078,10 +2278,10 @@ components: type: array items: $ref: '#/components/schemas/MarginPosition' - MarginPosition: type: object required: + - subaccount - market_ticker - position - entry_price @@ -2089,12 +2289,19 @@ components: - margin_used - fees properties: + subaccount: + type: integer + description: >- + The subaccount number that holds this position (0 for primary, 1-63 + for subaccounts) market_ticker: type: string description: Market ticker symbol position: $ref: '#/components/schemas/FixedPointCount' - description: Position size as a fixed-point count string (positive = long, negative = short) + description: >- + Position size as a fixed-point count string (positive = long, + negative = short) entry_price: $ref: '#/components/schemas/FixedPointDollars' description: Weighted average entry price of the open position @@ -2106,13 +2313,16 @@ components: description: Maintenance-margin-based capital usage for the open position fees: $ref: '#/components/schemas/FixedPointDollars' - description: Total fees accumulated over the lifetime of the current open position, resets when position is fully closed + description: >- + Total fees accumulated over the lifetime of the current open + position, resets when position is fully closed roe: type: number format: double nullable: true - description: Return on equity as a percentage (unrealized_pnl / margin_used * 100), null when margin_used is zero - + description: >- + Return on equity as a percentage (unrealized_pnl / margin_used * + 100), null when margin_used is zero GetMarginTradesResponse: type: object required: @@ -2125,7 +2335,6 @@ components: $ref: '#/components/schemas/MarginTrade' cursor: type: string - MarginTrade: type: object required: @@ -2157,9 +2366,10 @@ components: description: Side of the taker in this trade BookSide: type: string - enum: ['bid', 'ask'] + enum: + - bid + - ask description: The side of an order or trade (bid or ask) - MarginEnabledResponse: type: object required: @@ -2168,7 +2378,6 @@ components: enabled: type: boolean description: Indicates whether margin trading is enabled for the user - NotionalRiskLimitResponse: type: object required: @@ -2177,16 +2386,21 @@ components: properties: default_notional_value_risk_limit: type: string - description: The notional value risk limit for the user as a fixed-point dollar string with 4 decimal places (e.g., "5000.0000") - example: "5000.0000" + description: >- + The notional value risk limit for the user as a fixed-point dollar + string with 4 decimal places (e.g., "5000.0000") + example: '5000.0000' notional_value_risk_limits_by_market_ticker: type: object additionalProperties: type: string - description: Map of market_ticker to notional value risk limit as a fixed-point dollar string with 4 decimal places (e.g., "5000.0000"). If present, the market-level risk limit overrides the default notional value risk limit. + description: >- + Map of market_ticker to notional value risk limit as a fixed-point + dollar string with 4 decimal places (e.g., "5000.0000"). If present, + the market-level risk limit overrides the default notional value + risk limit. example: - "market-abc-123": "5000.0000" - + market-abc-123: '5000.0000' MarginSubaccountBalance: type: object required: @@ -2203,23 +2417,34 @@ components: description: The subaccount number (0 for primary, 1-63 for subaccounts) position_value: $ref: '#/components/schemas/FixedPointDollars' - description: Mark-to-market value of open positions for this subaccount in fixed-point dollars + description: >- + Mark-to-market value of open positions for this subaccount in + fixed-point dollars account_equity: $ref: '#/components/schemas/FixedPointDollars' - description: Account equity for this subaccount in fixed-point dollars. 0 for self clearing members. + description: >- + Account equity for this subaccount in fixed-point dollars. 0 for + self clearing members. maintenance_margin: $ref: '#/components/schemas/FixedPointDollars' - description: Maintenance margin requirement for this subaccount in fixed-point dollars + description: >- + Maintenance margin requirement for this subaccount in fixed-point + dollars initial_margin: $ref: '#/components/schemas/FixedPointDollars' - description: Initial margin requirement for this subaccount in fixed-point dollars. 0 for self clearing members. + description: >- + Initial margin requirement for this subaccount in fixed-point + dollars. 0 for self clearing members. resting_orders_margin: $ref: '#/components/schemas/FixedPointDollars' - description: Margin locked by resting orders for this subaccount in fixed-point dollars. 0 unless compute_available_balance is passed. + description: >- + Margin locked by resting orders for this subaccount in fixed-point + dollars. 0 unless compute_available_balance is passed. available_balance: $ref: '#/components/schemas/FixedPointDollars' - description: Available balance for this subaccount in fixed-point dollars. 0 for institutional users or if compute_available_balance was not passed. - + description: >- + Available balance for this subaccount in fixed-point dollars. 0 for + institutional users or if compute_available_balance was not passed. GetMarginBalanceResponse: type: object required: @@ -2234,7 +2459,6 @@ components: settled_funds: $ref: '#/components/schemas/FixedPointDollars' description: Total settled funds across all subaccounts in fixed-point dollars - MarginRiskPosition: type: object required: @@ -2258,21 +2482,29 @@ components: description: Current mark price for the market in fixed-point dollars position_notional: $ref: '#/components/schemas/FixedPointDollars' - description: Absolute notional value of the position (|qty| * mark_price) in fixed-point dollars + description: >- + Absolute notional value of the position (|qty| * mark_price) in + fixed-point dollars maintenance_margin_required: $ref: '#/components/schemas/FixedPointDollars' - description: Maintenance margin requirement for this position in fixed-point dollars. Null if margin config is missing. + description: >- + Maintenance margin requirement for this position in fixed-point + dollars. Null if margin config is missing. nullable: true position_leverage: type: number format: double - description: 'Position leverage ratio (position_notional / maintenance_margin_required). Null when maintenance margin is zero or config is missing.' + description: >- + Position leverage ratio (position_notional / + maintenance_margin_required). Null when maintenance margin is zero + or config is missing. nullable: true estimated_liquidation_price: $ref: '#/components/schemas/FixedPointDollars' - description: 'Estimated portfolio-aware liquidation price for this position within the subaccount. Null when no valid liquidation price exists.' + description: >- + Estimated portfolio-aware liquidation price for this position within + the subaccount. Null when no valid liquidation price exists. nullable: true - GetMarginRiskResponse: type: object required: @@ -2283,20 +2515,26 @@ components: account_leverage: type: number format: double - description: 'Account-level leverage (total_position_notional / total_maintenance_margin). Null when total maintenance margin is zero.' + description: >- + Account-level leverage (total_position_notional / + total_maintenance_margin). Null when total maintenance margin is + zero. nullable: true total_position_notional: $ref: '#/components/schemas/FixedPointDollars' - description: Sum of absolute position notional values across all positions in fixed-point dollars + description: >- + Sum of absolute position notional values across all positions in + fixed-point dollars total_maintenance_margin: $ref: '#/components/schemas/FixedPointDollars' - description: Sum of maintenance margin requirements across all positions in fixed-point dollars + description: >- + Sum of maintenance margin requirements across all positions in + fixed-point dollars positions: type: array items: $ref: '#/components/schemas/MarginRiskPosition' description: Per-position risk breakdown grouped by subaccount and market - GetMarginFeeTiersResponse: type: object required: @@ -2308,14 +2546,19 @@ components: additionalProperties: type: number format: double - description: A map of margin market ticker to the maker-side fee rate as a decimal fraction of notional (e.g. 0.0005 = 0.05% = 5 bps). Multiply notional by this value to compute the fee. + description: >- + A map of margin market ticker to the maker-side fee rate as a + decimal fraction of notional (e.g. 0.0005 = 0.05% = 5 bps). Multiply + notional by this value to compute the fee. taker_fee_rates: type: object additionalProperties: type: number format: double - description: A map of margin market ticker to the taker-side fee rate as a decimal fraction of notional (e.g. 0.0012 = 0.12% = 12 bps). Multiply notional by this value to compute the fee. - + description: >- + A map of margin market ticker to the taker-side fee rate as a + decimal fraction of notional (e.g. 0.0012 = 0.12% = 12 bps). + Multiply notional by this value to compute the fee. MarginFundingHistoryEntry: type: object required: @@ -2343,7 +2586,9 @@ components: description: Mark price at the time of funding funding_amount: $ref: '#/components/schemas/FixedPointDollars' - description: Dollar amount of the funding payment (positive = received, negative = paid) + description: >- + Dollar amount of the funding payment (positive = received, negative + = paid) quantity: $ref: '#/components/schemas/FixedPointCount' description: Position size at time of funding as a fixed-point count string @@ -2351,7 +2596,6 @@ components: type: integer nullable: true description: Subaccount number (0 for primary) - GetMarginFundingHistoryResponse: type: object required: @@ -2362,7 +2606,6 @@ components: items: $ref: '#/components/schemas/MarginFundingHistoryEntry' description: Array of historical funding payment entries - MarginFundingRate: type: object required: @@ -2385,7 +2628,6 @@ components: mark_price: $ref: '#/components/schemas/FixedPointDollars' description: Mark price at the time of funding - GetMarginHistoricalFundingRatesResponse: type: object required: @@ -2396,7 +2638,6 @@ components: items: $ref: '#/components/schemas/MarginFundingRate' description: Array of historical funding rate entries - GetMarginFundingRateEstimateResponse: type: object required: @@ -2420,7 +2661,6 @@ components: type: string format: date-time description: Timestamp of the next scheduled funding event - GetMarginMarketCandlesticksResponse: type: object required: @@ -2435,7 +2675,6 @@ components: description: Array of candlestick data points for the specified time range. items: $ref: '#/components/schemas/MarginMarketCandlestick' - MarginMarketCandlestick: type: object required: @@ -2454,26 +2693,39 @@ components: description: Unix timestamp for the inclusive end of the candlestick period. bid: $ref: '#/components/schemas/BidAskDistributionHistorical' - description: Open, high, low, close (OHLC) data for buy offers on the market during the candlestick period. + description: >- + Open, high, low, close (OHLC) data for buy offers on the market + during the candlestick period. ask: $ref: '#/components/schemas/BidAskDistributionHistorical' - description: Open, high, low, close (OHLC) data for sell offers on the market during the candlestick period. + description: >- + Open, high, low, close (OHLC) data for sell offers on the market + during the candlestick period. price: $ref: '#/components/schemas/PriceDistributionHistorical' - description: Open, high, low, close (OHLC) and more data for trade prices on the market during the candlestick period. + description: >- + Open, high, low, close (OHLC) and more data for trade prices on the + market during the candlestick period. volume: $ref: '#/components/schemas/FixedPointCount' - description: Number of contracts traded on the market during the candlestick period. + description: >- + Number of contracts traded on the market during the candlestick + period. volume_notional_value_dollars: $ref: '#/components/schemas/FixedPointDollars' - description: Notional value of contracts traded on the market during the candlestick period. + description: >- + Notional value of contracts traded on the market during the + candlestick period. open_interest: $ref: '#/components/schemas/FixedPointCount' - description: Number of contracts held on the market by end of the candlestick period (end_period_ts). + description: >- + Number of contracts held on the market by end of the candlestick + period (end_period_ts). open_interest_notional_value_dollars: $ref: '#/components/schemas/FixedPointDollars' - description: Notional value of contracts held on the market by end of the candlestick period (end_period_ts). - + description: >- + Notional value of contracts held on the market by end of the + candlestick period (end_period_ts). BidAskDistributionHistorical: type: object required: @@ -2481,7 +2733,10 @@ components: - low - high - close - description: OHLC data for quoted prices on one side of the orderbook during the candlestick period. These values reflect bid or ask quotes, not executed trade prices. + description: >- + OHLC data for quoted prices on one side of the orderbook during the + candlestick period. These values reflect bid or ask quotes, not executed + trade prices. properties: open: $ref: '#/components/schemas/FixedPointDollars' @@ -2495,7 +2750,6 @@ components: close: $ref: '#/components/schemas/FixedPointDollars' description: Quoted price at the end of the candlestick period (in dollars). - PriceDistributionHistorical: type: object required: @@ -2510,38 +2764,52 @@ components: allOf: - $ref: '#/components/schemas/FixedPointDollars' nullable: true - description: Price of the first trade during the candlestick period (in dollars). Null if no trades occurred. + description: >- + Price of the first trade during the candlestick period (in dollars). + Null if no trades occurred. low: allOf: - $ref: '#/components/schemas/FixedPointDollars' nullable: true - description: Lowest trade price during the candlestick period (in dollars). Null if no trades occurred. + description: >- + Lowest trade price during the candlestick period (in dollars). Null + if no trades occurred. high: allOf: - $ref: '#/components/schemas/FixedPointDollars' nullable: true - description: Highest trade price during the candlestick period (in dollars). Null if no trades occurred. + description: >- + Highest trade price during the candlestick period (in dollars). Null + if no trades occurred. close: allOf: - $ref: '#/components/schemas/FixedPointDollars' nullable: true - description: Price of the last trade during the candlestick period (in dollars). Null if no trades occurred. + description: >- + Price of the last trade during the candlestick period (in dollars). + Null if no trades occurred. mean: allOf: - $ref: '#/components/schemas/FixedPointDollars' nullable: true - description: Volume-weighted average price during the candlestick period (in dollars). Null if no trades occurred. + description: >- + Volume-weighted average price during the candlestick period (in + dollars). Null if no trades occurred. previous: allOf: - $ref: '#/components/schemas/FixedPointDollars' nullable: true - description: Close price from the previous candlestick period (in dollars). Null if this is the first candlestick or no prior trade exists. - + description: >- + Close price from the previous candlestick period (in dollars). Null + if this is the first candlestick or no prior trade exists. parameters: CursorQuery: name: cursor in: query - description: Pagination cursor. Use the cursor value returned from the previous response to get the next page of results. Leave empty for the first page. + description: >- + Pagination cursor. Use the cursor value returned from the previous + response to get the next page of results. Leave empty for the first + page. schema: type: string x-go-type-skip-optional-pointer: true @@ -2556,7 +2824,7 @@ components: maximum: 1000 default: 100 x-oapi-codegen-extra-tags: - validate: "omitempty,min=1,max=1000" + validate: omitempty,min=1,max=1000 MarginOrdersLimitQuery: name: limit in: query @@ -2568,7 +2836,7 @@ components: maximum: 10000 default: 100 x-oapi-codegen-extra-tags: - validate: "omitempty,min=1,max=10000" + validate: omitempty,min=1,max=10000 MaxTsQuery: name: max_ts in: query @@ -2614,7 +2882,9 @@ components: name: subaccount in: query required: false - description: Subaccount number (0 for primary, 1-63 for subaccounts). If omitted, defaults to all subaccounts. + description: >- + Subaccount number (0 for primary, 1-63 for subaccounts). If omitted, + defaults to all subaccounts. schema: type: integer minimum: 0 diff --git a/specs/perps_scm_openapi.yaml b/specs/perps_scm_openapi.yaml index 07aa3df..e9f7c2c 100644 --- a/specs/perps_scm_openapi.yaml +++ b/specs/perps_scm_openapi.yaml @@ -2,77 +2,54 @@ openapi: 3.0.0 info: title: Kalshi Self-Clearing Member API version: 0.0.1 - description: > + description: | Klear API endpoints available to Self-Clearing Members (SCMs) — - institutional users who clear their own margin activity directly with - Kalshi. - ## Authentication - - All endpoints require an admin access token passed in the `Authorization` - header: - + All endpoints require an admin access token passed in the `Authorization` header: `Authorization: Bearer :` - To generate an access token and obtain your admin user id, sign in at - https://klearing.kalshi.com, and navigate to the "Security" page. - If you are in the process of onboarding to be a self-clearing member, - please contact your contact at Kalshi for credentials. Otherwise, - please contact institutional@kalshi.com. + servers: - url: https://api.klear.kalshi.com/klear-api/v1 description: Production - url: https://demo-api.kalshi.co/klear-api/v1 description: Demo + security: - kalshiBearer: [] + paths: /margin/reports: get: operationId: GetMarginReports summary: Get Margin Reports - description: >- - Margin reports for the authenticated clearing member, filterable by date - range. + description: Margin reports for the authenticated clearing member, filterable by date range. + parameters: - - name: start_date - in: query - required: true - schema: - type: string - format: date - - name: end_date - in: query - required: true - schema: - type: string - format: date + - { name: start_date, in: query, required: true, schema: { type: string, format: date } } + - { name: end_date, in: query, required: true, schema: { type: string, format: date } } responses: '200': description: Successful response content: application/json: - schema: - $ref: '#/components/schemas/GetMarginReportsResponse' - '400': - $ref: '#/components/responses/BadRequestError' - '401': - $ref: '#/components/responses/UnauthorizedError' - '403': - $ref: '#/components/responses/ForbiddenError' - '500': - $ref: '#/components/responses/InternalServerError' + schema: { $ref: '#/components/schemas/GetMarginReportsResponse' } + '400': { $ref: '#/components/responses/BadRequestError' } + '401': { $ref: '#/components/responses/UnauthorizedError' } + '403': { $ref: '#/components/responses/ForbiddenError' } + '500': { $ref: '#/components/responses/InternalServerError' } + /margin/active_obligation: get: operationId: GetActiveMarginObligation @@ -82,244 +59,208 @@ paths: current cycle, if one exists. A negative amount indicates a net payable to Kalshi Klear; a positive amount indicates a net receivable. Returns null when no obligation is pending. + responses: '200': description: Successful response content: application/json: - schema: - $ref: '#/components/schemas/GetActiveMarginObligationResponse' - '401': - $ref: '#/components/responses/UnauthorizedError' - '403': - $ref: '#/components/responses/ForbiddenError' - '500': - $ref: '#/components/responses/InternalServerError' + schema: { $ref: '#/components/schemas/GetActiveMarginObligationResponse' } + '401': { $ref: '#/components/responses/UnauthorizedError' } + '403': { $ref: '#/components/responses/ForbiddenError' } + '500': { $ref: '#/components/responses/InternalServerError' } + /margin/obligation_history: get: operationId: GetObligationHistory summary: Get Obligation History + description: Completed obligations from previous settlements, ordered by most recent first. + + parameters: + - { name: limit, in: query, required: false, schema: { type: integer, default: 20, maximum: 100 }, description: Number of results per page. } + - { name: cursor, in: query, required: false, schema: { type: string, format: date-time }, description: Cursor from a previous response to fetch the next page. } + responses: + '200': + description: Successful response + content: + application/json: + schema: { $ref: '#/components/schemas/GetObligationHistoryResponse' } + '401': { $ref: '#/components/responses/UnauthorizedError' } + '403': { $ref: '#/components/responses/ForbiddenError' } + '500': { $ref: '#/components/responses/InternalServerError' } + + /margin/large_trader_positions: + get: + operationId: GetLargeTraderPositions + summary: Get Large Trader Positions description: >- - Completed obligations from previous settlements, ordered by most recent - first. + Positions of the authenticated clearing member that meet the CFTC + large-trader reporting levels for a settlement day (17 CFR 15.03(b); + currently 25 contracts for crypto). Members with reportable positions + are subject to their own CFTC Part 17 large-trader reporting + obligations; this endpoint provides the position data needed to meet + them. Empty when no positions meet the reporting levels. See the + CFTC's Large Trader Reporting Program + (https://www.cftc.gov/IndustryOversight/MarketSurveillance/LargeTraderReportingProgram/index.htm) + and reporting levels at 17 CFR 15.03 + (https://www.ecfr.gov/current/title-17/chapter-I/part-15). + parameters: - - name: limit - in: query - required: false - schema: - type: integer - default: 20 - maximum: 100 - description: Number of results per page. - - name: cursor - in: query - required: false - schema: - type: string - format: date-time - description: Cursor from a previous response to fetch the next page. + - { name: report_date, in: query, required: false, schema: { type: string, format: date }, description: ET settlement day to report, YYYY-MM-DD. Defaults to the most recent ET settlement day whose settlement window has closed. } responses: '200': description: Successful response content: application/json: - schema: - $ref: '#/components/schemas/GetObligationHistoryResponse' - '401': - $ref: '#/components/responses/UnauthorizedError' - '403': - $ref: '#/components/responses/ForbiddenError' - '500': - $ref: '#/components/responses/InternalServerError' + schema: { $ref: '#/components/schemas/GetLargeTraderPositionsResponse' } + '401': { $ref: '#/components/responses/UnauthorizedError' } + '403': { $ref: '#/components/responses/ForbiddenError' } + '500': { $ref: '#/components/responses/InternalServerError' } + /margin/settlement_estimate: get: operationId: GetSettlementEstimate summary: Get Settlement Estimate - description: >- - Estimated next settlement amounts for the authenticated clearing member, - including per-subtrader breakdowns. + description: Estimated next settlement amounts for the authenticated clearing member, including per-subtrader breakdowns. + responses: '200': description: Successful response content: application/json: - schema: - $ref: '#/components/schemas/GetSettlementEstimateResponse' - '401': - $ref: '#/components/responses/UnauthorizedError' - '403': - $ref: '#/components/responses/ForbiddenError' - '500': - $ref: '#/components/responses/InternalServerError' + schema: { $ref: '#/components/schemas/GetSettlementEstimateResponse' } + '401': { $ref: '#/components/responses/UnauthorizedError' } + '403': { $ref: '#/components/responses/ForbiddenError' } + '500': { $ref: '#/components/responses/InternalServerError' } + /margin/settlement_balance: get: operationId: GetSettlementBalance summary: Get Settlement Balance description: Settlement buffer balance for the authenticated clearing member. + responses: '200': description: Successful response content: application/json: - schema: - $ref: '#/components/schemas/GetSettlementBalanceResponse' - '401': - $ref: '#/components/responses/UnauthorizedError' - '403': - $ref: '#/components/responses/ForbiddenError' - '500': - $ref: '#/components/responses/InternalServerError' + schema: { $ref: '#/components/schemas/GetSettlementBalanceResponse' } + '401': { $ref: '#/components/responses/UnauthorizedError' } + '403': { $ref: '#/components/responses/ForbiddenError' } + '500': { $ref: '#/components/responses/InternalServerError' } + /margin/guaranty_fund_balance: get: operationId: GetGuarantyFundBalance summary: Get Guaranty Fund Balance - description: >- - Guaranty fund contribution balance for the authenticated clearing - member. + description: Guaranty fund contribution balance for the authenticated clearing member. + responses: '200': description: Successful response content: application/json: - schema: - $ref: '#/components/schemas/GetGuarantyFundBalanceResponse' - '401': - $ref: '#/components/responses/UnauthorizedError' - '403': - $ref: '#/components/responses/ForbiddenError' - '500': - $ref: '#/components/responses/InternalServerError' + schema: { $ref: '#/components/schemas/GetGuarantyFundBalanceResponse' } + '401': { $ref: '#/components/responses/UnauthorizedError' } + '403': { $ref: '#/components/responses/ForbiddenError' } + '500': { $ref: '#/components/responses/InternalServerError' } + /margin/settlement_balance_history: get: operationId: GetSettlementBalanceHistory summary: Get Settlement Balance History - description: >- - Settlement balance changes for the authenticated clearing member, - ordered by most recent first. + description: Settlement balance changes for the authenticated clearing member, ordered by most recent first. + parameters: - - name: limit - in: query - required: false - schema: - type: integer - default: 100 - maximum: 500 - description: Number of results per page. - - name: cursor - in: query - required: false - schema: - type: string - description: Cursor from a previous response to fetch the next page. + - { name: limit, in: query, required: false, schema: { type: integer, default: 100, maximum: 500 }, description: Number of results per page. } + - { name: cursor, in: query, required: false, schema: { type: string }, description: Cursor from a previous response to fetch the next page. } responses: '200': description: Successful response content: application/json: - schema: - $ref: '#/components/schemas/GetSettlementBalanceHistoryResponse' - '400': - $ref: '#/components/responses/BadRequestError' - '401': - $ref: '#/components/responses/UnauthorizedError' - '403': - $ref: '#/components/responses/ForbiddenError' - '500': - $ref: '#/components/responses/InternalServerError' + schema: { $ref: '#/components/schemas/GetSettlementBalanceHistoryResponse' } + '400': { $ref: '#/components/responses/BadRequestError' } + '401': { $ref: '#/components/responses/UnauthorizedError' } + '403': { $ref: '#/components/responses/ForbiddenError' } + '500': { $ref: '#/components/responses/InternalServerError' } + /margin/withdraw_settlement_balance: post: operationId: WithdrawSettlementBalance summary: Withdraw Settlement Balance - description: >- - Initiate a wire withdrawal from the clearing member's settlement buffer. - The withdrawal is processed asynchronously. + description: Initiate a wire withdrawal from the clearing member's settlement buffer. The withdrawal is processed asynchronously. + requestBody: required: true content: application/json: - schema: - $ref: '#/components/schemas/WithdrawSettlementBalanceRequest' + schema: { $ref: '#/components/schemas/WithdrawSettlementBalanceRequest' } responses: '200': description: Withdrawal initiated content: application/json: - schema: - $ref: '#/components/schemas/WithdrawSettlementBalanceResponse' - '400': - $ref: '#/components/responses/BadRequestError' - '401': - $ref: '#/components/responses/UnauthorizedError' - '403': - $ref: '#/components/responses/ForbiddenError' - '500': - $ref: '#/components/responses/InternalServerError' + schema: { $ref: '#/components/schemas/WithdrawSettlementBalanceResponse' } + '400': { $ref: '#/components/responses/BadRequestError' } + '401': { $ref: '#/components/responses/UnauthorizedError' } + '403': { $ref: '#/components/responses/ForbiddenError' } + '500': { $ref: '#/components/responses/InternalServerError' } + /margin/settlement_balance_withdrawal: get: operationId: GetSettlementBalanceWithdrawal summary: Get Settlement Balance Withdrawal description: Get the status of a settlement balance withdrawal by ID. + parameters: - - name: id - in: query - required: true - schema: - type: string + - { name: id, in: query, required: true, schema: { type: string } } responses: '200': description: Successful response content: application/json: - schema: - $ref: '#/components/schemas/GetSettlementBalanceWithdrawalResponse' - '400': - $ref: '#/components/responses/BadRequestError' - '401': - $ref: '#/components/responses/UnauthorizedError' - '403': - $ref: '#/components/responses/ForbiddenError' - '500': - $ref: '#/components/responses/InternalServerError' + schema: { $ref: '#/components/schemas/GetSettlementBalanceWithdrawalResponse' } + '400': { $ref: '#/components/responses/BadRequestError' } + '401': { $ref: '#/components/responses/UnauthorizedError' } + '403': { $ref: '#/components/responses/ForbiddenError' } + '500': { $ref: '#/components/responses/InternalServerError' } + components: securitySchemes: kalshiBearer: type: http scheme: bearer bearerFormat: admin_user_id:access_token - description: > - Pass `Authorization: Bearer :` on each - request. + description: | + Pass `Authorization: Bearer :` on each request. + responses: BadRequestError: description: Bad request - invalid input content: application/json: - schema: - $ref: '#/components/schemas/Error' + schema: { $ref: '#/components/schemas/Error' } UnauthorizedError: description: Missing or invalid authentication content: application/json: - schema: - $ref: '#/components/schemas/Error' + schema: { $ref: '#/components/schemas/Error' } ForbiddenError: description: Caller is not permitted to access this resource content: application/json: - schema: - $ref: '#/components/schemas/Error' + schema: { $ref: '#/components/schemas/Error' } InternalServerError: description: Internal server error content: application/json: - schema: - $ref: '#/components/schemas/Error' + schema: { $ref: '#/components/schemas/Error' } + schemas: Error: type: object - required: - - code - - message + required: [code, message] properties: code: type: string @@ -331,14 +272,10 @@ components: type: string service: type: string + MarginReport: type: object - required: - - report_type - - url - - date - - created_ts - - is_end_of_day + required: [report_type, url, date, created_ts, is_end_of_day] properties: report_type: type: string @@ -348,26 +285,19 @@ components: - market_price_snapshot - funding_periods - settlement_periods - url: - type: string - description: Presigned download URL (omitted from logs). - date: - type: string - format: date - created_ts: - type: string - format: date-time - is_end_of_day: - type: boolean + url: { type: string, description: Presigned download URL (omitted from logs). } + date: { type: string, format: date } + created_ts: { type: string, format: date-time } + is_end_of_day: { type: boolean } + GetMarginReportsResponse: type: object - required: - - reports + required: [reports] properties: reports: type: array - items: - $ref: '#/components/schemas/MarginReport' + items: { $ref: '#/components/schemas/MarginReport' } + ObligationInfo: type: object required: @@ -380,10 +310,8 @@ components: - execution_time - last_updated_ts properties: - id: - type: string - user_id: - type: string + id: { type: string } + user_id: { type: string } amount_centicents: type: integer format: int64 @@ -394,47 +322,22 @@ components: of PnL, fees, and maintenance margin changes. Negative means the clearing member pays Kalshi Klear; positive means Kalshi Klear pays the clearing member. - fees_centicents: - type: integer - format: int64 - description: Trading fees incurred during the settlement period. - maintenance_margin_centicents: - type: integer - format: int64 - description: Current maintenance margin requirement for this obligation. - pnl_centicents: - type: integer - format: int64 - description: Realized PnL for this settlement period. - execution_time: - type: string - format: date-time - description: Settlement cycle time this obligation belongs to. - last_updated_ts: - type: string - format: date-time - description: Timestamp of the last status change on this obligation. + fees_centicents: { type: integer, format: int64, description: Trading fees incurred during the settlement period. } + maintenance_margin_centicents: { type: integer, format: int64, description: Current maintenance margin requirement for this obligation. } + pnl_centicents: { type: integer, format: int64, description: Realized PnL for this settlement period. } + execution_time: { type: string, format: date-time, description: Settlement cycle time this obligation belongs to. } + last_updated_ts: { type: string, format: date-time, description: Timestamp of the last status change on this obligation. } + ObligationReceiveInfo: type: object - required: - - id - - type - - amount_centicents - - external_reference - - created_ts + required: [id, type, amount_centicents, external_reference, created_ts] properties: - id: - type: string - type: - type: string - amount_centicents: - type: integer - format: int64 - external_reference: - type: string - created_ts: - type: string - format: date-time + id: { type: string } + type: { type: string } + amount_centicents: { type: integer, format: int64 } + external_reference: { type: string } + created_ts: { type: string, format: date-time } + SettlementDetail: type: object required: @@ -445,24 +348,13 @@ components: - total_fees_centicents - total_amount_centicents properties: - id: - type: string - market_ticker: - type: string - subtrader_id: - type: string - pnl_centicents: - type: integer - format: int64 - description: PnL. - total_fees_centicents: - type: integer - format: int64 - description: Total fees. - total_amount_centicents: - type: integer - format: int64 - description: Total amount. + id: { type: string } + market_ticker: { type: string } + subtrader_id: { type: string } + pnl_centicents: { type: integer, format: int64, description: PnL. } + total_fees_centicents: { type: integer, format: int64, description: Total fees. } + total_amount_centicents: { type: integer, format: int64, description: Total amount. } + MaintenanceMarginDetail: type: object required: @@ -471,72 +363,65 @@ components: - maintenance_margin_centicents - maintenance_margin_delta_centicents properties: - id: - type: string - subtrader_id: - type: string - description: Empty when not populated. - maintenance_margin_centicents: - type: integer - format: int64 - description: Maintenance margin requirement after this settlement. - maintenance_margin_delta_centicents: - type: integer - format: int64 - description: >- - Change in maintenance margin between the previous settlement and - this one. + id: { type: string } + subtrader_id: { type: string, description: Empty when not populated. } + maintenance_margin_centicents: { type: integer, format: int64, description: Maintenance margin requirement after this settlement. } + maintenance_margin_delta_centicents: { type: integer, format: int64, description: Change in maintenance margin between the previous settlement and this one. } + ObligationEntry: allOf: - $ref: '#/components/schemas/ObligationInfo' - type: object - required: - - receives - - settlement_details - - maintenance_margin_details + required: [receives, settlement_details, maintenance_margin_details] properties: receives: type: array - items: - $ref: '#/components/schemas/ObligationReceiveInfo' + items: { $ref: '#/components/schemas/ObligationReceiveInfo' } settlement_details: type: array - items: - $ref: '#/components/schemas/SettlementDetail' + items: { $ref: '#/components/schemas/SettlementDetail' } description: | Per-market, per-subtrader breakdown of the settlement amount. This structure may change in future versions as margin methodology evolves (e.g. portfolio margin). maintenance_margin_details: type: array - items: - $ref: '#/components/schemas/MaintenanceMarginDetail' + items: { $ref: '#/components/schemas/MaintenanceMarginDetail' } description: | Breakdown of the maintenance margin requirement and the delta from the prior settlement. + GetActiveMarginObligationResponse: type: object properties: obligation: $ref: '#/components/schemas/ObligationEntry' - description: >- - The outstanding settlement obligation for the current cycle, or null - when no obligation is pending. + description: The outstanding settlement obligation for the current cycle, or null when no obligation is pending. + + GetLargeTraderPositionsResponse: + type: object + properties: + user_id: { type: string } + report_date: { type: string, format: date, description: ET settlement day the positions are reported for. } + positions: + type: array + items: + type: object + properties: + market_ticker: { type: string } + position: { type: integer, description: Signed reportable contract count; positive long, negative short. } GetObligationHistoryResponse: type: object - required: - - obligations + required: [obligations] properties: obligations: type: array - items: - $ref: '#/components/schemas/ObligationEntry' + items: { $ref: '#/components/schemas/ObligationEntry' } cursor: type: string format: date-time - description: >- - Pass as the `cursor` query param to fetch the next page. Absent when - there are no more results. + description: Pass as the `cursor` query param to fetch the next page. Absent when there are no more results. + SettlementEstimate: type: object required: @@ -546,159 +431,81 @@ components: - maintenance_margin_required_centicents - total_amount_centicents properties: - variation_margin_centicents: - type: integer - format: int64 - description: Variation margin. - total_fees_centicents: - type: integer - format: int64 - description: Total fees. - maintenance_margin_delta_centicents: - type: integer - format: int64 - description: Change in maintenance margin requirement. - maintenance_margin_required_centicents: - type: integer - format: int64 - description: Maintenance margin requirement. - total_amount_centicents: - type: integer - format: int64 - description: Estimated total settlement amount. + variation_margin_centicents: { type: integer, format: int64, description: Variation margin. } + total_fees_centicents: { type: integer, format: int64, description: Total fees. } + maintenance_margin_delta_centicents: { type: integer, format: int64, description: Change in maintenance margin requirement. } + maintenance_margin_required_centicents: { type: integer, format: int64, description: Maintenance margin requirement. } + total_amount_centicents: { type: integer, format: int64, description: Estimated total settlement amount. } + GetSettlementEstimateResponse: type: object - required: - - user_breakdown - - settlement_balance_centicents + required: [user_breakdown, settlement_balance_centicents] properties: - user_breakdown: - $ref: '#/components/schemas/SettlementEstimate' + user_breakdown: { $ref: '#/components/schemas/SettlementEstimate' } subtrader_breakdowns: type: object description: Map of subtrader ID to that subtrader's settlement estimate. - additionalProperties: - $ref: '#/components/schemas/SettlementEstimate' - settlement_balance_centicents: - type: integer - format: int64 - description: Current settlement buffer balance. + additionalProperties: { $ref: '#/components/schemas/SettlementEstimate' } + settlement_balance_centicents: { type: integer, format: int64, description: Current settlement buffer balance. } + GetSettlementBalanceResponse: type: object - required: - - user_id - - balance_available_centicents + required: [user_id, balance_available_centicents] properties: - user_id: - type: string - balance_available_centicents: - type: integer - format: int64 - description: Settlement buffer balance. - locked_balance_centicents: - type: integer - format: int64 - description: Locked settlement balance (e.g. pending withdrawals). + user_id: { type: string } + balance_available_centicents: { type: integer, format: int64, description: Settlement buffer balance. } + locked_balance_centicents: { type: integer, format: int64, description: Locked settlement balance (e.g. pending withdrawals). } + GetGuarantyFundBalanceResponse: type: object - required: - - user_id - - amount_centicents - - updated_ts + required: [user_id, amount_centicents, updated_ts] properties: - user_id: - type: string - amount_centicents: - type: integer - format: int64 - description: >- - Guaranty fund contribution balance. Zero when no contribution has - been made yet. - updated_ts: - type: string - format: date-time - description: Timestamp of the most recent contribution entry. + user_id: { type: string } + amount_centicents: { type: integer, format: int64, description: Guaranty fund contribution balance. Zero when no contribution has been made yet. } + updated_ts: { type: string, format: date-time, description: Timestamp of the most recent contribution entry. } + GetSettlementBalanceWithdrawalResponse: type: object - required: - - id - - amount - - status - - created_ts + required: [id, amount, status, created_ts] properties: - id: - type: string - amount: - type: string - description: Withdrawal amount in USD as a fixed-point string (e.g. "500.00"). - status: - type: string - enum: - - pending - - processing - - processed - - failed - created_ts: - type: string - format: date-time + id: { type: string } + amount: { type: string, description: "Withdrawal amount in USD as a fixed-point string (e.g. \"500.00\")." } + status: { type: string, enum: [pending, processing, processed, failed] } + created_ts: { type: string, format: date-time } + WithdrawSettlementBalanceRequest: type: object - required: - - amount + required: [amount] properties: amount: type: string - description: >- - Amount to withdraw in USD as a fixed-point string (e.g. "500.00"). - Must be positive. + description: Amount to withdraw in USD as a fixed-point string (e.g. "500.00"). Must be positive. + WithdrawSettlementBalanceResponse: type: object - required: - - id + required: [id] properties: id: type: string description: ID of the withdrawal. The withdrawal is processed asynchronously. + SettlementBalanceHistoryEntry: type: object - required: - - balance_delta_centicents - - locked_balance_delta_centicents - - reason - - business_transaction_id - - created_ts + required: [balance_delta_centicents, locked_balance_delta_centicents, reason, business_transaction_id, created_ts] properties: - balance_delta_centicents: - type: integer - format: int64 - description: Change to the settlement buffer balance. - locked_balance_delta_centicents: - type: integer - format: int64 - description: >- - Change to the locked settlement balance. Funds are locked during - pending withdrawals. - reason: - type: string - description: Reason for the balance change. - business_transaction_id: - type: string - description: Identifier of the business transaction that caused this entry. - created_ts: - type: string - format: date-time - description: Timestamp when the entry was created. + balance_delta_centicents: { type: integer, format: int64, description: Change to the settlement buffer balance. } + locked_balance_delta_centicents: { type: integer, format: int64, description: Change to the locked settlement balance. Funds are locked during pending withdrawals. } + reason: { type: string, description: Reason for the balance change. } + business_transaction_id: { type: string, description: Identifier of the business transaction that caused this entry. } + created_ts: { type: string, format: date-time, description: Timestamp when the entry was created. } + GetSettlementBalanceHistoryResponse: type: object - required: - - entries + required: [entries] properties: entries: type: array - items: - $ref: '#/components/schemas/SettlementBalanceHistoryEntry' + items: { $ref: '#/components/schemas/SettlementBalanceHistoryEntry' } cursor: type: string - description: >- - Pass as the `cursor` query param to fetch the next page. Absent when - there are no more results. + description: Pass as the `cursor` query param to fetch the next page. Absent when there are no more results. diff --git a/tests/_contract_support.py b/tests/_contract_support.py index a283a23..d824d5f 100644 --- a/tests/_contract_support.py +++ b/tests/_contract_support.py @@ -162,6 +162,11 @@ class Exclusion: http_method="GET", path_template="/account/endpoint_costs", ), + MethodEndpointEntry( + sdk_method="kalshi.resources.account.AccountResource.volume_progress", + http_method="GET", + path_template="/account/api_usage_level/volume_progress", + ), MethodEndpointEntry( # Spec defines no requestBody for this POST, so there is no # request_body_schema to drift-check (same as subaccounts.create). @@ -627,6 +632,29 @@ class Exclusion: http_method="PUT", path_template="/communications/quotes/{quote_id}/confirm", ), + # block trade proposals (openapi 3.21.0) + MethodEndpointEntry( + sdk_method="kalshi.resources.communications.BlockTradeProposalsResource.list", + http_method="GET", + path_template="/communications/block-trade-proposals", + ), + MethodEndpointEntry( + sdk_method="kalshi.resources.communications.BlockTradeProposalsResource.list_all", + http_method="GET", + path_template="/communications/block-trade-proposals", + ), + MethodEndpointEntry( + sdk_method="kalshi.resources.communications.BlockTradeProposalsResource.create", + http_method="POST", + path_template="/communications/block-trade-proposals", + request_body_schema="#/components/schemas/ProposeBlockTradeRequest", + ), + MethodEndpointEntry( + sdk_method="kalshi.resources.communications.BlockTradeProposalsResource.accept", + http_method="POST", + path_template="/communications/block-trade-proposals/{block_trade_proposal_id}/accept", + request_body_schema="#/components/schemas/AcceptBlockTradeProposalRequest", + ), # ── subaccounts ───────────────────────────────────────────────────────── MethodEndpointEntry( sdk_method="kalshi.resources.subaccounts.SubaccountsResource.create", @@ -1105,6 +1133,13 @@ class Exclusion: reason="paginator-handled; not a caller-facing kwarg on list_all", kind="paginator_handled", ), + ( + "kalshi.resources.communications.BlockTradeProposalsResource.list_all", + "cursor", + ): Exclusion( + reason="paginator-handled; not a caller-facing kwarg on list_all", + kind="paginator_handled", + ), ("kalshi.resources.markets.MarketsResource.list_all_trades", "cursor"): Exclusion( reason="paginator-handled; not a caller-facing kwarg on list_all", kind="paginator_handled", @@ -1297,6 +1332,7 @@ class Exclusion: "kalshi.resources.markets.MarketsResource.list_all_trades", "kalshi.resources.communications.RFQsResource.list_all", "kalshi.resources.communications.QuotesResource.list_all", + "kalshi.resources.communications.BlockTradeProposalsResource.list_all", "kalshi.resources.milestones.MilestonesResource.list_all", "kalshi.resources.events.EventsResource.list_all", "kalshi.resources.events.EventsResource.list_all_multivariate", @@ -1326,6 +1362,7 @@ class Exclusion: "kalshi.resources.markets.AsyncMarketsResource.list_all_trades", "kalshi.resources.communications.AsyncRFQsResource.list_all", "kalshi.resources.communications.AsyncQuotesResource.list_all", + "kalshi.resources.communications.AsyncBlockTradeProposalsResource.list_all", "kalshi.resources.milestones.AsyncMilestonesResource.list_all", "kalshi.resources.events.AsyncEventsResource.list_all", "kalshi.resources.events.AsyncEventsResource.list_all_multivariate", diff --git a/tests/_request_model_fixtures.py b/tests/_request_model_fixtures.py index d67b1b5..8770d23 100644 --- a/tests/_request_model_fixtures.py +++ b/tests/_request_model_fixtures.py @@ -6,8 +6,9 @@ exported from ``kalshi.models``. The walker handles primitives, ``Literal``, ``Union``/``Optional``, -``list[X]``, nested ``BaseModel`` subclasses, and ``UUID``. Anything else -must be supplied via the per-model override map ``_OVERRIDES`` below. +``list[X]``, nested ``BaseModel`` subclasses, ``UUID``, and aware datetimes. +Anything else must be supplied via the per-model override map ``_OVERRIDES`` +below. """ from __future__ import annotations @@ -15,10 +16,11 @@ import types import typing import uuid +from datetime import UTC, datetime from decimal import Decimal from typing import Any, Literal, Union, get_args, get_origin -from pydantic import BaseModel +from pydantic import AwareDatetime, BaseModel _PRIMITIVE_DEFAULTS: dict[type, Any] = { str: "x", @@ -28,6 +30,7 @@ Decimal: Decimal("1"), uuid.UUID: uuid.UUID(int=0), bytes: b"x", + AwareDatetime: datetime(2026, 1, 1, tzinfo=UTC), } diff --git a/tests/perps/test_portfolio.py b/tests/perps/test_portfolio.py index aebc35d..117659e 100644 --- a/tests/perps/test_portfolio.py +++ b/tests/perps/test_portfolio.py @@ -26,6 +26,7 @@ def _long_position() -> dict[str, object]: return { + "subaccount": 0, "market_ticker": "BTC-PERP", "position": "100.00", "entry_price": "0.5600", @@ -38,6 +39,7 @@ def _long_position() -> dict[str, object]: def _short_position() -> dict[str, object]: return { + "subaccount": 1, "market_ticker": "ETH-PERP", "position": "-40.00", "entry_price": "0.3300", diff --git a/tests/test_account.py b/tests/test_account.py index bc48819..b8ae53b 100644 --- a/tests/test_account.py +++ b/tests/test_account.py @@ -2,6 +2,8 @@ from __future__ import annotations +from decimal import Decimal + import httpx import pytest import respx @@ -265,3 +267,118 @@ async def test_requires_auth( ) -> None: with pytest.raises(AuthRequiredError): await unauth_async_account.upgrade() + + +class TestAccountVolumeProgress: + @respx.mock + def test_returns_progress(self, account: AccountResource) -> None: + respx.get( + "https://test.kalshi.com/trade-api/v2/account/api_usage_level/volume_progress", + ).mock( + return_value=httpx.Response( + 200, + json={ + "volume_progress": [ + { + "computed_ts": 1893456000, + "trailing_30d_volume_fp": "12500.00", + "goals": [ + { + "level": "premier", + "earn_volume_goal_fp": "10000.00", + "keep_volume_goal_fp": "5000.00", + }, + { + "level": "paragon", + "earn_volume_goal_fp": "50000.00", + "keep_volume_goal_fp": "25000.00", + }, + ], + } + ] + }, + ) + ) + progress = account.volume_progress() + assert len(progress.volume_progress) == 1 + snap = progress.volume_progress[0] + assert snap.computed_ts == 1893456000 + assert snap.trailing_30d_volume == Decimal("12500.00") + assert len(snap.goals) == 2 + assert snap.goals[0].level == "premier" + assert snap.goals[0].earn_volume_goal == Decimal("10000.00") + assert snap.goals[0].keep_volume_goal == Decimal("5000.00") + assert snap.goals[1].level == "paragon" + + @respx.mock + def test_returns_empty_progress(self, account: AccountResource) -> None: + # Edge case: no snapshots yet (cron hasn't run for this user). + respx.get( + "https://test.kalshi.com/trade-api/v2/account/api_usage_level/volume_progress", + ).mock(return_value=httpx.Response(200, json={"volume_progress": []})) + progress = account.volume_progress() + assert progress.volume_progress == [] + + def test_requires_auth(self, unauth_account: AccountResource) -> None: + with pytest.raises(AuthRequiredError): + unauth_account.volume_progress() + + @respx.mock + def test_server_rejects_auth(self, account: AccountResource) -> None: + respx.get( + "https://test.kalshi.com/trade-api/v2/account/api_usage_level/volume_progress", + ).mock(return_value=httpx.Response(401, json={"error": "unauthorized"})) + with pytest.raises(KalshiAuthError): + account.volume_progress() + + +class TestAsyncAccountVolumeProgress: + @respx.mock + @pytest.mark.asyncio + async def test_returns_progress( + self, async_account: AsyncAccountResource, + ) -> None: + respx.get( + "https://test.kalshi.com/trade-api/v2/account/api_usage_level/volume_progress", + ).mock( + return_value=httpx.Response( + 200, + json={ + "volume_progress": [ + { + "computed_ts": 1893456000, + "trailing_30d_volume_fp": "0.00", + "goals": [ + { + "level": "premier", + "earn_volume_goal_fp": "10000.00", + "keep_volume_goal_fp": "5000.00", + } + ], + } + ] + }, + ) + ) + progress = await async_account.volume_progress() + snap = progress.volume_progress[0] + assert snap.trailing_30d_volume == Decimal("0.00") + assert snap.goals[0].earn_volume_goal == Decimal("10000.00") + + @respx.mock + @pytest.mark.asyncio + async def test_returns_empty_progress( + self, async_account: AsyncAccountResource, + ) -> None: + respx.get( + "https://test.kalshi.com/trade-api/v2/account/api_usage_level/volume_progress", + ).mock(return_value=httpx.Response(200, json={"volume_progress": []})) + progress = await async_account.volume_progress() + assert progress.volume_progress == [] + + @pytest.mark.asyncio + async def test_requires_auth( + self, unauth_async_account: AsyncAccountResource, + ) -> None: + with pytest.raises(AuthRequiredError): + await unauth_async_account.volume_progress() diff --git a/tests/test_communications.py b/tests/test_communications.py index c9dd6df..64efc6f 100644 --- a/tests/test_communications.py +++ b/tests/test_communications.py @@ -18,18 +18,23 @@ from kalshi.errors import ( AuthRequiredError, KalshiNotFoundError, + KalshiServerError, KalshiValidationError, ) from kalshi.models.communications import ( RFQ, + AcceptBlockTradeProposalRequest, AcceptQuoteRequest, + BlockTradeProposal, CreateQuoteRequest, CreateQuoteResponse, CreateRFQRequest, CreateRFQResponse, + GetBlockTradeProposalsResponse, GetCommunicationsIDResponse, GetQuoteResponse, GetRFQResponse, + ProposeBlockTradeRequest, Quote, ) from kalshi.resources.communications import ( @@ -1199,3 +1204,334 @@ async def test_issue_348_async_flat_names_emit_deprecation_warning( with pytest.warns(DeprecationWarning, match=r"quotes\.confirm"): await async_comms.confirm_quote("q-1") + + +# ── block trade proposals (openapi 3.21.0) ───────────────────────────────── + + +_MINIMAL_BTP = { + "id": "btp-1", + "proposer_user_id": "u-prop", + "buyer_user_id": "u-buy", + "seller_user_id": "u-sell", + "market_ticker": "MKT-1", + "price_centi_cents": 5600, + "centicount": 10000, + "maker_side": "yes", + "expiration_ts": "2026-04-18T13:00:00Z", + "status": "open", + "created_ts": "2026-04-18T12:00:00Z", + "updated_ts": "2026-04-18T12:00:00Z", + "buyer_accepted": False, + "seller_accepted": False, +} + + +class TestBlockTradeProposalModels: + def test_block_trade_proposal_parses(self) -> None: + btp = BlockTradeProposal.model_validate(_MINIMAL_BTP) + assert btp.id == "btp-1" + assert btp.price_centi_cents == 5600 + assert btp.centicount == 10000 + assert btp.maker_side == "yes" + assert btp.buyer_accepted is False + + def test_get_block_trade_proposals_response_wraps_list(self) -> None: + resp = GetBlockTradeProposalsResponse.model_validate( + {"block_trade_proposals": [_MINIMAL_BTP], "cursor": "next"} + ) + assert len(resp.block_trade_proposals) == 1 + assert resp.cursor == "next" + + def test_propose_block_trade_request_serializes(self) -> None: + req = ProposeBlockTradeRequest( + buyer_user_id="u-buy", + seller_user_id="u-sell", + market_ticker="MKT-1", + price_centi_cents=5600, + centicount=10000, + maker_side="yes", + expiration_ts="2026-04-18T13:00:00Z", + ) + body = req.model_dump(exclude_none=True, by_alias=True, mode="json") + assert body["price_centi_cents"] == 5600 + assert body["centicount"] == 10000 + assert "buyer_subtrader_id" not in body # exclude_none drops it + + def test_propose_block_trade_request_forbids_extra(self) -> None: + with pytest.raises(ValidationError): + ProposeBlockTradeRequest( + buyer_user_id="u-buy", + seller_user_id="u-sell", + market_ticker="MKT-1", + price_centi_cents=5600, + centicount=10000, + maker_side="yes", + expiration_ts="2026-04-18T13:00:00Z", + bogus="x", # type: ignore[call-arg] + ) + + def test_propose_block_trade_request_rejects_zero_price(self) -> None: + with pytest.raises(ValidationError): + ProposeBlockTradeRequest( + buyer_user_id="u-buy", + seller_user_id="u-sell", + market_ticker="MKT-1", + price_centi_cents=0, + centicount=10000, + maker_side="yes", + expiration_ts="2026-04-18T13:00:00Z", + ) + + def test_propose_block_trade_request_requires_market_ticker(self) -> None: + with pytest.raises(ValidationError): + ProposeBlockTradeRequest( # type: ignore[call-arg] # market_ticker omitted + buyer_user_id="u-buy", + seller_user_id="u-sell", + price_centi_cents=5600, + centicount=10000, + maker_side="yes", + expiration_ts="2026-04-18T13:00:00Z", + ) + + def test_accept_block_trade_proposal_request_allows_empty(self) -> None: + req = AcceptBlockTradeProposalRequest() + assert req.model_dump(exclude_none=True, by_alias=True, mode="json") == {} + + def test_accept_block_trade_proposal_request_forbids_extra(self) -> None: + with pytest.raises(ValidationError): + AcceptBlockTradeProposalRequest(bogus="x") # type: ignore[call-arg] + + +_BTP_URL = "https://test.kalshi.com/trade-api/v2/communications/block-trade-proposals" + + +class TestListBlockTradeProposals: + @respx.mock + def test_returns_paged_proposals(self, comms: CommunicationsResource) -> None: + respx.get(_BTP_URL).mock( + return_value=httpx.Response(200, json={"block_trade_proposals": [_MINIMAL_BTP]}) + ) + page = comms.block_trade_proposals.list() + assert len(page.items) == 1 + assert isinstance(page.items[0], BlockTradeProposal) + assert page.items[0].id == "btp-1" + + @respx.mock + def test_passes_filter_params(self, comms: CommunicationsResource) -> None: + route = respx.get(_BTP_URL).mock( + return_value=httpx.Response(200, json={"block_trade_proposals": []}) + ) + comms.block_trade_proposals.list(market_ticker="MKT-1", status="open", limit=50) + req = route.calls[0].request + assert req.url.params["market_ticker"] == "MKT-1" + assert req.url.params["status"] == "open" + assert req.url.params["limit"] == "50" + + @respx.mock + def test_list_all_auto_paginates(self, comms: CommunicationsResource) -> None: + respx.get(_BTP_URL).mock( + side_effect=[ + httpx.Response( + 200, json={"block_trade_proposals": [_MINIMAL_BTP], "cursor": "page2"} + ), + httpx.Response( + 200, json={"block_trade_proposals": [{**_MINIMAL_BTP, "id": "btp-2"}]} + ), + ] + ) + ids = [p.id for p in comms.block_trade_proposals.list_all()] + assert ids == ["btp-1", "btp-2"] + + @respx.mock + def test_500_raises(self, comms: CommunicationsResource) -> None: + respx.get(_BTP_URL).mock(return_value=httpx.Response(500, json={"message": "boom"})) + with pytest.raises(KalshiServerError): + comms.block_trade_proposals.list() + + +class TestProposeBlockTrade: + @respx.mock + def test_sends_correct_body(self, comms: CommunicationsResource) -> None: + route = respx.post(_BTP_URL).mock( + return_value=httpx.Response(201, json={"block_trade_proposal_id": "btp-new"}) + ) + resp = comms.block_trade_proposals.create( + buyer_user_id="u-buy", + seller_user_id="u-sell", + market_ticker="MKT-1", + price_centi_cents=5600, + centicount=10000, + maker_side="yes", + expiration_ts="2026-04-18T13:00:00Z", + ) + assert resp.block_trade_proposal_id == "btp-new" + body = json.loads(route.calls[0].request.content) + assert body == { + "buyer_user_id": "u-buy", + "seller_user_id": "u-sell", + "market_ticker": "MKT-1", + "price_centi_cents": 5600, + "centicount": 10000, + "maker_side": "yes", + "expiration_ts": "2026-04-18T13:00:00Z", + } + + @respx.mock + def test_accepts_request_model(self, comms: CommunicationsResource) -> None: + route = respx.post(_BTP_URL).mock( + return_value=httpx.Response(201, json={"block_trade_proposal_id": "btp-r"}) + ) + req = ProposeBlockTradeRequest( + buyer_user_id="u-buy", + seller_user_id="u-sell", + market_ticker="MKT-1", + price_centi_cents=4400, + centicount=5000, + maker_side="no", + expiration_ts="2026-04-18T13:00:00Z", + buyer_subaccount=3, + ) + resp = comms.block_trade_proposals.create(request=req) + assert resp.block_trade_proposal_id == "btp-r" + body = json.loads(route.calls[0].request.content) + assert body["buyer_subaccount"] == 3 + assert body["maker_side"] == "no" + + def test_create_rejects_request_with_kwargs(self, comms: CommunicationsResource) -> None: + req = ProposeBlockTradeRequest( + buyer_user_id="u-buy", + seller_user_id="u-sell", + market_ticker="MKT-1", + price_centi_cents=5600, + centicount=10000, + maker_side="yes", + expiration_ts="2026-04-18T13:00:00Z", + ) + with pytest.raises(TypeError): + comms.block_trade_proposals.create(request=req, buyer_user_id="x") + + @respx.mock + def test_400_maps_to_validation_error(self, comms: CommunicationsResource) -> None: + respx.post(_BTP_URL).mock(return_value=httpx.Response(400, json={"message": "bad"})) + with pytest.raises(KalshiValidationError): + comms.block_trade_proposals.create( + buyer_user_id="u-buy", + seller_user_id="u-sell", + market_ticker="MKT-1", + price_centi_cents=5600, + centicount=10000, + maker_side="yes", + expiration_ts="2026-04-18T13:00:00Z", + ) + + +class TestAcceptBlockTradeProposal: + @respx.mock + def test_sends_post_with_empty_body(self, comms: CommunicationsResource) -> None: + route = respx.post(f"{_BTP_URL}/btp-1/accept").mock( + return_value=httpx.Response(204) + ) + comms.block_trade_proposals.accept("btp-1") + assert route.called + # empty AcceptBlockTradeProposalRequest serializes to {} + assert route.calls[0].request.content == b"{}" + + @respx.mock + def test_sends_post_with_subaccount(self, comms: CommunicationsResource) -> None: + route = respx.post(f"{_BTP_URL}/btp-1/accept").mock( + return_value=httpx.Response(204) + ) + comms.block_trade_proposals.accept("btp-1", subaccount=2) + body = json.loads(route.calls[0].request.content) + assert body == {"subaccount": 2} + + @respx.mock + def test_404(self, comms: CommunicationsResource) -> None: + respx.post(f"{_BTP_URL}/gone/accept").mock( + return_value=httpx.Response(404, json={"message": "missing"}) + ) + with pytest.raises(KalshiNotFoundError): + comms.block_trade_proposals.accept("gone") + + +class TestAsyncBlockTradeProposals: + async def test_list( + self, async_comms: AsyncCommunicationsResource, respx_mock: respx.MockRouter, + ) -> None: + respx_mock.get(_BTP_URL).mock( + return_value=httpx.Response(200, json={"block_trade_proposals": [_MINIMAL_BTP]}) + ) + page = await async_comms.block_trade_proposals.list() + assert len(page.items) == 1 + assert isinstance(page.items[0], BlockTradeProposal) + + async def test_list_all( + self, async_comms: AsyncCommunicationsResource, respx_mock: respx.MockRouter, + ) -> None: + respx_mock.get(_BTP_URL).mock( + side_effect=[ + httpx.Response( + 200, json={"block_trade_proposals": [_MINIMAL_BTP], "cursor": "page2"} + ), + httpx.Response( + 200, json={"block_trade_proposals": [{**_MINIMAL_BTP, "id": "btp-2"}]} + ), + ] + ) + ids = [p.id async for p in async_comms.block_trade_proposals.list_all()] + assert ids == ["btp-1", "btp-2"] + + async def test_create( + self, async_comms: AsyncCommunicationsResource, respx_mock: respx.MockRouter, + ) -> None: + route = respx_mock.post(_BTP_URL).mock( + return_value=httpx.Response(201, json={"block_trade_proposal_id": "btp-9"}) + ) + resp = await async_comms.block_trade_proposals.create( + buyer_user_id="u-buy", + seller_user_id="u-sell", + market_ticker="MKT-1", + price_centi_cents=5600, + centicount=10000, + maker_side="yes", + expiration_ts="2026-04-18T13:00:00Z", + ) + assert resp.block_trade_proposal_id == "btp-9" + assert route.called + + async def test_accept( + self, async_comms: AsyncCommunicationsResource, respx_mock: respx.MockRouter, + ) -> None: + route = respx_mock.post(f"{_BTP_URL}/btp-1/accept").mock( + return_value=httpx.Response(204) + ) + await async_comms.block_trade_proposals.accept("btp-1", subtrader_id="st-1") + body = json.loads(route.calls[0].request.content) + assert body == {"subtrader_id": "st-1"} + + +class TestBlockTradeProposalsAuthGuard: + def test_list_requires_auth(self, unauth_comms: CommunicationsResource) -> None: + with pytest.raises(AuthRequiredError): + unauth_comms.block_trade_proposals.list() + + def test_list_all_requires_auth(self, unauth_comms: CommunicationsResource) -> None: + with pytest.raises(AuthRequiredError): + list(unauth_comms.block_trade_proposals.list_all()) + + def test_create_requires_auth(self, unauth_comms: CommunicationsResource) -> None: + with pytest.raises(AuthRequiredError): + unauth_comms.block_trade_proposals.create( + buyer_user_id="u-buy", + seller_user_id="u-sell", + market_ticker="MKT-1", + price_centi_cents=5600, + centicount=10000, + maker_side="yes", + expiration_ts="2026-04-18T13:00:00Z", + ) + + def test_accept_requires_auth(self, unauth_comms: CommunicationsResource) -> None: + with pytest.raises(AuthRequiredError): + unauth_comms.block_trade_proposals.accept("btp-1") diff --git a/tests/test_contracts.py b/tests/test_contracts.py index 008e75a..8517e36 100644 --- a/tests/test_contracts.py +++ b/tests/test_contracts.py @@ -857,8 +857,9 @@ class TestWsSpecDrift: # corresponding WS_CONTRACT_MAP entry. _DEMO_DIVERGENCE_ALLOWLIST: ClassVar[set[tuple[str, str]]] = set() + @staticmethod @pytest.fixture(autouse=True, scope="class") - def _load(self, request: pytest.FixtureRequest) -> None: + def _load(request: pytest.FixtureRequest) -> None: request.cls.spec = _load_asyncapi_spec() @pytest.mark.parametrize( @@ -1227,6 +1228,12 @@ def _assert_params_match( "#/components/schemas/CreateRFQRequest": ("kalshi.models.communications.CreateRFQRequest"), "#/components/schemas/CreateQuoteRequest": ("kalshi.models.communications.CreateQuoteRequest"), "#/components/schemas/AcceptQuoteRequest": ("kalshi.models.communications.AcceptQuoteRequest"), + "#/components/schemas/ProposeBlockTradeRequest": ( + "kalshi.models.communications.ProposeBlockTradeRequest" + ), + "#/components/schemas/AcceptBlockTradeProposalRequest": ( + "kalshi.models.communications.AcceptBlockTradeProposalRequest" + ), "#/components/schemas/ApplySubaccountTransferRequest": ( "kalshi.models.subaccounts.ApplySubaccountTransferRequest" ),