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

# Create Complex Order

> 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.



## OpenAPI

````yaml /openapi.json post /v1/complex-orders
openapi: 3.1.0
info:
  title: River Markets API
  description: >+
    # Getting Started



    River Markets provides users with a unified prime brokerage interface for
    prediction markets, including

    - Liquidity aggregation

    - Order routing

    - Market and data search


    This API guide will help you get up and running quickly.


    ## Concepts


    ### River IDs


    Every market across all exchanges is assigned a unique **River ID** - a
    unified identifier that works across our entire platform. This allows you
    to:


    - Reference the same market consistently regardless of which exchange it
    trades on

    - Place orders using a single identifier format

    - Track positions and fills across exchanges with one ID


    When searching for markets, the API returns both the exchange-native
    identifier (e.g., Kalshi ticker, Polymarket slug) and the River ID. Use the
    River ID when placing orders.


    ### Subaccounts


    **Subaccounts** let you organize your trading activity into separate
    containers. Each subaccount:


    - Has its own set of exchange credentials

    - Maintains separate positions and order history

    - Can represent different strategies, clients, or portfolios


    This is useful for:

    - **Fund managers**: Segregate client portfolios

    - **Traders**: Separate strategies (e.g., momentum vs. mean reversion)

    - **Teams**: Give team members isolated trading environments


    ## 1. Create an Account


    Sign up at [app.rivermarkets.com](https://app.rivermarkets.com) to create
    your account.


    ## 2. Generate an API Key


    1. Log in to your dashboard

    2. Navigate to **Settings → API Keys**

    3. Click **Create API Key**

    4. Copy and securely store your key - it will only be shown once


    ## 3. Install required packages


    ```python

    pip install requests

    ```


    ## 4. Make Your First Request


    Test your API key by searching for markets.


    We support ticker (kalshi ticker, polymarket condition_id/slug, river_id)
    and fuzzy search ('bitcoin', 'fed rates').


    > **Using the SDK?** `rivermarkets` (Python) 

    > handle request signing for you — pass your `KEY_ID` and `PRIVATE_KEY` to
    the

    > client constructor and forget about the rest of this section. The raw
    example

    > below is for anyone integrating without an SDK.


    ```python

    import base64, hashlib, time

    from urllib.parse import urlsplit, urlencode, parse_qsl, quote

    from nacl.signing import SigningKey

    import requests


    KEY_ID = "<uuid from Settings → API Keys>"

    PRIVATE_KEY_B64 = "<base64 private key shown once at creation>"

    BASE_URL = "https://api.rivermarkets.com/v1"


    signing_key = SigningKey(base64.b64decode(PRIVATE_KEY_B64))



    def sign(method: str, url: str, body: bytes = b"") -> dict:
        parts = urlsplit(url)
        # quote_via=quote encodes spaces as %20 to match RFC 3986 / the server.
        sorted_q = urlencode(sorted(parse_qsl(parts.query, keep_blank_values=True)), quote_via=quote)
        ts = str(int(time.time()))
        canonical = "\n".join([
            method.upper(), parts.path, sorted_q, ts, hashlib.sha256(body).hexdigest(),
        ]).encode()
        sig = signing_key.sign(canonical).signature
        return {
            "X-River-Key-Id": KEY_ID,
            "X-River-Timestamp": ts,
            "X-River-Signature": base64.b64encode(sig).decode(),
        }


    url = f"{BASE_URL}/markets/search?q=shutdown&exchange=POLYMARKET"

    response = requests.get(url, headers=sign("GET", url))

    for market in response.json()["results"]:
        print(f"River ID: {market['river_id']}, Ticker: {market['slug']}")
    ```


    ## 5. Set Up a Subaccount


    River allows users to setup subaccounts - which allow them to manage
    different trading strategies or client portfolios.


    These can be added through the UI by going to Settings -> Subaccounts

    or programatically.


    ### Video Walkthrough


    Watch this tutorial to see how to create a subaccount, add a Polymarket
    account, and place your first trade:


    <div style="position: relative; padding-bottom: 54.37499999999999%; height:
    0;"><iframe
    src="https://www.loom.com/embed/9b49e269c09e436d98b72f3cb55d7691"
    frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen
    style="position: absolute; top: 0; left: 0; width: 100%; height:
    100%;"></iframe></div>


    ### Programmatic Setup 


    ```python

    # Create a subaccount

    response = requests.post(
        f"{BASE_URL}/subaccounts",
        headers=headers,
        json={"name": "My Trading Account"}
    )

    subaccount = response.json()

    subaccount_id = subaccount["id"]

    ```


    ## 6. Add Exchange Credentials


    Exchange credentials can also be added via UI under Settings -> Subaccounts,

    or programatically as shown below.


    For best results, we recommend

    - Polymarket : create an account using email (not a wallet) and get your
    wallet and PK directly from Polymarket under [Settings -> Export Private
    Key](https://polymarket.com/settings)

    - Kalshi : create a secret/key pair with Read/Write access under [Settings
    -> Account & security -> API keys](https://kalshi.com/account/profile)


    ```python

    # Add Polymarket credentials

    response = requests.post(
        f"{BASE_URL}/credentials",
        headers=headers,
        json={
            "subaccount_id": subaccount_id,
            "exchange": "polymarket",
            "wallet_address": "your_polymarket_wallet_address",
            "private_key": "your_polymarket_private_key"
        }
    )

    # Add Kalshi credentials

    response = requests.post(
        f"{BASE_URL}/credentials",
        headers=headers,
        json={
            "subaccount_id": subaccount_id,
            "exchange": "kalshi",
            "api_key": "your_kalshi_api_key",
            "api_secret": "your_kalshi_secret"
        }
    )

    ```


    We use asymmetric encryption so your credentials are not transferred between
    services or stored in plain text.

    We delete your credentials when you delete a subaccount. 


    ## 7. Place Your First Order


    Use the River ID from your market search to place an order.


    ```python

    # Place a limit order (buy 10 contracts at $0.50)

    response = requests.post(
        f"{BASE_URL}/orders",
        headers=headers,
        json={
            "subaccount_id": subaccount_id,
            "river_id": 4552150,       # From market search
            "order_type": "LIMIT",      # LIMIT or MARKET
            "time_in_force": "GTC",     # FOK, GTC, GTD, or IOC
            "buy_flag": True,           # True=buy, False=sell
            "price": 0.50,              # Limit price (0-1)
            "qty": 10,                  # Number of contracts
        }
    )

    order = response.json()

    print(f"Order placed: {order['river_order_id']}")

    ```


    ## 8. Check Order Status


    Monitor your order's progress by fetching its current state.


    ```python

    # Get order status

    order_id = order['river_order_id']

    response = requests.get(
        f"{BASE_URL}/orders/{order_id}",
        headers=headers
    )

    order_status = response.json()

    print(f"Status: {order_status['status']}, Filled:
    {order_status['traded_qty']}/{order_status['qty']}")

    ```


    Possible order statuses:

    - `pending_submission` - Order received, awaiting processing

    - `resting` - Order live on the exchange (may include partially-filled live
    orders)

    - `filled` - Terminal: order fully executed

    - `partially_filled` - Terminal: order cancelled with some quantity filled

    - `cancelled` - Terminal: order cancelled with no fills

    - `rejected` - Order rejected (see `reject_reason`)


    ## 9. Cancel an Order


    Cancel a resting order before it's fully filled.


    ```python

    # Cancel an order

    order_id = order['river_order_id']

    response = requests.delete(
        f"{BASE_URL}/orders/{order_id}",
        headers=headers
    )

    if response.status_code == 200:
        print("Order cancelled successfully")
    ```


    Note: Only orders with status `pending_submission` or `resting` can be
    cancelled (`partially_filled` is terminal).


    ## Supported Exchanges


    | Exchange | Markets | Status |

    |----------|---------|--------|

    | Kalshi | US regulated prediction markets | Available |

    | Polymarket | Crypto prediction markets | Available |

    | Polymarket US | US regulated prediction markets | Available |

    | Novig | US regulated prediction markets | Coming soon |

    | Rothera | US regulated prediction markets | Future integration |


    ## Rate Limits


    - **Standard**: 10 requests/second

    - **Premium**: Contact support for higher limits




    ## Authentication


    All endpoints require authentication via one of:

    - **Bearer Token**: `Authorization: Bearer <jwt_token>` (for web clients)

    - **Signed Request** (programmatic access): three headers per REST request,
    or
      three query params on the WebSocket handshake.

    > **Using the SDK?** `rivermarkets` (Python) 

    > sign every REST request and WS handshake for you. You only need the raw

    > recipes below if you're integrating without an SDK.


    ### REST signing


    Send three headers on every request:

    - `X-River-Key-Id`: UUID of your API key

    - `X-River-Timestamp`: current unix seconds (must be within 30s of server
    time)

    - `X-River-Signature`: base64 Ed25519 signature over the canonical request


    The REST canonical string is LF-joined:

    ```

    METHOD\nPATH\nSORTED_QUERY\nTIMESTAMP\nSHA256(body) hex

    ```


    ```python

    import base64, hashlib, time

    from urllib.parse import urlsplit, urlencode, parse_qsl, quote

    from nacl.signing import SigningKey


    signing_key = SigningKey(base64.b64decode(PRIVATE_KEY_B64))


    def sign(method: str, url: str, body: bytes = b"") -> dict:
        parts = urlsplit(url)
        # quote_via=quote encodes spaces as %20 to match RFC 3986 / the server.
        sorted_q = urlencode(sorted(parse_qsl(parts.query, keep_blank_values=True)), quote_via=quote)
        ts = str(int(time.time()))
        canonical = "\n".join([
            method.upper(), parts.path, sorted_q, ts, hashlib.sha256(body).hexdigest(),
        ]).encode()
        sig = signing_key.sign(canonical).signature
        return {
            "X-River-Key-Id": KEY_ID,
            "X-River-Timestamp": ts,
            "X-River-Signature": base64.b64encode(sig).decode(),
        }
    ```


    ### WebSocket signing


    Browsers can't set custom headers on the WS upgrade, so the same three
    values

    move to query params: `?key_id=&ts=&sig=`. The WS canonical string omits the

    body hash and uses the literal `"WS"` as the method:

    ```

    WS\nPATH\nSORTED_QUERY (excluding key_id/ts/sig)\nTIMESTAMP

    ```


    ```python

    import asyncio, base64, time

    from urllib.parse import urlencode, quote

    import websockets

    from nacl.signing import SigningKey


    signing_key = SigningKey(base64.b64decode(PRIVATE_KEY_B64))



    def sign_ws(path: str, extra_params: dict | None = None) -> str:
        """Return a fully-formed wss:// URL with signing query params appended."""
        params = dict(extra_params or {})
        sorted_q = urlencode(sorted(params.items()), quote_via=quote)
        ts = str(int(time.time()))
        canonical = "\n".join(["WS", path, sorted_q, ts]).encode()
        sig = base64.b64encode(signing_key.sign(canonical).signature).decode()
        params.update({"key_id": KEY_ID, "ts": ts, "sig": sig})
        return f"wss://api.rivermarkets.com{path}?{urlencode(params)}"


    async def stream_orders(subaccount_id: str):
        url = sign_ws("/v1/ws/orders", {"subaccount_id": subaccount_id})
        async with websockets.connect(url) as ws:
            async for frame in ws:
                print(frame)


    asyncio.run(stream_orders("411b3f8c-85f9-41c9-90b7-3ff6d74efc4f"))

    ```


    ### Security notes


    - Your private key never traverses the wire. Generate a keypair at
      `Settings → API Keys`; the private key is shown once.
    - Same signature cannot be submitted twice within 60 seconds (replay
    protection).
      On network retries, re-sign with a fresh timestamp.
    - Timestamps must be within 30s of server time. Sync your clock via NTP.



    ---




    # Order Types Documentation


    Complete guide to all order types available in the River Markets trading
    platform.


    ---


    ## Basic Order Types


    ### Market Order

    Executes immediately at the best available price.

    - **Use case**: When you need immediate execution and price is less
    important

    - **Example**: Market buy 100 contracts → fills at current best ask price


    ### Limit Order

    Rests on the order book at a specified price.

    - **Use case**: When you want price control and can wait for execution

    - **Example**: Limit buy 100 @ $0.65 → only fills at $0.65 or better


    ---


    ## Conditional Order Types


    Conditional orders are **not placed immediately**. They activate ("trigger")
    when specific conditions are met.


    ### 1. Stop Orders (STOP)


    **Stop orders trigger when price moves AGAINST your desired direction.**
    Used primarily for **stop losses** (exit protection) or **breakout
    entries**.


    #### Stop Market

    - **Triggers**: When market trades at or through your stop price

    - **Executes**: As a market order (immediate fill at best available price)

    - **Example**:
      ```
      You're LONG at $0.70, want to exit if price falls to $0.60
      → Stop Market SELL @ $0.60
      → Triggers when price ≤ $0.60
      → Sends market sell order → fills immediately
      ```

    #### Stop Limit

    - **Triggers**: When market trades at or through your stop price

    - **Executes**: As a limit order at your specified limit price

    - **Example**:
      ```
      You're LONG at $0.70, want to exit around $0.60 but not worse than $0.59
      → Stop Limit SELL @ $0.60, Limit $0.59
      → Triggers when price ≤ $0.60
      → Sends limit sell order @ $0.59 → waits for fill at $0.59 or better
      ```
    - **Risk**: May not fill if price moves too fast through your limit


    **Directional Logic:**

    - **BUY stop**: Triggers at or **above** stop price (breakout entry or short
    exit)

    - **SELL stop**: Triggers at or **below** stop price (stop loss or long
    exit)


    ---


    ### 2. Reverse Stop Orders (REVERSE_STOP)


    **Reverse stop orders trigger when price moves IN your desired direction.**
    Used exclusively for **take profit** scenarios.


    **Key Concept**: A "reverse stop" is called "reverse" because it triggers in
    the OPPOSITE direction of a normal stop order.


    #### Reverse Stop Market (TP Market)

    - **Triggers**: When market trades at or through your target price (OPPOSITE
    direction from normal stop)

    - **Executes**: As a market order

    - **Example**:
      ```
      You're LONG at $0.60, want to take profit if price rises to $0.80
      → TP Market (Reverse Stop Market) SELL @ $0.80
      → Normal stop would trigger BELOW, but reverse stop triggers ABOVE
      → Triggers when price ≥ $0.80
      → Sends market sell order → fills immediately
      ```

    **Directional Logic (REVERSED from normal stop):**

    - **BUY reverse stop**: Triggers at or **below** target (opposite of normal
    buy stop)

    - **SELL reverse stop**: Triggers at or **above** target (opposite of normal
    sell stop)


    **Why "reverse"?**

    - Normal **SELL stop** @ $0.60 triggers when price ≤ $0.60 (price falling)

    - **SELL reverse stop** @ $0.80 triggers when price ≥ $0.80 (price rising)

    - The trigger direction is reversed!


    #### Reverse Stop Limit (TP Limit)

    - **Triggers**: When market trades at or through your target price

    - **Executes**: As a limit order at your specified limit price

    - **Example**:
      ```
      You're LONG at $0.60, want to take profit around $0.80 but not worse than $0.79
      → TP Limit (Reverse Stop Limit) SELL @ $0.80, Limit $0.79
      → Triggers when price ≥ $0.80
      → Sends limit sell order @ $0.79 → waits for fill at $0.79 or better
      ```

    ---


    ### 3. Take Profit Orders (TP)


    **Parent-child orders**: Automatically triggers a child order when a parent
    order **fills**.


    #### TP Market

    - **Triggers**: When parent order is **fully filled**

    - **Executes**: Immediately places the child order (can be another TP/SL or
    direct order)

    - **Example**:
      ```
      Place limit buy 100 @ $0.60 WITH TP Market @ $0.80
      → When buy fills → immediately activates TP Market SELL @ $0.80
      → That TP Market is a reverse stop that triggers when price ≥ $0.80
      ```

    #### TP Limit

    - **Triggers**: When parent order is **fully filled**

    - **Executes**: Activates TP Limit order (reverse stop limit)

    - **Example**:
      ```
      Place limit buy 100 @ $0.60 WITH TP Limit @ $0.80 (limit $0.79)
      → When buy fills → activates TP Limit SELL
      → Triggers when price ≥ $0.80 → sends limit sell @ $0.79
      ```

    ---


    ### 4. Stop Loss Orders (SL)


    **Parent-child orders**: Automatically triggers a child order when a parent
    order **fills**.


    #### SL Market

    - **Triggers**: When parent order is **fully filled**

    - **Executes**: Immediately places the child order (can be another SL/TP or
    direct order)

    - **Example**:
      ```
      Place limit buy 100 @ $0.60 WITH SL Market @ $0.55
      → When buy fills → immediately activates SL Market SELL @ $0.55
      → That SL Market is a stop order that triggers when price ≤ $0.55
      ```

    #### SL Limit

    - **Triggers**: When parent order is **fully filled**

    - **Executes**: Activates SL Limit order (stop limit)

    - **Example**:
      ```
      Place limit buy 100 @ $0.60 WITH SL Limit @ $0.55 (limit $0.54)
      → When buy fills → activates SL Limit SELL
      → Triggers when price ≤ $0.55 → sends limit sell @ $0.54
      ```

    ---


    ## Order Type Comparison


    | Type | Trigger Condition | Execution | Primary Use Case |

    |------|------------------|-----------|------------------|

    | **Market** | None (immediate) | Immediate at best price | Need immediate
    fill |

    | **Limit** | None (rests) | At limit price or better | Want price control |

    | **Stop Market** | Price moves AGAINST you | Market order (immediate) |
    Stop loss, breakout entry |

    | **Stop Limit** | Price moves AGAINST you | Limit order (may not fill) |
    Stop loss with price protection |

    | **TP Market** | Parent fills + price moves FOR you | Market order via
    reverse stop | Take profit with immediate exit |

    | **TP Limit** | Parent fills + price moves FOR you | Limit order via
    reverse stop | Take profit with price control |

    | **SL Market** | Parent fills + price moves AGAINST you | Market order via
    stop | Stop loss from entry |

    | **SL Limit** | Parent fills + price moves AGAINST you | Limit order via
    stop | Stop loss with price floor |


    ---


    ## Key Concepts


    ### Stop vs Reverse Stop

    - **Stop**: Triggers when price moves AGAINST you (exit losses, enter
    breakouts)

    - **Reverse Stop**: Triggers when price moves FOR you (take profits)


    ### Parent-Child Orders

    - **TP/SL orders** are "meta-orders" that activate child orders when a
    parent fills

    - The child order itself is usually a stop or reverse stop order

    - This creates a two-step process: Parent fill → Child activation → Price
    trigger → Execution


    ### Trigger Direction Summary

    | Order Side | Stop (Loss/Breakout) | Reverse Stop (Profit) |

    |------------|---------------------|----------------------|

    | **BUY** | Triggers ≥ stop price | Triggers ≤ target price |

    | **SELL** | Triggers ≤ stop price | Triggers ≥ target price |


    ---


    ## Examples


    ### Complete Trading Scenario

    ```

    1. Place limit BUY 100 @ $0.60
       WITH TP Market @ $0.80 (reverse stop)
       AND SL Market @ $0.55 (normal stop)

    2. Buy fills at $0.60
       → TP Market SELL @ $0.80 activated (reverse stop)
       → SL Market SELL @ $0.55 activated (normal stop)

    3a. If price rises to $0.80:
        → TP triggers (price ≥ $0.80) → market sell executes
        → SL cancelled automatically

    3b. If price falls to $0.55:
        → SL triggers (price ≤ $0.55) → market sell executes
        → TP cancelled automatically
    ```


    ### Breakout Entry with Protection

    ```

    Price is at $0.70, resistance at $0.75, support at $0.65


    1. Place Stop Market BUY @ $0.76 (breakout entry)
       → Triggers when price ≥ $0.76 (breaks resistance)
       → Market buy executes

    2. Add SL Market @ $0.74 to the stop order
       → When breakout buy fills → SL activates
       → Protects if breakout fails
    ```

  contact:
    name: River Markets
    url: https://rivermarkets.com/
  license:
    name: Proprietary
  version: 1.0.0
servers:
  - url: https://api.rivermarkets.com
security:
  - SignedRequestKeyId: []
    SignedRequestTimestamp: []
    SignedRequestSignature: []
  - BearerAuth: []
tags:
  - name: markets
    description: Search and discover prediction markets across Kalshi and Polymarket.
  - name: subaccounts
    description: >-
      Manage trading subaccounts. Each subaccount can have its own exchange
      credentials and positions.
  - name: positions
    description: View current portfolio positions across all connected exchanges.
  - name: fills
    description: Retrieve trade execution history and fill details.
  - name: prices
    description: Get historical price data and candlesticks from exchanges.
  - name: tradeprints
    description: >-
      Recent trades for a market. Pairs with the /v1/ws/tradeprints WebSocket
      for live updates.
  - name: orders
    description: Place and manage orders on prediction market exchanges.
  - name: complex-orders
    description: >-
      Manage complex orders: conditional orders (take-profit and stop-loss),
      TWAP, and other advanced order types.
paths:
  /v1/complex-orders:
    post:
      tags:
        - complex-orders
      summary: Create Complex Order
      description: >-
        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.
      operationId: create_complex_order_v1_complex_orders_post
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ComplexOrderCreateRequest'
      responses:
        '202':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ComplexOrderCreateResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
components:
  schemas:
    ComplexOrderCreateRequest:
      properties:
        subaccount_id:
          type: string
          format: uuid
          title: Subaccount Id
          description: Subaccount to create the order under
        river_id:
          anyOf:
            - type: integer
            - type: 'null'
          title: River Id
          description: Instrument ID. Mutually exclusive with generic_asset_id.
        generic_asset_id:
          anyOf:
            - type: string
              format: uuid
            - type: 'null'
          title: Generic Asset Id
          description: Generic asset basket ID. Mutually exclusive with river_id.
        conditional_order_params:
          anyOf:
            - $ref: '#/components/schemas/ConditionalOrderCreate'
            - type: 'null'
          description: Conditional order parameters (TP/SL/STOP)
        iceberg_order_params:
          anyOf:
            - $ref: '#/components/schemas/IcebergOrderParams'
            - type: 'null'
          description: Iceberg order parameters
        peg_order_params:
          anyOf:
            - $ref: '#/components/schemas/PegOrderParams'
            - type: 'null'
          description: Peg order parameters
        smart_taker_order_params:
          anyOf:
            - $ref: '#/components/schemas/SmartTakerOrderParams'
            - type: 'null'
          description: Smart-taker order parameters
      type: object
      required:
        - subaccount_id
      title: ComplexOrderCreateRequest
      description: |-
        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.
    ComplexOrderCreateResponse:
      properties:
        complex_order_id:
          type: string
          format: uuid
          title: Complex Order Id
          description: Unique complex order identifier
      type: object
      required:
        - complex_order_id
      title: ComplexOrderCreateResponse
      description: >-
        Schema for a complex order response (unified across all complex order
        types).
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    ConditionalOrderCreate:
      properties:
        conditional_order_type:
          type: string
          enum:
            - TP
            - SL
            - STOP
            - REVERSE_STOP
          description: 'Type of conditional order: TP (take profit), SL (stop loss), or STOP'
        stop_order_price:
          anyOf:
            - type: number
              exclusiveMaximum: 1
              exclusiveMinimum: 0
            - type: 'null'
          title: Stop Order Price
          description: >-
            Activation price for STOP conditional orders. This is the price at
            which the conditional order triggers and places the trigger_order.
        trigger_order:
          $ref: '#/components/schemas/TriggerOrder'
          description: >-
            The order that gets placed when the conditional order activates. For
            TP/SL this happens after the parent order fills; for STOP this
            happens when stop_order_price is reached.
        parent_river_order_id:
          anyOf:
            - type: string
              format: uuid
            - type: 'null'
          title: Parent River Order Id
          description: Parent order ID (required for TP and SL)
        parent_complex_order_id:
          anyOf:
            - type: string
              format: uuid
            - type: 'null'
          title: Parent Complex Order Id
          description: Parent complex order ID (for chaining)
      type: object
      required:
        - conditional_order_type
        - trigger_order
      title: ConditionalOrderCreate
      description: >-
        Schema for a conditional order (take profit or stop loss) attached to a
        parent order.
    IcebergOrderParams:
      properties:
        buy_flag:
          type: boolean
          title: Buy Flag
          description: 'Direction: true=buy, false=sell'
        total_qty:
          type: number
          exclusiveMinimum: 0
          title: Total Qty
          description: Total iceberg quantity (across all tranches)
        displayed_qty:
          type: number
          exclusiveMinimum: 0
          title: Displayed Qty
          description: Tranche size — quantity shown to the market at any moment
        limit_price:
          type: number
          exclusiveMaximum: 1
          exclusiveMinimum: 0
          title: Limit Price
          description: Static limit price for every tranche (between 0 and 1)
        post_only:
          type: boolean
          title: Post Only
          description: If true, every tranche is posted as post-only (maker-only)
          default: false
        cancel_order_on_pause:
          type: boolean
          title: Cancel Order On Pause
          description: >-
            Kalshi only: if true, resting tranches are cancelled by the exchange
            when it enters a trading pause. Ignored on other venues.
          default: true
        reload_delay_s:
          anyOf:
            - type: integer
              maximum: 3600
              minimum: 0
            - type: 'null'
          title: Reload Delay S
          description: >-
            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:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          title: Expiry Ts Utc
          description: >-
            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.
      type: object
      required:
        - buy_flag
        - total_qty
        - displayed_qty
        - limit_price
      title: IcebergOrderParams
      description: >-
        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.
    PegOrderParams:
      properties:
        buy_flag:
          type: boolean
          title: Buy Flag
          description: 'Direction: true=buy, false=sell'
        total_qty:
          type: number
          exclusiveMinimum: 0
          title: Total Qty
          description: Total peg quantity
        min_price:
          anyOf:
            - type: number
              exclusiveMaximum: 1
              exclusiveMinimum: 0
            - type: 'null'
          title: Min Price
          description: Price floor — the child never rests below this (between 0 and 1)
        max_price:
          anyOf:
            - type: number
              exclusiveMaximum: 1
              exclusiveMinimum: 0
            - type: 'null'
          title: Max Price
          description: Price ceiling — the child never rests above this (between 0 and 1)
        post_only:
          type: boolean
          title: Post Only
          description: >-
            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
          default: false
        expiry_ts_utc:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          title: Expiry Ts Utc
          description: >-
            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:
          anyOf:
            - type: integer
              maximum: 3600
              minimum: 0
            - type: 'null'
          title: Peg Min Stay Time S
          description: >-
            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:
          anyOf:
            - type: number
              exclusiveMinimum: 0
            - type: 'null'
          title: Max Qty Level
          description: >-
            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.
      type: object
      required:
        - buy_flag
        - total_qty
      title: PegOrderParams
      description: >-
        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.
    SmartTakerOrderParams:
      properties:
        buy_flag:
          type: boolean
          title: Buy Flag
          description: 'Direction: true=buy, false=sell'
        total_qty:
          type: number
          exclusiveMinimum: 0
          title: Total Qty
          description: Total quantity to acquire/offload across all IOC clips
        limit_price:
          type: number
          exclusiveMaximum: 1
          exclusiveMinimum: 0
          title: Limit Price
          description: >-
            Worst price the taker will accept — max for buy, min for sell
            (between 0 and 1)
        min_qty:
          type: number
          exclusiveMinimum: 0
          title: Min Qty
          description: >-
            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:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          title: Expiry Ts Utc
          description: >-
            Optional expiry timestamp in UTC (ISO 8601). Once it passes, the
            order stops firing and is torn down by the periodic reconciliation
            sweep.
      type: object
      required:
        - buy_flag
        - total_qty
        - limit_price
        - min_qty
      title: SmartTakerOrderParams
      description: >-
        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.
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
              - type: string
              - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
        input:
          title: Input
        ctx:
          type: object
          title: Context
      type: object
      required:
        - loc
        - msg
        - type
      title: ValidationError
    TriggerOrder:
      properties:
        order_type:
          type: string
          enum:
            - LIMIT
            - MARKET
          description: 'Order type for the triggered order: ''LIMIT'' or ''MARKET'''
        qty:
          type: number
          exclusiveMinimum: 0
          title: Qty
          description: Quantity (number of contracts) for the triggered order
        price:
          anyOf:
            - type: number
              exclusiveMaximum: 1
              exclusiveMinimum: 0
            - type: 'null'
          title: Price
          description: >-
            Limit price for the triggered order (between 0 and 1). Required when
            order_type is LIMIT.
        buy_flag:
          type: boolean
          title: Buy Flag
          description: 'Direction of the triggered order: true=buy, false=sell'
        stop_order_price:
          anyOf:
            - type: number
              exclusiveMaximum: 1
              exclusiveMinimum: 0
            - type: 'null'
          title: Stop Order Price
          description: >-
            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.
      type: object
      required:
        - order_type
        - qty
        - buy_flag
      title: TriggerOrder
      description: >-
        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.
  securitySchemes:
    SignedRequestKeyId:
      type: apiKey
      in: header
      name: X-River-Key-Id
      description: UUID of your API key (from Settings → API Keys).
    SignedRequestTimestamp:
      type: apiKey
      in: header
      name: X-River-Timestamp
      description: Current unix seconds. Must be within 30s of server time.
    SignedRequestSignature:
      type: apiKey
      in: header
      name: X-River-Signature
      description: >-
        Base64 Ed25519 signature over the canonical request:
        METHOD\nPATH\nSORTED_QUERY\nTIMESTAMP\nSHA256(body) hex. See
        /api-reference/authentication for the full recipe.
    BearerAuth:
      type: http
      scheme: bearer
      description: JWT bearer token for web client authentication.

````