There is no NO order. Buying NO at 40¢ is submitted as an ask at 60¢, displays as “Sell Yes”, and lands in your fills as a sale. Here is why, and how to account for it without breaking your P&L.
Every Kalshi market has two sides, and a YES contract plus a NO contract on the same market pay exactly $1.00 combined, always. That identity is the whole reason the API looks the way it does.
Because YES + NO = $1, owning a NO contract is identical to being short a YES contract. Not similar — identical, at every price, in every outcome:
buy NO at 40¢ == sell YES at 60¢
market resolves YES → NO pays 0 == bought back at 100, lose 40
market resolves NO → NO pays 100 == bought back at 0, gain 60
Since the two are the same position, the exchange only needs one book. It keeps the YES book, and expresses everything in terms of it. There is nothing to add.
The order takes a side of bid or ask
— not yes or no. To buy NO, you post an ask on the
YES book at the complement of your price:
want: buy NO at 40¢
submit: side = "ask", price = 0.60
displays: "Sell Yes 60¢"
The general rule is yes_price = 1.00 - no_price. Want NO at 22¢?
Post an ask at 78¢. Want NO at 5¢? Post an ask at 95¢.
The display quirk is harmless. The accounting one is not.
When that order fills, it arrives in your fills feed as a sale:
action = "sell"
outcome_side = "no"
Read only action and you will book a NO purchase as a YES sale, at
the complement price, in the wrong direction. Every downstream number — position
size, average cost, realised P&L — is then wrong, and wrong consistently
rather than randomly, which makes it much harder to notice.
Read both fields together and it resolves cleanly:
| action | outcome_side | What actually happened |
|---|---|---|
| buy | yes | Bought YES |
| sell | yes | Sold YES you held |
| sell | no | Bought NO — a new long position |
| buy | no | Closed a NO position you held |
Two other details worth knowing while you are in there. Fill counts come back as
count_fp and are fractional, so a dust fill of 0.02
contracts will pass a naive “greater than zero” test and look like a
completed trade. And orders are created at
POST /portfolio/events/orders — the older
/portfolio/orders path returns 410 deprecated_v1_order_endpoint,
which some clients swallow silently while continuing to log as though everything is fine.
Because buying NO is selling YES, you cannot buy both sides cheaply. The YES ask and the NO ask always sum to at least 100¢ — that is the same identity again, not a coincidence of liquidity. Any strategy premised on assembling a dollar for less than a dollar runs into it immediately.
That turns out to close off a larger family of ideas than it first appears. The proof is here, along with what happened when I tested it against 68 settled markets.