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

# Trades

> The trade state machine from execution to settlement or reversal: statuses, settlement windows, the settle and reverse actions, and the webhooks that report each change.

A trade moves money between two of your currency balances at the rate locked in its quote. This page covers what happens after you [execute a trade](/v3/api-reference/trade/execute-trade): the statuses it passes through, what moves it forward, and the two actions you can take on it. How you request a rate and execute against it is on [Quotes](/v3/quotes).

<Note title="Why this matters">
  Funds move when a trade reaches <span class="ofx-enum">EXECUTED</span>, not
  when you create it. A trade created with a <span class="ofx-enum">T1</span> or
  <span class="ofx-enum">T2</span> window waits, and on a per-trade settlement
  account it then waits for you. Read `status` before you assume a balance has
  changed.
</Note>

## Endpoints

| Path | Description | Idempotency-Key |
| - | - | - |
| [`GET /v3/fx/trades/{id}`](/v3/api-reference/trade/get-trade) | Read a trade's current `status` | — |
| [`GET /v3/fx/trades`](/v3/api-reference/trade/list-trades) | List trades, newest first | — |
| [`POST /v3/fx/trades/{id}/settle`](/v3/api-reference/trade/settle-trade) | Finalize a manually settled trade | Required, 24-hr TTL |
| [`POST /v3/fx/trades/{id}/reverse-quote`](/v3/api-reference/trade/generate-reverse-quote) | Preview the cost of unwinding a trade | Required, 30-min TTL |
| [`POST /v3/fx/trades/{id}/reverse`](/v3/api-reference/trade/reverse-trade) | Unwind a trade against a reverse quote | Required, 24-hr TTL |

## State machine

```mermaid theme={"theme":{"light":"poimandres","dark":"poimandres"}}
%%{init: {'theme':'base','themeVariables':{'fontFamily':'Inter, system-ui, sans-serif','fontSize':'13px'}}}%%
stateDiagram-v2
  direction TB
  [*] --> PENDING: POST /v3/fx/trades
  PENDING --> EXECUTED: IMMEDIATE or T0
  PENDING --> LOCKED: T1 or T2
  LOCKED --> EXECUTED: Window opens, auto-settled
  LOCKED --> READY_TO_SETTLE: Window opens, manual settlement
  READY_TO_SETTLE --> EXECUTED: POST .../settle
  READY_TO_SETTLE --> REVERSED: POST .../reverse
  EXECUTED --> [*]
  REVERSED --> [*]

  classDef ok stroke-width:1px
  classDef bad stroke-width:1px
  classDef pending stroke-width:1px
  classDef hold stroke-width:1px
  classDef returned stroke-width:1px
  classDef neutral stroke-width:1px
  class PENDING pending
  class LOCKED neutral
  class READY_TO_SETTLE hold
  class EXECUTED ok
  class REVERSED bad
```

`Trade.status` is a closed enum, and a trade ends in <span class="ofx-enum">EXECUTED</span> or <span class="ofx-enum">REVERSED</span>.

