Orders
Market and limit orders, time in force, resting orders, cancellation, idempotency, and slippage capture.
POST /api/v2/portfolio/orders
| Field | Type | Required | Description |
|---|---|---|---|
ticker | string | yes | Kalshi ticker, or Polymarket slug / condition id / token id. |
action | string | yes | buy or sell. |
yes_no | string | yes | yes or no — the side you are buying or selling. |
count | integer | yes | Contracts. Polymarket markets enforce a minimum of 5. |
type | string | no | market (default), limit, stop, take_profit, or bracket. |
limit_price | number | limit only | Dollars in (0, 1) on the market's tick grid (Kalshi 0.01; Polymarket 0.01 or 0.001). |
time_in_force | string | no | GTC (default), IOC, or FOK. Limit orders only. |
expires_at | ISO-8601 | no | Auto-cancel time for GTC limit and conditional orders. |
trigger_price | number | stop/TP only | Trigger level for stop / take_profit. |
stop_price / take_profit_price | number | bracket only | The two legs of a bracket. |
client_order_id | string | no | 1–64 chars [A-Za-z0-9_-]. Idempotency key — see below. |
strategy | string | no | Free-form tag (≤64 chars) used by P&L attribution. |
venue | string | no | kalshi or polymarket. Auto-detected from the identifier when omitted. |
dry_run | boolean | no | Preview without writing anything (alias: preview). |
Market orders
A market buy walks the ask side of the live book from the best price up, accumulating a VWAP; a market sell walks the bids down. Fills are all-or-nothing against displayed depth: if the visible book cannot absorb your full count, the order is rejected with an insufficient-liquidity error rather than silently part-filling. Kalshi books are fetched at depth 20; Polymarket books are fetched in full.
Limit orders
A limit order executes its marketable portion immediately (every displayed level at or better than your limit, as a taker) and then, under GTC, rests the remainder. IOC cancels the remainder instead; FOK rejects the whole order unless it can fill completely at or better than the limit.
- Resting buys place a cash hold:
limit_price × remaining + worst-case taker fee, released as the order fills, cancels, or expires. Held cash is not spendable (reserved_balanceon responses). - Resting sells place a contract hold (
reservedContractson the position) so the same contracts cannot be sold twice. - Resting orders fill as MAKERS at your limit price when the displayed opposite side crosses it — checked by a matching loop that runs about once a minute. See Simulation vs. Reality for exactly what this does and does not model.
- Each maker fill creates a normal executed-order record (
resting_order_idlinks it back); the resting order tracksremaining_count,filled_count, andchild_order_ids. - Open resting orders are capped per tier (Free 5 / Starter 25 / Pro 100 / Enterprise 1000).
Order statuses
| Status | Meaning |
|---|---|
executed | Fully filled immediately (market, or fully marketable limit). |
partially_filled | Limit order: part filled as taker, remainder resting. |
resting | Resting on the book (or waiting on a trigger), nothing filled yet. |
filled | Resting order completely filled by maker executions. |
cancelled / expired | Removed before completion; terminal_reason says why (user_cancelled, order_expired, market_closed, oco_sibling_filled, position_closed, ...). |
Cancel and inspect
# Inspect any order (executed or resting)
curl https://predarena.org/api/v2/portfolio/orders/ORDER_ID \
-H "Authorization: Bearer $PREDARENA_API_KEY"
# Cancel a resting order (releases its cash/contract holds atomically)
curl -X DELETE https://predarena.org/api/v2/portfolio/orders/ORDER_ID \
-H "Authorization: Bearer $PREDARENA_API_KEY"Cancelling an already-executed order returns 410 Gone. Listing GET /api/v2/portfolio/orders returns executed orders, individual fills, and open resting_orders; pass ?status=resting for just the open book.
Idempotency with client_order_id
If an order with the same client_order_id already exists on the account (executed or resting), the API returns that original order with idempotent_replay: true instead of executing again — checked inside the same transaction that writes the order, so a retried request can never double-fill. Always set it from bots: network timeouts make retries inevitable.
Slippage capture
Every immediate execution records mid_price_at_execution (midpoint of best displayed bid/ask at fill time), slippage_per_contract (signed: positive = worse than mid), and slippage_cost. This is your ground truth for execution quality — the analytics endpoint aggregates it by order-size bucket so you can see exactly where size starts costing you.