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

# Rates

> GET /v1/rates and POST /v1/rates/quote - live FX rates, and a rate you can hold for two minutes.

<Warning>
  **Not available yet.** Both rate endpoints answer `503 not_configured`. No FX
  pricing source is wired to this deployment, and a made-up rate is a price somebody
  moves money on. The shape below is the contract they will answer with.
</Warning>

Two ways to read FX for the bank rail. `GET /v1/rates` lists the live rate for
every pair - use it for display. `POST /v1/rates/quote` locks a rate for one
conversion - use it when you show a user a figure they will act on.

For card payments, rates come from
[`GET /v1/card/rate`](/api-reference/card-rate) instead - the card rail prices
differently.

## GET /v1/rates

Lists every currency pair with its live rate. No parameters.

<ResponseField name="rates" type="array">
  One entry per pair.

  <Expandable title="rates[]">
    <ResponseField name="base" type="string">
      The currency being priced, ISO 4217.
    </ResponseField>

    <ResponseField name="quote" type="string">
      The currency the rate is expressed in, ISO 4217.
    </ResponseField>

    <ResponseField name="rate" type="string">
      Units of `quote` per one unit of `base`, as a decimal string, spread
      included.
    </ResponseField>

    <ResponseField name="spreadBps" type="number">
      The spread inside `rate`, in basis points.
    </ResponseField>

    <ResponseField name="updatedAt" type="string">
      ISO 8601 timestamp of the last rate update.
    </ResponseField>
  </Expandable>
</ResponseField>

<Warning>
  A listed rate is indicative. It moves with the market and nothing is held for
  you. Anything a user commits money against goes through `/v1/rates/quote`.
</Warning>

## POST /v1/rates/quote

Locks a rate for one conversion. **The rate holds for two minutes** - convert
within the window or quote again.

<ParamField body="currencyIn" type="string" required>
  ISO 4217 code of the currency being converted from.
</ParamField>

<ParamField body="currencyOut" type="string" required>
  ISO 4217 code of the currency being converted to.
</ParamField>

<ParamField body="amountIn" type="string">
  Amount to convert, as a decimal string in `currencyIn`'s major unit. Send
  either this or `amountOut`, not both.
</ParamField>

<ParamField body="amountOut" type="string">
  Amount that must land, as a decimal string in `currencyOut`'s major unit. The
  input side is solved backwards from it.
</ParamField>

### Response

<ResponseField name="id" type="string">
  The quote id.
</ResponseField>

<ResponseField name="currencyIn" type="string">
  Echo of the input currency.
</ResponseField>

<ResponseField name="currencyOut" type="string">
  Echo of the output currency.
</ResponseField>

<ResponseField name="amountIn" type="string">
  What goes in, as a decimal string.
</ResponseField>

<ResponseField name="amountOut" type="string">
  What comes out, as a decimal string.
</ResponseField>

<ResponseField name="rate" type="string">
  The locked rate: units of `currencyOut` per one unit of `currencyIn`, spread
  included.
</ResponseField>

<ResponseField name="spreadBps" type="number">
  The spread inside `rate`, in basis points.
</ResponseField>

<ResponseField name="expiresAt" type="string">
  ISO 8601 timestamp when the lock ends - two minutes after creation. After it,
  the quote is only a record of what was once offered.
</ResponseField>

<RequestExample>
  ```bash GET /v1/rates theme={null}
  curl "$RHEON_API/v1/rates" \
    -H "Authorization: Bearer $RHEON_API_KEY"
  ```

  ```bash POST /v1/rates/quote theme={null}
  curl -X POST "$RHEON_API/v1/rates/quote" \
    -H "Authorization: Bearer $RHEON_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "currencyIn": "EUR",
      "currencyOut": "USD",
      "amountIn": "1000.00"
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json 200 list theme={null}
  {
    "rates": [
      {
        "base": "EUR",
        "quote": "USD",
        "rate": "1.0851",
        "spreadBps": 50,
        "updatedAt": "2026-08-31T10:00:00Z"
      },
      {
        "base": "USD",
        "quote": "EUR",
        "rate": "0.9169",
        "spreadBps": 50,
        "updatedAt": "2026-08-31T10:00:00Z"
      }
    ]
  }
  ```

  ```json 200 quote theme={null}
  {
    "id": "rq_7c2e90b1f4",
    "currencyIn": "EUR",
    "currencyOut": "USD",
    "amountIn": "1000.00",
    "amountOut": "1085.10",
    "rate": "1.0851",
    "spreadBps": 50,
    "expiresAt": "2026-08-31T10:02:00Z"
  }
  ```
</ResponseExample>

## Errors

| HTTP | `code`            | When                                                |
| ---- | ----------------- | --------------------------------------------------- |
| 400  | `invalid_request` | An unknown currency, both amounts sent, or neither. |
| 401  | `unauthorized`    | Missing, malformed, or unknown API key.             |
| 429  | `rate_limited`    | Over your key's rate limit.                         |
| 502  | `upstream_error`  | The FX source is unavailable.                       |
| 500  | `internal`        | Unexpected server error.                            |
