---
title: "Check whether a pair can be traded"
description: "Find out with one test quote whether Gravv can convert a pair such as USD to EUR for your business, and what to do if not."
---
This recipe uses one test quote to find out whether Gravv can convert a pair, such as USD to EUR, for your business. It also says what to do if Gravv cannot.

**Who it is for.** A UK freelancer platform that holds USD and EUR accounts for its customers and wants to let them switch USD into EUR.

**Status.** NGN to USDC and USDC to NGN are Available once Gravv sets a rate for your business. Every other pair is Not yet available until Gravv sets it up for you.

## Money example

Amelia has 2,000 USD in her USD account and a EUR account.

1. As a test, you request a quote to sell 10 USD for EUR.
2. Gravv returns `quote currency pair is not supported`, because the pair is not set up for your business.
3. You ask support to enable USD to EUR. Once support enables it, the same quote returns a rate such as 0.86, so 10 USD buys 8.60 EUR. You then place orders from her USD account to her EUR account, as in [Convert naira to USDC](/recipes/fx/convert-naira-to-usdc).

## Before you start

You need an API key. A scoped key needs `fx:read`.

## Find out what is required

The two lists below are display data, and neither proves that you can trade a pair. Only the test quote tells you.

## Steps

### 1. See which pairs Gravv knows

<CodeGroup>
```bash title="cURL"
curl --request GET \
     --url https://api.gravv.xyz/v1/fx/supported-currencies \
     --header 'Api-Key: <API_KEY>'
```
```javascript title="Node"
const response = await fetch("https://api.gravv.xyz/v1/fx/supported-currencies", {
  method: "GET",
  headers: {
    "Api-Key": process.env.GRAVV_API_KEY,
  },
});
console.log(response.status, await response.json());
```
```python title="Python"
import os

import requests

response = requests.get(
    "https://api.gravv.xyz/v1/fx/supported-currencies",
    headers={
        "Api-Key": os.environ["GRAVV_API_KEY"],
    },
)
print(response.status_code, response.json())
```
</CodeGroup>

Every key is `FROM_FROMCOUNTRY_TO_TOCOUNTRY` (`XX` for crypto), and one currency can appear under several countries. The `*_name` values are not clean display names, so show your own labels. The NGN and USDC pair is not in this list. The call takes no filters.

### 2. Read a display rate

<CodeGroup>
```bash title="cURL"
curl --request GET \
     --url 'https://api.gravv.xyz/v1/fx/rates?directions=USD_EUR' \
     --header 'Api-Key: <API_KEY>'
```
```javascript title="Node"
const response = await fetch("https://api.gravv.xyz/v1/fx/rates?directions=USD_EUR", {
  method: "GET",
  headers: {
    "Api-Key": process.env.GRAVV_API_KEY,
  },
});
console.log(response.status, await response.json());
```
```python title="Python"
import os

import requests

response = requests.get(
    "https://api.gravv.xyz/v1/fx/rates?directions=USD_EUR",
    headers={
        "Api-Key": os.environ["GRAVV_API_KEY"],
    },
)
print(response.status_code, response.json())
```
</CodeGroup>

One direction can return several rows, one per country pair. A row can be weeks old, so read `timestamp` and do not show a stale rate.

### 3. Send a test quote

<CodeGroup>
```bash title="cURL"
curl --request POST \
     --url https://api.gravv.xyz/v1/fx/quote \
     --header 'Api-Key: <API_KEY>' \
     --header 'Idempotency-Key: 161e139d-7062-4c42-8863-88baaf5fdd71' \
     --header 'Content-Type: application/json' \
     --data '
{
  "currency_pair": "USD_EUR",
  "amount": "10"
}
'
```
```javascript title="Node"
const response = await fetch("https://api.gravv.xyz/v1/fx/quote", {
  method: "POST",
  headers: {
    "Api-Key": process.env.GRAVV_API_KEY,
    "Idempotency-Key": "161e139d-7062-4c42-8863-88baaf5fdd71",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "currency_pair": "USD_EUR",
    "amount": "10"
  }),
});
console.log(response.status, await response.json());
```
```python title="Python"
import os

import requests

response = requests.post(
    "https://api.gravv.xyz/v1/fx/quote",
    headers={
        "Api-Key": os.environ["GRAVV_API_KEY"],
        "Idempotency-Key": "161e139d-7062-4c42-8863-88baaf5fdd71",
        "Content-Type": "application/json",
    },
    json={
        "currency_pair": "USD_EUR",
        "amount": "10",
    },
)
print(response.status_code, response.json())
```
</CodeGroup>

- A 200 with a `quote_id` means the pair is enabled. The test quote expires on its own, and Gravv charges nothing.
- A 400 `quote currency pair is not supported` means the pair is not enabled for you. Contact support with the pair and the volume you expect.

### 4. Once enabled, check both accounts

Gravv does not check that the source is in the currency you sell or that the destination is in the currency you buy. Read both with `GET /v2/accounts/{id}` before every order.

## What can go wrong

| Response | Why | Fix |
| :-- | :-- | :-- |
| 400 `quote currency pair is not supported` | The pair is not set up or priced for you | Contact support |
| 400 `invalid currency_type` on rates | You sent a value other than `fiat` or `crypto` | Send `fiat` or `crypto` |
| 400 `fx cache is not ready` | The rate cache is empty or unreadable | Retry later |
| A rate of exactly `"1"` between two different currencies | The rate feed has a fault | Do not show the rate, and report it. Gravv prices quotes separately |
| You need EUR paid to someone else's bank | That is a payout, not an FX order | [Pay a euro account by SEPA](/recipes/bank-payouts/pay-a-euro-account-by-sepa) |

## Webhooks you will receive

Gravv sends no webhooks for FX.

## Testing in sandbox

The same calls work with a sandbox key. A "not supported" response in sandbox says nothing about live, and a live response says nothing about sandbox.

## Reference

- [Get exchange rates](/platform/foreign-exchange/get-exchange-rates)
- [Get FX quote](/api-reference/fx/post-v1-fx-quote)
