Kalshi Markets API
This FastAPI service exposes the Kalshi market data that the crawler stores in PostgreSQL and augments it with candlestick retrieval via the Kalshi API. When the web service starts it automatically launches the crawler in the same process, so the database stays fresh while the API is serving requests.
Prerequisites
- Python 3.10+
-
A running PostgreSQL instance accessible with the credentials stored
in
.env(DB_NAME,DB_USER,DB_PASSWORD,DB_HOST,DB_PORT,DB_SSLMODE). -
Kalshi API credentials already configured for the crawler
(
KEYID,KEYFILE). -
Recommended Python packages (install inside your virtualenv):
pip install fastapi uvicorn psycopg psycopg2-binary python-dotenv
Running the Service
-
Activate your virtualenv and ensure the environment variables in
.envare accurate for the target database and Kalshi credentials. -
Start the FastAPI app with Uvicorn:
uvicorn backend.api.main:app --host 0.0.0.0 --port 8000 --reload -
On startup the app will:
-
Create the markets table (
kalshi_marketsby default) if it does not exist. - Start the crawler thread in the background. The crawler keeps logging table size snapshots every minute.
-
Create the markets table (
-
Shutdown (
Ctrl+C) stops the crawler gracefully before exiting.
Available Endpoints
GET /
Landing page summarizing available endpoints and pointing to this README.
GET /markets
Retrieve markets from PostgreSQL with rich filtering.
Query parameters
-
limit(int, default 100, max 10,000) andoffset(int, default 0) control pagination. -
max_duration_minutes(int, optional) filters to markets where bothopen_timeandclose_timeare present and differ by no more than the specified number of minutes. -
min_duration_minutes(int, optional) filters to markets where bothopen_timeandclose_timediffer by at least the specified number of minutes. -
Exact match filters: pass
?field=valuefor any column listed below. -
Regex filters: append
_regexto string fields (case-insensitive). Example:?title_regex=Election. -
Comparison operators for numeric, decimal, or datetime fields using
suffixes:
__lt,__lte,__gt,__gte,__eq. Example:?volume__gt=1000. -
Ordering controls:
order_by(defaultrecent) combined withorder_direction(defaultdesc).recentsorts by the most recent timestamp available, preferringclose_timewhen set and falling back toopen_time. Supported values fororder_byarerecent,close_time,open_time,volume,liquidity,open_interest,settlement_value, andticker.
Filterable columns
-
String (regex allowed):
ticker,event_ticker,title,subtitle,market_type,strike_type,result,rules_primary -
Integer:
volume,liquidity,open_interest - Decimal:
settlement_value -
Datetime (ISO 8601 string or Unix timestamp):
open_time,close_time
Response
{
"items": [ { ...market fields... }, ... ],
"count": 2
}
Example
curl "https://www.api.eventquant.com/markets?ticker_regex=^KAL&volume__gt=50000&limit=20&order_by=volume&order_direction=desc"
GET /markets/{ticker}
Fetch a single market by ticker. Returns HTTP 404 if the ticker is not present.
curl https://www.api.eventquant.com/markets/KALSHI-TICKER
POST /markets/candlesticks
Fetch candlestick data for one or more tickers using the authenticated Kalshi API client.
Request body
{
"tickers": ["TICKER1", "TICKER2"],
"start_ts": 1700000000,
"end_ts": 1700600000,
"period_interval": 60
}
start_ts, end_ts, and
period_interval are optional. tickers must
contain between 1 and 10,000 ticker strings.
Response
{
"results": [
{
"ticker": "TICKER1",
"candlesticks": [ ... ],
"error": null
},
{
"ticker": "TICKER2",
"candlesticks": [],
"error": "Kalshi API message (if any)"
}
]
}
Example
curl -X POST https://www.api.eventquant.com/markets/candlesticks \
-H "Content-Type: application/json" \
-d '{"tickers":["TICKER1","TICKER2"],"period_interval":1}'
Data Model
Each market object exposes the following fields:
ticker, event_ticker, title,
subtitle, market_type,
strike_type, open_time,
close_time, volume, liquidity,
open_interest, result,
settlement_value, rules_primary.
The database table name defaults to kalshi_markets;
override it by setting MARKETS_TABLE in your environment.
Notes
- The API shares database helper logic with the crawler but keeps the fetch generator out of the request path.
-
All database interactions use
psycopgv3 when available, falling back topsycopg2. - Errors from the Kalshi HTTP API during candlestick requests are surfaced per ticker rather than failing the entire response.