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

# Orderbook Trading

> Limit and market orders, time-in-force, direction, order flags, trigger and algo orders, replace, and cancellation.

Every order is placed with `private/order`, a signed [action](/authentication/action-signing) against the
`TRADE_MODULE`. The same payload shape describes limit and market orders, resting and
immediate orders, and (with a few extra fields) trigger and algo orders. This page covers the
enums and flags that shape order behaviour; see the **API Reference** tab for exact
field types and the full request/response schemas.

<Note>
  Prices, amounts, and fees (`limit_price`, `amount`, `max_fee`, `trigger_price`, `extra_fee`) are decimal strings. The
  signer signs the fixed-point encoding of these values as part of the EIP-712 action — see [Action
  signing](/authentication/action-signing).
</Note>

## Order type

`order_type` selects how the order interacts with the book. Default `limit`.

| Value    | Behaviour                                                                                 |
| -------- | ----------------------------------------------------------------------------------------- |
| `limit`  | Rests on the book at `limit_price` (subject to time-in-force).                            |
| `market` | Crosses the book immediately; any unfilled portion is cancelled rather than left resting. |

<Warning>
  `limit_price` is **required even for market orders** — it is a component of the order signature. For a market order it
  acts as a worst-acceptable price bound; the unfilled remainder is cancelled instead of resting.
</Warning>

## Time in force

`time_in_force` controls resting vs. immediate execution. Default `gtc`.

