---
title: "Create Complex Order"
method: POST
path: "/v1/complex-orders"
tags: ["complex-orders"]
---

# Create Complex Order

`POST /v1/complex-orders`

Create a new complex order (conditional or iceberg).

Provide exactly one of `conditional_order_params` (TP/SL/STOP) or
`iceberg_order_params`. The body shape determines the complex_order_type.

Returns 202 Accepted with the persisted complex order in PENDING status,
enqueued for activation by the appropriate consumer service.

## Request body

- ComplexOrderCreateRequest — Request body for creating a complex order. Provide exactly one of `conditional_order_params` (TP/SL/STOP) or `iceberg_order_params` (iceberg). The active param block determines the complex_order_type.
  - `subaccount_id` string, uuid, required — Subaccount to create the order under
  - `river_id` integer, nullable — Instrument ID. Mutually exclusive with generic_asset_id.
  - `generic_asset_id` string, uuid, nullable — Generic asset basket ID. Mutually exclusive with river_id.
  - `conditional_order_params` ConditionalOrderCreate — Schema for a conditional order (take profit or stop loss) attached to a parent order.
    - `conditional_order_type` 'TP' | 'SL' | 'STOP' | 'REVERSE_STOP', required — Type of conditional order: TP (take profit), SL (stop loss), or STOP
    - `stop_order_price` number, nullable — Activation price for STOP conditional orders. This is the price at which the conditional order triggers and places the trigger_order.
    - `trigger_order` TriggerOrder, required — The order that will be sent to the exchange when the conditional order's condition is met. For TP/SL: the parent order fills → the conditional activates → this trigger order is placed. For STOP/REVERSE_STOP: the stop_order_price is reached → this trigger order is placed.
      - `order_type` 'LIMIT' | 'MARKET' | 'RFQ_TAKER', required — Order type for the triggered order: 'LIMIT' or 'MARKET'
      - `qty` number, required — Quantity (number of contracts) for the triggered order
      - `price` number, nullable — Limit price for the triggered order (between 0 and 1). Required when order_type is LIMIT.
      - `buy_flag` boolean, required — Direction of the triggered order: true=buy, false=sell
      - `stop_order_price` number, nullable — Price at which the triggered order activates as a stop or reverse stop. Required for SL (stop trigger) and TP MARKET (reverse stop trigger). For SL: triggers when price moves against you. For TP MARKET: triggers when price moves in your favor.
    - `parent_river_order_id` string, uuid, nullable — Parent order ID (required for TP and SL)
    - `parent_complex_order_id` string, uuid, nullable — Parent complex order ID (for chaining)
  - `iceberg_order_params` IcebergOrderParams — Parameters for creating an iceberg complex order. An iceberg's `total_qty` is split into sequential `displayed_qty` tranches posted at the same `limit_price`. When a tranche fully fills, the next is placed automatically until the total is exhausted or the iceberg is cancelled.
    - `buy_flag` boolean, required — Direction: true=buy, false=sell
    - `total_qty` number, required — Total iceberg quantity (across all tranches)
    - `displayed_qty` number, required — Tranche size — quantity shown to the market at any moment
    - `limit_price` number, required — Static limit price for every tranche (between 0 and 1)
    - `post_only` boolean — If true, every tranche is posted as post-only (maker-only)
    - `cancel_order_on_pause` boolean — Kalshi only: if true, resting tranches are cancelled by the exchange when it enters a trading pause. Ignored on other venues.
    - `reload_delay_s` integer, nullable — Optional delay between a tranche fully filling and the next one being placed, in seconds. NULL or 0 = place next tranche immediately.
    - `expiry_ts_utc` string, date-time, nullable — Optional expiry timestamp in UTC (ISO 8601). When set, every tranche is submitted to the venue as GTD with this expiry; venue-side expiry of a tranche cascades to cancel the parent iceberg.
  - `peg_order_params` PegOrderParams — Parameters for creating a peg complex order. A peg's child limit order rests on the venue at the current best bid (for buys) or best ask (for sells), clamped to the absolute band [min_price, max_price]: the child never rests below min_price or above max_price. Both bounds are optional — an unset min floors at 0, an unset max ceils at 1. The peg worker repegs the child as the top of book moves.
    - `buy_flag` boolean, required — Direction: true=buy, false=sell
    - `total_qty` number, required — Total peg quantity
    - `min_price` number, nullable — Price floor — the child never rests below this (between 0 and 1)
    - `max_price` number, nullable — Price ceiling — the child never rests above this (between 0 and 1)
    - `post_only` boolean — If true, the resting child order is posted as post-only; a repeg that would cross the book cancels the peg instead of taking liquidity
    - `expiry_ts_utc` string, date-time, nullable — Optional expiry timestamp in UTC (ISO 8601). When set, the resting child is submitted to the venue as GTD with this expiry; venue-side expiry cancels the peg (caught by the periodic reconciliation sweep).
    - `peg_min_stay_time_s` integer, nullable — Optional repeg gate. When set, a price-driven repeg is suppressed until the resting child has been on the book for at least this many seconds (measured from send time). Expiry-driven cancels are unaffected.
    - `max_qty_level` number, nullable — Penny-jump threshold (contracts). If the level the peg would join holds more than this many contracts, rest one tick tighter instead (if not crossing the book and not already quoting the level). Unset to disable.
  - `smart_taker_order_params` SmartTakerOrderParams — Parameters for creating a smart-taker complex order. A smart-taker rests nothing on the book. It watches the opposite side and fires an IOC sweep (at `limit_price`, for the full remaining qty) whenever at least `min_qty` of acceptable liquidity (price within `limit_price`) is resting on the book — amortising taker fee/spread and refusing to cross into a thin book.
    - `buy_flag` boolean, required — Direction: true=buy, false=sell
    - `total_qty` number, required — Total quantity to acquire/offload across all IOC clips
    - `limit_price` number, required — Worst price the taker will accept — max for buy, min for sell (between 0 and 1)
    - `min_qty` number, required — Book-depth trigger gate: only fire when at least this much acceptable liquidity sits within limit_price on the opposite side. A depth floor, not a per-clip fill floor — it may exceed total_qty (e.g. 'take my 100 only when >=500 is resting') and an IOC may fill less if liquidity vanishes mid-flight.
    - `expiry_ts_utc` string, date-time, nullable — Optional expiry timestamp in UTC (ISO 8601). Once it passes, the order stops firing and is torn down by the periodic reconciliation sweep.

## Response `202`

Successful Response

- ComplexOrderCreateResponse — Schema for a complex order response (unified across all complex order types).
  - `complex_order_id` string, uuid, required — Unique complex order identifier

## Other responses

- `422` — Validation Error

---

[API](https://skmtc.net/rivermarkets/apis/river-finance-api.md) · [All operations](https://skmtc.net/rivermarkets/apis/river-finance-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/rivermarkets/river-finance-api/revisions/3776a0431319/schema)
