pandas-style Python client for the Kalshi Trade API
Project description
kalshi-pandas
pandas-style Python client for the Kalshi Trade API
A pandas-style Python client for the Kalshi prediction-market API. Every list endpoint returns a pandas.DataFrame, every dict endpoint returns a TypedDict, and every shape is enforced by a pandera schema. Sync + async, with optional WebSocket, Streamlit explorer, and FastMCP server extras.
Compatibility
| kalshi-pandas | Tested Kalshi Trade API |
|---|---|
| 0.1.0 | 3.12.0 |
The package follows its own semver — bug fixes and helper additions ship as patch/minor releases regardless of upstream API changes. The currently-targeted upstream API version is exposed at runtime as KalshiPandas.API_VERSION.
Install
uv pip install kalshi-pandas # core
uv pip install "kalshi-pandas[ws]" # + WebSocket
uv pip install "kalshi-pandas[explorer]" # + Streamlit dashboard
uv pip install "kalshi-pandas[mcp]" # + FastMCP server
uv pip install "kalshi-pandas[dev]" # + test/lint toolchain
Authentication
Kalshi uses RSA-PSS request signing. Each authenticated request sends three headers (KALSHI-ACCESS-KEY, KALSHI-ACCESS-SIGNATURE, KALSHI-ACCESS-TIMESTAMP); the client builds them automatically once you provide your API key ID and private key.
One-time setup
- Create an API key in the Kalshi web UI (prod or demo). Save the key ID and the private key PEM file that downloads.
- Copy the example env file and fill in the values:
cp .env.example .env $EDITOR .env
- The relevant env vars are:
KALSHI_API_KEY_ID— your key IDKALSHI_PRIVATE_KEY_PATH— absolute path to the PEM file (preferred)KALSHI_PRIVATE_KEY_PEM— inline PEM string (alternative, useful for CI)KALSHI_API_BASE_URL— optional base-URL override (defaults to production)
You can also pass them directly to the constructor:
KalshiPandas(api_key_id="...", private_key_path="/path/to/key.pem")
The client reads env vars in __post_init__, so loading .env (via python-dotenv or your shell) before instantiation is enough.
Quickstart
Sync
from dotenv import load_dotenv
from kalshi_pandas import KalshiPandas
load_dotenv()
with KalshiPandas() as client:
# Public endpoint — no auth needed
df = client.get_markets(limit=50)
print(df.head())
# Private endpoint — uses signed request
balance = client.get_balance()
print(balance)
Async
import asyncio
from dotenv import load_dotenv
from kalshi_pandas import AsyncKalshiPandas
load_dotenv()
async def main():
async with AsyncKalshiPandas() as client:
df = await client.get_markets(limit=50)
print(df.head())
asyncio.run(main())
Features
| Feature | Module |
|---|---|
| Sync HTTP client | kalshi_pandas.KalshiPandas |
| Async HTTP client | kalshi_pandas.AsyncKalshiPandas |
| WebSocket (sync) | kalshi_pandas.KalshiWebSocket (extra: ws) |
| WebSocket (async) | kalshi_pandas.AsyncKalshiWebSocket (extra: ws) |
| Pandera schemas | kalshi_pandas.schemas |
| TypedDicts | kalshi_pandas.types |
| Exception hierarchy | kalshi_pandas.exceptions |
| Streamlit explorer | kalshi-pandas-explore (extra: explorer) |
| FastMCP server | kalshi-pandas-mcp (extra: mcp) |
Pagination
Every cursor-paginated list endpoint has an _all variant that auto-paginates:
df = client.get_markets() # one page
df = client.get_markets_all() # all pages, concatenated
Error handling
from kalshi_pandas import KalshiAPIError, KalshiAuthError, KalshiRateLimitError
try:
df = client.get_markets()
except KalshiAuthError:
...
except KalshiRateLimitError:
...
except KalshiAPIError as e:
print(e.status_code, e.url, e.detail)
Development
uv pip install -e ".[dev]"
uv run pytest tests/test_unit.py -v
uv run ruff check .
uv run mypy kalshi_pandas
CI runs the same checks on every push and PR via .github/workflows/ci.yml across Python 3.11, 3.12, and 3.13.
Releasing
Releases are cut by pushing a v* tag. .github/workflows/release.yml then:
- Runs the test job first — ruff + mypy + mocked pytest + live integration suite. If this fails, the build, publish, and release jobs are all skipped automatically.
- Builds sdist + wheel via
uv build - Publishes to PyPI via trusted publishing (OIDC, no API token)
- Creates a GitHub release with the built artifacts attached
One-time setup (before the first release):
- Create the project on PyPI (or reserve the name).
- Add a pending publisher at https://pypi.org/manage/account/publishing/:
- PyPI project name:
kalshi-pandas - Owner: your GitHub user/org
- Repository name:
kalshi-pandas - Workflow name:
release.yml - Environment name:
pypi
- PyPI project name:
- In your GitHub repo settings, create an
Environmentnamedpypi. - Add the live-test secrets to the same
pypienvironment (Settings → Environments → pypi → Environment secrets):KALSHI_API_KEY_IDKALSHI_PRIVATE_KEY_PEM(paste the entire PEM contents, including-----BEGIN ... END-----lines)
To cut a release:
# 1. Update CHANGELOG.md — move [Unreleased] entries under a new version header
# 2. Bump version in pyproject.toml
# 3. Commit, tag, push
git commit -am "Release v0.1.1"
git tag v0.1.1
git push origin main --tags
To force a release when the test job is broken (not the code):
gh workflow run release.yml -f tag=v0.1.1 -f skip_tests=true
License
Apache-2.0
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file kalshi_pandas-0.1.0.tar.gz.
File metadata
- Download URL: kalshi_pandas-0.1.0.tar.gz
- Upload date:
- Size: 33.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8d9d3e32a3c613f441961fbffb7a2856e8afebb364f8acf3f97b550647b798af
|
|
| MD5 |
5683365a3be3f9d48af714d97c7f7e66
|
|
| BLAKE2b-256 |
1687ded8b24ea1bf4c24064a9e5737dc072c492612bed6e42545f735a3acc072
|
Provenance
The following attestation bundles were made for kalshi_pandas-0.1.0.tar.gz:
Publisher:
release.yml on sigma-quantiphi/kalshi-pandas
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
kalshi_pandas-0.1.0.tar.gz -
Subject digest:
8d9d3e32a3c613f441961fbffb7a2856e8afebb364f8acf3f97b550647b798af - Sigstore transparency entry: 1261615394
- Sigstore integration time:
-
Permalink:
sigma-quantiphi/kalshi-pandas@fe48265227e9eb4bd648e7664d5e40df11413155 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/sigma-quantiphi
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@fe48265227e9eb4bd648e7664d5e40df11413155 -
Trigger Event:
push
-
Statement type:
File details
Details for the file kalshi_pandas-0.1.0-py3-none-any.whl.
File metadata
- Download URL: kalshi_pandas-0.1.0-py3-none-any.whl
- Upload date:
- Size: 42.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5b6cff178c3e1daba5bf6c718aefdf22a1e3e6b1bbe13cb0e20aa53080cb395d
|
|
| MD5 |
cfe1c042e45e829c99798b6372608b65
|
|
| BLAKE2b-256 |
ba1858774c90a16f27d9befe77afc7ebeea5c9e688ec3b1a871b318dc9dac969
|
Provenance
The following attestation bundles were made for kalshi_pandas-0.1.0-py3-none-any.whl:
Publisher:
release.yml on sigma-quantiphi/kalshi-pandas
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
kalshi_pandas-0.1.0-py3-none-any.whl -
Subject digest:
5b6cff178c3e1daba5bf6c718aefdf22a1e3e6b1bbe13cb0e20aa53080cb395d - Sigstore transparency entry: 1261615482
- Sigstore integration time:
-
Permalink:
sigma-quantiphi/kalshi-pandas@fe48265227e9eb4bd648e7664d5e40df11413155 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/sigma-quantiphi
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@fe48265227e9eb4bd648e7664d5e40df11413155 -
Trigger Event:
push
-
Statement type: