> ## Documentation Index
> Fetch the complete documentation index at: https://docs.parlayx.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Kalshi

> Tickers, order controls, amend and decrease on Kalshi.

Kalshi is an account venue: an admin connects the venue credential at the
organization and ties it to a pod, and traders in that pod trade through the
tie. Submitting, amending, decreasing or cancelling an order needs a key with
the `trade` capability.

Every endpoint is listed under [Kalshi](/api-reference/kalshi/submit-order) in
the API reference. `@parlayx/sdk` and Python `parlayx` reach all of them
through `client.kalshi`.

## Addressing a market

`ticker` names the Kalshi market. A ticker is uppercase alphanumeric segments
joined by `-`, with `.` allowed inside a segment for a decimal strike:

```
^[A-Z0-9]+([.-][A-Z0-9]+)*$
```

`KXPRES-2028` and `KXBTCD-26AUG0607-T64599.99` are both well formed.

`side` picks the direction on that market's YES book. `BID` buys YES contracts
and profits if the market resolves YES. `ASK` sells them and profits if it
resolves NO. Selling YES and buying NO are the same order on Kalshi, so `ASK`
is how you do either.

A Kalshi listing from market discovery carries `bookSide`, the `side` that buys
its outcome.

> [!WARNING]
>
> Tickers are case sensitive and are not upcased for you. A ticker that does not
> match is refused with `400 INVALID_REQUEST` and no order is created.

A well-formed ticker naming a market the venue cannot resolve comes back
`404 NOT_FOUND`.

## Sizing and pricing

`count` is contracts and `price` is dollars per contract, both decimal strings.
`{ "count": "10", "price": "0.38" }` bids for ten contracts at 38 cents each.

Contracts trade in steps of 0.01, so `"2.50"` is a valid size. Prices go as fine
as \$0.0001, but each market sets its own grid of valid prices, and many quote
only whole cents. A price off the market's grid is refused with `400`, and never
moved to the nearest price the market does take.

`price` is always on the market's YES book, whichever direction you are trading.
To buy NO at 40 cents, send an `ASK` at `"0.60"`; to sell NO at 40 cents, send a
`BID` at the same price.

If you are coming from the previous `side` and `action` pair, the four
combinations map onto the two directions like this:

| Previously | Now | Price |
| - | - | - |
| `YES` + `BUY` | `BID` | as you sent it, so 38 becomes `"0.38"` |
| `NO` + `SELL` | `BID` | its complement, so 40 becomes `"0.60"` |
| `YES` + `SELL` | `ASK` | as you sent it |
| `NO` + `BUY` | `ASK` | its complement |

Every Kalshi order is a limit order. There is no order type field. An immediate
execution policy together with an aggressive price is how you ask for a market
order.

## Execution policy

| `timeInForce` | Behavior |
| - | - |
| Omitted or `{ "type": "GTC" }` | Rest until filled or cancelled. |
| `{ "type": "IOC" }` | Fill what is available now, cancel the rest. |
| `{ "type": "FOK" }` | Fill entirely or cancel. |
| `{ "type": "GTD", "expiresAt": "..." }` | Rest until the time you set. |

Three further controls shape a resting order. `postOnly: true` refuses the
order if it would cross the book instead of resting as a maker.
`cancelOrderOnPause: true` cancels the order if the exchange pauses trading
instead of leaving it resting. `selfTradePrevention` chooses which order is
cancelled when your order would trade against another order from the same
Kalshi account.

| Policy | Meaning |
| - | - |
| `TAKER_AT_CROSS` | Cancels the order you are placing, leaving the resting one on the book. |
| `MAKER` | Cancels the resting order and lets the order you are placing keep matching. |

`selfTradePrevention` defaults to `TAKER_AT_CROSS`.

> [!WARNING]
>
> `MAKER` names the order that is cancelled, not the one that is favoured. It
> removes your own resting quote. If the resting order is the one you want to
> keep, use `TAKER_AT_CROSS`, which cancels the incoming order instead.

## Submitting

A 201 means the order was accepted, not that the venue holds it. The `status` it
returns is the order's recorded state when the response was produced, so read the
order back to learn whether it rested or filled. A retry under the same idempotency
key returns the order it already created, carrying whatever state that order has
now. Read its fills for execution.

`filledCount` and `remainingCount` report what the venue said when it acknowledged
the order: contracts filled at that instant, and contracts left resting. Both read
null when there is no such acknowledgement to report, which covers a replay of an
order placed earlier and an outcome established by reading the order back, and when
the venue stated no count. Null is not zero, so treat it as unknown and read the
order for its current state.

`averagePrice` is what those filled contracts averaged, and it reads null when
nothing filled. It is on the market's YES book, like the `price` you sent, so nothing
stands between the two.

All three are decimal strings. Kalshi reports contract counts to a hundredth, a fill can be
fractional even when the order size was whole, and an average over fills at `"0.38"` and
`"0.39"` is `"0.384"` whatever limit you set. Parse them as decimals.

Retry an unresolved submission with the same `Idempotency-Key` and the same
body. A different key creates a different order.

[Batch Submit Orders](/api-reference/kalshi/batch-submit-orders) places up to 20
orders in one request, sent as `{ orders: [order, ...] }` under one
`Idempotency-Key` header that covers the whole batch. Resending the identical
batch under the same key reaches the same orders and places nothing twice. Each
order gets its own outcome, so one refused order does not fail the others. A
`200` means the batch was read, not that every order was placed, so check each
element of `orders`. Element `i` answers request entry `i`, including an entry
refused before submission, and carries the `clientOrderId` you sent (null if you
sent none or the entry was invalid). Each element is one flat record, the way
the venue's own batch receipt is: `orderId`, `status`, `filledCount`,
`remainingCount` and `averagePrice` beside `error`. Read `error` first:

| `error` | Meaning |
| - | - |
| null | The order was accepted, not confirmed at the venue, and is not a fill. A replayed entry reports the order's current state. `orderId` and `status` are set, and the three counts follow the same null rules as a single submission. |
| code `ORDER_RECONCILIATION_REQUIRED` | The outcome is unknown and the order may be live, so this is not proof that nothing was placed. `orderId` is set and `status` is null. Read the order back by `orderId` before retrying. |
| code `INTERNAL_ERROR` | The outcome is unknown and no order id is known, so this is not proof that nothing was placed. Resend the identical batch under the same `Idempotency-Key`. |
| any other code | This entry was refused and `error` carries the code and reason. `orderId`, `status` and the counts are null. |

Never resend a batch under a new `Idempotency-Key`, which places its orders a
second time. The key covers every order you sent, including the ones refused as
invalid. A key reused with a different batch is rejected with
`422 IDEMPOTENCY_CONFLICT`, and a missing or malformed key with `400`.

To fix a refused order, send only the corrected order as a new batch under a new
key. Resending the whole batch under a new key places the accepted orders again,
and any of them that carries a `clientOrderId` is refused as already in use
rather than placed twice.

`clientOrderId` is your own name for an order: at most 64 characters of letters,
digits, or `-` `_` `:` `/` `+` `=`. It is returned unchanged on every read of the
order and its fills. An order placed without one returns its `orderId` there
instead.

Each value may be used once and is never freed, including after the order carrying
it is filled or cancelled. A second order under a label already used is rejected
with `400 INVALID_REQUEST`.

The label reaches Kalshi, so it must be unique across everything trading under the
same Kalshi account, not only across your own orders. A label another trader on
that account has used is unavailable to you. Where several traders share an
account, give each one its own prefix, or use a generated id.

> [!NOTE]
>
> `clientOrderId` and `Idempotency-Key` answer different questions. The key
> answers whether this is the same request. The label answers which of your own
> quotes an order is.

A refusal you can act on comes back as a `4xx`: `400 INSUFFICIENT_BALANCE` for
an order larger than your available balance, `404 NOT_FOUND` for an unknown or
expired market, and `400 INVALID_REQUEST` for anything else, with the venue's
own explanation in `message`. A body carrying a field the request does not
define is rejected rather than stripped.

Kalshi holds a pod's cash separately for each Market Group, and an order can
only use the cash in its market's group. If that group has too little, the order
is refused with a message naming the group. An admin can move cash into the
group from Transfer Funds on the Platform.