| Value       | Behaviour                                                                                      |
| ----------- | ---------------------------------------------------------------------------------------------- |
| `gtc`       | Good til cancelled — rests until filled, cancelled, or the signature expires.                  |
| `post_only` | Maker-only limit order; see [`reject_post_only`](#post-only) for cross handling.               |
| `fok`       | Fill or kill — rejected unless fully filled immediately.                                       |
| `ioc`       | Immediate or cancel — fills what it can at the limit (or market) price; the rest is cancelled. |

Orders always expire at `signature_expiry_sec` regardless of time-in-force. `market`, `ioc`,
and `fok` orders never leave a resting order in the book.

## Direction

`direction` is `buy` or `sell`.

## Order flags

<ParamField body="reject_post_only" type="boolean" default="true">
  Applies to `post_only` orders. When `true`, a post-only order that would cross the book is rejected. When `false`, its
  limit price is instead adjusted to one tick away from the best bid/offer so it rests as a maker order.
</ParamField>

<ParamField body="reduce_only" type="boolean" default="false">
  When `true`, the order can only reduce an existing position — never increase it. If the amount exceeds the current
  position size, the order fills up to that size and cancels the remainder. Supported only for market orders and
  non-resting limit orders (`ioc` or `fok`).
</ParamField>

<ParamField body="mmp" type="boolean" default="false">
  Tags the order for [Market Maker Protection](/trading/market-maker-protection). Tagged orders count toward the MMP counters
  and are cancelled when protection trips.
</ParamField>

<ParamField body="label" type="string">
  Optional client-defined tag (max 64 chars). Enables bulk cancel via `private/cancel_by_label`.
</ParamField>

`max_fee` is the max fee per unit of volume the signer accepts; the order is rejected if the
estimated fee exceeds it. Optional advanced fields include `referral_code`, `client`,
`reject_timestamp`, `extra_fee`, and `is_atomic_signing` (EIP-1271 atomic-signing orders).

### Place an order

<CodeGroup>
  ```typescript TypeScript (SDK) theme={null}
  import { DeriveClient } from '@derivexyz/sdk';

  const client = new DeriveClient({
    network: 'mainnet',
    wallet: process.env.PRIVATE_KEY!,
  });
  await client.connect();
  await client.login();

  const { order, trades } = await client.orders.place({
    subaccountId: 1234,
    instrumentName: 'ETH-PERP',
    direction: 'buy',
    orderType: 'limit',
    timeInForce: 'gtc',
    amount: '1.5',
    limitPrice: '3000',
    maxFee: '10',
    reduceOnly: false,
    mmp: false,
  });

  console.log(order.order_id, order.order_status);
  ```

  ```python Python (SDK) theme={null}
  import asyncio
  from decimal import Decimal

  from derive_py import WebSocketClient
  from derive_py.data_types import Direction, OrderType
  from derive_py.data_types.generated_models import TimeInForce


  async def main():
      client = WebSocketClient.from_env()
      await client.connect()

      response = await client.orders.create(
          instrument_name="ETH-PERP",
          direction=Direction.buy,
          order_type=OrderType.limit,
          time_in_force=TimeInForce.gtc,
          amount=Decimal("1.5"),
          limit_price=Decimal("3000"),
          max_fee=Decimal("10"),
          reduce_only=False,
          mmp=False,
      )
      print(response.order.order_id, response.order.order_status)

      await client.disconnect()


  asyncio.run(main())
  ```

  ```rust Rust (SDK) theme={null}
  use bigdecimal::BigDecimal;
  use derive_rs::{
      Environment, WsClient,
      actions::OrderArgs,
      models::{Direction, OrderType, TimeInForce},
  };

  #[tokio::main]
  async fn main() -> Result<(), Box<dyn std::error::Error>> {
      let client = WsClient::new(
          Environment::Mainnet,
          Some(std::env::var("DERIVE_PRIVATE_KEY")?),
          Some(std::env::var("DERIVE_WALLET")?),
          Some(1234),
      )
      .await?;
      client.login().await?;

      // max_fee and the nonce/signature/expiry are filled in by the SDK.
      let order = OrderArgs::builder()
          .instrument_name("ETH-PERP".to_string())
          .direction(Direction::Buy)
          .order_type(OrderType::Limit)
          .time_in_force(TimeInForce::Gtc)
          .amount(BigDecimal::from(1))
          .limit_price(BigDecimal::from(3000))
          .reduce_only(false)
          .mmp(false)
          .build();

      let response = client.orders().place(order).await?;
      println!("{} {:?}", response.order.order_id, response.order.order_status);
      Ok(())
  }
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.derive.xyz/v3/order \
    -H "Content-Type: application/json" \
    -H "X-DeriveWallet: 0xYourWallet" \
    -H "X-DeriveTimestamp: 1695836058725" \
    -H "X-DeriveSignature: 0x…" \
    -d '{
      "subaccount_id": 1234,
      "instrument_name": "ETH-PERP",
      "direction": "buy",
      "order_type": "limit",
      "time_in_force": "gtc",
      "amount": "1.5",
      "limit_price": "3000",
      "max_fee": "10",
      "reduce_only": false,
      "mmp": false,
      "nonce": "1695836058725001000",
      "signature_expiry_sec": 1695836358,
      "signer": "0xYourWalletOrSessionKey",
      "signature": "0x…"
    }'
  ```

  ```json Request theme={null}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "private/order",
    "params": {
      "subaccount_id": 1234,
      "instrument_name": "ETH-PERP",
      "direction": "buy",
      "order_type": "limit",
      "time_in_force": "gtc",
      "amount": "1.5",
      "limit_price": "3000",
      "max_fee": "10",
      "reduce_only": false,
      "mmp": false,
      "nonce": "1695836058725001000",
      "signature_expiry_sec": 1695836358,
      "signer": "0xYourWalletOrSessionKey",
      "signature": "0x…"
    }
  }
  ```

  ```json Response theme={null}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "result": {
      "order": {
        "order_id": "8f7e…",
        "subaccount_id": 1234,
        "instrument_name": "ETH-PERP",
        "direction": "buy",
        "order_type": "limit",
        "time_in_force": "gtc",
        "order_status": "open",
        "amount": "1.5",
        "filled_amount": "0",
        "limit_price": "3000",
        "average_price": "0",
        "mmp": false,
        "nonce": "1695836058725001000"
      },
      "trades": []
    }
  }
  ```
</CodeGroup>

<Tip>
  Preview an order's price and fee without placing it using `public/order_quote` (unauthenticated) or
  `private/order_quote` (authenticated). Both take the **same fully-signed order payload** as `private/order` (including
  `nonce`, `signer`, `signature`, and `signature_expiry_sec`) — they simply return the quote instead of resting the
  order.
</Tip>

## Trigger (conditional) orders

Supply the trigger fields to submit a stop-loss or take-profit that stays dormant
(`order_status: untriggered`) until its trigger price is reached, then enters the book.

| Field                | Values                   | Notes                                |
| -------------------- | ------------------------ | ------------------------------------ |
| `trigger_type`       | `stoploss`, `takeprofit` | Required for a trigger order.        |
| `trigger_price_type` | `mark`, `index`          | Reference price the trigger watches. |
| `trigger_price`      | decimal string           | Price at which the order activates.  |

<Info>
  `trigger_price_type: index` is defined in the schema but not yet supported by the matching engine — use `mark`.
</Info>

Query and cancel trigger orders with `private/get_trigger_orders`,
`private/cancel_trigger_order` (by `order_id`), and `private/cancel_all_trigger_orders`.

## Algo orders

An algo order (e.g. slice-based execution) is submitted by supplying `algo_type` alongside
`algo_duration_sec` and `algo_num_slices`. Its lifecycle status is `algo_active`. Trigger and
algo fields are **mutually exclusive** — an order carrying both is rejected.

<Info>`twap` is currently the only supported `algo_type`; any other value is rejected.</Info>

Query and cancel algo orders with `private/get_algo_orders`, `private/cancel_algo_order`
(by `order_id`), and `private/cancel_all_algo_orders`.

## Replace (atomic cancel + replace)

`private/replace` atomically cancels an existing order and places a new one in a single call —
avoiding the race where a separate cancel-then-place leaves you briefly out of the book. The
payload is a `private/order` params object plus the cancel-target fields:

| Field                    | Notes                                                                                             |
| ------------------------ | ------------------------------------------------------------------------------------------------- |
| `order_id_to_cancel`     | The order to replace.                                                                             |
| `nonce_to_cancel`        | Cancel target by nonce (alternative to `order_id_to_cancel`).                                     |
| `expected_filled_amount` | Optional guard — the replace is rejected if the target's filled amount has moved past this value. |

## Cancelling orders

<CardGroup cols={2}>
  <Card title="Single order" icon="xmark">
    `private/cancel` — by `order_id` (plus `instrument_name`, `subaccount_id`).
  </Card>

  <Card title="By nonce" icon="hashtag">
    `private/cancel_by_nonce` — cancels the order(s) for a `nonce` on an `instrument_name`.
  </Card>

  <Card title="By instrument" icon="layer-group">
    `private/cancel_by_instrument` — all open orders on one `instrument_name`.
  </Card>

  <Card title="By label" icon="tag">
    `private/cancel_by_label` — all orders carrying a `label` (optionally scoped to one instrument).
  </Card>
</CardGroup>

`private/cancel_all` cancels every open order on a subaccount. Set `cancel_trigger_orders` and
`cancel_algo_orders` to also clear untriggered trigger orders and active algo orders.

<Note>For multi-leg block trades, use the [RFQ](/trading/rfq) workflow rather than individual orders.</Note>

Order-placing and cancel methods are rate-limited under the `matching` class (with
`cancel_all` under `endpoint` and `cancel_by_label` under `custom`); see
[Rate limits](/rate-limits).


## Related topics

- [Orderbook](/api-reference/channels/orderbook.md)
- [RFQ Trading](/trading/rfq.md)
- [Instrument Names](/trading/instrument-names.md)
