> ## 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.

# Quotes

> Atomic FX trades: discover supported pairs, quote a rate, execute the trade against the quote.

OpenFX trading is a quote-then-execute model. You request a quote (a rate locked in for 3 seconds by default), then execute a trade against that quote. Execution is atomic: it either succeeds at the quoted rate or it fails. The same flow covers every conversion: fiat to fiat, fiat to stablecoin, stablecoin to stablecoin.

<Note title="Why this matters">
  Splitting quote and trade forces deterministic execution: the rate you saw is
  the rate that executes, or the trade fails; execution never silently
  re-prices. Your retry strategy follows from this. After <span class="ofx-enum">QUOTE\_EXPIRED</span> or
  <span class="ofx-enum">TRADE\_EXECUTION\_FAILED</span>, request a new quote and retry the trade with a NEW
  idempotency key; replaying the same key returns the cached failure.
</Note>

## The trading flow

```mermaid theme={"theme":{"light":"poimandres","dark":"poimandres"}}
%%{init: {'theme':'base','themeVariables':{'fontFamily':'Inter, system-ui, sans-serif','fontSize':'13px'}}}%%
sequenceDiagram
  participant Client
  participant OpenFX

  Client->>+OpenFX: GET /v3/fx/pairs
  OpenFX-->>-Client: List of tradable pairs

  Client->>+OpenFX: POST /v3/fx/quotes<br/>(Idempotency-Key)
  OpenFX-->>-Client: Quote<br/>{ id, buyAmount/sellAmount, quoteAmount, expiresAt }

  Note over Client,OpenFX: Quote is valid for 3s by default

  Client->>+OpenFX: POST /v3/fx/trades<br/>(quoteId · NEW Idempotency-Key)
  OpenFX-->>-Client: Trade (status: EXECUTED)

  Client->>+OpenFX: GET /v3/fx/balances
  OpenFX-->>-Client: Updated balances
```

## Endpoints

| Path | Description | Idempotency-Key |
| - | - | - |
| [`GET /v3/fx/pairs`](/v3/api-reference/trade/list-currency-pairs) | List all tradable currency pairs with min/max amounts | — |
| [`POST /v3/fx/quotes`](/v3/api-reference/trade/create-quote) | Lock in an exchange rate for a few seconds | Required, 30-min TTL |
| [`GET /v3/fx/quotes/{id}`](/v3/api-reference/trade/get-quote-by-id) | Look up a single quote (status) | — |
| [`POST /v3/fx/trades`](/v3/api-reference/trade/execute-trade) | Execute against a quote | Required, 24-hr TTL |
| [`GET /v3/fx/trades`](/v3/api-reference/trade/list-trades) | Paginated list of trades, newest first | — |
| [`GET /v3/fx/trades/{id}`](/v3/api-reference/trade/get-trade) | Look up a single trade | — |
| [`POST /v3/fx/trades/{id}/settle`](/v3/api-reference/trade/settle-trade) | Finalize a manual-settlement trade once its window opens | Required, 24-hr TTL |
| [`POST /v3/fx/trades/{id}/reverse-quote`](/v3/api-reference/trade/generate-reverse-quote) | Preview the differential for unwinding a trade | Required, 30-min TTL |
| [`POST /v3/fx/trades/{id}/reverse`](/v3/api-reference/trade/reverse-trade) | Execute a reversal against a reverse quote | Required, 24-hr TTL |

## Quote lifecycle

Quotes are **short-lived**: 3 seconds by default. You can extend via the `quoteForSeconds` request parameter.

<Note>
  **`quoteForSeconds` accepts a closed set of standard durations:** <span class="ofx-enum">3</span>, <span class="ofx-enum">15</span>,
  <span class="ofx-enum">30</span>, <span class="ofx-enum">45</span>, <span class="ofx-enum">60</span> seconds.
</Note>

