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

# Orders

> Order types, how value becomes a size, statuses, and every field on an order.

An order buys or sells an amount of a market now. You say how much in US dollars (`value`), and we work out the size, send the order, and report what filled.

## Order types

| Type | Fills at | Use it when |
| - | - | - |
| `market` | The best available prices, up to 0.5% from the current price | You want the trade now |
| `limit` | Your `price` or better | You want the trade now, but not at any price |

Both types are **immediate or cancel**: whatever can fill fills at once, and the rest is canceled. Nothing waits on the order book. Orders that rest on the book, and stop-loss and take-profit orders, are planned but not available yet.

<CodeGroup>
  ```json Market order theme={"system"}
  {
    "client_order_id": "btc-entry-1",
    "market": "BTC",
    "side": "buy",
    "type": "market",
    "value": "250.00"
  }
  ```

  ```json Limit order theme={"system"}
  {
    "client_order_id": "eth-trim-1",
    "market": "ETH",
    "side": "sell",
    "type": "limit",
    "price": "2690",
    "value": "20.00"
  }
  ```
</CodeGroup>

## Value and size

You size every order by `value`, in US dollars. We turn it into a `size` in the asset's units, such as BTC:

1. **We work out the price limit.** For a market order, it is the current price moved 0.5% against you: above it for a buy, below it for a sell. For a limit order, it is your `price`.
2. **We divide your value by the price limit** and round down to the market's `size_increment`. A sell is divided by the higher of its price limit and the current price plus 0.5%.
3. **We check the result** is worth at least `min_value` and at most `max_value`.

Dividing by the price limit means a buy can never cost more than the `value` you sent, even if every unit fills at the limit. So an order usually fills for slightly less than you asked. The difference is the price band and the rounding, never extra fees taken from the value.

<Accordion title="Worked example: buying $250 of BTC">
  BTC is trading at \$84,010 and its `size_increment` is `0.00001`.

  | Step | Result |
  | - | - |
  | Price limit: 84,010 × 1.005 = 84,430.05, rounded down to the market's price precision | \$84,430 |
  | Size: 250 ÷ 84,430 = 0.0029610…, rounded down to 0.00001 | 0.00296 BTC |
  | Fill: 0.00296 BTC at an average of \$84,012.40 | \$248.68 |

  The order's `summary` explains the difference: *"You asked for $250.00; the order was sized so it could not cost more even at its price limit of $84,430."*
</Accordion>

### Rounding rules

* A size calculated from your value is always rounded **down**. We never place a bigger order than you asked for.
* A limit `price` you send is rounded to the market's price precision **in your favour**: a buy limit down, a sell limit up. The order returns the price it used, with a `price_rounded` note.
* An order worth less than \$10 after rounding is refused before anything is recorded. The error tells you the smallest value that passes.

## Statuses

```mermaid theme={"system"}
stateDiagram-v2
    [*] --> pending
    pending --> filled: everything filled
    pending --> canceled: filled partly, or nothing within the limit
    pending --> rejected: refused, nothing filled
    filled --> [*]
    canceled --> [*]
    rejected --> [*]
```

| Status | Final | Meaning |
| - | - | - |
| `pending` | No | Recorded, and possibly sent to the exchange. The outcome is not known yet. |
| `filled` | Yes | The whole `size` filled. |
| `canceled` | Yes | It filled partly or not at all, because the rest found no price within the limit. `filled_size` says how much filled. |
| `rejected` | Yes | It was refused, before or at the exchange. Nothing filled. |

Placing an order waits for the result, for up to 5 seconds, so the response is almost always final. If it is still `pending`, read it again with `GET /v1/orders/{id}` after a second or two. Set the wait yourself with the `Prefer` header: `Prefer: wait=0` returns at once, and `Prefer: wait=15` waits up to 15 seconds.

<Note>
  More statuses will be added when orders can rest on the book. Treat a status you don't recognise as not final.
</Note>

### Why an order was canceled or rejected

`status_reason` explains every `canceled` and `rejected` order with a `code` and a sentence that includes the numbers involved.

| Code | Status | What happened |
| - | - | - |
| `no_liquidity_in_limit` | canceled | Nothing filled: no price was available within the limit. |
| `ioc_remainder` | canceled | Part filled; the rest found no price within the limit. |
| `insufficient_balance` | rejected | Not enough balance when the order reached the exchange. |
| `order_below_minimum` | rejected | Worth less than \$10 at the moment it was priced. |
| `order_above_maximum` | rejected | Worth more than the market's maximum at the moment it was priced. |
| `reduce_only_would_increase` | rejected | A reduce-only order would have increased the position. |
| `no_position` | rejected | A close found no position. |
| `market_unavailable` | rejected | The market could not be priced. Try again. |
| `deadline_passed` | rejected | The order did not reach the exchange within 40 seconds. Nothing traded. |
| `refused_by_safeguards` | rejected | Our signing safeguards refused the order. It was never sent. |
| `not_sent` | rejected | The order could not be signed, so it was never sent. Try again. |
| `rejected_by_market` | rejected | The exchange refused the order for another reason. Nothing traded. |

