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

# FX quotes and rates

> Locking an exchange rate with a quote token from POST /tools/fx-quote, or taking the prevailing market rate at creation — and what the token is bound to.

Only the `international-fx` rail converts currency, and every converted payment is executed at some
rate. You choose when that rate is fixed:

* **Lock it.** Quote the conversion, show the payer a number, and create the payment with the
  quote's token. You are charged what was quoted.
* **Take the market rate.** Create the payment without a token and it is priced at creation, at
  whatever rate then applies.

Neither path involves fees. An FX quote prices the conversion only; fees come from
`POST /tools/fee-calculator` and the two are independent.

`international-gusd` is dollar-denominated, so there is nothing to quote — `fxQuoteToken` is not part
of its payload and sending one is a `400`.

## Locking a rate

```http theme={null}
POST /v2/tools/fx-quote
api-key: <your key>
Melio-Entity-Id: ent_8c6f...
Content-Type: application/json
```

```json theme={null}
{
  "receivingAccountId": "acct_2a4f9c31-77ad-4c1e-8b52-6d3f0a91c4e7",
  "amount": 100000,
  "currency": "EUR",
  "purpose": "payment for consulting services"
}
```

`amount` is what the counterparty would receive, in minor units of `currency` — 100000 is €1,000.00.
`currency` is optional but worth sending: it turns a wrong assumption about the account into a `400`
instead of a quote in a currency you did not expect. Send the same `purpose` you will send as
`compliance.purpose` on the payment, since it is passed to the provider when the quote is minted.

```json theme={null}
{
  "currency": "EUR",
  "foreignAmount": 100000,
  "amount": 110250,
  "usdToForeignRate": 0.907,
  "midMarketRate": 0.9125,
  "quoteToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "expiresAt": "2026-09-06T12:34:56Z"
}
```

* `foreignAmount` — what the counterparty receives (what you asked for).
* `amount` — what the business is debited, in USD minor units, before fees. 110250 is \$1,102.50.
* `usdToForeignRate` — the applied rate, units of `currency` per USD.
* `midMarketRate` — the reference rate, for showing a comparison.
* `expiresAt` — when the token stops being accepted. Read it rather than assuming a lifetime; it is
  short.

Then create the payment with the token:

```json theme={null}
{
  "amount": 100000,
  "currency": "EUR",
  "originatingAccountId": "acct_3f2504e0-...",
  "receivingAccountId": "acct_2a4f9c31-77ad-4c1e-8b52-6d3f0a91c4e7",
  "deductionDate": "2026-07-10",
  "deliveryPreference": "international-fx",
  "fxQuoteToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "compliance": { "type": "goods-and-services", "purpose": "payment for consulting services" }
}
```

### What the token is bound to

A converted payment takes both of its amounts from the quote, so a token is only accepted for the
payment it was quoted for. It is checked against:

* the **currency** it was issued for, which must be the receiving account's currency, and
* the **amount** it was issued for, which must be the payment's `amount`, and
* its **expiry**.

Anything else — an expired token, a token for €1,000 spent on a €2,000 payment, a token for GBP on a
EUR account — is rejected with `400 FX_QUOTE_INVALID`. The payment is not created and nothing is
silently substituted: a token that no longer describes what you are sending is an error rather than a
quiet re-price.

Practical consequences:

* **Re-quote when the payer changes the amount.** There is no partial use of a quote: a token issued
  for €1,000 prices a €1,000 payment and nothing else.
* **Quote per payment.** A quote describes one amount in one currency, so a batch of payments needs
  a quote each.
* **Treat the token as opaque.** Its format is not part of the contract; do not parse it.

### If the quote expires before the payer confirms

Quote again and create the payment with the new token, or drop the token and let the payment take the
rate at creation. Which is better depends on your UI: if you have shown the payer a price you are
committed to, re-quoting and comparing against what you displayed is the honest option.

## Taking the market rate

Omit `fxQuoteToken` entirely:

```json theme={null}
{
  "amount": 100000,
  "currency": "EUR",
  "originatingAccountId": "acct_3f2504e0-...",
  "receivingAccountId": "acct_2a4f9c31-77ad-4c1e-8b52-6d3f0a91c4e7",
  "deductionDate": "2026-07-10",
  "deliveryPreference": "international-fx",
  "compliance": { "type": "goods-and-services", "purpose": "payment for consulting services" }
}
```

The payment is priced at creation. The counterparty still receives exactly the `amount` you asked
for — the conversion is quoted in reverse, and it is the USD debit that follows the rate. The
response reports the payment in the currency the counterparty receives:

```json theme={null}
{
  "id": "pay_4d5e6f7a8b9c0d1e",
  "amount": 100000,
  "currency": "EUR",
  "deliveryPreference": "international-fx",
  "status": "scheduled"
}
```

Use this path when nothing has been shown to a payer, or when you are creating payments from a batch
or a scheduler where a quote would have expired before the payment ran. Use a locked quote when a
person is looking at a price.

> **Displaying a rate without committing to it.** `POST /tools/fx-quote` is also fine to call just
> for `usdToForeignRate` and `midMarketRate` — quoting mints nothing that has to be used, and the
> token can simply be discarded.

## See also

* [International payments](https://developers.melio.com/docs/international-payments) — the FX and GUSD rails end to end
* [Payment attachments](https://developers.melio.com/docs/payment-attachments) — when a converted payment needs a document


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