Add your description here
Project description
dtr-kalshi
A lightweight Python client for the Kalshi Trade API.
Quickstart
Installation
pip install dtr-kalshi
Authentication
Kalshi uses RSA key-pair authentication. You'll need:
- API Key ID — found in your Kalshi account settings.
- RSA private key file — a
.keyfile in PEM format, downloaded when you create an API key.
Export both as environment variables so you don't hardcode credentials:
export KALSHI_API_KEY_ID="your-api-key-id"
export KALSHI_API_KEY_SECRET="/path/to/your/private_key.key"
Alternatively, pass them directly to the client constructor.
Sync usage
KalshiSyncClient is a straightforward blocking client suitable for scripts and simple applications.
from dtr_kalshi import KalshiSyncClient
# credentials are read from environment variables by default
client = KalshiSyncClient()
# use use_sandbox=True to hit the demo environment instead
# client = KalshiSyncClient(use_sandbox=True)
# GET /portfolio/balance
balance = client.get('/portfolio/balance')
print(balance)
# POST /portfolio/orders
order = client.post('/portfolio/orders', data={
'ticker': 'INXD-23DEC31-B4000',
'side': 'yes',
'count': 10,
'type': 'limit',
'yes_price': 55,
})
print(order)
# DELETE /portfolio/orders/{order_id}
client.delete(f"/portfolio/orders/{order['order']['order_id']}")
Async usage
KalshiAsyncClient uses a shared httpx.AsyncClient for connection pooling. Use it as an async context manager so the underlying connection is closed cleanly on exit.
import asyncio
from dtr_kalshi import KalshiAsyncClient
async def main():
async with KalshiAsyncClient() as client:
balance = await client.get('/portfolio/balance')
print(balance)
# fan out multiple requests concurrently
btc, eth = await asyncio.gather(
client.get('/markets/KXBTC-25DEC31'),
client.get('/markets/KXETH-25DEC31'),
)
print(btc, eth)
asyncio.run(main())
WebSocket usage
KalshiWebSocketConnection streams real-time market data. Use it as an async context manager.
Send commands with .send_message(cmd, params), which maps directly to the Kalshi WebSocket protocol.
Callback-based (recommended for multiple channels)
Register handlers with .on(channel, handler), then call .listen() to process messages indefinitely.
import asyncio
from dtr_kalshi import KalshiWebSocketConnection
async def main():
async with KalshiWebSocketConnection() as ws:
ws.on("ticker", lambda msg: print("ticker:", msg))
ws.on("trade", lambda msg: print("trade:", msg))
await ws.send_message("subscribe", {
"channels": ["ticker", "trade"],
"market_ticker": ["INXD-23DEC31-B4000"],
})
await ws.listen()
asyncio.run(main())
Iterator-based (for custom message handling)
Iterate directly over the connection with async for to handle all messages yourself.
import asyncio
from dtr_kalshi import KalshiWebSocketConnection
async def main():
async with KalshiWebSocketConnection() as ws:
await ws.send_message("subscribe", {
"channels": ["orderbook_delta"],
"market_ticker": ["INXD-23DEC31-B4000"],
})
async for msg in ws:
print(msg)
asyncio.run(main())
Concurrent REST and WebSocket
Wrap .listen() in a task to run alongside REST calls.
import asyncio
from dtr_kalshi import KalshiAsyncClient, KalshiWebSocketConnection
async def main():
async with KalshiAsyncClient() as client, KalshiWebSocketConnection() as ws:
await ws.send_message("subscribe", {
"channels": ["ticker"],
"market_ticker": ["INXD-23DEC31-B4000"],
})
listen_task = asyncio.create_task(ws.listen())
balance = await client.get('/portfolio/balance')
print(balance)
listen_task.cancel()
asyncio.run(main())
Project details
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 dtr_kalshi-0.1.3.tar.gz.
File metadata
- Download URL: dtr_kalshi-0.1.3.tar.gz
- Upload date:
- Size: 6.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
802ac2e894b4079d94de14648c5afc4c9ca3165006f8c52112cb9ac666ca0f35
|
|
| MD5 |
7c8e37a4c09331278c98d05c2fe6d2db
|
|
| BLAKE2b-256 |
1b842db7c5a050fbd990f4ecc78e454aa63643efc293122bc48138e8c1c1fe7a
|
File details
Details for the file dtr_kalshi-0.1.3-py3-none-any.whl.
File metadata
- Download URL: dtr_kalshi-0.1.3-py3-none-any.whl
- Upload date:
- Size: 6.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7180540314e14a278634e4c98d2e45b703611498d12aa70bbc2d368c4c22e173
|
|
| MD5 |
0f8f9d292fd30d3f3abc1b1b524461cc
|
|
| BLAKE2b-256 |
1c6795f5bff49be6ad5bcd3d9899d8d197c035a7624e044bdbd30c4c8eb335cc
|