How to scrape salary ranges from Ashby job boards with Python
Pull startup job postings with pay ranges from Ashby boards, annualised to yearly amounts, with currency and remote filters and an only-new feed.
datagrit › Guides › Kalshi Settlement Calendar & Order Book Depth
GuideBuild a Kalshi settlement calendar with bid, ask, spread, volume and order book depth near the touch, filtered by liquidity, using Python or cURL.
Published 2026-10-01 · uses the Kalshi Settlement Calendar & Order Book Depth Actor
On a prediction market, time to settlement shapes how you trade. A contract that resolves tonight is a different position from one that resolves in March, and close to settlement the data feed that decides the outcome matters more than any opinion.
If you trade on Kalshi, build bots for it or study its markets, the question you keep asking is: which open markets settle in the next N hours, which of them are actually quoted, and how much can I trade near the best price? Kalshi's public API holds all the pieces. It just does not give them to you as one table.
This post shows what the API offers, the traps in combining it, and how to get a settlement calendar with liquidity attached in one call.
Kalshi exposes a public market data API at api.elections.kalshi.com/trade-api/v2 that needs no account for reading. It has markets (with quotes, volume, open interest and timing fields), a series catalog (with categories, frequency and settlement sources) and order books per market.
Building a settlement calendar on top of it involves more than one endpoint and several surprises:
expected_expiration_time). Many markets can close early, so the close time is often far later than when the market actually resolves. The Kalshi Settlement Calendar Actor on Apify filters and sorts on the expected settlement time.maxItems candidates while it scans.KXBTCD-B versus KXBTCD), so splitting an event ticker at the first dash attaches the wrong series. The Actor matches the longest event ticker prefix present in the catalog.category field silently drops markets. The Actor uses the full membership list.Crypto and financial markets settling within the next 24 hours, with at least some activity and a spread of 3 cents or less:
{
"settlesWithinHours": 24,
"settlesAfterHours": 0,
"categories": ["Crypto", "Financials"],
"seriesTickers": [],
"keywords": [],
"minVolume24h": 100,
"minOpenInterest": 0,
"requireTwoSidedQuote": true,
"maxSpreadCents": 3,
"sortBy": "settlement",
"includeOrderbook": true,
"depthCents": 5,
"includeRules": false,
"maxItems": 50
}
sortBy accepts settlement, volume24h, openInterest or spread. A negative settlesAfterHours (for example -6) also lists markets whose expected settlement time has passed but which have not settled yet. Naming seriesTickers such as KXBTCD is much faster than scanning the whole exchange: a run without named series scans the full catalog, which takes about a minute and a half.
from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run_input = {
"settlesWithinHours": 24,
"seriesTickers": ["KXBTCD"],
"maxSpreadCents": 3,
"includeOrderbook": True,
"depthCents": 5,
"maxItems": 50,
}
run = client.actor("datagrit/kalshi-settlement-calendar").call(run_input=run_input)
markets = [m for m in client.dataset(run["defaultDatasetId"]).iterate_items() if m.get("found")]
for m in markets:
print(f'{m["hoursToSettle"]:>6}h {m["ticker"]:<32} bid {m["yesBid"]} ask {m["yesAsk"]} '
f'depth {m["yesBidDepth"]}/{m["yesAskDepth"]}')
curl -X POST \
"https://api.apify.com/v2/acts/datagrit~kalshi-settlement-calendar/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"settlesWithinHours": 48, "seriesTickers": ["KXBTCD"], "maxItems": 20}'
One row per open market. Prices are in dollars (0.58 = 58 cents, read as a 58% implied probability); volume, open interest and depth are in contracts.
| Field | Example | Meaning |
|---|---|---|
ticker | KXBTCD-26OCT0117-T83249.99 | Market ticker |
title | Bitcoin price on Oct 1, 2026? | What the market asks |
expectedSettlementTime | 2026-10-01T21:00:00.000Z | When Kalshi expects it to settle |
hoursToSettle | 18.26 | Hours from run start; negative = overdue |
settlementSources | CF Benchmarks | Who decides the outcome |
yesBid / yesAsk | 0.58 / 0.59 | Best YES quotes |
spreadCents | 1 | Ask minus bid in cents |
volume24h | 29185.23 | Contracts traded in 24 hours |
openInterest | 17101.47 | Contracts outstanding |
yesBidDepth / yesAskDepth | 16839.01 / 19022.45 | Contracts within depthCents of the touch |
Rows also carry seriesTicker, seriesTitle, category, categories, frequency, outcome, closeTime, latestSettlementTime, canCloseEarly, settlementSourceUrls, midPrice, NO-side quotes, sizes at the touch, whole-book levels and totals, and, if requested, the rules text.
Schedule the Actor hourly with settlesWithinHours: 6 and sortBy: "settlement", and write the dataset to Google Sheets through an Apify integration or a short script. The sheet always shows what resolves next, with the spread and depth needed to judge whether it is tradable.
import pandas as pd
df = pd.DataFrame(markets)
tradable = df[(df["spreadCents"] <= 2) & (df["yesAskDepth"] >= 500)]
print(tradable.sort_values("hoursToSettle")[["ticker", "hoursToSettle", "midPrice", "spreadCents", "yesAskDepth"]])
yesAskDepth counts contracts you can buy within the depth window above the best ask, so it is a direct answer to "can I get 500 contracts without walking the book more than 5 cents?".
Run with a one-week window (settlesWithinHours: 168), then group by settlementSources. That shows which data feeds (for example CF Benchmarks for the Bitcoin series) decide the most markets this week, which helps when you build source-specific models or alerts.
A settlement-sorted view with depth near the touch is a small thing that saves a lot of glue code; pricing is pay per result, the Actor is on Apify, and every field is described in the documentation.
Pull startup job postings with pay ranges from Ashby boards, annualised to yearly amounts, with currency and remote filters and an only-new feed.
Monitor open roles at a list of companies across 8 applicant tracking systems in one schema, with numeric salaries and a daily only-new feed.
Build lists of French companies from the official Sirene register, filtered by net result, revenue, NAF code and location, using Python or cURL.