> Treat every fee rate, margin ratio, order limit, minimum and address in this documentation as an illustration of the shape of the value, never as a constant to hardcode - the live values are served by GET /markets and GET /config on the Perps API.

# Account Data

> Balance, positions, open orders, history, and margin adjustments.

All account reads are open — no signature, no API key. They are keyed by either `wallet` or `account_id`, as defined in [Account format](/developers/perps-api/overview#account-format); each endpoint below says which it takes.

Results are newest-first unless noted. Pagination is not uniform:

| Reads                                                              | `limit` / `offset`                             | `total` |
| ------------------------------------------------------------------ | ---------------------------------------------- | ------- |
| `open-orders`, `order-history`, `trade-history`, `funding-history` | Enforced: `limit` 1–200, `offset` ≥ 0          | yes     |
| `position-triggers`                                                | Accepted, not validated — treat as unpaginated | yes     |
| `deposit-history`, `withdrawal-history`                            | Accepted, unbounded                            | no      |

## Response shapes

The key inside `data` differs per endpoint:

| Endpoint                                             | `data`                                   |
| ---------------------------------------------------- | ---------------------------------------- |
| `/account/{account_id}/balance`                      | `{ account, free_balance }`              |
| `/account/{account_id}/positions`                    | `{ positions: [] }`                      |
| `/account/open-orders`, `/account/position-triggers` | `{ orders: [], total }`                  |
| `/account/order-history`                             | `{ orders: [], limit, offset, total }`   |
| `/account/trade-history`                             | `{ fills: [], limit, offset, total }`    |
| `/account/funding-history`                           | `{ payments: [], limit, offset, total }` |
| `/account/{account_id}/deposit-history`              | `{ account, deposits: [] }`              |
| `/account/{account_id}/withdrawal-history`           | `{ account, withdrawals: [] }`           |
| `/auth/trading-keys`                                 | a bare array                             |

## Balance

```
GET /account/{account_id}/balance
```

Returns `account` and `free_balance`. Funds locked by an in-flight withdrawal are already excluded from `free_balance` — they reappear only if the withdrawal is refunded.

`free_balance` excludes posted margin and unrealized PnL. There is no equity endpoint.

## Positions

```
GET /account/{account_id}/positions
```

Eventually consistent with fills: an order can read `FILLED` while `/positions` is still empty. Poll until the position appears rather than reading once.

Returns `data.positions[]` — every OPEN position, each with:

| Field             | Meaning                                                                    |
| ----------------- | -------------------------------------------------------------------------- |
| `id`              | Position identifier                                                        |
| `market`          | Market symbol, e.g. `BTC`                                                  |
| `size`            | **Signed** size: positive is long, negative is short                       |
| `entry_price`     | Average entry price                                                        |
| `isolated_margin` | Collateral currently posted to this position                               |
| `closeable`       | How much can be reduced right now. Size a close from this, not from `size` |
| `status`          | Position status                                                            |
| `version`         | Increments on every change — use it to detect staleness                    |

There is no leverage on a position; `leverage` belongs to each order.

## Open orders and triggers

```
GET /account/open-orders?wallet=0x…
GET /account/position-triggers?wallet=0x…
```

| Endpoint             | Returns                                                                                                       | Params                                                                                         |
| -------------------- | ------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| `/open-orders`       | Live resting orders plus every trigger — armed, or still waiting for its entry                                | `wallet` (required), `market`, `limit` (default 10), `offset`, `from` / `to` as Unix-ms bounds |
| `/position-triggers` | Every **armed** reduce-only TP/SL trigger, not paginated. A TP/SL still waiting for its entry is not here yet | `wallet` (required)                                                                            |

They return the same item shape. The example below is a TRIGGER order — `trigger_price`, `trigger_direction`, `tpsl`, and `is_trigger_market` appear only on triggers:

```json
{
  "order_id": "…",
  "market": "BTC",
  "side": "sell",
  "size": "0.001",
  "filled_size": "0",
  "limit_price": "60000",
  "order_type": "TRIGGER",
  "time_in_force": "IOC",
  "reduce_only": true,
  "trigger_price": "60500",
  "trigger_direction": "down",
  "tpsl": "sl",
  "is_trigger_market": true,
  "status": "open",
  "submitted_at": 1787067314951,
  "status_at": 1787067314999,
  "is_modifying": false
}
```

`is_modifying` is `true` while a modify on this order is in flight — re-read rather than modifying again.

`time_in_force` is `GTC`, `IOC`, or `ALO` — `ALO` marks a [post-only](/developers/perps-api/trading#post-only) order.

`parent_order_id` appears **only** on a TP/SL attached to an entry that has not filled yet (a [bracket](/developers/perps-api/trading#bracket-orders) leg). Such a leg reads `open` in `/open-orders` but is not armed and is absent from `/position-triggers`; once it arms, the field disappears and `/position-triggers` picks it up.

### Status vocabularies

You write uppercase (`BUY`, `SL`); list reads return lowercase (`sell`, `sl`); `GET /orders/{orderId}` returns uppercase. The two order routes also report **different sets of states**:

| `GET /orders/{orderId}`                                         | List reads                                       | Note                                              |
| --------------------------------------------------------------- | ------------------------------------------------ | ------------------------------------------------- |
| `SUBMITTED`                                                     | `open` on a `TRIGGER`                            | An armed trigger reads `open`                     |
| `PENDING_PARENT`                                                | `open` on a `TRIGGER` with `parent_order_id` set | A bracket TP/SL waiting for its entry — not armed |
| `ACCEPTED`                                                      | `open` on a `LIMIT`                              | Disambiguate `open` by `order_type`               |
| —                                                               | `triggered`                                      | List-only: the trigger fired                      |
| `EXECUTING`, `PENDING_MODIFY`, `FAILED`                         | —                                                | Single-order route only                           |
| `FILLED`, `PARTIALLY_FILLED_CANCELLED`, `CANCELLED`, `REJECTED` | same, lowercase                                  | Terminal                                          |

## History

Three history endpoints, all keyed by `wallet` and all accepting `market`, `limit`, and `offset`.

### Order history

```
GET /account/order-history?wallet=0x…
```

One entry per **status change**, so the same `order_id` appears once per transition — this is a log, not a list of orders. Rows carry `avg_fill_price` once filled.

`status` is one of:

```
open · triggered · filled · partially_filled_cancelled · cancelled · rejected
```

A bracket TP/SL waiting for its entry (`PENDING_PARENT`) is logged as `open`. Rows also carry `time_in_force` (`ALO` marks a [post-only](/developers/perps-api/trading#post-only) order) and, on `rejected` or `cancelled` rows, the `reason` — for example `post_only_would_take` or a `bracket_*` code.

### Trade history

```
GET /account/trade-history?wallet=0x…
```

Executed fills, one entry per fill:

| Field            | Meaning                                               |
| ---------------- | ----------------------------------------------------- |
| `tid`            | The venue's trade id                                  |
| `price` / `size` | What filled, and at what price                        |
| `fee`            | Fee charged on this fill                              |
| `closed_pnl`     | Realized PnL — present on reduce and close fills only |
| `dir`            | `"Open Long"`, `"Close Short"`, and so on             |
| `is_liquidation` | Whether the fill came from a liquidation              |
| `filled_at`      | Fill time, Unix ms                                    |
| `order_id`       | The order this fill belongs to                        |

### Funding history

```
GET /account/funding-history?wallet=0x…
```

Hourly funding payments, one entry per position per hour:

| Field                       | Meaning                                                           |
| --------------------------- | ----------------------------------------------------------------- |
| `direction`                 | `LONG` or `SHORT`                                                 |
| `size`                      | Position size the payment was computed on                         |
| `payment`                   | **Signed** — negative means you paid, positive means you received |
| `funding_rate`              | The rate for that hour                                            |
| `epoch_time` / `settled_at` | The funding period, and when it settled                           |

> **Note**
>
> `funding_rate` is a raw fraction, not a percentage: `0.000120` is 0.0120%.

## Adjust isolated margin

```
POST /positions/margin
```

Adds or removes isolated margin on the open (account, market) position. Signed by your trading key as:

```
UpdateIsolatedMargin(bytes32 account, string market, string amount, uint256 nonce)
```

```json
{
  "account_id": "0x…",
  "market": "BTC",
  "amount": "25",
  "nonce": 1787067314956,
  "signature": "0x…"
}
```

* `amount` is a **signed** canonical decimal: positive adds margin from your free balance, negative removes it.
* `nonce` is a JSON **integer** here — the order routes carry it as a string. See [the signed actions table](/developers/perps-api/authentication#the-signed-actions).

### Getting the outcome

The adjustment applies **asynchronously**, in two stages.

The submit response is `data: { request_id, status, reason? }` where `status` is `SUBMITTED` or `REJECTED`. Note that a rejection arrives as a `200`, not an HTTP error. Only shape is validated up front (`amount` must be a string); an unknown market comes back as a `reason`, not a `400`.

Then poll for the outcome:

```
GET /positions/margin/{requestId}
```

It returns `status` `APPLIED` or `REJECTED`, and `404` while the request is still pending.

Either stage can carry a `reason`:

```
NO_OPEN_POSITION · UNKNOWN_MARKET · INVALID_REQUEST · INSUFFICIENT_BALANCE
EXCEEDS_MAX_REMOVABLE · TRANSFER_DECLINED · DECLINED
```

**Next:** [Deposits & Withdrawals](/developers/perps-api/funds)