FOREIGN EXCHANGE Copy Page
Lock an FX rate
POST https://production.dutchapi.co/v1/fx/quote
Locks a conversion rate for a short time. Convert with the returned id before expires_at.
🔒 Send the project API key as a Bearer token and your Business ID with this call.
Wallet conversions: between any two different wallet currencies (USD, XAF, GHS, ZAR, NGN, RWF, UGX, KES). Stablecoin conversions: USDT or USDC to USD or XAF, 1.45% fee, minimum 10.
Body Params fromstring required
Any wallet currency, or USDT / USDC.
tostring required
Any wallet currency other than from (USD or XAF when from is USDT / USDC).
amountnumber required
Amount of the from currency.
Responses
201 400
{
"id": "fxq_5a1c",
"from": "USD",
"to": "XAF",
"rate": 590.4,
"send_amount": 100,
"receive_amount": 59040,
"fee": 0,
"expires_at": "2026-10-13T09:33:00.000Z"
}
{
"error": "valid_currency_pair_required",
"message": "Use two different wallet currencies, or USDT/USDC to USD/XAF."
}
Errors Status error Meaning 400 valid_currency_pair_requiredUse two different wallet currencies, or USDT/USDC to USD/XAF. 400 valid_amount_requiredamount must be a positive number. 400 crypto_swap_amount_out_of_rangeStablecoin conversions start at 10. 502 quote_unavailableThe partner returned no rate.
Language Shell Node Ruby PHP Python
Credentials Bearer
curl --request POST --url "https://production.dutchapi.co/v1/fx/quote" \
--header "Authorization: Bearer $DUTCH_PROJECT_KEY" \
--header "X-Business-Id: $DUTCH_BUSINESS_ID" \
--header "Content-Type: application/json" \
--data '{"from":"USD","to":"XAF","amount":100}'const res = await fetch("https://production.dutchapi.co/v1/fx/quote", {
method: "POST",
headers: {
"Authorization": "Bearer " + process.env.DUTCH_PROJECT_KEY,
"X-Business-Id": process.env.DUTCH_BUSINESS_ID,
"Content-Type": "application/json",
},
body: JSON.stringify({"from": "USD", "to": "XAF", "amount": 100})
});
console.log(await res.json());require "net/http"
require "json"
uri = URI("https://production.dutchapi.co/v1/fx/quote")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer #{ENV.fetch('DUTCH_PROJECT_KEY')}"
req["X-Business-Id"] = ENV.fetch("DUTCH_BUSINESS_ID")
req["Content-Type"] = "application/json"
req.body = "{\"from\":\"USD\",\"to\":\"XAF\",\"amount\":100}"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
puts res.body<?php
$ch = curl_init("https://production.dutchapi.co/v1/fx/quote");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer " . getenv("DUTCH_PROJECT_KEY"),
"X-Business-Id: " . getenv("DUTCH_BUSINESS_ID"),
"Content-Type: application/json"],
CURLOPT_POSTFIELDS => '{"from":"USD","to":"XAF","amount":100}',
]);
echo curl_exec($ch);import os, requests, json
res = requests.request(
"POST",
"https://production.dutchapi.co/v1/fx/quote",
headers={
"Authorization": "Bearer " + os.environ["DUTCH_PROJECT_KEY"],
"X-Business-Id": os.environ["DUTCH_BUSINESS_ID"],
},
json=json.loads("{\"from\":\"USD\",\"to\":\"XAF\",\"amount\":100}")
)
print(res.json())
Show example
Response Click `Show example` to see an example response. Nothing is sent from this page: endpoints are live, so run real requests from your own code with small amounts.
201 - Result 400 - Result