Context
OpenAPI v3.18.0 added fields to several mid-tier response models. None individually justify a dedicated PR, but grouping them keeps each model surface coherent. Removes 9 of the remaining additive-drift warnings.
Depends on #158. Independent of #159, #PR3, #PR4 — can land in parallel.
Scope
Files
kalshi/models/events.py — add 3 to Event, 2 to EventMetadata
kalshi/models/portfolio.py — add 1 to Settlement
kalshi/models/historical.py — add 2 to Trade
kalshi/models/incentive_programs.py — add 1 to IncentiveProgram
- Tests: extend the relevant
tests/test_<resource>.py to cover (de)serialization of new fields
Field-level changes
Event (+3):
| Field |
Spec type |
SDK type |
Notes |
exchange_index |
integer |
int | None = None |
matches the same field on Market/Order |
fee_multiplier_override |
number |
DollarDecimal | None = None |
confirm — spec may type as plain number or string; check at edit time |
fee_type_override |
string |
str | None = None |
enum-like; keep str |
EventMetadata (+2):
| Field |
Spec type |
SDK type |
Notes |
competition |
string |
str | None = None |
sport/event competition name |
competition_scope |
string |
str | None = None |
|
Settlement (+1):
| Field |
Spec type |
SDK type |
Notes |
value |
integer |
int | None = None |
payout per yes contract, in cents per spec description. Plain int, not DollarDecimal — verify at edit time |
Trade (+2):
| Field |
Spec type |
SDK type |
Notes |
taker_outcome_side |
string |
SideLiteral | None = None |
Literal["yes", "no"] — mirrors Order.outcome_side in #159 |
taker_book_side |
string |
BookSideLiteral | None = None |
Literal["bid", "ask"] |
IncentiveProgram (+1):
| Field |
Spec type |
SDK type |
Notes |
incentive_description |
string |
str | None = None |
optional descriptive blurb returned alongside the program |
Conventions
Same as #159:
- Append-only at end of each model.
- Use existing
*Literal aliases (SideLiteral, BookSideLiteral from kalshi/models/orders.py — import if needed).
extra="allow" policy already set on each model; do not change.
Acceptance criteria
Notes
Settlement.value description from spec: "Payout of a single yes contract in cents." → int, not DollarDecimal. Confirm by reading specs/openapi.yaml Settlement.value.
- Cross-model field naming:
exchange_index appears on Market (PR1), Order (PR1), Event (this PR), OrderGroup/{Get,Create}OrderGroupResponse (PR3). All int | None = None. Keep the same shape.
Effort
~50 lines model code + ~20 lines tests.
Part of the response-side spec drift hardening stack.
Tracking: #157.
Context
OpenAPI v3.18.0 added fields to several mid-tier response models. None individually justify a dedicated PR, but grouping them keeps each model surface coherent. Removes 9 of the remaining additive-drift warnings.
Depends on #158. Independent of #159, #PR3, #PR4 — can land in parallel.
Scope
Files
kalshi/models/events.py— add 3 toEvent, 2 toEventMetadatakalshi/models/portfolio.py— add 1 toSettlementkalshi/models/historical.py— add 2 toTradekalshi/models/incentive_programs.py— add 1 toIncentiveProgramtests/test_<resource>.pyto cover (de)serialization of new fieldsField-level changes
Event(+3):exchange_indexint | None = Nonefee_multiplier_overrideDollarDecimal | None = Nonefee_type_overridestr | None = NonestrEventMetadata(+2):competitionstr | None = Nonecompetition_scopestr | None = NoneSettlement(+1):valueint | None = Noneint, notDollarDecimal— verify at edit timeTrade(+2):taker_outcome_sideSideLiteral | None = NoneLiteral["yes", "no"]— mirrorsOrder.outcome_sidein #159taker_book_sideBookSideLiteral | None = NoneLiteral["bid", "ask"]IncentiveProgram(+1):incentive_descriptionstr | None = NoneConventions
Same as #159:
*Literalaliases (SideLiteral,BookSideLiteralfromkalshi/models/orders.py— import if needed).extra="allow"policy already set on each model; do not change.Acceptance criteria
uv run pytest "tests/test_contracts.py::TestSpecDrift::test_additive_drift[Event]" "tests/test_contracts.py::TestSpecDrift::test_additive_drift[EventMetadata]" "tests/test_contracts.py::TestSpecDrift::test_additive_drift[Settlement]" "tests/test_contracts.py::TestSpecDrift::test_additive_drift[Trade]" "tests/test_contracts.py::TestSpecDrift::test_additive_drift[IncentiveProgram]" -v— all five pass without warnings.uv run pytest tests/ -q --ignore=tests/integrationpasses.uv run mypy kalshi/strict-clean.uv run ruff check .clean.Notes
Settlement.valuedescription from spec: "Payout of a single yes contract in cents." →int, notDollarDecimal. Confirm by readingspecs/openapi.yamlSettlement.value.exchange_indexappears on Market (PR1), Order (PR1), Event (this PR), OrderGroup/{Get,Create}OrderGroupResponse (PR3). Allint | None = None. Keep the same shape.Effort
~50 lines model code + ~20 lines tests.
Part of the response-side spec drift hardening stack.
Tracking: #157.