| Status | Meaning | What moves it forward |
| - | - | - |
| <span class="ofx-status-pill ofx-status-pill--purple">PENDING</span> | Created, funds not yet moved | OpenFX, immediately on execution |
| <span class="ofx-status-pill ofx-status-pill--gray">LOCKED</span> | A <span class="ofx-enum">T1</span> or <span class="ofx-enum">T2</span> trade before its settlement window opens | OpenFX, when the window opens |
| <span class="ofx-status-pill ofx-status-pill--yellow">READY\_TO\_SETTLE</span> | The window opened on a manually settled trade | You: [settle](#settle-a-trade) or [reverse](#reverse-a-trade) it |
| <span class="ofx-status-pill ofx-status-pill--green">EXECUTED</span> | Funds have moved. Terminal | Nothing; the trade is complete |
| <span class="ofx-status-pill ofx-status-pill--red">REVERSED</span> | A <span class="ofx-enum">READY\_TO\_SETTLE</span> trade was unwound. Terminal | Nothing; the reversal is its own trade |

## Settlement window

Every trade carries a `settlementWindow` that you choose on the [quote request](/v3/api-reference/trade/create-quote): <span class="ofx-enum">IMMEDIATE</span>, <span class="ofx-enum">T0</span>, <span class="ofx-enum">T1</span>, or <span class="ofx-enum">T2</span>. It defaults to <span class="ofx-enum">T0</span>.

* <span class="ofx-enum">IMMEDIATE</span> and <span class="ofx-enum">T0</span> trades settle synchronously, so the execute response already reads <span class="ofx-enum">EXECUTED</span>.
* <span class="ofx-enum">T1</span> and <span class="ofx-enum">T2</span> trades are future-dated. They sit in <span class="ofx-enum">LOCKED</span> until the window opens.

What happens when the window opens depends on your organization's settlement model, an account-level setting rather than a request option.

| `tradeSettlementMode` | Model | At window open |
| - | - | - |
| <span class="ofx-enum">AUTO</span> | Netted | The trade settles on its own and reaches <span class="ofx-enum">EXECUTED</span>. You take no action |
| <span class="ofx-enum">MANUAL</span> | Per-trade | The trade reaches <span class="ofx-enum">READY\_TO\_SETTLE</span> and waits for you |

The models are compared on [Settlement models](/v3/settlement-models).

## Settle a trade

Settling applies only to a trade in <span class="ofx-enum">READY\_TO\_SETTLE</span> on a <span class="ofx-enum">MANUAL</span> account. It completes the trade at the locked rate and populates `settledAt` and `settlementStartTime`.

```bash cURL theme={"theme":{"light":"poimandres","dark":"poimandres"}}
curl -X POST https://api.openfx.com/v3/fx/trades/tde_5W7guYdHT24JFnRQrZN9y8/settle \
  -H "Authorization: Bearer $OPENFX_JWT" \
  -H "X-Request-Signature: $OPENFX_SIGNATURE" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{}'
```

A successful response wraps a `TradeSettlement` in `data`. The trade is now <span class="ofx-enum">EXECUTED</span>:

```json theme={"theme":{"light":"poimandres","dark":"poimandres"}}
{
  "object": "trade",
  "id": "tde_5W7guYdHT24JFnRQrZN9y8",
  "quoteId": "qte_TmHeAhdFLes63uGgDjcJRx",
  "buyCurrency": "USDC",
  "sellCurrency": "USD",
  "executedAmount": "999.25",
  "status": "EXECUTED",
  "clientReferenceId": "order-123",
  "createdAt": "2026-07-13T10:00:00.000Z",
  "settlementWindow": "T0",
  "settledAt": "2026-07-13T10:02:00.000Z",
  "settlementStartTime": "2026-07-13T10:00:30.000Z"
}
```

| Error | Cause |
| - | - |
| `409` <span class="ofx-enum">TRADE\_NOT\_MANUAL</span> | The account settles automatically, so there is nothing to settle |
| `409` <span class="ofx-enum">TRADE\_NOT\_SETTLEABLE</span> | The trade is already settled, not yet executed, or reversed. Read the trade, then decide |
| `409` <span class="ofx-enum">TRADE\_ALREADY\_SETTLED</span> | The trade has already been settled |

## Reverse a trade

A reversal unwinds a trade in <span class="ofx-enum">READY\_TO\_SETTLE</span> instead of settling it. It takes two calls, so you see the cost before you commit.

<Steps>
  <Step title="Generate a reverse quote">
    [`POST /v3/fx/trades/{id}/reverse-quote`](/v3/api-reference/trade/generate-reverse-quote) returns a time-limited quote. `quoteForSeconds` takes the same closed set of durations as a trade quote: <span class="ofx-enum">3</span>, <span class="ofx-enum">15</span>, <span class="ofx-enum">30</span>, <span class="ofx-enum">45</span>, or <span class="ofx-enum">60</span>.

    ```bash cURL theme={"theme":{"light":"poimandres","dark":"poimandres"}}
    curl -X POST https://api.openfx.com/v3/fx/trades/tde_5W7guYdHT24JFnRQrZN9y8/reverse-quote \
      -H "Authorization: Bearer $OPENFX_JWT" \
      -H "X-Request-Signature: $OPENFX_SIGNATURE" \
      -H "Idempotency-Key: $(uuidgen)" \
      -H "Content-Type: application/json" \
      -d '{ "quoteForSeconds": 30 }'
    ```

    Read `reversalDetails` before you act. `direction` says whether the reversal would <span class="ofx-enum">DEBIT</span> or <span class="ofx-enum">CREDIT</span> your balance, and `differentialAmount` is the unsigned magnitude in `currency`.

    ```json theme={"theme":{"light":"poimandres","dark":"poimandres"}}
    {
      "object": "quote",
      "id": "qte_TmHeAhdFLes63uGgDjcJRx",
      "buyCurrency": "USD",
      "sellCurrency": "USDC",
      "quoteAmount": "122.93850769",
      "createdAt": "2026-07-13T10:00:00.000Z",
      "expiresAt": "2026-07-13T10:00:30.000Z",
      "reversalDetails": {
        "direction": "DEBIT",
        "differentialAmount": "0.75",
        "currency": "USD"
      },
      "buyAmount": "122.93850769"
    }
    ```
  </Step>

  <Step title="Execute the reversal">
    [`POST /v3/fx/trades/{id}/reverse`](/v3/api-reference/trade/reverse-trade) names the reverse quote's `id` as `quoteId`. Send it before `expiresAt`. An optional `clientReferenceId` labels the reversal.

    ```bash cURL theme={"theme":{"light":"poimandres","dark":"poimandres"}}
    curl -X POST https://api.openfx.com/v3/fx/trades/tde_5W7guYdHT24JFnRQrZN9y8/reverse \
      -H "Authorization: Bearer $OPENFX_JWT" \
      -H "X-Request-Signature: $OPENFX_SIGNATURE" \
      -H "Idempotency-Key: $(uuidgen)" \
      -H "Content-Type: application/json" \
      -d '{ "quoteId": "qte_TmHeAhdFLes63uGgDjcJRx", "clientReferenceId": "order-123-reversal" }'
    ```

    The response is a new trade, created already <span class="ofx-enum">EXECUTED</span>. Its `originalTradeId` points at the trade it unwound, and the original trade reads <span class="ofx-enum">REVERSED</span>.

    ```json theme={"theme":{"light":"poimandres","dark":"poimandres"}}
    {
      "object": "trade",
      "id": "tde_8XvH7fKH8hcFyopFF2PFas",
      "quoteId": "qte_TmHeAhdFLes63uGgDjcJRx",
      "buyCurrency": "USD",
      "sellCurrency": "USDC",
      "executedAmount": "999.25",
      "status": "EXECUTED",
      "clientReferenceId": "order-123-reversal",
      "createdAt": "2026-07-13T10:00:00.000Z",
      "settlementWindow": "T0",
      "settlementStartTime": null,
      "originalTradeId": "tde_5W7guYdHT24JFnRQrZN9y8",
      "reversalDetails": {
        "direction": "CREDIT",
        "differentialAmount": "0.75",
        "currency": "USD"
      }
    }
    ```
  </Step>
</Steps>

A trade that is outside its reversal window, or already reversed or settled, returns `409` <span class="ofx-enum">TRADE\_NOT\_REVERSIBLE</span>.

## Track a trade

Trade webhooks report each transition, so you don't need to poll. The three events map one-to-one onto the statuses a trade reaches under your own action or OpenFX's.

| Webhook | Fires when | `data.status` |
| - | - | - |
| [<span class="ofx-enum">fx.trade.ready\_to\_settle</span>](/v3/webhooks/trades/trade-ready-to-settle) | A future-dated, manually settled trade reaches its window and awaits settle | <span class="ofx-enum">READY\_TO\_SETTLE</span> |
| [<span class="ofx-enum">fx.trade.settled</span>](/v3/webhooks/trades/trade-settled) | A trade reaches <span class="ofx-enum">EXECUTED</span>, immediately or once settled | <span class="ofx-enum">EXECUTED</span> |
| [<span class="ofx-enum">fx.trade.reversed</span>](/v3/webhooks/trades/trade-reversed) | A <span class="ofx-enum">READY\_TO\_SETTLE</span> trade is unwound | <span class="ofx-enum">REVERSED</span> |

An <span class="ofx-enum">AUTO</span> account only receives <span class="ofx-enum">fx.trade.settled</span>. A <span class="ofx-enum">MANUAL</span> account can receive all three.

The webhook `data` is close to the `Trade` resource but not identical. It adds `tradeSettlementMode` and `settledAt`, and on <span class="ofx-enum">fx.trade.reversed</span> it adds `reversalTradeId` and `reversalDetails`. `settledAt` is `null` on a reversal, because a reversal only ever unwinds a trade that was never settled. [Webhooks setup](/v3/webhooks/setup) covers delivery and signature verification.

If you can't receive webhooks yet, poll [`GET /v3/fx/trades/{id}`](/v3/api-reference/trade/get-trade) and read `status`.

## Effect on balances and exposure

A trade changes your [balances](/v3/balances) when it reaches <span class="ofx-enum">EXECUTED</span>. Read [`GET /v3/fx/balances`](/v3/api-reference/trade-settlement/list-balances) afterward; the trade response does not carry the balance impact.

Before then, an open trade counts against your exposure limit. A <span class="ofx-enum">LOCKED</span> trade counts as `settlableLater` exposure and a <span class="ofx-enum">READY\_TO\_SETTLE</span> trade as `settlableNow`. See [Exposure](/v3/exposure#settlable-now-vs-settlable-later).

## Common mistakes

* **Expecting <span class="ofx-enum">EXECUTED</span> from a future-dated trade.** A <span class="ofx-enum">T1</span> or <span class="ofx-enum">T2</span> trade returns before its window opens, so its funds have not moved.
* **Calling settle on an automatic account.** It returns `409` <span class="ofx-enum">TRADE\_NOT\_MANUAL</span>. Netted accounts never settle by hand.
* **Letting a reverse quote lapse.** The reversal must reach `POST /v3/fx/trades/{id}/reverse` before `expiresAt`; generate a new reverse quote with a new idempotency key.
* **Reading the reversal as the original.** The reversal is a separate trade with its own `id`. Match it to the original through `originalTradeId`, or `reversalTradeId` on the webhook.
* **Retrying a failed execution blind.** After <span class="ofx-enum">TRADE\_EXECUTION\_FAILED</span>, call `GET /v3/fx/trades/{id}` to check state first.

## What's next

<CardGroup cols={2}>
  <Card title="Settlement models" icon="https://public-assets.openfx.com/docs/icons/settlement-models.svg" href="/v3/settlement-models">
    Netted and per-trade settlement, side by side.
  </Card>

  <Card title="Balances" icon="https://public-assets.openfx.com/docs/icons/balances.svg" href="/v3/balances">
    What changes in each currency when a trade executes.
  </Card>

  <Card title="Trade webhooks" icon="https://public-assets.openfx.com/docs/icons/webhook-trades.svg" href="/v3/webhooks/trades/trade-ready-to-settle">
    Ready-to-settle, settled, and reversed events.
  </Card>

  <Card title="Exposure" icon="https://public-assets.openfx.com/docs/icons/exposure.svg" href="/v3/exposure">
    Exposure-limit usage from trades that have not settled.
  </Card>
</CardGroup>
