---
title: "Get a single order by internal id"
method: GET
path: "/orders/{order_id}"
tags: ["Orders"]
---

# Get a single order by internal id

`GET /orders/{order_id}`

## Request

- Base URL: `https://execution.kairos.trade`
- URL: `https://execution.kairos.trade/orders/{order_id}`
- Auth: API key in header `X-Client-Id` and API key in header `X-Api-Key` and API key in header `X-Api-Secret`

Returns the full order row (including `raw`, the unredacted venue response, and `metadata`) for a single order the caller owns. Use this after `POST /orders` to poll a specific order's terminal state, or after `GET /orders` (which strips `raw`/`metadata`) to drill into one row.

## Path parameters

- `order_id` string, uuid, required

## Response `200`

The order, including `raw` and `metadata`.

- Order: Exchange-agnostic order record.
  - `id` string, uuid, required: Internal Kairos order id.
  - `user_id` string, required: Owning user's id.
  - `exchange_id` string, required: Venue identifier (e.g. `polymarket`, `kalshi`, `predictfun`, `hyperliquid`).
  - `market_id` string, required: Market/contract identifier on the venue (condition id for Polymarket; numeric HIP-4 outcome id for Hyperliquid).
  - `token_id` string, nullable: Outcome-token id. Hyperliquid uses a side coin such as `#1010` or `#1011`.
  - `side` 'buy' | 'sell', required: Order/intent side. Lower-case on the wire.
  - `kind` 'market' | 'limit', required: Order type. `market` orders still require a `price` (the limit you'll cross to); `limit` orders rest at `price` until filled or cancelled.
  - `quantity` string, required: Order quantity (decimal string, full precision), shares/contracts.
  - `price` string, nullable: Limit price as a decimal string in `[tick, 1]` (prediction-market venues).
  - `price_bps` integer, nullable: `price` expressed in basis points (price × 10000), for DB/analytics compatibility.
  - `time_in_force` 'GTC' | 'GTD' | 'FOK' | 'FAK' | 'IOC', required: Time-in-force, always UPPER-CASE on the wire. `GTC`/`GTD` are resting (limit-style); `FOK`/`FAK`/`IOC` are immediate taker executions.
  - `post_only` boolean: Whether this order was submitted maker-only. A post-only order is one the venue was told to REJECT rather than let cross the spread and take liquidity. Always present; `false` for ordinary orders and for venues with no post-only concept.
  - `expires_at` string, date-time, nullable: Expiration timestamp for GTD orders.
  - `filled_quantity` string, required: Cumulative filled quantity (decimal string).
  - `avg_fill_price` string, nullable: Size-weighted average fill price (decimal string, 0..1), null until any fill lands.
  - `avg_fill_price_bps` integer, nullable: `avg_fill_price` in basis points.
  - `exchange_order_id` string, nullable: Venue-assigned order handle. Null until the order reaches the venue.
  - `status` 'pending' | 'queued' | 'locked' | 'executing' | 'live' | 'partial' | 'filled' | 'cancelled' | 'expired' | 'failed' | 'orphaned', required: Lifecycle status. `partial` is the wire spelling of a partially-filled order (NOT `partially_filled`). The internal states `queued`, `locked` and `orphaned` are **persisted as `pending`**, so an order read back from `GET /orders` or `GET /orders/{order_id}` reports `pending` for all three — they are listed here because they are part of the type and can appear on in-process/streamed values. `executing` is the exception: once a worker claims the order for submission it is persisted as `executing`, and read-back endpoints report `executing` until the venue acknowledges (then `live`) or the attempt fails. The one place a caller sees `queued` directly is the `status` field of a fresh `POST /orders` response, which is the literal string `"queued"`.
  - `terminal_fill_verification` TerminalFillVerification
    - `state` 'pending' | 'complete', required
    - `exchange_order_id` string, required: Exact venue-order generation covered by the barrier.
    - `reason` 'explicit_cancel' | 'venue_absent', required
    - `target_status` 'cancelled' | 'expired', required
    - `started_at` string, date-time, required
    - `final_filled_quantity` string, nullable: Exact venue cumulative, including explicit `0`; required when state is complete.
    - `verified_at` string, date-time, nullable: Receipt completion timestamp; required when state is complete.
  - `created_at` string, date-time, required
  - `updated_at` string, date-time, required
  - `locked_by` string, nullable: Worker id currently holding the execution lock, if any.
  - `lock_expires_at` string, date-time, nullable
  - `error_message` string, nullable: Failure detail when `status` is `failed`.
  - `failure` OrderFailure: Structured failure detail attached to a `failed` order (`GET /orders`, `GET /orders/{order_id}`, and the `order_update` WebSocket event). OMITTED entirely (not `null`) when the order has no failure. `classification` is the **authoritative retry policy**: `expected_user_rejection` is a well-formed request the venue or the user's own inputs rejected — do not retry without changing the order; `retryable` is a transient condition that may succeed on retry; `non_retryable` cannot succeed by retrying the same order. `details.actions` is a **UI affordance only**. It is derived from `code` independently of `classification` and may include `retry` (even as `primary`) on a `non_retryable` failure, because the suggested buttons target an end user who may be able to change something first. Do NOT build an automatic retry loop from `actions`; branch on `classification`. A client that is not rendering buttons can ignore `actions` entirely.
    - `code` string, required: Machine-readable failure code. This is NOT the same namespace as `details.code`: `code` is the execution error's wire code (e.g. `FOK_NOT_FILLED`), while `details.code` is the `OrderErrorCode` used for incident grouping (e.g. `MARKET_FOK_NOT_FILLED`). For a venue `ExchangeError` the two coincide.
    - `classification` 'expected_user_rejection' | 'retryable' | 'non_retryable', required: Authoritative retry policy for this failure.
    - `details` OrderErrorDetails, required: Structured, machine-readable error payload shared across order-execution error responses.
      - `code` 'AUTH_CREDENTIALS_NOT_FOUND' | 'AUTH_CREDENTIALS_INVALID' | 'AUTH_POLICY_OUTDATED' | 'AUTH_INSUFFICIENT_SCOPE' | 'AUTH_POLYMARKET_API_KEY_INVALID' | 'AUTH_TURNKEY_WALLET_NOT_FOUND' | 'AUTH_TURNKEY_AUTH_FAILED' | 'AUTH_TURNKEY_SIGNING_FAILED' | 'VALIDATION_INVALID_ORDER' | 'VALIDATION_INVALID_PRICE' | 'VALIDATION_INVALID_SIZE' | 'VALIDATION_MARKET_NOT_FOUND' | 'VALIDATION_TOKEN_NOT_FOUND' | 'VALIDATION_ORDER_EXPIRED' | 'VALIDATION_MARKET_NOT_SETTLED_ON_CHAIN' | 'AUTH_IDENTITY_MISMATCH' | 'FUNDS_INSUFFICIENT_USDC' | 'FUNDS_INSUFFICIENT_GAS' | 'FUNDS_INSUFFICIENT_TOTAL' | 'FUNDS_INSUFFICIENT_BALANCE' | 'FUNDS_COLLATERAL_LOCATION' | 'ALLOWANCE_USDC_NOT_SET' | 'ALLOWANCE_CTF_NOT_SET' | 'ALLOWANCE_APPROVAL_FAILED' | 'NETWORK_RPC_ERROR' | 'NETWORK_TIMEOUT' | 'NETWORK_HTTP_ERROR' | 'NETWORK_ERROR' | 'EXCHANGE_POLYMARKET_API_ERROR' | 'EXCHANGE_POLYMARKET_UNAUTHORIZED' | 'EXCHANGE_POLYMARKET_MARKET_CLOSED' | 'EXCHANGE_POLYMARKET_RATE_LIMITED' | 'EXCHANGE_KALSHI_API_ERROR' | 'EXCHANGE_KALSHI_UNAUTHORIZED' | 'EXCHANGE_KALSHI_MARKET_CLOSED' | 'EXCHANGE_ERROR' | 'EXCHANGE_UNSUPPORTED' | 'SIGNATURE_EIP712_FAILED' | 'SIGNATURE_ERROR' | 'GAS_ESTIMATION_FAILED' | 'TRANSACTION_FAILED' | 'GAS_SPONSORSHIP_FAILED' | 'TRANSACTION_TIMEOUT' | 'MARKET_NOT_READY' | 'MARKET_PAUSED' | 'MARKET_INSUFFICIENT_LIQUIDITY' | 'ORDERBOOK_UNAVAILABLE' | 'MARKET_FOK_NOT_FILLED' | 'MARKET_ORDER_SIZE_EXCEEDS_MAX' | 'DATABASE_ERROR' | 'DATABASE_CREDENTIAL_DECRYPTION_FAILED' | 'INTERNAL_ERROR', required: Machine-readable error code, SCREAMING_SNAKE_CASE on the wire.
      - `message` string, required: Human-readable error message.
      - `details` string, nullable: Optional extended explanation.
      - `metadata` unknown
      - `actions` OrderErrorAction[], required: Zero or more actionable recovery steps a client can surface.
        - `action` 'enable_trading' | 'reenable_trading' | 'update_policies' | 'regenerate_api_key' | 'contact_support' | 'retry' | 'review_order' | 'adjust_price' | 'adjust_size' | 'browse_markets' | 'refresh_market' | 'create_new_order' | 'add_funds' | 'reduce_size' | 'swap_usdc' | 'add_matic' | 'approve_usdc' | 'approve_ctf' | 'retry_approval' | 'wait_and_retry' | 'check_status' | 'use_limit_order' | 'update_kalshi_credentials' | 'enable_bridge_funding', required: Machine-readable recovery-action identifier, snake_case on the wire.
        - `label` string, required: Human-readable button/link label.
        - `url` string, nullable
        - `primary` boolean, required: Whether this is the primary/recommended action.
  - `fee_amount` string, nullable: Fee charged for this order, decimal string.
  - `fee_currency` string, nullable
  - `client_order_id` string, nullable: Caller-supplied idempotency key, if one was provided at submission.
  - `wallet_id` string, nullable: FK to the user's wallet used for this order.
  - `outcome` string, nullable: Human-readable outcome label (e.g. "Yes", "No", a team name).
  - `outcome_id` string, nullable: Outcome id — equals `token_id` on Polymarket.
  - `trigger_price` string, nullable: Trigger price for stop-loss/take-profit style orders, decimal string.
  - `trigger_price_bps` integer, nullable
  - `gas_sponsored` boolean, required: Whether Kairos sponsored gas for this order (always `false` on the self-custody external-signing lane).
  - `collateral_mode` 'skip' | 'check' | 'fund', required: The collateral mode resolved for this order at submit. Always present; `skip` for an order that asked for nothing.
  - `shard_funding` boolean, required: Whether the Kalshi shard move was permitted for this order. Always present; `true` unless the caller opted out.
  - `max_bridge_fee_usdc` string, nullable: The order's bridge-fee ceiling in USDC, decimal string. Only ever set under `collateral_mode=fund`.
  - `max_funding_wait_ms` integer, nullable: The order's funding-wait ceiling in milliseconds. Only ever set under `collateral_mode=fund`.
  - `gas_amount` string, nullable: Gas spent, decimal string, if applicable.
  - `maker_address` string, nullable: On-chain maker/signer address, for Polymarket reconciliation.
  - `tx_hash` string, nullable: On-chain transaction hash (Polygon), if the fill involved one.
  - `raw` unknown
  - `bot_id` string, nullable: Trading-bot id that placed this order, if any (null for manual/API orders).
  - `source` string, nullable: Attribution for who initiated the order: `manual` (web UI), `bot`, `copytrade`, `api` (API-key auth), or `fastlane` (external-signing lane).
  - `metadata` unknown
  - `holding_wallet` string, required: On-chain wallet that holds (or will hold) the resulting shares — the EOA for legacy Polymarket orders, or the Safe deposit-wallet proxy for upgraded/external-signing users. Empty string for non-Polymarket orders.

## Other responses

- `400`: `order_id` is not a valid UUID (framework-level path rejection — plain-text body, not JSON).
- `401`: No valid credential presented — missing/invalid API-key headers or an invalid/expired session token.
- `403`: Order belongs to another user, missing `trade:read` scope, or API-key access to the order's provider is disabled. Empty body (status code only).
- `404`: No order with that id. Empty body (status code only).
- `500`: Database read failed. Empty body (status code only).
- `503`: API-key access to the order's provider could not be checked (access-cache read failed — fails closed). Empty body (status code only).

---

[API](https://skmtc.dev/kairos/apis/kairos-order-execution-api.md) - [All operations](https://skmtc.dev/kairos/apis/kairos-order-execution-api/llms.txt) - [OpenAPI document](https://skmtc.dev/kairos/apis/kairos-order-execution-api/revisions/9ba7d463d505?raw)