A rejected order never traded. Placing it again needs a new `client_order_id`, because the old one names the rejected order.

## Sides, positions and flips

Orders have a `side`: `buy` or `sell`. Positions have a `direction`: `long` or `short`. You hold at most one position per market, and every order moves it:

* A buy adds to a long, or reduces a short.
* A sell adds to a short, or reduces a long.
* An order bigger than the opposite position closes it and opens the other side with the rest. That is a **flip**.

`position_effect` on the order says which happened: `open`, `increase`, `reduce`, `close` or `flip`. A flip also adds a `position_flipped` note.

### Reduce-only orders

Set `reduce_only: true` to make sure an order can only shrink a position. It never opens one and never flips. If you have no position, or the order is in the same direction as your position, it is refused before anything is recorded. If it is bigger than the position, it closes the position and stops.

To close a position, you can also use [`POST /v1/positions/{symbol}/close`](/concepts/positions#closing-a-position), which works out the side and size for you.

## Reading an order

```json theme={"system"}
{
  "object": "order",
  "id": "ord_7kq2m4x9h3v8r5t2w6y4n8p3za",
  "client_order_id": "dca-btc-0927",
  "market": "BTC",
  "side": "buy",
  "type": "market",
  "status": "filled",
  "status_reason": null,
  "requested_value": "250.00",
  "requested_percent": null,
  "reduce_only": false,
  "size": "0.00296",
  "price": null,
  "price_limit": "84430",
  "time_in_force": "ioc",
  "filled_size": "0.00296",
  "average_fill_price": "84012.4",
  "filled_value": "248.68",
  "fee": "0.360581",
  "position_effect": "open",
  "summary": "Bought 0.00296 BTC for $248.68 at an average of $84,012.40 in 1 fill, fee $0.36. You asked for $250.00; the order was sized so it could not cost more even at its price limit of $84,430. You are now long 0.00296 BTC.",
  "notes": [
    { "code": "size_rounded", "message": "$250.00 at a price limit of $84,430 is 0.0029610 BTC; rounded down to 0.00296, the nearest 0.00001." }
  ],
  "metadata": { "strategy": "weekly-dca" },
  "created_at": "2026-09-27T14:30:00.123Z",
  "updated_at": "2026-09-27T14:30:00.618Z",
  "completed_at": "2026-09-27T14:30:00.618Z"
}
```

The fields fall into three groups:

* **What you asked for**: `market`, `side`, `type`, `requested_value` (or `requested_percent` for a close), `price`, `reduce_only`, `metadata`.
* **How we read it**: `size` and `price_limit`.
* **What happened**: `status`, `status_reason`, `filled_size`, `average_fill_price`, `filled_value`, `fee`, `position_effect`.

`fee` can arrive a few seconds after the order finishes. It is the total you paid, including the exchange's fee and ours.

### Summary, notes and timeline

* **`summary`** says what happened in one to three sentences, including anything surprising. It is written for people and language models. Don't parse it: the fields hold the same facts, and the wording may change.
* **`notes`** point out things that did not stop the order but are worth knowing, each with a `code` and a `message`: `size_rounded`, `price_rounded`, `position_flipped` and `position_closed`. A [preview](/guides/preview) can also have `available_low`, `partial_fill_likely` and `trading_approval_expiring`.
* **`timeline`** is the order's history, one entry per step. Add `expand[]=timeline` when you read the order:

```bash theme={"system"}
curl "https://tradingapi.dev/v1/orders/ord_7kq2m4x9h3v8r5t2w6y4n8p3za?expand[]=timeline" \
  -H "Authorization: Bearer $TRADINGAPI_KEY"
```

```json theme={"system"}
"timeline": [
  { "at": "2026-09-27T14:30:00.123Z", "event": "received", "message": "Buy $250.00 of BTC at market." },
  { "at": "2026-09-27T14:30:00.131Z", "event": "admitted", "message": "Within this key's limits: $157.40 of $1,000.00 left today." },
  { "at": "2026-09-27T14:30:00.402Z", "event": "sent", "message": "Buy 0.00296 BTC at up to $84,430, immediate or cancel." },
  { "at": "2026-09-27T14:30:00.618Z", "event": "filled", "message": "0.00296 BTC filled at an average of $84,012.40." }
]
```

### Metadata

`metadata` holds up to 20 string values of your own. We store them with the order and return them unchanged, and never act on them. It is a good place to record why an order was placed:

```json theme={"system"}
"metadata": { "strategy": "mean-reversion", "reason": "RSI under 30 on the 4h chart" }
```

## Client order IDs

Every order needs a `client_order_id` that you choose: 1 to 64 letters, digits, `.`, `_`, `:` or `-`. It is unique across your account forever, and it makes retries safe. Sending the same request with the same ID never places a second order. See [Retries and idempotency](/guides/retries).