See [Kalshi's exchange sharding guide](https://docs.kalshi.com/getting_started/exchange_sharding).

## Changing an order

[Amend Order](/api-reference/kalshi/amend-order) reprices or resizes a resting
order in place, keeping its id. Send the terms you want the order to hold, not
the change you want applied.

> [!WARNING]
>
> `count` on an amend is the order's already filled count plus the resting
> count you want after the amend, not the resting count on its own. An order
> that has filled 4 of 10 and should keep 2 contracts resting takes
> `count: 6`.

An amend to the terms the order already holds answers `200` with the order
unchanged. Both responses carry `previous`, the price and count the order held
before the call.

[Decrease Order](/api-reference/kalshi/decrease-order) reduces a resting order
to an absolute `remainingCount`. A `remainingCount` naming more contracts than
the order has resting is refused with `400`, and so is `0`. Cancel the order
instead.

Either route answers `409` when the order cannot be changed from its current
state. A `503` means the venue's outcome is unknown, and an amend can cross and
fill, so read the order before retrying.

## Cancelling

[Cancel Order](/api-reference/kalshi/cancel-order) cancels by the issued order
id. A `409` carrying `ORDER_NOT_CANCELLABLE` means the order cannot be
cancelled from its current state, most often because it is still being placed
and has no venue order yet. Read the order and retry once it reports a
`venueOrderId`.

A `503` means the cancel did not complete. It carries `INTERNAL_ERROR`, the
same code a `500` carries, so branch on the status rather than the code, and
bound any retry rather than repeating indefinitely.

[Cancel Orders](/api-reference/kalshi/cancel-all-orders) cancels the eligible
orders placed by the signing key's owner, optionally narrowed with `ticker`.
`cancelled` lists the orders whose remaining quantity was confirmed cancelled,
and `notCancelled` names each of the rest with a reason:

| Code | Meaning |
| - | - |
| `STILL_SUBMITTING` | The order has no venue id yet. Retry once it reports one. |
| `ALREADY_COMPLETED` | The order had already reached a terminal state. |
| `UNCONFIRMED` | The outcome is undetermined. Read the order. |

When `nextPageToken` is present, send it back with the same `ticker` to
continue through the orders the request did not reach.

## Reading orders and fills

Orders and fills report `yesPrice` and `noPrice` in dollars per contract.
`noPrice` is exactly one minus `yesPrice`. Orders also report
`averageYesPrice` and `averageNoPrice`, both null before any fill.

`outcomeSide` names the order's economic direction: `YES` for `BID`, `NO`
for `ASK`. Fills carry their parent order's direction. An `ASK` can close an
existing YES holding, so this field does not describe the resulting position.
`side` remains the book direction and the order request is unchanged.

The read fields `price` and `averagePrice` are deprecated aliases for
`yesPrice` and `averageYesPrice`. They retain their existing values.

An order placed with an immediate policy, `IOC` or `FOK`, reports `SUBMITTED`
while it is live at the venue rather than `OPEN`. It has no remainder that can
rest, so it is not cancellable. `OPEN` means resting and cancellable.

`filledCount`, `averagePrice`, `feesCents` and `feesUsd` read null before
the first fill. A submit response reports the counts at acknowledgement instead
(see [Submitting](#submitting)), so an order that has not filled can read `0` there
and null on a read. `feesCents` is a rounded render of `feesUsd` and the two round
independently, so summing an order's fills can differ from the order's own total
by a cent. Reconcile on `feesUsd`.
[Get Order Fills](/api-reference/kalshi/get-order-fills) returns the fills
oldest first, each with its own count, price and fee.

`queuePosition` on [Get Order](/api-reference/kalshi/get-order) is a
diagnostic: a decimal string counting the Kalshi contracts ahead of the order
in price-time priority, with `"0.00"` meaning none. It is a snapshot, and
guarantees neither execution order nor fill timing.

[List Order Queue Positions](/api-reference/kalshi/list-order-queue-positions)
returns the same figure for a page of your resting orders in one call, up to 100
at a time.

> [!NOTE]
>
> `null`, or an absent field, means unknown rather than none. Order list, amend,
> decrease and cancel responses return null, a submit response omits the field,
> and the other venues' order views return null too.

## Positions and balance

Positions report `averageYesPrice`, `averageNoPrice`, `yesMark` and `noMark`
as decimal dollar strings. Each NO price is exactly one minus its YES price,
and is null when the corresponding YES price is unavailable. `averagePrice`
and `mark` are deprecated aliases for `averageYesPrice` and `yesMark`, with
unchanged values. Signed `contracts`, `valueUsd` and `unrealizedPnlUsd` retain
their existing meaning.

[List Positions](/api-reference/kalshi/list-positions) keys a position by
ticker alone, because Kalshi nets a market into one holding: buying the no side
offsets a yes holding rather than opening a second position. `contracts` is a
decimal string on the market's yes side, and its sign is what says which way the
holding leans. Positive is long yes; negative is long no, which is the same
holding as short yes. It is a decimal because contracts trade in steps of 0.01,
so a holding of `"2.63"` is ordinary.

`averagePrice` and `mark` are dollar strings from 0 to 1 on that same yes side,
the same frame you submit a `price` in. They are not rounded to a whole cent:
Kalshi sets its tick size per market and bands it within one market, so many
markets quote in tenths of a cent and a whole-cent figure is not a price those
books can take. `averagePrice` reads null when the holding has no single entry
price, and `mark` reads null when no fresh price is available. `valueUsd` and
`unrealizedPnlUsd` are dollar strings composed from those two figures, and read
null when a price they need is null.

The listing carries open rows only. A market that settles drops out of it
rather than turning settled, so a row that disappears is not a loss.

On [Get Balance](/api-reference/kalshi/get-balance), `available` is the account
cash you can place orders against, in USD, with cash committed to your resting
buy orders already excluded. Kalshi's own reported balance still contains that
cash, so sizing against the venue's figure oversizes.

> [!WARNING]
>
> A balance that could not be read fresh from the venue returns `503`. Do not
> treat that response as zero. A `404` means the pod has no Kalshi account
> connected, or its connection needs reconnecting.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.