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

# Submit and Manage Orders Using the Molecule Orders API

> Create LIMIT and MARKET orders, configure routing modes, manage order lifecycle, and retrieve fill history using the Molecule orders API.

The `client.orders` namespace lets you submit orders to any live venue, amend or cancel them individually or in bulk, poll for status updates, and retrieve your fill history. Routing decisions — whether to target a specific venue instrument or to let Molecule find the best available price — are controlled per order through the `routing` field.

## Creating an Order

Submit a single order with `client.orders.create()` or the top-level shortcut `client.create_order()`. Both call `POST /v1/orders`.

```python theme={"dark"}
import os
from molecule import Molecule

client = Molecule(
    base_url=os.environ["MOLECULE_BASE_URL"],
    key_id=os.environ["MOLECULE_KEY_ID"],
    private_key=os.environ["MOLECULE_PRIVATE_KEY"],
)

order = client.create_order(
    subaccount_id=os.environ["MOLECULE_SUBACCOUNT_ID"],
    instrument_id=98712,          # venue-specific ID, used with DIRECT routing
    side="BUY",
    outcome="YES",
    type="LIMIT",
    tif="GTC",
    price="0.62",
    qty="100",
    routing={"mode": "DIRECT"},
    client_order_id="strat-alpha-001",   # idempotency key
)

print(order["id"], order["status"])
```

### Order parameters

<ParamField body="subaccount_id" type="string" required>
  The subaccount to trade from. All risk checks and fill attribution apply to this subaccount.
</ParamField>

<ParamField body="instrument_id" type="integer">
  Venue-specific instrument identifier. Required when `routing.mode` is `DIRECT`. Obtain this from `client.markets.get()` or `client.markets.search()`.
</ParamField>

<ParamField body="generic_asset_id" type="integer">
  Cross-venue asset identifier. Required when `routing.mode` is `BEST_PRICE` or `SPLIT`.
</ParamField>

<ParamField body="side" type="&#x22;BUY&#x22; | &#x22;SELL&#x22;" required>
  Order direction.
</ParamField>

<ParamField body="outcome" type="&#x22;YES&#x22; | &#x22;NO&#x22;">
  Outcome side for binary markets. Specifies which contract you are buying or selling.
</ParamField>

<ParamField body="type" type="&#x22;LIMIT&#x22; | &#x22;MARKET&#x22;" required>
  Order type. `LIMIT` requires a `price`. `MARKET` fills at the best available price.
</ParamField>

<ParamField body="tif" type="&#x22;GTC&#x22; | &#x22;IOC&#x22; | &#x22;FOK&#x22; | &#x22;GTD&#x22;">
  Time-in-force policy.

  * `GTC` — Good Till Cancelled. Rests on the book until filled or explicitly cancelled.
  * `IOC` — Immediate Or Cancel. Fills whatever is available immediately; cancels the remainder.
  * `FOK` — Fill Or Kill. Must fill in full immediately, or the entire order is cancelled.
  * `GTD` — Good Till Date. Rests until a specified expiry.
</ParamField>

<ParamField body="price" type="string">
  Limit price expressed as a decimal string (e.g., `"0.62"`). Required for `LIMIT` orders.
</ParamField>

<ParamField body="qty" type="string" required>
  Order quantity expressed as a decimal string (e.g., `"100"`).
</ParamField>