The reverse-quote endpoint (`POST /v3/fx/trades/{id}/reverse-quote`) defaults `quoteForSeconds` to 15 seconds. It can return <span class="ofx-enum">TRADE\_NOT\_FOUND</span> or <span class="ofx-enum">TRADE\_NOT\_REVERSIBLE</span>; `POST /v3/fx/trades/{id}/reverse` can also return <span class="ofx-enum">QUOTE\_NOT\_FOUND</span>, <span class="ofx-enum">QUOTE\_EXPIRED</span>, <span class="ofx-enum">QUOTE\_ALREADY\_CONSUMED</span>, and <span class="ofx-enum">TRADE\_INSUFFICIENT\_BALANCE</span>.

The quote is binding only if you execute `POST /v3/fx/trades` before `expiresAt`. Once expired, executing returns `409` <span class="ofx-enum">QUOTE\_EXPIRED</span>; request a new quote and execute against the new `id`.

## Retrieving a quote

You can fetch a previously-created quote by ID for **2 days from its `createdAt`**. The endpoint reads from durable storage, not the create-call's idempotency cache, so the quote stays retrievable long after the 30-minute idempotency TTL has expired. After 2 days, `GET /v3/fx/quotes/{id}` returns `404` <span class="ofx-enum">QUOTE\_NOT\_FOUND</span>, the same as an unknown ID.

### Quote status

`GET /v3/fx/quotes/{id}` includes a `status` field not present on the `POST /v3/fx/quotes` create response:

| Status | Meaning | Trade execution |
| - | - | - |
| <span class="ofx-status-pill ofx-status-pill--green">ACTIVE</span> | Unconsumed and within the validity window | Will succeed (subject to balance + compliance) |
| <span class="ofx-status-pill ofx-status-pill--gray">EXPIRED</span> | Unconsumed and past `expiresAt` | Returns `409` <span class="ofx-enum">QUOTE\_EXPIRED</span>; re-quote and retry |
| <span class="ofx-status-pill ofx-status-pill--gray">CONSUMED</span> | A trade has executed against this quote | Returns `409` <span class="ofx-enum">QUOTE\_ALREADY\_CONSUMED</span>; quotes are single-use |

## After execution

The execute response returns the `Trade`. <span class="ofx-enum">IMMEDIATE</span> and <span class="ofx-enum">T0</span> trades are already <span class="ofx-enum">EXECUTED</span>; a <span class="ofx-enum">T1</span> or <span class="ofx-enum">T2</span> trade waits for its settlement window. The statuses, the settle and reverse actions, and the webhooks for each are on [Trades](/v3/trades).

## Common mistakes

* **Expired quote (<span class="ofx-enum">QUOTE\_EXPIRED</span>).** Quotes default to 3 seconds. Recover by re-quoting and retrying with a NEW idempotency key.
* **Execution failed mid-flight (<span class="ofx-enum">TRADE\_EXECUTION\_FAILED</span>).** Call `GET /v3/fx/trades/{id}` first to check state before retrying.
* **Idempotency key replay (<span class="ofx-enum">IDEMPOTENCY\_MISMATCH</span>).** Reusing a key with a different request body returns `422` <span class="ofx-enum">IDEMPOTENCY\_MISMATCH</span>.

## What's next

<CardGroup cols={2}>
  <Card title="Trades" icon="https://public-assets.openfx.com/docs/icons/trades.svg" href="/v3/trades">
    Trade statuses, settlement windows, and the settle and reverse actions.
  </Card>

  <Card title="Settlement models" icon="https://public-assets.openfx.com/docs/icons/settlement-models.svg" href="/v3/settlement-models">
    Netted vs Per-Trade settlement models, plus deposits and withdrawals.
  </Card>

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

  <Card title="Quickstart" icon="https://public-assets.openfx.com/docs/icons/quickstart.svg" href="/v3/quickstart">
    Worked end-to-end: quote → trade → balance.
  </Card>

  <Card title="Idempotency" icon="https://public-assets.openfx.com/docs/icons/idempotency.svg" href="/v3/idempotency">
    Why both /quotes and /trades require keys.
  </Card>
</CardGroup>
