Build a Kalshi AI Trading Bot (Demo First, With Hard Limits)

Kalshi Paper / demo first

PASS WITH FIXES Tested on Composer 2.5, , result: PASS WITH FIXES. We built this bot from the prompt and ran its loop on live public Kalshi data (2 tests passing). Orders, order groups and cancel-all used a mock broker, and the LLM research step used a deterministic stub: no real keys, orders or money. The prompt below includes the fixes from that run.

Short answer: To build a Kalshi AI trading bot safely, have your AI coding tool write it against the Kalshi demo environment first, place orders with Create Order V2 (POST /portfolio/events/orders), cap exposure in code, and add order groups that auto-cancel resting orders when fills exceed a limit. An optional LLM research step only ever sees public market text, never your keys or balances.

What are the key facts?

  • Create orders with POST /portfolio/events/orders (Create Order V2). Kalshi says the legacy /portfolio/orders endpoint will be deprecated no earlier than May 6, 2026.
  • V2 order body: ticker, side (bid/ask), count (string), price (fixed-point dollars, e.g. "0.5600"), time_in_force (good_till_canceled / immediate_or_cancel / fill_or_kill), self_trade_prevention_type, plus optional client_order_id, post_only, reduce_only, cancel_order_on_pause.
  • Order groups (POST /portfolio/order_groups/create) auto-cancel every resting order in the group if fills exceed a contracts limit in a rolling 15-second window.
  • Cancel everything: DELETE /portfolio/events/orders. Cancel one: DELETE /portfolio/events/orders/{order_id}.
  • Demo base URL: https://external-api.demo.kalshi.co/trade-api/v2. Separate keys from production.
DifficultyIntermediate
Time3–4 hours
Cost$0 API · optional LLM API usage
Works withClaude Code, Cursor, ChatGPT / Codex, Grok

What will you build?

A Kalshi bot that runs on demo: it watches a few markets, applies your rule (optionally informed by an LLM research step), checks hard limits, and places small limit orders with a server-side safety net.

Who is it for?

People who've done the Kalshi API starter and want a real bot loop, on their own account, for their own trading.

Not for: Running a bot for friends, selling signals, or copy trading. Kalshi's Developer Agreement prohibits facilitating other members' trading.

What prompt do you paste into your AI coding tool?

Works in Claude Code, Cursor, Codex/ChatGPT, Grok or any agent that can write files. Paste it into an empty folder. Read what it builds before you run anything.

Build a Kalshi trading bot in Python that runs on the Kalshi DEMO environment
by default. Use only endpoints/fields from https://docs.kalshi.com. Follow the
rules in CLAUDE.md/AGENTS.md. If unsure about an endpoint, ask me.

Reuse (or create) a signed client: headers KALSHI-ACCESS-KEY,
KALSHI-ACCESS-TIMESTAMP (ms), KALSHI-ACCESS-SIGNATURE over
timestamp+METHOD+path (path from /trade-api/v2, no query string; RSA-PSS
SHA-256 for RSA keys, direct signature for Ed25519). Key file path and key id
come from env vars; the key file lives outside the repo.

Modules:
- config.toml: env ("demo"|"prod", default demo), tickers to watch (from
  the SAME env: demo and prod list different markets, so a prod ticker
  returns 404 on demo; never read quotes from one env and order on another),
  poll seconds, strategy params.
- limits.json: max_contracts_per_order, max_open_exposure_usd,
  max_daily_loss_usd, max_orders_per_minute, order_group_contracts_limit.
- data.py: GET /markets/{ticker}, GET /markets/{ticker}/orderbook (public).
  Use *_dollars price fields. Remember the book has bids only.
- research.py (OPTIONAL, off by default): sends ONLY public market text
  (title, rules_primary, current prices) to an LLM and asks for a short
  written summary and a probability estimate with reasoning. Never send keys,
  balances or positions to the LLM. Log every LLM output. If no LLM API key
  is set, don't call the network: use a deterministic stub that is clearly
  labeled "stub, not a forecast", or skip research.
- strategy.py: my rule. Start with a placeholder: propose a 1-contract
  limit bid only if my own configured fair price minus the best ask is above
  a configured margin. The research output is advisory input only.
- risk.py: kill switch (KILL file or BOT_KILL=1) + every limit in
  limits.json, checked before every order. Unit tests.
