Submit a new order
Submits a custodial order: Kairos signs and routes it to the venue on the caller's behalf (custodial signing). This is the standard order-entry path used by both the web app and API-key consumers who have not been allow-listed onto the self-custody "external-signing" lane (POST /v2/orders/intent + POST /v2/orders/submit). Ownership. The order is always created for the authenticated caller; any user_id in the body is accepted for backwards compatibility but is ignored — the JWT/API-key identity wins. Ack semantics (async). A 200 response means the order was validated, persisted, and enqueued — it does NOT mean the order is live on the venue yet. The response status is "queued" (or, on an idempotent replay, the current status of the previously-created order). Track the order via GET /orders/{order_id}, GET /orders polling, or (lowest latency) the /ws socket, which pushes order_update / fill events as the worker submits to the venue and fills arrive. Idempotency. Pass client_order_id to make retries safe: a second submit with the same (user, exchange_id, market_id, client_order_id) tuple returns the existing order instead of creating a duplicate, and does not consume a rate-limit slot. If omitted, the server generates a random one (i.e. retries without a client-supplied id are NOT deduped). Provider routing. exchange_id selects the venue-specific executor (polymarket, kalshi, predictfun, opinion, hyperliquid, …; kalshi_offchain is a deprecated alias of kalshi). Each venue advertises its own capabilities (supported time_in_force values, max price, order types) — a request that is well-formed in general but unsupported by the specific venue is rejected with 400 EXCHANGE_UNSUPPORTED / 400 VALIDATION_INVALID_ORDER. Hyperliquid HIP-4. Use the numeric outcome id as market_id, the selected display label as outcome, and the side coin from the market-data OrderbookSnapshot.token_ids as token_id (for example #1010 or #1011). Quantities are whole shares. Hyperliquid maps GTC/GTD to venue GTC and IOC/FAK/FOK to venue IOC. Single-order and selected-order batch cancellation are supported; cancel-all and fee quotes are unavailable. Order types. kind="market" is a marketable taker order — pair it with time_in_force FOK (fill-or-kill) or FAK/IOC (fill-and-kill / immediate-or-cancel, partials allowed, remainder cancelled). kind="limit" is a resting quote — pair it with GTC (good-til-cancelled) or GTD (good-til-date, requires expiration_minutes). price is REQUIRED for every order, including market orders — for a marketable order it is the limit you are willing to cross to, not a market-price sentinel. Circuit breakers & gating. Before persisting, the order passes through, in order: the per-user order rate limit, size/price bounds, the venue time-in-force capability gate, a global + per-exchange execution kill-switch, the custodial trading-enabled check, the post-only capability gate, side/kind/TIF-specific breakers, and the API-key minimum-notional rule. Kill-switch and restriction rejections are 503 with error_details.code = MARKET_PAUSED; a disabled or identity-less account is 403 with AUTH_CREDENTIALS_INVALID. Designated canary users bypass both breaker checks. Rate limiting. A Redis sliding-window limiter caps order submissions per authenticated user (default 5 orders per second, ORDER_RATE_LIMIT_PER_SEC). API keys with an orders override are checked against BOTH their own per-credential window and the aggregate per-user window (either denying is a 429); idempotent replays are resolved before the limiter and never consume a slot. The limiter fails closed — an unreachable Redis denies with 429. The 429 body carries error_details.code = VALIDATION_INVALID_ORDER with the message Order rate limit exceeded (there is no dedicated rate-limit code on this path), and no Retry-After header. Auth & scope. Requires trade:execute. This mutation endpoint is additionally gated by a service-token/CSRF/API-key check (RequireServiceToken), which any request bearing X-Client-Id / X-Api-Key / X-Api-Secret satisfies automatically — no extra header is needed for API-key consumers.
Request
- Base URLhttps://execution.kairos.trade
- AuthAPI key in header X-Client-Id and API key in header X-Api-Key and API key in header X-Api-Secret
Request body
Example request
{
"exchange_id": "polymarket",
"outcome": "Yes",
"side": "buy",
"kind": "limit",
"quantity": "100",
"price": "0.52",
"time_in_force": "GTC",
"expiration_minutes": 60,
"collateral": "skip",
"shard_funding": true,
"max_bridge_fee_usdc": "1.50",
"max_funding_wait_ms": 30000,
"max_slippage_cents": 5,
"source": "api"
}Response
Order accepted, persisted, and enqueued for execution. Does not imply the order is live on the venue yet — poll or subscribe to /ws for the terminal state.
Example response
{
"status": "queued"
}Changes
No recorded changes to this operation across all 1 revision of this API.