release: 3.0.1 — spec sync 3.18.0 → 3.19.0 (#383)#384
Conversation
Single additive request-side constraint upstream: GET /structured_targets gained `maxItems: 2000` on the `ids` query param. Mirrored at the SDK boundary so an oversize filter fails fast with a clear `ValueError` instead of paying a network round trip for a 400. No endpoint, channel, or response-model changes; regenerated `kalshi/_generated/models.py` is byte-identical to the v3.18.0 output. Closes #383
Code Review — PR #384: spec sync 3.18.0 → 3.19.0Overall this is a clean, minimal, well-scoped PR. The implementation follows existing project patterns correctly. A few small items below. What the PR doesSyncs Issues1. Multi-line comment block violates project style ( CLAUDE.md says: "Never write multi-line comment blocks — one short line max." The 3-line block on # Spec v3.19.0: GET /structured_targets ids param gained maxItems: 2000.
_MAX_IDS = 2000The why is clear from one line; the extra explanation repeats the PR description. 2. Boundary test is only on
3. Inconsistent validation ordering between In sync/async The Observations (non-blocking)
SummaryTwo actionable items:
Everything else looks good. The implementation is minimal, the tests cover all four call paths for the rejection case, and the PR follows the |
Summary
OpenAPI spec sync from v3.18.0 → v3.19.0. Single additive request-side constraint upstream:
GET /structured_targetsgainedmaxItems: 2000on theidsquery param. Mirror it at the SDK boundary so an oversize filter fails fast with a clearValueErrorinstead of paying a network round trip for a 400.No endpoint, channel, or response-model changes. Regenerated
kalshi/_generated/models.pyis byte-identical to the v3.18.0 output (request-param constraints don't surface in response models).Spec checksums match the upstream snapshot from the spec-drift workflow:
specs/openapi.yaml:5eaeca6bb64b2ff0aa4f63f9e13381da5a8f6d8f9b34328408499a0503a3085dspecs/asyncapi.yaml:6ff8a7f34b74964838ed81518567c4ab650bafa82e1ab91eacffb352722e73f4(unchanged)Changes
kalshi/resources/structured_targets.py: new module-level_MAX_IDS = 2000constant +_validate_ids()helper, wired into all four entry points (sync/async ×list/list_all). Follows the existinglive_data.batch(milestone_ids, _MAX_BATCH=100)andmarkets.bulk_*(tickers, _MAX_BULK=100)precedent.tests/test_structured_targets.py: newTestIdsCapclass — 5 tests covering oversize rejection on sync+async list/list_all, plus a 2000-boundary acceptance test (the specmaxItemscap is inclusive).specs/openapi.yaml: synced (version bump + the 1-linemaxItems: 2000addition).pyproject.toml:version = "3.0.1".kalshi/__init__.py:__version__ = "3.0.1"(also corrects a pre-existing stale value of2.6.0).CHANGELOG.md: new## 3.0.1 — 2026-05-26section.README.md+docs/index.md: coverage banners bumped to "OpenAPI v3.19.0".Test plan
uv run pytest tests/ --ignore=tests/integration -q— unit (2959 passed, 3 skipped)uv run ruff check .— lint cleanuv run mypy kalshi/— strict cleanuv run pytest tests/integration/against demo — N/A (client-side validator only; no wire-protocol change)tests/_contract_support.py::METHOD_ENDPOINT_MAP— N/A (no new endpoint;structured_targets.list/list_all/getalready mapped)Notes for reviewers
maxItemssemantics). Tested at exactly 2000 and 2001 entries.list_allis intentionally a plaindefreturning anAsyncIterator, so_validate_idsfires synchronously at call time rather than on first iteration. Matches the existing_validate_max_pagesplacement in the same file._validate_idsis a small module-private helper rather than four inlinedlen(ids) > 2000checks — same cost, one source of truth, one error message that callers can match against in their own tests.Issue links
Closes #383