- broker.py:
    create_order_group(contracts_limit) -> POST /portfolio/order_groups/create
    place_order(...) -> POST /portfolio/events/orders with ticker, side
      ("bid" = buy YES, "ask" = sell YES), count (string, e.g. "1.00"),
      price (fixed-point dollars string, e.g. "0.3500"), time_in_force
      (fill_or_kill | good_till_canceled | immediate_or_cancel; GTT is not a
      valid value), self_trade_prevention_type (taker_at_cross | maker), client_order_id (uuid4), and the order
      group id (field: order_group_id). Use post_only where sensible; reduce_only for exits;
      cancel_order_on_pause=true.
    cancel_all() -> DELETE /portfolio/events/orders
    positions() -> GET /portfolio/positions
- bot.py: loop = kill switch -> data -> (research) -> strategy -> risk ->
  broker -> log to logs/decisions.jsonl. "prod" requires --live AND typing
  "I accept the risk". Print the environment loudly at startup.
- cancel_all.py: one-shot cancel-all.
- Bounded exponential backoff on 429/5xx; never retry a rejected order in a
  loop. Use client_order_id so retries can't double-submit.
- If demo keys are not set (or BROKER_MOCK=1), use a mock broker that logs
  the exact request it would send and sends nothing, so the whole loop runs
  without an account.
- pytest tests for risk, signing, and the live gate.

Show the plan, build, then give me the commands to run on demo.

How do you build it, step by step?

  1. Do the Kalshi API Starter first so you have demo keys and a working signed client.
  2. Add the Safety Pack (rules file, .gitignore, deny rules, gitleaks hook).
  3. Paste the prompt. Check broker.py against the Create Order V2 page: path /portfolio/events/orders, count as a string, price as a fixed-point dollar string.
  4. Pick 1–3 demo tickers with GET https://external-api.demo.kalshi.co/trade-api/v2/markets?status=open&mve_filter=exclude, and put them in config.toml. Take them from demo: demo and production list different markets, so a ticker copied from kalshi.com usually returns 404 on demo.
  5. Set tiny limits (1 contract per order, $5 exposure, $2 daily loss) and an order-group limit of a few contracts.
  6. Run on demo: python bot.py. No demo keys yet? Run BROKER_MOCK=1 python bot.py first; the mock broker logs each order it would send and sends nothing. Watch logs/decisions.jsonl and your demo account's open orders.
  7. Drill the safety net. touch KILL to stop new orders, then python cancel_all.py to clear resting ones. Confirm in the demo UI that they're gone.
  8. Turn on research only if you want it. Set research.enabled = true. Read what the LLM writes. LLM probability estimates are often confident and badly calibrated, so measure them against outcomes over time before trusting them.
  9. Live is a separate decision. If you ever switch to prod, create a new production key, keep the same tiny limits, and stay at the keyboard for the first sessions.

How do you test it in paper or demo mode first?

Kalshi gives you a real demo exchange with mock funds, which is better than a simulated ledger: your orders hit a real matching engine, get real rejections and exercise your real code paths.

  • Demo base URL: https://external-api.demo.kalshi.co/trade-api/v2, with WebSocket at wss://external-api-ws.demo.kalshi.co/trade-api/ws/v2.
  • Demo keys can't touch production, so a bug can't drain a real account.
  • Kalshi notes demo prices and behavior may differ from real markets. Use demo to prove your code works, not that your strategy works.

Track a simple scorecard in demo: orders placed, rejected (and why), filled, kill-switch drills passed, and PnL after fees.

What safety checks does it need before real money?

Tick every box before the bot touches real money. The full rules file, .gitignore and pre-commit hook are in the Safety Pack.

Which official docs did we check?

Endpoints and rules were checked against these pages on Oct 19, 2026. APIs change, so if something here disagrees with the official docs, trust the docs and tell us.

Frequently asked questions

Are trading bots allowed on Kalshi?

Kalshi offers a public trading API, and its Developer Agreement allows using it to facilitate your own trading. It prohibits facilitating trading for other members, sharing API data with third parties without written permission, and manipulative behavior like spoofing or wash trading.

Which Kalshi endpoint places orders now?

Use Create Order V2 at POST /portfolio/events/orders. Kalshi's docs say the legacy /portfolio/orders endpoint will be deprecated no earlier than May 6, 2026, and clients should migrate.

How do I stop a Kalshi bot fast?

Have three layers: a local kill switch (a KILL file your bot checks before every order), a cancel-all command using DELETE /portfolio/events/orders, and Kalshi order groups, which auto-cancel resting orders when fills exceed a limit in a rolling 15-second window.

Can an AI predict Kalshi markets?

An LLM can summarize information and produce a probability estimate, but there's no guarantee it beats the market price, and its estimates are often overconfident. Treat it as a research assistant, log every output, and measure it in demo before relying on it. BotCookery doesn't provide predictions or picks.

Is there a Kalshi trading bot on GitHub I can use?

There are several. If you use one, audit it first and run it on demo with demo keys. See how to audit a bot repo.

Related recipes