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

# Place an order (consolidated)

> Single high-level order endpoint. `type` = LIMIT | MARKET | PEGGED | TWAP | ICEBERG. Optional `take_profit` / `stop_loss` brackets attach to a LIMIT/MARKET buy entry (placed after the entry; best-effort — a failing bracket is reported, not rolled back). Idempotency-Key required.



## OpenAPI

````yaml /api-reference/openapi/v2-trade.json post /v2/trade/order
openapi: 3.1.0
info:
  title: Bravado Trade API
  version: '2.0'
  description: >
    Consolidated order execution API for Bravado partners (v2). One high-level

    order endpoint replaces the v1 limit/market/advanced split, plus native

    position redeem, split/merge, pUSD withdraw, and managed-strategy admin.

    `/v1/trade/*` remains available and unchanged — v2 is additive.


    Auth, idempotency, rate-limit, numeric-as-string, timestamp, and error-

    envelope conventions are identical to v1 (see the v1 spec), except every

    path is under `/v2/trade`.


    Endpoints:

    * `POST /v2/trade/order` — single consolidated order. `type` =
      `LIMIT | MARKET | PEGGED | TWAP | ICEBERG | TAKE_PROFIT | STOP_LOSS |
      TRAILING_STOP | TRAILING_BUY`. Optional `take_profit` / `stop_loss`
      brackets attach to a
      LIMIT/MARKET buy entry (best-effort). Managed strategies (PEGGED / TWAP /
      ICEBERG / STOP_LOSS / TRAILING_STOP / TRAILING_BUY) return a `record_id`
      instead of an
      `order_id`.
    * `GET /v2/trade/strategies` + `DELETE /v2/trade/strategies/{record_id}` —
      list and cancel managed strategies (see the guide below).
    * `POST /v2/trade/positions/redeem` — redeem a resolved position to pUSD;
      `/positions/split` and `/positions/merge` — on-chain CTF split/merge.
    * `POST /v2/trade/withdraw` — withdraw pUSD to an external address. Requires
      the dedicated `trade.withdraw` scope (not granted by `trade.execute`).
    * `POST /v2/trade/combo/quote|accept|redeem` + `GET
    /v2/trade/combo/positions`
      — multi-leg RFQ parlays (Combos). Quote → accept within ~8.5s → manual
      redeem. Requires the dedicated `trade.combos` scope.
    * Reads (`account`, `balances`, `positions`, `orders/open`, `activity`),
      cancels, and user provisioning are the same as v1, mounted under
      `/v2/trade`.

    Tags:

    * `trade.health` — liveness probe and OpenAPI spec.

    * `trade.read` — account, balances, positions, open orders, activity,
      strategies.
    * `trade.execute` — consolidated order placement + position redeem.

    * `trade.cancel` — single, batch, cancel-all, and strategy cancel.

    * `trade.withdraw` — pUSD withdrawals to external addresses.

    * `trade.combos` — multi-leg RFQ parlay quote/accept/redeem + positions.

    * `trade.users` — provision integration users (white-label flow).


    All endpoints return `application/json`.



    ## Advanced orders — correct payloads (`POST /v2/trade/order`)


    Most integration bugs come from **units** — read this table first.


    | Field | Unit | Example | NOT |

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

    | `price`, `take_profit.price`, `stop_loss.price`, `price_floor`,
    `price_ceiling`, `execution.trailing_offset`, `execution.high_water_mark`,
    `execution.low_water_mark` | **decimal probability** 0.001–0.999 | `"0.60"`
    (= 60¢) | ❌ cents `"60"` |

    | `size`, `execution.clip_size`, bracket `size` | **shares** | `"100"` | — |

    | `budget_usdc`, `quote_amount` | **US dollars** | `"50"` | ❌ micro-units |

    | `offset_ticks` | CLOB ticks (1 tick = 0.1¢) | `0` | — |

    | `execution.trailing_offset_pct`, `execution.randomize_pct`,
    `execution.price_tolerance_pct` | percent 0–100 | `5` | — |

    | `execution.duration_sec`, `execution.interval_sec` | seconds (interval ≥
    10) | `3600`, `60` | — |


    All field names are **snake_case**. Send a `price` of `72` and you'll get

    `price must be a decimal probability 0.001–0.999; received 72 — did you mean
    0.72?`.

    Every mutating request needs an `Idempotency-Key` header.


    ### LIMIT / MARKET (with optional protective brackets)


    ```jsonc

    // Limit buy at 62¢ for 100 shares, with a take-profit and a partial
    stop-loss

    {
      "symbol": "<token_id>", "side": "buy", "type": "LIMIT",
      "price": "0.62", "size": "100",
      "take_profit": { "price": "0.72" },              // whole entry by default
      "stop_loss":   { "price": "0.55", "size": "50" } // positive size = partial
    }

    // Bracket size: omitted OR "0" = the whole entry.

    // Market buy = USD to spend; market sell = shares

    { "symbol": "<token_id>", "side": "buy", "type": "MARKET", "quote_amount":
    "10" }

    { "symbol": "<token_id>", "side": "sell", "type": "MARKET", "size": "100" }

    ```


    Brackets attach only to a **buy** LIMIT/MARKET entry, best-effort: the entry

    still succeeds if a bracket fails. **Always inspect the response** — a
    failed

    bracket is reported at `brackets.take_profit.error` /
    `brackets.stop_loss.error`

    AND surfaced in a top-level `warnings: [...]`.


    ### PEGGED


    ```jsonc

    {
      "symbol": "<token_id>", "side": "buy", "type": "PEGGED",
      "outcome": "yes", "offset_ticks": 0,
      "budget_usdc": "50",                          // dollars, > 0 (snake_case)
      "price_floor": 0.05, "price_ceiling": 0.95,   // optional decimals
      "condition_id": "0x…"
    }

    ```


    `budget_usdc` is required (`quote_amount` is accepted as an alias — the same

    dollar field a MARKET buy uses).


    ### ICEBERG


    ```jsonc

    {
      "symbol": "<token_id>", "side": "buy", "type": "ICEBERG",
      "price": "0.62", "size": "1000",
      "execution": { "clip_size": "50", "price_tolerance_pct": 5 }
    }

    ```


    Each slice must be **≥ $1 in notional** (`clip_size × price ≥ 1`) and

    `clip_size < size`. Slices are **post-only** — price the iceberg passively

    (at or below the bid for a buy); at/above the ask it is rejected with

    `order crosses book`.


    ### TWAP


    ```jsonc

    // Fully explicit

    {
      "symbol": "<token_id>", "side": "buy", "type": "TWAP",
      "price": "0.62", "size": "1000",
      "execution": { "duration_sec": 3600, "interval_sec": 60 }
    }

    // Market-style: dollars only — price derived from the live top of book

    // (best ask for a buy, best bid for a sell); size = quote_amount / price

    {
      "symbol": "<token_id>", "side": "buy", "type": "TWAP",
      "quote_amount": "5",
      "execution": { "duration_sec": 60, "interval_sec": 10 }
    }

    ```


    `interval_sec` (≥ 10) and `duration_sec` are required, plus **either**
    `size`

    (shares) **or** `quote_amount` (dollars). `price` is optional — when omitted

    the derived limit is echoed in the response `message`. The derived price is
    a

    **limit**: slices never chase past it. `clip_size` / `randomize_pct` are

    ignored (the engine auto-sizes slices) and produce a `warnings` entry.


    ### TRAILING_STOP


    ```jsonc

    {
      "symbol": "<token_id>", "side": "sell", "type": "TRAILING_STOP",
      "size": "100",
      "execution": {
        "trailing_offset_pct": 5,        // the trail distance
        "high_water_mark": "0.60"        // current market price as the reference
      }
    }

    ```


    Requires `size` + an offset (`trailing_offset_pct` **or** `trailing_offset`)

    + a reference (`execution.high_water_mark` or top-level `price`).


    ### TRAILING_BUY


    The entry mirror of TRAILING_STOP. A trailing stop follows the price up and

    sells when it falls back by your offset; a trailing buy follows the ask down

    and buys when it bounces back up by your offset. Use it to enter on a dip

    without having to pick the bottom.


    ```jsonc

    {
      "symbol": "<token_id>", "side": "buy", "type": "TRAILING_BUY",
      "quote_amount": "50",              // US DOLLARS to spend, not shares
      "execution": {
        "trailing_offset_pct": 5,        // the bounce that triggers the entry
        "low_water_mark": "0.40",        // optional starting reference
        "price_ceiling": "0.55"          // optional hard cap
      }
    }

    ```


    Requires `quote_amount` + an offset (`trailing_offset_pct` **or**

    `trailing_offset`). It takes dollars rather than shares because the share

    count is not known until the entry price is.


    `low_water_mark` is optional: omit it and the engine seeds the reference
    from

    the first ask it sees, which is what you want when arming at the current
    market.


    `price_ceiling` is a veto, not a trigger. If the ask gaps straight past it
    the

    entry does not fire at any price, and the order stays armed in case a
    cheaper

    ask comes back. A ceiling below the entry your offset implies is rejected at

    arm time, since it could never fire.


    ### TAKE_PROFIT / STOP_LOSS (standalone, on an existing position)


    ```jsonc

    { "symbol": "<token_id>", "side": "sell", "type": "TAKE_PROFIT", "price":
    "0.72", "size": "50" }

    { "symbol": "<token_id>", "side": "sell", "type": "STOP_LOSS",  "price":
    "0.55", "size": "50" }

    ```


    These SELL shares you already hold — `size` is checked against your
    **share**

    balance (not pUSD): `Not enough shares to place this sell — holding X…`.


    ### Market microstructure constraints (rejections that are NOT bugs)


    - Resting orders have a **per-market share minimum** (usually 5).

    - Market orders have a **$1 minimum amount**.

    - Iceberg slices are **post-only** (see ICEBERG above).


    ### Tracking & canceling managed strategies


    "Where do I see my iceberg / trailing stop?" — **`GET
    /v2/trade/strategies`**

    lists every partner-created TWAP / ICEBERG / PEGGED / STOP_LOSS /

    TRAILING_STOP; `DELETE /v2/trade/strategies/{record_id}` cancels one.


    - The `record_id` returned by `POST /v2/trade/order` is the id to
    track/cancel.

    - Pre-trigger stop-losses and trailing stops exist **only** in this list;
    they
      appear on `/orders/open` (`is_stop_loss: true`) only after the runner
      triggers them into a real CLOB order.
    - **`price` is not the fill.** On a STOP_LOSS or TRAILING_STOP it is the
    level
      the order was armed at, and on a TRAILING_BUY it is the ceiling. The price the
      order actually got is `executed_price`, with `filled_size` alongside it.
      Both are null until it executes. Showing `price` as the exit makes every
      trailing stop look like it closed exactly where it opened.
    - An iceberg's working slice IS a live CLOB order and also shows on
      `/orders/open`; the parent totals live in the strategy record.
    - Standalone TAKE_PROFIT places a real CLOB sell immediately — it lives on
      `/orders/open` (`is_take_profit: true`), not in the strategies list.
    - A stop-loss can be canceled only while untriggered; once executing, cancel
      the resulting order via `DELETE /v2/trade/orders/{order_id}`.

    ### Response conventions


    - **Managed strategies** return `record_id` + `status: "PENDING" | "ACTIVE"`
      plus a `message` — `PENDING` is **not** a rejection.
    - **CLOB orders** (LIMIT / MARKET / TAKE_PROFIT) return `order_id`.

    - Check `warnings: string[]` on every response — a `200` can still carry
      "entry OK, but the take-profit didn't place because …".
    - On `429`, respect `Retry-After` instead of retrying immediately.




    ## Combos — multi-leg RFQ parlays (`/v2/trade/combo/*`)


    A **combo** is a single position that pays out only if **every** leg wins —
    a

    parlay. Unlike a normal order it is priced by **request-for-quote (RFQ)**:
    you

    ask for a quote, then accept it within a short window. Requires the
    dedicated

    **`trade.combos`** scope.


    The lifecycle is three calls (accept is money-moving and on-chain):


    `quote` → `accept` (within ~8.5s) → *(after the event resolves)* `redeem`


    ### Units — read this first


    | Field | Unit | Example |

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

    | `leg_position_ids` | 2–10 **YES position ids** (one per leg) | `["7248…",
    "9931…"]` |

    | `notional_usd` | **US dollars** the user spends (BUY) | `5` |

    | `price_cents` (response) | cents per blended YES share | `2` (= $0.02) |

    | `maker_amount_usd` (response) | dollars the maker posts | `1.2` |

    | `taker_shares` (response) | combo shares received | `66.5` |

    | `payout_usd` (redeem response) | pUSD paid out for winning shares | `50` |


    Field names are **snake_case**. Every mutating request needs an

    `Idempotency-Key` header. Only **`BUY`** is supported (there is no combo
    sell —

    exit is redeem-on-win or let it resolve to $0).


    ### 1) Quote — `POST /v2/trade/combo/quote`


    ```jsonc

    {
      "leg_position_ids": ["<yes_position_id_A>", "<yes_position_id_B>"],
      "notional_usd": 5            // dollars to spend
      // "side": "BUY"             // optional; BUY is the only value
    }

    ```


    Returns the priced quote:


    ```jsonc

    {
      "combo_order_id": "…",       // pass both of these to /accept
      "quote_id": "…",
      "rfq_id": "…",
      "price_cents": 2,
      "maker_amount_usd": 1.2,
      "taker_shares": 66.5,
      "expires_at": "2026-07-17T15:04:05.000Z"   // ISO — accept BEFORE this
    }

    ```


    The quote is valid **~8.5 seconds**. It is a real maker RFQ, not an estimate
    —

    don't cache it.


    ### 2) Accept — `POST /v2/trade/combo/accept`


    ```jsonc

    { "combo_order_id": "…", "quote_id": "…" }

    ```


    ```jsonc

    { "combo_order_id": "…", "status": "EXECUTED", "transaction_hash": "0x…" }

    ```


    Accept signs and submits on-chain. It must land **before `expires_at`** — a

    stale accept returns **`410 QUOTE_EXPIRED`**. On expiry, **re-quote and
    accept

    the fresh quote** — never blind-retry the same accept: the price may have
    moved

    (same lesson as any RFQ). Idempotency-Key protects against double-submit of
    the

    *same* accept, not against re-pricing.


    ### 3) Redeem — `POST /v2/trade/combo/redeem`


    A combo does **not** auto-settle to cash. After the event resolves in your

    favor, claim it manually:


    ```jsonc

    { "combo_order_id": "…" }          // or { "combo_position_id": "…" } from
    /positions

    ```


    ```jsonc

    { "combo_order_id": "…", "status": "REDEEMED", "payout_usd": 50,
    "transaction_hash": "0x…" }

    ```


    Only a **`RESOLVED_WIN`** combo pays out — one losing leg zeroes the whole

    combo (that is a correct parlay result, not a bug). Redeem before resolution
    or

    on a losing combo is rejected.


    ### 4) Positions — `GET /v2/trade/combo/positions`


    Lists the bound user's combo positions. Filters:

    `status` = `OPEN | PARTIAL | RESOLVED_WIN | RESOLVED_LOSS`, plus `limit`

    (≤ 500) and `offset`. Use the returned position id as `combo_position_id`
    for

    redeem.


    ### Rejections that are NOT bugs


    - **`410 QUOTE_EXPIRED`** — accept came after `expires_at`. Re-quote.

    - **`422 INSUFFICIENT_BALANCE`** — the wallet can't cover `notional_usd`
    **plus
      the fee**. The message states the dollars needed and the largest affordable
      notional; size the combo a little under the balance.
    - **`422 NO_LIQUIDITY` / no maker** — no counterparty quoted the legs right
    now
      (common on thin/near-event markets). Retry, or reduce `notional_usd`.
