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

# FX

> Rates, quotes and conversions.

A conversion is one entry through the tenant's FX position accounts, balanced in each currency on its own.

## Before you start

You need `AST:FXP:<CCY>` in both currencies. Without them a conversion gets `FX_POSITION_MISSING`. Open them with `POST /v1/accounts`.

## Rates

A manual desk rate is entered in the console and is not usable until a second person signs it off.

```bash theme={null}
curl "$PANOQORE_URL/v1/fx/rates?liveOnly=true" -H "Authorization: Bearer $PANOQORE_API_KEY"
```

```json theme={null}
{
  "rates": [{
    "id": "fxr_01M6F1DSCZFJ1T4JZ4S2384YE9",
    "base": "USD",
    "quote": "NGN",
    "mid": "1500.25",
    "spreadBps": "50",
    "source": "manual",
    "status": "LIVE"
  }],
  "page": { "total": "1" }
}
```

`mid` is units of `quote` per one `base`, as a decimal string. A rate older than the tenant's maximum age blocks conversions with `RATE_STALE`.

## Quote

A quote prices an amount at the live rate less the spread, and holds it for 60 seconds. It needs `entries:write` or `fx:write`.

```bash theme={null}
curl -X POST "$PANOQORE_URL/v1/fx/quotes" \
  -H "Authorization: Bearer $PANOQORE_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"base":"USD","quote":"NGN","baseAmount":"10000"}'
```

```json theme={null}
{
  "id": "fxq_01M6F1DSWGEQVRYGRRZKRNEQPE",
  "rateId": "fxr_01M6F1DSCZFJ1T4JZ4S2384YE9",
  "base": "USD",
  "quote": "NGN",
  "baseAmount": "10000",
  "quoteAmount": "14927487",
  "rate": "1492.74875",
  "expiresAt": "2026-11-02T21:08:43.632378Z"
}
```

\$100.00 at 1492.74875 comes to ₦149,274.87. Quotes are by `baseAmount`.

## Convert

A conversion needs `entries:write`.

```bash theme={null}
curl -X POST "$PANOQORE_URL/v1/fx/convert" \
  -H "Authorization: Bearer $PANOQORE_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"quoteId":"'"$QUOTE"'","fromAccountId":"'"$USD_WALLET"'","toAccountId":"'"$NGN_WALLET"'","externalRef":"fx-1"}'
```

The answer is an entry with `kind: FX` and `fxRateId` set.

| Account | Side | Amount |
| - | - | - |
| `LIA:WAL:USD:0001` | `DEBIT` | `10000` USD |
| `AST:FXP:USD` | `CREDIT` | `10000` USD |
| `AST:FXP:NGN` | `DEBIT` | `14927487` NGN |
| `LIA:WAL:NGN:0001` | `CREDIT` | `14927487` NGN |

A quote can be used once, and a second try gets `QUOTE_USED`. After 60 seconds it gets `QUOTE_EXPIRED`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.