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
Metadata
Release files for kalshi-pandas 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| kalshi_pandas-0.1.0.tar.gz | 33.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| kalshi_pandas-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 76.6 kB
Release files / kalshi_pandas-0.1.0.tar.gz
| Download URL | kalshi_pandas-0.1.0.tar.gz |
|---|---|
| Size | 33.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8d9d3e32a3c613f441961fbffb7a2856e8afebb364f8acf3f97b550647b798af
|
|
BLAKE2b-256 checksum How to use checksums |
1687ded8b24ea1bf4c24064a9e5737dc072c492612bed6e42545f735a3acc072
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 9, 2026.
Transparency logRelease files / kalshi_pandas-0.1.0-py3-none-any.whl
| Download URL | kalshi_pandas-0.1.0-py3-none-any.whl |
|---|---|
| Size | 42.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5b6cff178c3e1daba5bf6c718aefdf22a1e3e6b1bbe13cb0e20aa53080cb395d
|
|
BLAKE2b-256 checksum How to use checksums |
ba1858774c90a16f27d9befe77afc7ebeea5c9e688ec3b1a871b318dc9dac969
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 9, 2026.
Transparency log