---
title: "Create an FX quote"
description: "Returns a foreign exchange rate quote for a given currency pair and amount. The quote includes a `quote_id` and an expiry time. Use the `quote_id` when submitting a transfer to lock in the quoted rate."
protocol: rest
method: POST
endpoint: "/v1/fx/quote"
baseUrl: "https://api.gravv.xyz"
group: "Fx"
auth:
  label: "Api-Key"
  name: "Api-Key"
  in: header
---

# Create an FX quote

<Endpoint method="POST" path="/v1/fx/quote" />

Returns a foreign exchange rate quote for a given currency pair and amount.
The quote includes a `quote_id` and an expiry time. Use the `quote_id` when
submitting a transfer to lock in the quoted rate.

The `Idempotency-Key` header is required; requests without it are rejected.

## Headers

<ParamField name="Idempotency-Key" header="Idempotency-Key" type="string" required>
  A unique key to prevent duplicate requests. Required on all FX write operations; requests without it are rejected with a `400`.
</ParamField>

## Request Body

<ParamField name="from_currency" body="from_currency" type="string" required>
  Source currency code (ISO 4217).
</ParamField>

<ParamField name="to_currency" body="to_currency" type="string" required>
  Target currency code (ISO 4217).
</ParamField>

<ParamField name="amount" body="amount" type="number" required>
  Amount in the source currency to convert. Must be greater than zero.
</ParamField>

<ParamField name="direction" body="direction" type="string" required>
  Direction of the trade.

  Possible values: `BUY`, `SELL`
</ParamField>

### Request Examples

<RequestExample>

```json title="Request"
{
  "from_currency": "USD",
  "to_currency": "ZAR",
  "amount": 10,
  "direction": "BUY"
}
```

</RequestExample>

## Responses

| Status | Description |
| --- | --- |
| `200` | FX quote returned successfully |
| `400` | Invalid request |
| `401` | Missing or invalid API key |
| `500` | Internal server error |

### 200 response

<ResponseField name="data" type="object">

  <Expandable title="properties">
    <ResponseField name="amount" type="number">
    </ResponseField>

    <ResponseField name="direction" type="string">

      Possible values: `BUY`, `SELL`
    </ResponseField>

    <ResponseField name="expires_at" type="string">
    </ResponseField>

    <ResponseField name="from_currency" type="string">
    </ResponseField>

    <ResponseField name="quote_id" type="string">
    </ResponseField>

    <ResponseField name="rate" type="number">
    </ResponseField>

    <ResponseField name="display_rate" type="number">
      Human-readable display rate for the quote.
    </ResponseField>

    <ResponseField name="display_rate_label" type="string">
      Formatted label expressing the rate in plain language.
    </ResponseField>

    <ResponseField name="to_currency_amount" type="number">
      The amount received in the target currency after applying the rate.
    </ResponseField>

    <ResponseField name="to_currency" type="string">
    </ResponseField>

  </Expandable>
</ResponseField>

<ResponseField name="error" type="string,null">
</ResponseField>

<ResponseExample>

```json title="Response"
{
  "data": {
    "amount": 10,
    "direction": "BUY",
    "display_rate": 16.283561522388,
    "display_rate_label": "1 USD = 16.2836 ZAR",
    "expires_at": "2026-07-03T16:30:05.640502651+01:00",
    "from_currency": "USD",
    "quote_id": "QT-rypoCbnP",
    "rate": 16.283561522388,
    "to_currency": "ZAR",
    "to_currency_amount": 162.83561522388
  },
  "error": null
}
```

</ResponseExample>

### 400 response

<ResponseField name="data" type="null">
  Always null for error responses.
</ResponseField>

<ResponseField name="error" type="string">
  Human-readable error message.
</ResponseField>

<ResponseExample>

```json title="MissingIdempotencyKey"
{
  "data": null,
  "error": "missing idempotency key in request headers"
}
```

```json title="MissingField"
{
  "data": null,
  "error": "missing required field 'amount'"
}
```

```json title="MissingMultipleFields"
{
  "data": null,
  "error": "missing required field 'from_currency', missing required field 'to_currency', missing required field 'amount', missing required field 'direction'"
}
```

```json title="InvalidAmount"
{
  "data": null,
  "error": "field 'amount' must be greater than 0"
}
```

```json title="InvalidDirection"
{
  "data": null,
  "error": "field 'direction' must be one of: BUY SELL"
}
```

```json title="UnsupportedPair"
{
  "data": null,
  "error": "currency pair KWD/NGN not supported"
}
```

</ResponseExample>

### 401 response

<ResponseField name="data" type="null">
  Always null for error responses.
</ResponseField>

<ResponseField name="error" type="string">
  Human-readable error message.
</ResponseField>

<ResponseExample>

```json title="MissingApiKey"
{
  "data": null,
  "error": "Invalid or missing Api-Key header. Api-Key is required!"
}
```

```json title="InvalidApiKey"
{
  "data": null,
  "error": "Invalid token!"
}
```

</ResponseExample>

### 500 response

<ResponseField name="data" type="null">
  Always null for error responses.
</ResponseField>

<ResponseField name="error" type="string">
  Human-readable error message.
</ResponseField>

<ResponseExample>

```json title="Response"
{
  "data": null,
  "error": "failed to retrieve FX quote"
}
```

</ResponseExample>

## Authorization

- **ApiKeyAuth**