<ParamField body="routing" type="object">
  Routing configuration object.

  <Expandable title="routing fields">
    <ParamField body="routing.mode" type="&#x22;DIRECT&#x22; | &#x22;BEST_PRICE&#x22; | &#x22;SPLIT&#x22;">
      Routing strategy. See [Routing Modes](#routing-modes) below.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="client_order_id" type="string">
  Your reference ID for this order. Sent as the `Idempotency-Key` header — use it to safely retry order submission. See [Idempotency](#idempotency).
</ParamField>

***

## Routing Modes

Every order declares how Molecule should route it to execution venues.

<CardGroup cols={3}>
  <Card title="DIRECT" icon="arrow-right">
    Routes to a single venue-specific instrument. Requires `instrument_id`. Use this when you have a strong venue preference or are responding to a specific market condition on one venue.
  </Card>

  <Card title="BEST_PRICE" icon="chart-line">
    Finds the best available price across all live venues for the given `generic_asset_id`. Molecule selects the optimal venue at execution time.
  </Card>

  <Card title="SPLIT" icon="code-branch">
    Splits the order quantity across multiple live venues using `generic_asset_id`, improving fill probability for larger sizes.
  </Card>
</CardGroup>

<Note>
  `DIRECT` routing requires `instrument_id`. `BEST_PRICE` and `SPLIT` routing require `generic_asset_id`. Passing the wrong identifier for the routing mode results in a `ValidationError`.
</Note>

```python theme={"dark"}
# BEST_PRICE — let Molecule find the best venue
order = client.create_order(
    subaccount_id=os.environ["MOLECULE_SUBACCOUNT_ID"],
    generic_asset_id=4401,
    side="BUY",
    outcome="YES",
    type="LIMIT",
    tif="IOC",
    price="0.60",
    qty="200",
    routing={"mode": "BEST_PRICE"},
    client_order_id="strat-alpha-002",
)

# SPLIT — distribute across venues
order = client.create_order(
    subaccount_id=os.environ["MOLECULE_SUBACCOUNT_ID"],
    generic_asset_id=4401,
    side="BUY",
    outcome="YES",
    type="LIMIT",
    tif="GTC",
    price="0.59",
    qty="500",
    routing={"mode": "SPLIT"},
    client_order_id="strat-alpha-003",
)
```

***

## Idempotency

The `client_order_id` field doubles as an idempotency key. The SDK sends it as an `Idempotency-Key` HTTP header on every `POST /v1/orders` call.

* **Same key, same body** — safe to retry after a network timeout. The API returns the original order response without creating a duplicate.
* **Same key, different body** — the API raises a `ConflictError` with `error="idempotency_conflict"`.

```python theme={"dark"}
import uuid
from molecule.errors import ConflictError

client_order_id = f"strat-alpha-{uuid.uuid4()}"

payload = dict(
    subaccount_id=os.environ["MOLECULE_SUBACCOUNT_ID"],
    instrument_id=98712,
    side="BUY",
    outcome="YES",
    type="LIMIT",
    tif="GTC",
    price="0.55",
    qty="50",
    routing={"mode": "DIRECT"},
    client_order_id=client_order_id,
)

for attempt in range(3):
    try:
        order = client.create_order(**payload)
        print("Submitted:", order["id"])
        break
    except ConflictError as exc:
        if exc.error == "idempotency_conflict":
            # Different payload sent with the same key — do not retry
            raise
        raise
```

<Warning>
  Generate a fresh `client_order_id` for each logically distinct order. Reusing the same key with different parameters raises `ConflictError` and the order will not be submitted.
</Warning>

***

## Order Lifecycle

Orders move through a defined sequence of states:

```text theme={"dark"}
PENDING_SUBMISSION → OPEN → PARTIAL → FILLED
                          ↘ CANCELLED
                          ↘ REJECTED
                          ↘ EXPIRED
```

<Accordion title="Status definitions">
  | Status | Meaning |
  | - | - |
  | `PENDING_SUBMISSION` | Accepted by Molecule, not yet acknowledged by the venue. |
  | `OPEN` | Live on the venue order book, no fills yet. |
  | `PARTIAL` | Partially filled; remainder still resting. |
  | `FILLED` | Fully filled. |
  | `CANCELLED` | Cancelled by you or the venue. |
  | `REJECTED` | Rejected at submission by the venue or risk checks. |
  | `EXPIRED` | Expired per the time-in-force policy (e.g., `GTD` deadline reached). |
</Accordion>

Fetch a single order by ID, or list all orders for a subaccount:

<CodeGroup>
  ```python Get order theme={"dark"}
  # GET /v1/orders/{id}
  order = client.orders.get(order_id="ord_8kXq2Lp9")
  print(order["id"], order["status"], order["filled_qty"])
  ```

  ```python List orders theme={"dark"}
  # GET /v1/orders
  orders = client.orders.list(
      subaccount_id=os.environ["MOLECULE_SUBACCOUNT_ID"],
      status="OPEN",  # omit to return all statuses
  )
  for o in orders:
      print(o["id"], o["status"], o["qty"], o["filled_qty"])
  ```

  ```python Poll until terminal theme={"dark"}
  import time

  order_id = "ord_8kXq2Lp9"
  TERMINAL = {"FILLED", "CANCELLED", "REJECTED", "EXPIRED"}

  while True:
      order = client.orders.get(order_id)
      status = order["status"]
      print(status, order.get("filled_qty"))
      if status in TERMINAL:
          break
      time.sleep(0.5)
  ```
</CodeGroup>

<Tip>
  For real-time order updates without polling, subscribe to the WebSocket stream at `/v1/ws/orders` using `client.iter_ws("/v1/ws/orders")`.
</Tip>

***

## Amending an Order

Modify the price or quantity of a resting order with `client.orders.amend()`. Only open or partially filled orders can be amended.

```python theme={"dark"}
# PATCH /v1/orders/{id}
updated = client.orders.amend(
    "ord_8kXq2Lp9",
    price="0.57",
    qty="75",
)
print(updated["id"], updated["price"], updated["qty"])
```

<Note>
  Not all venues support in-flight amends. If the venue requires a cancel-replace, Molecule handles this transparently. Check the returned order object for the current state.
</Note>

***

## Cancelling Orders

Cancel a single order or all open orders for a subaccount.

<CodeGroup>
  ```python Cancel single order theme={"dark"}
  # DELETE /v1/orders/{id}
  result = client.orders.cancel("ord_8kXq2Lp9")
  print(result)
  ```

  ```python Cancel all orders theme={"dark"}
  # POST /v1/orders/cancel-all
  result = client.orders.cancel_all(
      subaccount_id=os.environ["MOLECULE_SUBACCOUNT_ID"]
  )
  print(result)
  ```
</CodeGroup>

<Warning>
  `cancel_all()` cancels every open and partially filled order for the specified subaccount across all venues simultaneously. Use `client.risk.kill_switch(enabled=True)` to halt all activity at the account level.
</Warning>

***

## Batch Orders

Submit multiple orders in a single request to reduce round trips and ensure consistent timing.

```python theme={"dark"}
# POST /v1/orders/batch
orders = [
    {
        "subaccount_id": os.environ["MOLECULE_SUBACCOUNT_ID"],
        "instrument_id": 98712,
        "side": "BUY",
        "outcome": "YES",
        "type": "LIMIT",
        "tif": "GTC",
        "price": "0.48",
        "qty": "100",
        "routing": {"mode": "DIRECT"},
        "client_order_id": "batch-leg-1",
    },
    {
        "subaccount_id": os.environ["MOLECULE_SUBACCOUNT_ID"],
        "instrument_id": 98713,
        "side": "SELL",
        "outcome": "YES",
        "type": "LIMIT",
        "tif": "GTC",
        "price": "0.52",
        "qty": "100",
        "routing": {"mode": "DIRECT"},
        "client_order_id": "batch-leg-2",
    },
]

results = client.orders.batch(orders)
for r in results:
    print(r["client_order_id"], r.get("id"), r.get("status"))
```

<Info>
  Each order in the batch is subject to the same validation and risk checks as individual orders. The response includes one entry per submitted order. A validation failure on one leg does not necessarily cancel the rest — inspect each entry's status independently.
</Info>

***

## Fills

Retrieve the fill history for a subaccount. Fills represent confirmed executions and are the source of truth for realized P\&L.

```python theme={"dark"}
# GET /v1/fills
fills = client.orders.fills(
    subaccount_id=os.environ["MOLECULE_SUBACCOUNT_ID"]
)
for fill in fills:
    print(
        fill["order_id"],
        fill["instrument_id"],
        fill["side"],
        fill["price"],
        fill["qty"],
        fill["timestamp"],
    )
```

<Note>
  Fills are also available via `client.portfolio.fills()`, which calls the same `/v1/fills` endpoint. The `client.orders.fills()` shortcut is provided for convenience when working primarily in the orders namespace.
</Note>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.