# Kalshi Markets API — Odds, Volume & Open Interest (`memo23/kalshi-markets-api`) Actor

Pull Kalshi prediction markets by keyword, event ticker or watchlist. Yes/no quotes, spread, implied probability, 24h and lifetime volume, open interest, liquidity, settlement rules and resolution windows. Filter by price, volume, open interest and time-to-close before you are billed.

- **URL**: https://apify.com/memo23/kalshi-markets-api.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** Developer tools, Automation, News
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 market returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Kalshi Markets API — Odds, Volume & Open Interest

<p align="center">
  <img src="https://raw.githubusercontent.com/muhamed-didovic/muhamed-didovic.github.io/main/assets/kalshi/logo.png" width="130" alt="Kalshi Markets API">
</p>

Pull live markets from **Kalshi**, the CFTC-regulated US prediction exchange, by keyword, event ticker or a fixed watchlist. Every row carries the yes/no book, the implied probability, traded volume, open interest, resting liquidity and the resolution window.

Reads Kalshi's own public trade API. No login, no browser, no proxy, no anti-bot to fight.

### Why use it

- **The question, not just the ticker.** Kalshi splits things: the question lives on the *event*, the outcome name on the *market*. Read only the markets feed and you get "Klaus Iohannis" with no idea what is being asked. Every row here carries both.
- **Filters run before billing.** Narrow by price, volume, open interest, liquidity or time-to-close and the excluded markets never reach your dataset, so they cost nothing.
- **Depth, not just a price.** `yesBid`, `yesAsk`, `spread` and `impliedProbability` together tell you whether a quote is real or a one-sided stub.
- **Skips the dead listings.** Kalshi lists many contracts that have never been quoted. `requireLiveQuote` drops them in one switch.
- **An empty run fails.** If a run returns nothing at all it exits FAILED with a reason, rather than reporting success on an empty dataset.

### What it does

| You give it | You get |
|---|---|
| Keywords | Every market whose question, outcome or ticker matches |
| Event tickers | Every outcome under those events |
| Market tickers | Exactly those markets, no discovery |
| Nothing | The whole open board, capped by `maxItems` |

### Input

| Field | Type | Description |
|---|---|---|
| `searchQueries` | array | Keywords matched against question, outcome and ticker. |
| `eventTickers` | array | Restrict to given Kalshi event tickers. |
| `marketTickers` | array | Exact watchlist. Skips discovery and ignores the filters. |
| `status` | select | `open` (default), `closed`, `settled` or `any`. |
| `minVolume24h` / `minVolume` | integer | Contract-volume floors. |
| `minOpenInterest` | integer | Outstanding-contract floor — a better liveness signal than volume. |
| `minLiquidity` | integer | Resting order-book liquidity floor, in dollars. |
| `minYesPrice` / `maxYesPrice` | number | Implied-probability band, 0 to 1. |
| `closesWithinHours` | integer | Keep only markets resolving inside this window. |
| `requireLiveQuote` | boolean | Drop markets with no resting bid or ask. |
| `includeRules` | boolean | Add the settlement rules text. Long, so off by default. |
| `maxItems` | integer | Row cap. Scanning stops the moment it is reached. |

> A market where Kalshi leaves a field empty is **kept**, not dropped. Freshly listed markets often have no volume or liquidity yet, and silently discarding them would shrink a filtered run in a way you cannot reconcile against what Kalshi shows.

#### Examples

Everything crypto with a real quote, resolving within a day:

```json
{
  "searchQueries": ["bitcoin", "ethereum"],
  "requireLiveQuote": true,
  "closesWithinHours": 24,
  "maxItems": 200
}
```

Longshots with genuine depth:

```json
{
  "maxYesPrice": 0.1,
  "minOpenInterest": 500,
  "minLiquidity": 250
}
```

A fixed watchlist, checked on a schedule:

```json
{ "marketTickers": ["KXBTCPRICE-85000-26AUG28"] }
```

### Output

One row per tradable outcome:

```json
{
  "ticker": "KXBTCPRICE-85000-26AUG28",
  "eventTicker": "KXBTCPRICE-26AUG28",
  "question": "When will Bitcoin cross $85k again?",
  "outcome": "By Aug 28, 2026",
  "category": "Crypto",
  "status": "active",
  "yesBid": 0.02,
  "yesAsk": 0.49,
  "spread": 0.47,
  "impliedProbability": 0.255,
  "volume24h": 17.24,
  "openInterest": 55.56,
  "liquidity": 0,
  "closeTime": "2026-08-28T15:00:00Z",
  "hoursToClose": 30.05,
  "marketUrl": "https://kalshi.com/markets/kxbtcprice-85000"
}
```

#### Key fields

| Field | Description |
|---|---|
| `impliedProbability` | Midpoint of the YES book — the usual probability read. Null unless both sides quote. |
| `spread` | `yesAsk − yesBid`. A wide spread means the quote is thin, whatever the midpoint says. |
| `openInterest` | Contracts still outstanding. Survives quiet days better than volume does. |
| `hoursToClose` | Hours from scrape time to close. Negative once the market has closed. |
| `result` | Settlement result once resolved, otherwise null. |

