Kalshi runs a full copy of its exchange for testing. It has its own website, its own API hosts and its own play-money balances. If you're writing a trading bot for Kalshi's 15-minute markets, the demo environment is where you find out whether your code signs requests, places orders and handles fills properly before any real money is involved. This guide covers how the demo works, how to point your code at it, what you can and can't learn there, and a sensible order for moving from demo to live.
We checked every URL and number below against docs.kalshi.com and Kalshi's public API on October 25, 2026.
What the Kalshi demo environment is
The demo is a separate exchange at demo.kalshi.co. Note the .co domain; production is kalshi.com. Kalshi's docs say three things about it:
- It uses mock funds. Orders, fills and balances are all play money.
- It shares no credentials with production. Kalshi keeps the two environments apart for safety, so you create a separate demo account and separate demo API keys. A demo key won't work on production and a production key won't work on demo.
- Prices and behavior may differ from the real market. Kalshi says outright that demo market prices and behavior "may not be reflective" of real markets. This is the most important limitation, and we cover it in detail below.
Kalshi's help center has a step-by-step guide to creating a demo account. Treat the demo login as its own account with its own password and keys.
Demo vs. production API endpoints
The API surface is the same in both environments. Only the host changes. These are the base URLs from Kalshi's API environments page:
| Production | Demo | |
|---|---|---|
| REST (recommended) | https://external-api.kalshi.com/trade-api/v2 |
https://external-api.demo.kalshi.co/trade-api/v2 |
| REST (also supported) | https://api.elections.kalshi.com/trade-api/v2 |
https://demo-api.kalshi.co/trade-api/v2 |
| WebSocket (recommended) | wss://external-api-ws.kalshi.com/trade-api/ws/v2 |
wss://external-api-ws.demo.kalshi.co/trade-api/ws/v2 |
| WebSocket (also supported) | wss://api.elections.kalshi.com/trade-api/ws/v2 |
wss://demo-api.kalshi.co/trade-api/ws/v2 |
One detail catches people: the request signature doesn't include the host. Kalshi's signed requests cover the timestamp, the HTTP method and the path, such as /trade-api/v2/portfolio/orders, without the hostname or the query string. So code that signs correctly on demo signs correctly on production too. Only the base URL and the key pair change. (For the signing steps, see our Kalshi API Python tutorial.)
Switching environments with one setting
Put the environment behind a single setting, so moving from demo to live is a config change and not a code edit:
import os
ENVIRONMENTS = {
"demo": {
"rest": "https://external-api.demo.kalshi.co/trade-api/v2",
"ws": "wss://external-api-ws.demo.kalshi.co/trade-api/ws/v2",
"key_id_env": "KALSHI_DEMO_KEY_ID",
"key_file_env": "KALSHI_DEMO_KEY_FILE",
},
"prod": {
"rest": "https://external-api.kalshi.com/trade-api/v2",
"ws": "wss://external-api-ws.kalshi.com/trade-api/ws/v2",
"key_id_env": "KALSHI_PROD_KEY_ID",
"key_file_env": "KALSHI_PROD_KEY_FILE",
},
}
ENV = os.environ.get("KALSHI_ENV", "demo") # default to demo, never to prod
cfg = ENVIRONMENTS[ENV]
print(f"Running against {ENV}: {cfg['rest']}")
Three habits that prevent expensive mistakes:
- Default to demo. If the setting is missing, the bot should fall back to the play-money exchange.
- Keep the keys in separate variables. If demo and production keys share one variable, sooner or later the wrong key ends up on the wrong host. Usually that's just an authentication error, but it's confusing to debug.
- Print the environment at startup and in every log line. When you read a log later, you need to know which exchange it came from.
Reading demo markets: no key needed
As on production, market data on demo is public. This call lists open 15-minute Bitcoin markets on the demo exchange:
curl "https://demo-api.kalshi.co/trade-api/v2/markets?series_ticker=KXBTC15M&status=open&limit=2"
When we ran it on October 25, 2026, demo listed the same ticker and target price as production: KXBTC15M-26OCT251215-15, with a floor strike of $80,532.45. The exchange status endpoint (/exchange/status) returned trading_active: true. So the market structure, tickers and strikes match. The trading activity does not.
Demo liquidity vs. real liquidity: a side-by-side
We pulled the same market from both environments within a few seconds of each other:
| KXBTC15M-26OCT251215-15 | Production | Demo |
|---|---|---|
| Target (floor strike) | $80,532.45 | $80,532.45 |
| Best YES bid / ask | 10¢ / 11¢ | 6¢ / 6.3¢ |
| Volume (contracts) | about 620,304 | 141 |
| Open interest (contracts) | about 284,420 | 110 |
Same contract, very different market. Production had more than four thousand times the volume, and the demo quote sat about 4¢ away from the real one. That's expected: demo traders are developers testing code with play money, not people pricing Bitcoin's next fifteen minutes.
That tells you what the demo can't do:
- It can't tell you whether a strategy has an edge. A strategy that "wins" on demo prices is winning against a different, much thinner order book. Demo profit and loss tells you nothing about live profit and loss.
- It can't tell you about real fills. Queue position, partial fills, slippage near the close and how quickly the book refills all depend on real participants. Demo fills are a poor guide to them.
- It can't stand in for your fee math on real prices. Fees are charged per contract and depend on price. Kalshi's general taker formula is 0.07 × contracts × price × (1 − price), rounded up to the next cent. At 50¢, ten contracts cost 0.07 × 10 × 0.50 × 0.50 = $0.175, which rounds up to $0.18. At 10¢ the same ten contracts cost $0.063, which rounds up to $0.07. Run the breakeven on real production quotes, not demo quotes. Our breakeven win rate guide walks through the math, and Kalshi's fee schedule is the authority on current rates.
What the demo is good for
The demo is a test bench for plumbing. Use it to prove that the parts of your bot that touch the exchange do what you think they do:
-
Authentication. Signed requests to
/portfolio/balancereturn a balance and no 401s. That confirms your key loading, timestamp handling and RSA-PSS signature. -
Order placement. Place a small limit order well away from the market so it rests, read it back from
/portfolio/orders, then cancel it. You've now exercised create, read and cancel. - Your own guards. If your bot has a per-order cost cap, a daily loss limit or a maximum position, set them low on demo and try to break them on purpose. A guard you've never seen fire is a guard you don't know works.
- Fills and position tracking. Cross the spread with one contract and check that your bot records the fill, the fee and the new position, and that its numbers match the exchange's portfolio endpoints.
- Settlement handling. Hold a one-contract position through a 15-minute close. Check that your bot notices the market settle, records the payout and moves on to the next market. If you need a refresher on how these markets resolve, see how Kalshi markets settle.
- Reconnects. Kill your WebSocket connection in the middle of a session and confirm the bot resubscribes and resyncs the order book without double-placing orders. Our rate limits and WebSocket guide covers the sequence-number checks.
- Restarts. Stop the bot while an order is resting, start it again and check that it finds the order instead of forgetting it.
Every item on that list is about code correctness, not market prediction. That's the right job for a play-money exchange.
A sensible path from demo to live
Think of it as three stages, each answering a different question:
- Demo: does the code work? Run the seven checks above until they pass reliably. Ignore demo profit and loss.
- Paper on production data: does the logic make sense on real prices? Point the read-only side of your bot at production market data and record the trades it would place, at real quotes, with fees included. This is where you learn whether your entry rules ever fire, and at what prices. Our paper vs. live comparison explains why paper fills still flatter you.
- Small live: what do real fills look like? Switch to production keys at the smallest size you can stand to lose, and compare live fills against your paper log. Only real fills tell you about slippage and queue position.
Judge each stage on its own question. A bot that passes demo has working plumbing, not an edge.
Common demo mistakes
- Hard-coding the production host in one helper. One forgotten URL in a balance check or a cancel helper sends that call to the wrong exchange. Build every URL from the single base-URL setting.
- Signing the full URL. If you include the host or query string in the signed message, you'll get authentication errors in both environments. Sign the path only.
- Treating demo prices as forecasts. The side-by-side above is the reason.
- Testing only the happy path. Rejected orders, cancels after a partial fill and a market closing under a resting order are where bots break. Make each one happen on demo on purpose.
Or skip the plumbing and use ready software
Building and testing all of this yourself is a solid way to learn how Kalshi's API behaves. If you'd rather start from finished software, DeskBot for Kalshi is a desktop app that runs on your own machine. It trades Kalshi's 15-minute markets on your own account through your own API key. It starts in paper mode until you switch a market live, and you choose the limits. The current offer is Try DeskBot for $1: first month $1, then $19.99/month, cancel anytime. It does not guarantee profits or win rates.
FAQ
Does Kalshi have a demo or sandbox environment?
Yes. The demo exchange is at demo.kalshi.co. It uses mock funds and has its own REST and WebSocket API hosts, listed in the table above.
Can I use my Kalshi API key on the demo?
No. Kalshi doesn't share credentials between the demo and production. You need a separate demo account and demo API keys, and each key only works on its own environment.
Is the Kalshi demo API the same as the production API?
The endpoints and request signing are the same. Only the base URL changes. The market data isn't the same: demo prices and volumes come from a much thinner pool of test traders.
Are Kalshi demo prices realistic?
Kalshi says demo prices and behavior may not reflect real markets. In our October 25, 2026 check, one 15-minute Bitcoin market had 141 contracts of volume on demo versus about 620,000 on production, with quotes about 4¢ apart.
Do the 15-minute crypto markets exist on the demo?
In our check they did. The demo listed KXBTC15M markets with the same tickers and target prices as production. Availability can change, so query /markets on the demo host to confirm.
Can a demo test prove my Kalshi bot will make money?
No. A demo test shows whether your code works. Whether a strategy holds up after fees and real fills only shows up on production prices, and any strategy can lose money.
Is DeskBot affiliated with Kalshi?
No. DeskBot is independent software. It uses Kalshi's public Trade API on the customer's own account.
Risk: Trading on Kalshi involves risk, and you can lose money. Nothing here guarantees profits, returns, win rates or income, and past, backtested, demo or paper results do not predict future results. This article explains API and testing mechanics. It is not legal, tax or investment advice. DeskBot is independent software and is not affiliated with or endorsed by Kalshi. Sources, checked October 25, 2026: docs.kalshi.com Demo Environment and API Environments pages, Kalshi's public API on production and demo (market KXBTC15M-26OCT251215-15 and /exchange/status), and Kalshi's fee schedule. Rules, fees and APIs change, so check the current documents before you rely on any detail.