Kalshi does not have a single "market order" button in its API. Every order is a limit order with a price, and a few extra fields decide how long it lives, whether it may take liquidity, and what happens when it meets your own resting order. If you trade the 15-minute crypto markets by hand you rarely see these choices. If you automate, they decide whether you get filled, what you pay in fees, and whether a bad loop can run away from you. This guide walks through each field in Kalshi's current Create Order (V2) endpoint, with worked fee math and the mistakes we see most often.
The short version
- Every Kalshi API order has a price and a count. A "market order" is just a limit order priced far enough through the book to fill.
-
time_in_force has three values:
good_till_canceled,immediate_or_cancelandfill_or_kill. Add anexpiration_timeto a good-till-canceled order to make it expire on its own. - post_only marks an order that should only rest on the book as a maker, never take.
-
reduce_only caps an order at your current position, and Kalshi only accepts it with
immediate_or_cancel. - self_trade_prevention_type is required and decides which side gets canceled if you would trade against yourself.
- Order groups cancel every resting order in the group if fills pass a contract limit inside a rolling 15-second window. They are a cheap circuit breaker for a bot.
How Kalshi describes a direction: bid, ask, Yes and No
The V2 endpoint quotes everything from the Yes side. Its side field takes bid or ask. Kalshi's docs define bid as buying Yes and ask as selling Yes, and they note that selling Yes is economically the same as buying No at one dollar minus the price.
Fills, orders and trades now report direction in two equivalent fields: outcome_side (yes or no) and book_side (bid or ask). Per Kalshi's order direction page, bid always means Yes exposure and ask always means No exposure. The old pair of action plus side collapses like this:
| Legacy action | Legacy side | outcome_side | book_side |
|---|---|---|---|
| buy | yes | yes | bid |
| sell | no | yes | bid |
| buy | no | no | ask |
| sell | yes | no | ask |
So "buy No at 44¢" and "sell Yes at 56¢" are the same order in V2: side: ask, price: "0.56". A lot of first-week bot bugs come from sending the No price into a Yes-quoted field and getting the opposite trade at the opposite price. One more trap: the WebSocket order book channels report No-side levels in No-leg pricing by default, so a No level at 0.30 matches Yes at 0.70. Kalshi lets you subscribe with use_yes_price: true to put both sides on one scale, and says that default will flip to true in a future release.
Prices and contract counts are strings now
V2 sends prices as fixed-point dollar strings, such as "0.5600", and contract counts as fixed-point strings, such as "10.00". Requests accept up to four decimal places on most price fields, but the valid steps for a given market are set by that market's price level structure, so do not assume every market trades in every tenth of a cent. Counts accept up to two decimals, and Kalshi lists 0.01 contracts as the minimum granularity. Store these as decimals or integers in your code, never as floats, or rounding will eventually send a price the exchange rejects.
The older /portfolio/orders endpoint still works, but Kalshi's docs say it will be deprecated no earlier than May 6, 2026, and point new code at /portfolio/events/orders. If you are writing a bot today, build on V2.
time_in_force: how long the order lives
good_till_canceled (GTC)
The order rests on the book until it fills, you cancel it, or the market closes. This is the default way to quote as a maker. On a 15-minute market, "until the market closes" is at most 15 minutes, but a forgotten GTC order can still fill at a price that made sense ten minutes ago and does not now.
Expiring orders: GTC plus expiration_time
To make an order cancel itself at a set moment, send good_till_canceled with an expiration_time in Unix seconds. Kalshi's docs are specific that "GTT" is an internal execution type and is not a valid API value, which trips up people porting code from other exchanges. For short markets this is the safer default for resting orders: give each quote a life of 30 to 120 seconds so stale quotes clear even if your bot crashes.
immediate_or_cancel (IOC)
The order takes whatever it can at your price or better right away, and the rest is canceled. The response's remaining_count already shows the final state after the unfilled part is gone. IOC cannot be combined with expiration_time. This is how most bots "hit" the market: price it at the worst level you accept, and you never leave anything behind on the book.
fill_or_kill (FOK)
The order fills in full immediately or not at all. Use it when a partial fill is worse than no fill, for example one leg of a two-market position where half a hedge leaves you exposed.
Worked example: what a taker order really costs
Say the Yes ask on a Bitcoin 15-minute market is 56¢ and you send an IOC bid for 10 contracts at "0.56".
- Cost before fees: 10 × $0.56 = $5.60.
- Taker fee: Kalshi's general fee model is about 0.07 × contracts × price × (1 − price). That is 0.07 × 10 × 0.56 × 0.44 = $0.1725, rounded up under Kalshi's fee-rounding rules.
- Payout if Yes wins: 10 × $1.00 = $10.00.
- Break-even win rate: ($5.60 + $0.1725) ÷ $10.00 ≈ 57.7%. The market price implies 56%. You need to be right about 1.7 points more often than the price says just to break even.
The fee is largest near 50¢ and shrinks toward the extremes: at 20¢ the same formula gives 0.07 × 0.20 × 0.80 = 1.12¢ per contract. Kalshi rounds fees and balances to a set precision. Its fee-rounding page explains that non-direct members are aligned to the cent, and a running accumulator rebates overpayment across the fills of one order. Small orders can therefore pay slightly more per contract than the formula suggests. The response to a filled order includes average_fill_price and average_fee_paid. Log both, because they are the numbers your break-even really depends on. For the full fee breakdown, see our Kalshi fees and break-even win rate guide.
post_only: quote as a maker, never take
post_only is a true or false flag on the order. The common use is a resting quote that must sit on the book as a maker order, so it can never accidentally cross the spread and pay the taker fee. Whether makers pay less, or nothing, depends on the market's fee schedule. Our maker vs taker fees article covers how to check that for each series. Kalshi's API reference lists the flag but does not spell out in the schema what happens to a post-only order that would cross, so test it on the demo environment (demo-api.kalshi.co) before you rely on it.
Queue position: why amending can cost you
Resting orders fill in price-time priority. Kalshi exposes a queue position endpoint that reports how many contracts must match ahead of your order before it gets any fill. The amend endpoint has a rule that matters for any quoting bot:
- Amending only the expiration time, or decreasing the size, keeps your place in the queue.
- Increasing the size or changing the price sends the order to the back of the queue.
Note that amend's count is the new total, meaning what already filled plus what you want resting, not the amount to add. If 4 of 10 contracts filled and you want 3 more resting, you send 7, not 3. There is also a separate Decrease Order endpoint that takes either reduce_by or reduce_to.
reduce_only, self-trade prevention and pause behavior
reduce_only
With reduce_only: true, the order's size is capped at your current position, so it can only shrink exposure, never flip it. Kalshi rejects reduce-only orders unless time_in_force is immediate_or_cancel. That is useful when a bot exits early: if a fill message was missed and the bot thinks it holds more than it does, reduce-only stops the exit order from opening a new position the other way.
self_trade_prevention_type
This field is required on every V2 order. It has two values:
-
taker_at_cross: if your incoming order would match your own resting order, the incoming order is canceled. Any partial fills already matched against other people stand. -
maker: your resting order is canceled and the incoming order keeps matching against the rest of the book.
If your bot quotes both sides of a market, pick on purpose. maker lets a fresh take go through when an old quote is in the way. taker_at_cross protects the resting quotes.
cancel_order_on_pause
Set this to true and an open order is canceled if trading on the exchange is paused for any reason. Without it, a resting order can survive the pause and fill the moment trading resumes, possibly into a very different market.
Order groups: a built-in circuit breaker
An order group is a contract limit measured over a rolling 15-second window. You create the group with a limit from 1 to 1,000,000 contracts, and Kalshi returns its ID. You attach that ID to each order as order_group_id. As those orders fill, matched contracts add up over the trailing 15 seconds. If the total passes the limit, the group is triggered: every resting order in it is canceled and new orders in the group are rejected until you reset it.
A group also triggers if you call Trigger by hand, or if you lower the limit below the current rolling volume. Reset clears the counter. Delete removes the group and cancels its orders. For an automated strategy, one group per market or per strategy, with a limit a little above your normal 15-second size, means a bug that starts filling far more than intended stops on its own within seconds.
A sensible default setup for a 15-minute bot
-
Entries that take liquidity: IOC, priced at the worst price you accept, with
client_order_idset so a retried request cannot double-submit. -
Resting quotes: GTC with a short
expiration_time, pluspost_onlyonce you have tested its behavior on demo. -
Exits: IOC with
reduce_only: true. -
Everything: attached to an order group, and
cancel_order_on_pause: true. -
Every fill: log
average_fill_price,average_fee_paidand the engine timestampts_ms, so you can measure your real break-even against your win rate.
None of this makes a strategy profitable. It makes the orders do what you meant, which is the precondition for finding out whether the strategy works at all. Rate limits apply to all of these calls, and our Kalshi API rate limits and WebSocket guide covers how to stay inside them. If you are new to the API, start with the Kalshi API Python tutorial.
Where DeskBot fits
DeskBot is a trading assistant for Kalshi's short-dated crypto markets. It handles the order plumbing described above, including IOC entries, expiring quotes and fee-aware sizing, and shows the fee and break-even math before it trades. You choose the settings and stay in control of whether it places orders and how much it can spend. You can try DeskBot for $1: the first month is $1, then $19.99 a month, cancel anytime. Trading can lose money, and DeskBot does not promise profits.
FAQ
Does Kalshi have market orders?
Not as a separate type in the V2 order endpoint. Every order needs a price. To trade "at market," send an immediate-or-cancel order priced at the worst level you are willing to pay. Anything that cannot fill at that price or better is canceled, so you never pay more than you set.
What is the difference between IOC and FOK on Kalshi?
Immediate-or-cancel fills whatever it can right away and cancels the rest, so partial fills are possible. Fill-or-kill fills the whole count immediately or nothing at all.
How do I make a Kalshi order expire automatically?
Send time_in_force: good_till_canceled with an expiration_time as a Unix timestamp in seconds. "GTT" is not an accepted value, and IOC orders cannot carry an expiration time.
Is "buy No" the same as "sell Yes" on Kalshi?
Yes. Both give you No exposure. In the V2 endpoint both are side: ask quoted at the Yes price, so buying No at 44¢ is an ask at 0.56.
Does changing my order's price lose my place in line?
Yes. Per Kalshi's amend docs, changing the price or increasing the size moves the order to the back of the queue. Changing only the expiration or decreasing the size keeps its position.
What is a Kalshi order group?
A set of orders that share a contract limit over a rolling 15-second window. If fills in that window pass the limit, Kalshi cancels every resting order in the group and blocks new ones until you reset it.
Can I test order types without real money?
Yes. Kalshi runs a demo API at demo-api.kalshi.co with the same order endpoints. Paper fills there are not the same as live fills, so treat demo as a test of your code, not of your strategy.
Risk: Trading on Kalshi involves risk, and you can lose money. There are no guaranteed results, and past or paper results do not predict future results. DeskBot is independent software and is not affiliated with or endorsed by Kalshi. Order fields, fee rules and endpoint behavior described here came from docs.kalshi.com (Create Order V2, Amend Order V2, Get Order Queue Position, Order Groups, Order Direction and Fee Rounding pages) on October 24, 2026. The API changes, so check Kalshi's docs before you build on it.