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

# Firm Quotes

> Locking an executable rate with inventory reservation

A firm quote returns an executable BID/ASK price with a hard expiry timestamp. Unlike indicative quotes, firm quotes reserve inventory — guaranteeing that the quoted rate is available for execution until the quote expires.

## When to use

* Your user has confirmed they want to execute a transfer
* You need a binding rate to display before the final confirmation step
* You're building a two-step flow: preview rate → confirm → execute

## Request

```
POST /v1/firm-quote
```

<ParamField body="pair" type="string" required>
  Currency pair to quote. Supported values: `USD-IDR`, `USD-SGD`, `MYR-IDR`.
</ParamField>

<ParamField body="side" type="string" required>
  Trade direction. `BUY` or `SELL`.
</ParamField>

<ParamField body="amount" type="number" required>
  Notional amount in the source currency.
</ParamField>

<ParamField body="quote_type" type="string" required>
  Must be `FIRM`.
</ParamField>

<ParamField body="client_ref" type="string">
  Your internal reference for reconciliation. Included in webhook payloads and settlement records.
</ParamField>

### Example request

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST "https://api.ratiofx.com/v1/firm-quote" \
    -H "Authorization: Bearer sk_live_abc123..." \
    -H "X-Partner-ID: partner_uuid_xyz" \
    -H "Content-Type: application/json" \
    -d '{
      "pair": "USD-IDR",
      "side": "BUY",
      "amount": 50000,
      "quote_type": "FIRM",
      "client_ref": "TXN-20260227-001"
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch("https://api.ratiofx.com/v1/firm-quote", {
    method: "POST",
    headers: {
      "Authorization": "Bearer sk_live_abc123...",
      "X-Partner-ID": "partner_uuid_xyz",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      pair: "USD-IDR",
      side: "BUY",
      amount: 50000,
      quote_type: "FIRM",
      client_ref: "TXN-20260227-001",
    }),
  });
  const firmQuote = await response.json();
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      "https://api.ratiofx.com/v1/firm-quote",
      json={
          "pair": "USD-IDR",
          "side": "BUY",
          "amount": 50000,
          "quote_type": "FIRM",
          "client_ref": "TXN-20260227-001",
      },
      headers={
          "Authorization": "Bearer sk_live_abc123...",
          "X-Partner-ID": "partner_uuid_xyz",
      },
  )
  firm_quote = response.json()
  ```
</CodeGroup>

## Response

```json theme={null}
{
  "quote_id": "QT-8821-USD-IDR",
  "pair": "USD-IDR",
  "side": "BUY",
  "amount": 50000,
  "bid": 15940.00,
  "ask": 16020.00,
  "adjusted_mid": 15980.00,
  "spread_bps": 25,
  "expiry_timestamp": "2026-02-27T10:00:45Z",
  "max_size": 50000,
  "allowed_direction": "BUY",
  "state_flag": "NORMAL",
  "quote_type": "FIRM",
  "execution_path": "DIRECT",
  "fee_breakdown": {
    "tier": "MEDIUM",
    "fixed_fee": 0.633,
    "fixed_fee_currency": "USD",
    "fixed_fee_in_dest": 10000,
    "fixed_fee_dest_currency": "IDR",
    "variable_fee": 10.00,
    "variable_fee_bips": 2,
    "base_spread_bps": 20,
    "total_spread_bps": 25,
    "total_fee_usd": 10.633,
    "amount_to_convert": 49989.37,
    "is_partner_override": false
  }
}
```

### Response fields

<ResponseField name="quote_id" type="string" required>
  Unique quote identifier. Pass this to `POST /v1/execute` to execute the swap.
</ResponseField>

<ResponseField name="pair" type="string">
  Currency pair.
</ResponseField>

<ResponseField name="side" type="string">
  Trade direction.
</ResponseField>

<ResponseField name="amount" type="number">
  Notional in source currency.
</ResponseField>

<ResponseField name="bid" type="number">
  Bid price — the rate at which the FX Engine buys the base currency.
</ResponseField>

<ResponseField name="ask" type="number">
  Ask price — the rate at which the FX Engine sells the base currency.
</ResponseField>

<ResponseField name="adjusted_mid" type="number">
  Oracle mid-rate after inventory adjustment.
</ResponseField>

<ResponseField name="spread_bps" type="number">
  Total spread in basis points.
</ResponseField>

<ResponseField name="expiry_timestamp" type="string">
  ISO 8601 hard expiry. The quote cannot be executed after this time.
</ResponseField>

<ResponseField name="max_size" type="number">
  Maximum executable size for this quote. Your execution `amount` must not exceed this value.
</ResponseField>

<ResponseField name="allowed_direction" type="string">
  Permitted trade direction under current system conditions.
</ResponseField>

<ResponseField name="state_flag" type="string">
  Current system state for this corridor: `NORMAL`, `PROTECT`, or `RESTRICT`.
</ResponseField>

<ResponseField name="quote_type" type="string">
  Always `FIRM`.
</ResponseField>

<ResponseField name="execution_path" type="string">
  How the trade will be filled. `DIRECT` means filled from Ratio's internal liquidity pools. `EXTERNAL_RFQ` means the trade size exceeds internal pool depth and will be filled via an external market maker.
</ResponseField>

<ResponseField name="fee_breakdown" type="object">
  Full breakdown of all fee components. See below.
</ResponseField>

### Fee breakdown

The `fee_breakdown` object provides full transparency on all fee components applied to this quote.

<ResponseField name="fee_breakdown.tier" type="string">
  Volume tier applied to this transaction: `MICRO`, `SMALL`, `MEDIUM`, `LARGE`, or `INSTITUTIONAL`.
</ResponseField>

<ResponseField name="fee_breakdown.fixed_fee" type="number">
  Fixed fee in source currency.
</ResponseField>

<ResponseField name="fee_breakdown.fixed_fee_currency" type="string">
  Source currency code.
</ResponseField>

<ResponseField name="fee_breakdown.fixed_fee_in_dest" type="number">
  Fixed fee converted to destination currency.
</ResponseField>

<ResponseField name="fee_breakdown.fixed_fee_dest_currency" type="string">
  Destination currency code.
</ResponseField>

<ResponseField name="fee_breakdown.variable_fee" type="number">
  Variable fee in source currency.
</ResponseField>

<ResponseField name="fee_breakdown.variable_fee_bips" type="number">
  Variable fee rate in basis points.
</ResponseField>

<ResponseField name="fee_breakdown.base_spread_bps" type="number">
  Base spread component from the fee tier.
</ResponseField>

<ResponseField name="fee_breakdown.total_spread_bps" type="number">
  Total spread including all dynamic components.
</ResponseField>

<ResponseField name="fee_breakdown.total_fee_usd" type="number">
  Total platform fee (fixed + variable) in USD equivalent.
</ResponseField>

<ResponseField name="fee_breakdown.amount_to_convert" type="number">
  Source amount after fee deduction. This is the amount converted at the quoted rate.
</ResponseField>

<ResponseField name="fee_breakdown.is_partner_override" type="boolean">
  Whether partner-specific custom rates were applied to this quote.
</ResponseField>

## Quote expiry

Firm quotes have a short expiry window — typically 30–60 seconds. After expiry:

* The quote cannot be executed.
* Reserved inventory is released back to the pool.
* You must request a new firm quote at current rates.

<Warning>
  Always execute before `expiry_timestamp`. Check the timestamp immediately after receiving the response and alert your users if they are slow to confirm.
</Warning>

## Next step

Submit the `quote_id` to execute the swap on-chain.

[Execute the swap →](/integration/executing-swaps)
