Kalshi 15 Minute Bitcoin Bot (2026): How to Build One With the API

The Short Answer
A Kalshi 15-minute Bitcoin bot trades the KXBTC15M series, where each market asks whether Bitcoin will finish a 15-minute window at or above where it started. The market rules settle on CF Benchmarks' Bitcoin Real Time Index (BRTI): a market resolves Yes if the simple average of the sixty seconds of BRTI before the close is at least the same average before the open. Find the live window with GET /markets?series_ticker=KXBTC15M and a min_close_ts filter, then place and cancel orders through the V2 order endpoints, which Kalshi's TypeScript SDK wraps as createOrderV2 and cancelOrderV2. Crypto markets trade on exchange shard 2, so move collateral there first.
Key Takeaways
KXBTC15Mlists one market per 15-minute window, around the clock except during Kalshi's Thursday maintenance, and one window is open at a time.- Each window's target price is the previous window's final value: across 198 consecutive pairs we checked, they matched exactly.
- Settlement uses a 60-second average of CF Benchmarks' BRTI, not Binance, Coinbase or any single exchange.
- Crypto markets sit on exchange shard 2, so fund that shard and pass
exchange_index: 2on orders. - Once a window closes, every order action is rejected, including cancels, and resting orders are canceled shortly after.
What is Kalshi's 15-minute Bitcoin market?
It is the series KXBTC15M, and each market in it is titled "BTC price up in next 15 mins?". The series metadata lists CF Benchmarks as the settlement source, a frequency of fifteen_min, Kalshi's quadratic fee type and exchange index 2. Windows close on the quarter hour, at :00, :15, :30 and :45, and each one opens the moment the previous one closes.
In the 96 windows that settled in the 24 hours to 3 October 2026, the median window traded 3.19 million contracts, with a low of 1.46 million and a high of 5.08 million. How these markets compare with Polymarket's short crypto markets is covered in how to track 15 minute Bitcoin markets.
How does a 15-minute Bitcoin market settle?
The window that closed at 3:30 PM EDT on 2 October 2026 resolved Yes when the 60-second BRTI average before 3:30 PM was at least the 60-second average before 3:15 PM. Its secondary rules specified 60 index readings in the final minute and an average rounded to two decimal places.
The starting average is published on the market as floor_strike, labeled as the target price, and the final average arrives as expiration_value. Because both use the same 60-second rule, each window's target is the previous window's final value:
| Market | Target (floor_strike) | Final (expiration_value) | Result |
|---|---|---|---|
KXBTC15M-26OCT021500-00 | 83,957.42 | 84,250.56 | Yes |
KXBTC15M-26OCT021515-15 | 84,250.56 | 84,118.74 | No |
KXBTC15M-26OCT021530-30 | 84,118.74 | 84,124.90 | Yes |
Across the last 200 settled windows we pulled, all 198 consecutive pairs matched this way. Settlement is quick: over the 96 windows of the previous 24 hours, the median settled 4 seconds after its close and the slowest 14 seconds after.
Kalshi's rules designate CF Benchmarks' Real Time Index as the settlement source. Prices shown by Google or Coinbase can guide a decision, but a bot using a single exchange's ticker is modeling a different value.
When do Kalshi's 15-minute Bitcoin markets open and close?
Every 15 minutes, all day. The ticker encodes the close in Eastern Time: KXBTC15M-26OCT021530-30 closes at 15:30 ET on 2 October 2026, and the suffix repeats the minute. Kalshi lists windows ahead of time with status initialized, which the status=unopened filter returns, and their target reads "TBD" until they open.
Two timing details matter for a bot:
- Thursday maintenance. Kalshi pauses trading every Thursday from 3:00 to 5:00 AM ET, and no 15-minute windows run through it. In our data, the window closing at 3:00 AM ET on Thursday 1 October was followed by one closing at 5:15 AM.
- The handover. At two quarter-hour boundaries we polled once a second,
status=openkept returning the closed window for 26 and 29 seconds before it listed the new one. Filtering by close time, as the code below does, found the new window within about a second, and its target price appeared within about 10 seconds of the open.
How do you get the current market and its order book?
All three calls are public, so no key is needed. This runs on Node 18 or newer with no dependencies:
const BASE = 'https://external-api.kalshi.com/trade-api/v2';
const now = Math.floor(Date.now() / 1000);
// Every window that closes after this second. The earliest of them is the one trading now.
const { markets } = await (await fetch(`${BASE}/markets?series_ticker=KXBTC15M&min_close_ts=${now + 1}&limit=200`)).json();
const live = markets.reduce((a, b) => (a.close_time < b.close_time ? a : b));
// Read it by ticker for fresh fields, then read its book.
const { market: m } = await (await fetch(`${BASE}/markets/${live.ticker}`)).json();
const { orderbook_fp: book } = await (await fetch(`${BASE}/markets/${m.ticker}/orderbook?depth=5`)).json();
const bestYesBid = Number(book.yes_dollars.at(-1)?.[0] ?? 0);
const bestYesAsk = 1 - Number(book.no_dollars.at(-1)?.[0] ?? 0);
const secondsLeft = Math.round((Date.parse(m.close_time) - Date.now()) / 1000);
console.log(m.ticker, m.status, '| target', m.floor_strike, '| yes', bestYesBid, '/', bestYesAsk.toFixed(4), '|', secondsLeft, 's left');
The list comes back newest first, 33 windows when we ran it, so the code picks the earliest close, and now + 1 skips a window closing that very second. The book returns bids only, sorted from lowest to highest, so the best bid is the last entry and the best yes ask is one dollar minus the best no bid. Prices step by 1 cent between 10 and 90 cents and by a tenth of a cent outside that band, per the market's price_ranges. Book math is covered in the Kalshi order book API guide.
How do you fund a Kalshi crypto bot?
Kalshi splits trading across matching engines, and since 24 August 2026 new crypto events are created on shard 2. Kalshi's docs say programmatic traders "must preallocate collateral on a given exchange shard before order placement", so cash sitting on the default shard 0 cannot back a Bitcoin order. Move it with the intra-account transfer endpoint, or set a target balance allocation and let Kalshi rebalance every 10 seconds. With the official TypeScript SDK:
import { readFileSync } from 'node:fs';
import { Configuration, PortfolioApi } from 'kalshi-typescript';
const portfolio = new PortfolioApi(new Configuration({
apiKey: 'YOUR_KEY_ID',
privateKeyPem: readFileSync('kalshi-private-key.pem', 'utf8'),
basePath: 'https://external-api.kalshi.com/trade-api/v2',
}));
// Move $100 of cash from shard 0 to shard 2, where crypto markets trade. Amounts are in centicents.
await portfolio.intraExchangeInstanceTransfer({
source: 'event_contract',
destination: 'event_contract',
amount: 1_000_000,
source_exchange_shard: 0,
destination_exchange_shard: 2,
});
const { data } = await portfolio.getBalance(undefined, 2);
console.log('shard 2 balance', data.balance_dollars);
A cent is 100 centicents, so $100 is 1,000,000. The transfer is processed asynchronously, which is why the balance check follows it. Creating the key itself is covered in how to get a Kalshi API key.
How do you place and cancel orders with the Kalshi SDK?
Orders go to the V2 endpoint, POST /portfolio/events/orders, which quotes everything from the Yes side. bid buys Yes, and ask sells Yes, which is the same as buying No at one dollar minus the price. Prices and counts are strings. With kalshi-typescript 3.33.0:
import { readFileSync } from 'node:fs';
import { randomUUID } from 'node:crypto';
import { Configuration, OrdersApi } from 'kalshi-typescript';
const orders = new OrdersApi(new Configuration({
apiKey: 'YOUR_KEY_ID',
privateKeyPem: readFileSync('kalshi-private-key.pem', 'utf8'),
basePath: 'https://external-api.kalshi.com/trade-api/v2',
}));
const ticker = process.env.KALSHI_MARKET_TICKER; // set this to the open window found above
if (!ticker) throw new Error('Set KALSHI_MARKET_TICKER to the current open market');
// Bid for 10 Yes contracts at 45 cents. post_only keeps it from crossing the spread.
const { data: placed } = await orders.createOrderV2({
ticker,
client_order_id: randomUUID(),
side: 'bid',
count: '10',
price: '0.4500',
time_in_force: 'good_till_canceled',
self_trade_prevention_type: 'taker_at_cross',
post_only: true,
cancel_order_on_pause: true,
exchange_index: 2,
});
console.log('placed', placed.order_id, 'filled', placed.fill_count, 'resting', placed.remaining_count);
// Cancel whatever is still resting. Arguments: order ID, subaccount, exchange index, ticker.
const { data: canceled } = await orders.cancelOrderV2(placed.order_id, undefined, 2, ticker);
console.log('canceled', canceled.reduced_by, 'contracts');
Passing exchange_index: 2 sends the order straight to the crypto shard. Leaving it out still works, because Kalshi auto-routes by ticker, but its docs note that auto-routing adds latency and bills the write to every shard's rate-limit bucket. cancel_order_on_pause pulls the order if trading pauses. The SDK signs each request for you, and Ed25519 keys need SDK 3.31.0 or later. A full bot loop, with a kill switch and position caps, is in how to build a Kalshi trading bot.
Where should a 15-minute bot get its Bitcoin price?
From the index that settles it, if you can. Kalshi's WebSocket has a cfbenchmarks_value channel that streams BRTI, index ID BRTI, roughly once a second over the same signed connection as its market channels:
{ "id": 1, "cmd": "subscribe", "params": { "channels": ["cfbenchmarks_value"], "index_ids": ["BRTI"] } }
Each update carries the index value and avg_60s_data, a trailing 60-second average. In the final minute before each quarter hour, it also carries last_60s_windowed_average_15min, a running average of that minute's ticks, which mirrors how the rules compute the final value. The arithmetic helps a bot: 45 seconds into the final minute, three quarters of the settlement average is already fixed.
To see other venues' prices beside Kalshi's, the Predictefy API streams Binance's BTC/USDT price and Chainlink's on-chain BTC/USD price next to Kalshi's trade tape on one WebSocket, and serves Kalshi's live order book in the same normalized shape it uses across 15+ venues. Neither feed settles these markets, so treat them as fast references beside BRTI, not a stand-in for it. Predictefy's paper trading also fills paper orders against Kalshi's live books at 0 credits, a way to rehearse a bot before it trades real money.
What are the risks of a 15-minute Bitcoin bot?
Each contract settles at $1 or $0 within 15 minutes, so a position can go to zero in one window: size every order as money you can afford to lose. Some mechanical risks are specific to these markets:
- No exit after the bell. Once
close_timepasses, all order actions, cancels included, are rejected withMARKET_INACTIVE. - Fees near 50 cents. The quadratic fee is largest at even odds, roughly where each window opens. Kalshi fees explained has the formula.
- Runaway loops. Order groups cancel every order in a group once fills exceed a contract limit over a rolling 15 seconds. They work within one shard, which suits a single-series bot.
- Blunt cancels. Cancel-all clears resting orders on every shard, and Kalshi warns that orders placed in the minute after the request may be canceled too.
- Rate limits. On the Basic tier, writes refill at 100 tokens a second and an order costs 10, as Kalshi API rate limits explains.
Frequently Asked Questions
What is the ticker for Kalshi's 15-minute Bitcoin market?
The series is KXBTC15M. Each window is its own market, such as KXBTC15M-26OCT021530-30, which closed at 3:30 PM ET on 2 October 2026.
How do Kalshi's 15-minute Bitcoin markets settle?
On CF Benchmarks' Bitcoin Real Time Index. A market resolves Yes if the simple average of the sixty seconds of BRTI before the window closes is at least the same average before it opened. Kalshi rounds the final average to two decimal places.
What is the target price on a Kalshi 15-minute Bitcoin market?
It is the 60-second BRTI average before the window opened, published as floor_strike once the market opens. It equals the previous window's final value: in 198 consecutive pairs we checked, every target matched the prior expiration_value.
Do Binance or Chainlink prices settle Kalshi's crypto markets?
No. Kalshi's crypto markets settle on CF Benchmarks' Real Time Indexes, which aggregate prices from multiple exchanges every second. Binance, Coinbase and Chainlink prices can track the same move but are not the settlement source.
Can you trade Kalshi's 15-minute Bitcoin markets with an API?
Yes. Market data and order books are public. Orders need an API key and go to POST /portfolio/events/orders, and because crypto markets trade on exchange shard 2, you need collateral on that shard first.