### Notes & limitations

- Prices are dollars per contract, 0 to 1, so they read directly as probabilities.
- `liquidity` is often `0` on thin markets — that is Kalshi's own value, not a parse failure.
- Keyword search runs client-side because the API offers no text search, so a narrow keyword scans many markets to find its matches. Nothing scanned is billed; only returned rows are.
- Settlement rules are omitted unless `includeRules` is on, since they are long.

### 🤖 For AI Agents & LLM Apps

Reference for agents calling this actor via the [Apify MCP server](https://mcp.apify.com) or the API (`memo23/kalshi-markets-api`).

**Purpose:** live Kalshi prediction-market odds and depth, one row per tradable outcome.

**Minimal input:**

```json
{ "searchQueries": ["fed"], "requireLiveQuote": true, "maxItems": 50 }
```

**Output fields:** ticker, eventTicker, seriesTicker, question, outcome, noOutcome, category, status, marketType, strikeType, yesBid, yesAsk, noBid, noAsk, lastPrice, previousPrice, spread, impliedProbability, volume, volume24h, openInterest, liquidity, notionalValue, openTime, closeTime, expirationTime, hoursToClose, result, canCloseEarly, marketUrl, scrapedAt.

**Behaviours to know:**

- Always set `maxItems`; the open board runs to tens of thousands of outcomes.
- `marketTickers` bypasses discovery and every filter — use it for watchlists.
- Filters drop rows before billing; a filtered-out market costs nothing.
- Fields Kalshi leaves empty pass the filters rather than failing them.
- Billed per returned row. See the Pricing tab.

### ⚠️ Disclaimer

This actor reads publicly available data from Kalshi's own public API. It is not affiliated with, endorsed by, or sponsored by Kalshi. Nothing it returns is financial advice, and prediction-market trading carries risk. Use it in line with Kalshi's terms and applicable law.

### SEO Keywords

kalshi api, kalshi scraper, kalshi markets, prediction market data, kalshi odds, event contracts, implied probability, kalshi open interest, prediction market api, kalshi event tickers, binary options data, forecasting markets

# Actor input Schema

## `searchQueries` (type: `array`):

Keep only markets whose question, outcome or ticker contains one of these (case-insensitive). Example: \["bitcoin", "fed"]. Empty = every market.

## `eventTickers` (type: `array`):

Restrict to these Kalshi event tickers, e.g. \["KXBTCPRICE"]. Empty = all events.

## `marketTickers` (type: `array`):

Exact market tickers to fetch directly, e.g. \["KXBTCPRICE-85000-26AUG28"]. Skips discovery entirely and ignores the filters below. Fastest way to monitor a fixed set.

## `status` (type: `string`):

Which markets to fetch. Default open, i.e. currently tradable.

## `minVolume24h` (type: `integer`):

Drop markets with less than this many contracts traded in 24h. Use 1+ to skip untraded listings. Example: 100.

## `minVolume` (type: `integer`):

Drop markets with less than this many contracts traded in total. Example: 1000.

## `minOpenInterest` (type: `integer`):

Drop markets with fewer outstanding contracts than this. A better liveness signal than volume. Example: 500.

## `minLiquidity` (type: `integer`):

Drop markets with less resting order-book liquidity than this, in dollars. Example: 250.

## `minYesPrice` (type: `integer`):

Keep only markets whose YES midpoint is at or above this, 0 to 1. Use 0.9 for near-certain outcomes.

## `maxYesPrice` (type: `integer`):

Keep only markets whose YES midpoint is at or below this, 0 to 1. Use 0.1 for longshots.

## `closesWithinHours` (type: `integer`):

Keep only markets resolving within this many hours. Example: 24 for markets settling today.

## `requireLiveQuote` (type: `boolean`):

On: drop markets with no resting bid or ask. Kalshi lists many contracts that have never been quoted.

## `includeRules` (type: `boolean`):

On: add rulesPrimary and rulesSecondary to each row. These are long legal texts, off by default to keep the dataset small.

## `maxItems` (type: `integer`):

Hard cap on rows returned. Scanning stops as soon as this is reached. Non-paying users are capped at 100.

## Actor input object example

```json
{
  "searchQueries": [
    "bitcoin"
  ],
  "status": "open",
  "requireLiveQuote": false,
  "includeRules": false,
  "maxItems": 500
}
```

# Actor output Schema

## `results` (type: `string`):

Dataset of Kalshi markets: question, outcome, yes/no quotes, spread, implied probability, volume, open interest, liquidity and close time.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "searchQueries": [
        "bitcoin"
    ],
    "maxItems": 500
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/kalshi-markets-api").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "searchQueries": ["bitcoin"],
    "maxItems": 500,
}

# Run the Actor and wait for it to finish
run = client.actor("memo23/kalshi-markets-api").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchQueries": [
    "bitcoin"
  ],
  "maxItems": 500
}' |
apify call memo23/kalshi-markets-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,memo23/kalshi-markets-api"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/j1ldXNcLURa4Y3De4/builds/0lxrfmMxgxXZvLKMY/openapi.json