servers:
  - url: https://api.bravadotrade.com
    description: Production
security: []
tags:
  - name: trade.health
    description: Liveness and OpenAPI spec
  - name: trade.read
    description: Account, balances, positions, open orders, activity, strategies
  - name: trade.cancel
    description: Cancel single / batch / all, and managed-strategy cancel
  - name: trade.users
    description: Provision integration users (white-label)
  - name: trade.execute
    description: Order placement, batch (bid ladder), position redeem/split/merge
  - name: trade.withdraw
    description: Withdraw collateral to an external address
  - name: trade.copytrade
    description: trade.copytrade
  - name: trade.combos
    description: Multi-leg RFQ parlays (quote / accept / redeem / positions)
paths:
  /v2/trade/order:
    post:
      tags:
        - trade.execute
      summary: Place an order (consolidated)
      description: >-
        Single high-level order endpoint. `type` = LIMIT | MARKET | PEGGED |
        TWAP | ICEBERG. Optional `take_profit` / `stop_loss` brackets attach to
        a LIMIT/MARKET buy entry (placed after the entry; best-effort — a
        failing bracket is reported, not rolled back). Idempotency-Key required.
      operationId: post_v2_trade_order
      requestBody:
        content:
          application/json:
            schema:
              additionalProperties: false
              type: object
              properties:
                venue:
                  description: >-
                    Trading venue. Omitted = polymarket (backward compatible).
                    predictfun requires the partner venue entitlement; LIMIT and
                    MARKET only for now.
                  anyOf:
                    - type: string
                      enum:
                        - polymarket
                    - type: string
                      enum:
                        - predictfun
                symbol:
                  description: Venue-native outcome token id
                  type: string
                side:
                  anyOf:
                    - type: string
                      enum:
                        - buy
                    - type: string
                      enum:
                        - sell
                type:
                  anyOf:
                    - type: string
                      enum:
                        - LIMIT
                    - type: string
                      enum:
                        - MARKET
                    - type: string
                      enum:
                        - PEGGED
                    - type: string
                      enum:
                        - TWAP
                    - type: string
                      enum:
                        - ICEBERG
                    - type: string
                      enum:
                        - TAKE_PROFIT
                    - type: string
                      enum:
                        - STOP_LOSS
                    - type: string
                      enum:
                        - TRAILING_STOP
                    - type: string
                      enum:
                        - TRAILING_BUY
                price:
                  description: >-
                    Decimal probability 0..1, e.g. "0.72" for 72¢ (NOT cents).
                    Required for LIMIT / ICEBERG / TAKE_PROFIT / STOP_LOSS.
                    Optional for TWAP (derived from the live top of book when
                    omitted) and TRAILING_STOP (reference;
                    execution.high_water_mark also works).
                  type: string
                size:
                  description: >-
                    Shares. Required for LIMIT / ICEBERG / TAKE_PROFIT /
                    STOP_LOSS / TRAILING_STOP and MARKET sell; for TWAP either
                    size or quote_amount works.
                  type: string
                quote_amount:
                  description: >-
                    US dollars. MARKET buy notional; TWAP: shares are derived
                    from it at the limit price; PEGGED: accepted as an alias for
                    budget_usdc.
                  type: string
                time_in_force:
                  description: >-
                    LIMIT only. GTC (default) rests on the book (GTD when
                    expiration is set). IOC fills whatever crosses immediately
                    and cancels the remainder (Polymarket FAK) — the response
                    reports the actual filled_size. FOK fills the full size
                    instantly or cancels entirely. Incompatible with expiration.
                    MARKET orders always behave as IOC/FAK.
                  anyOf:
                    - type: string
                      enum:
                        - GTC
                    - type: string
                      enum:
                        - IOC
                    - type: string
                      enum:
                        - FOK
                expiration:
                  type: number
                condition_id:
                  type: string
                outcome:
                  anyOf:
                    - type: string
                      enum:
                        - 'yes'
                    - type: string
                      enum:
                        - 'no'
                offset_ticks:
                  description: >-
                    PEGGED: distance from the touch in CLOB ticks (1 tick =
                    $0.001); 0 = passive at the touch.
                  type: number
                budget_usdc:
                  description: >-
                    PEGGED buy budget in US dollars, top-level decimal string,
                    e.g. "50". quote_amount is accepted as an alias.
                  type: string
                price_floor:
                  description: >-
                    PEGGED: lowest chase price, decimal probability 0..1 (NOT
                    cents).
                  type: number
                price_ceiling:
                  description: >-
                    PEGGED: highest chase price, decimal probability 0..1 (NOT
                    cents).
                  type: number
                execution:
                  additionalProperties: false
                  type: object
                  properties:
                    duration_sec:
                      description: TWAP total run length in seconds
                      type: number
                    clip_size:
                      description: Shares per slice (TWAP) / clip (Iceberg)
                      type: string
                    interval_sec:
                      description: TWAP seconds between slices (>= 10)
                      type: integer
                    randomize_pct:
                      description: TWAP slice-size jitter 0..50 (default 20)
                      type: number
                    passive:
                      description: >-
                        TWAP slice style. Default false: each slice takes the
                        touch (buy at the best ask, sell at the best bid), never
                        past your price, so it executes. True: rest one tick
                        inside the touch and never cross — cheaper when it
                        fills, but often it does not. Use it on long horizons.
                      type: boolean
                    price_tolerance_pct:
                      description: ICEBERG auto-cancel drift tolerance 0..100
                      type: number
                    trailing_offset_pct:
                      description: TRAILING_STOP trail distance, percent (0..100)
                      type: number
                    trailing_offset:
                      description: TRAILING_STOP trail distance, decimal prob (0..1)
                      type: string
                    high_water_mark:
                      description: TRAILING_STOP starting reference price (decimal)
                      type: string
                    low_water_mark:
                      description: >-
                        TRAILING_BUY starting reference price (decimal). Omit to
                        let the engine seed it from the first ask it sees, which
                        is what you want when arming at the current market.
                      type: string
                    price_ceiling:
                      description: >-
                        TRAILING_BUY hard cap, decimal probability 0..1. If the
                        ask gaps past it the entry does not fire at any price
                        and the order stays armed for a cheaper ask.
                      type: string
                take_profit:
                  additionalProperties: false
                  type: object
                  properties:
                    price:
                      description: Decimal probability 0..1 (NOT cents)
                      type: string
                    size:
                      description: >-
                        Shares for this bracket (optional). Omitted or "0" = the
                        whole entry; set a positive value to protect only part
                        of the position.
                      type: string
                  required:
                    - price
                stop_loss:
                  additionalProperties: false
                  type: object
                  properties:
                    price:
                      description: Decimal probability 0..1 (NOT cents)
                      type: string
                    size:
                      description: >-
                        Shares for this bracket (optional). Omitted or "0" = the
                        whole entry; set a positive value to protect only part
                        of the position.
                      type: string
                  required:
                    - price
                client_order_id:
                  type: string
                metadata:
                  type: string
              required:
                - symbol
                - side
                - type
        required: true
      responses:
        '200':
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  type:
                    type: string
                  order_id:
                    anyOf:
                      - type: string
                      - type: 'null'
                  record_id:
                    anyOf:
                      - type: string
                      - type: 'null'
                  status:
                    type: string
                  side:
                    type: string
                  price:
                    anyOf:
                      - type: string
                      - type: 'null'
                  size:
                    anyOf:
                      - type: string
                      - type: 'null'
                  filled_size:
                    anyOf:
                      - type: string
                      - type: 'null'
                  remaining_size:
                    anyOf:
                      - type: string
                      - type: 'null'
                  matched_amount:
                    anyOf:
                      - type: string
                      - type: 'null'
                  builder_code_used:
                    anyOf:
                      - type: string
                      - type: 'null'
                  created_at:
                    type: number
                  brackets:
                    type: object
                    properties:
                      take_profit:
                        additionalProperties: true
                        type: object
                        properties:
                          order_id:
                            type: string
                          id:
                            type: string
                          status:
                            type: string
                          error:
                            type: string
                      stop_loss:
                        additionalProperties: true
                        type: object
                        properties:
                          order_id:
                            type: string
                          id:
                            type: string
                          status:
                            type: string
                          error:
                            type: string
                  warnings:
                    type: array
                    items:
                      type: string
                  message:
                    type: string
                required:
                  - type
                  - order_id
                  - record_id
                  - status
                  - side
                  - price
                  - size
                  - filled_size
                  - remaining_size
                  - matched_amount
                  - builder_code_used
                  - created_at

````