curl --request POST \
--url https://api.rheon.io/v1/bank/payout/quote \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"cryptoCurrency": "USDC",
"chain": 42161,
"fiatCurrency": "GBP",
"country": "GB",
"cryptoAmount": "1000.00",
"fiatAmount": "100",
"rail": "faster_payments"
}
'import requests
url = "https://api.rheon.io/v1/bank/payout/quote"
payload = {
"cryptoCurrency": "USDC",
"chain": 42161,
"fiatCurrency": "GBP",
"country": "GB",
"cryptoAmount": "1000.00",
"fiatAmount": "100",
"rail": "faster_payments"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
cryptoCurrency: 'USDC',
chain: 42161,
fiatCurrency: 'GBP',
country: 'GB',
cryptoAmount: '1000.00',
fiatAmount: '100',
rail: 'faster_payments'
})
};
fetch('https://api.rheon.io/v1/bank/payout/quote', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.rheon.io/v1/bank/payout/quote",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'cryptoCurrency' => 'USDC',
'chain' => 42161,
'fiatCurrency' => 'GBP',
'country' => 'GB',
'cryptoAmount' => '1000.00',
'fiatAmount' => '100',
'rail' => 'faster_payments'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.rheon.io/v1/bank/payout/quote"
payload := strings.NewReader("{\n \"cryptoCurrency\": \"USDC\",\n \"chain\": 42161,\n \"fiatCurrency\": \"GBP\",\n \"country\": \"GB\",\n \"cryptoAmount\": \"1000.00\",\n \"fiatAmount\": \"100\",\n \"rail\": \"faster_payments\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.rheon.io/v1/bank/payout/quote")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"cryptoCurrency\": \"USDC\",\n \"chain\": 42161,\n \"fiatCurrency\": \"GBP\",\n \"country\": \"GB\",\n \"cryptoAmount\": \"1000.00\",\n \"fiatAmount\": \"100\",\n \"rail\": \"faster_payments\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.rheon.io/v1/bank/payout/quote")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"cryptoCurrency\": \"USDC\",\n \"chain\": 42161,\n \"fiatCurrency\": \"GBP\",\n \"country\": \"GB\",\n \"cryptoAmount\": \"1000.00\",\n \"fiatAmount\": \"100\",\n \"rail\": \"faster_payments\"\n}"
response = http.request(request)
puts response.read_body{
"environment": "sandbox",
"mock": true,
"quoteId": "bpq_42161_2e90c4a71f6d0b83",
"cryptoAmount": "1234567.89",
"fiatAmount": "1234567.89",
"rate": "1234567.89",
"rail": "faster_payments",
"estimatedSettlement": "instant",
"providerFee": "1234567.89",
"ourFee": "1234567.89",
"expiresAt": "2026-09-08T17:44:12.000Z"
}{
"environment": "sandbox",
"error": {
"code": "invalid_request",
"message": "amount must be a decimal string of the token's smallest unit.",
"fields": {
"applicantInfo.nationality": "iso3166_1_alpha2"
}
}
}{
"environment": "sandbox",
"error": {
"code": "invalid_request",
"message": "amount must be a decimal string of the token's smallest unit.",
"fields": {
"applicantInfo.nationality": "iso3166_1_alpha2"
}
}
}{
"environment": "sandbox",
"error": {
"code": "invalid_request",
"message": "amount must be a decimal string of the token's smallest unit.",
"fields": {
"applicantInfo.nationality": "iso3166_1_alpha2"
}
}
}{
"environment": "sandbox",
"error": {
"code": "invalid_request",
"message": "amount must be a decimal string of the token's smallest unit.",
"fields": {
"applicantInfo.nationality": "iso3166_1_alpha2"
}
}
}{
"environment": "sandbox",
"error": {
"code": "invalid_request",
"message": "amount must be a decimal string of the token's smallest unit.",
"fields": {
"applicantInfo.nationality": "iso3166_1_alpha2"
}
}
}Quote a bank payout
Prices a payout to a bank account you name - the one-off direction, no virtual account involved. Anonymous. The rail is resolved for real from the limits table (the fastest published payout rail for the currency, or the one you force), and chain and cryptoCurrency are checked against the catalogue and your key.
The provider behind this endpoint is currently being connected, docs updating. Until then every answer carries mock: true, every money figure is the placeholder 1234567.89, and ids and shapes are real and deterministic from your input.
curl --request POST \
--url https://api.rheon.io/v1/bank/payout/quote \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"cryptoCurrency": "USDC",
"chain": 42161,
"fiatCurrency": "GBP",
"country": "GB",
"cryptoAmount": "1000.00",
"fiatAmount": "100",
"rail": "faster_payments"
}
'import requests
url = "https://api.rheon.io/v1/bank/payout/quote"
payload = {
"cryptoCurrency": "USDC",
"chain": 42161,
"fiatCurrency": "GBP",
"country": "GB",
"cryptoAmount": "1000.00",
"fiatAmount": "100",
"rail": "faster_payments"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
cryptoCurrency: 'USDC',
chain: 42161,
fiatCurrency: 'GBP',
country: 'GB',
cryptoAmount: '1000.00',
fiatAmount: '100',
rail: 'faster_payments'
})
};
fetch('https://api.rheon.io/v1/bank/payout/quote', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.rheon.io/v1/bank/payout/quote",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'cryptoCurrency' => 'USDC',
'chain' => 42161,
'fiatCurrency' => 'GBP',
'country' => 'GB',
'cryptoAmount' => '1000.00',
'fiatAmount' => '100',
'rail' => 'faster_payments'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.rheon.io/v1/bank/payout/quote"
payload := strings.NewReader("{\n \"cryptoCurrency\": \"USDC\",\n \"chain\": 42161,\n \"fiatCurrency\": \"GBP\",\n \"country\": \"GB\",\n \"cryptoAmount\": \"1000.00\",\n \"fiatAmount\": \"100\",\n \"rail\": \"faster_payments\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.rheon.io/v1/bank/payout/quote")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"cryptoCurrency\": \"USDC\",\n \"chain\": 42161,\n \"fiatCurrency\": \"GBP\",\n \"country\": \"GB\",\n \"cryptoAmount\": \"1000.00\",\n \"fiatAmount\": \"100\",\n \"rail\": \"faster_payments\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.rheon.io/v1/bank/payout/quote")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"cryptoCurrency\": \"USDC\",\n \"chain\": 42161,\n \"fiatCurrency\": \"GBP\",\n \"country\": \"GB\",\n \"cryptoAmount\": \"1000.00\",\n \"fiatAmount\": \"100\",\n \"rail\": \"faster_payments\"\n}"
response = http.request(request)
puts response.read_body{
"environment": "sandbox",
"mock": true,
"quoteId": "bpq_42161_2e90c4a71f6d0b83",
"cryptoAmount": "1234567.89",
"fiatAmount": "1234567.89",
"rate": "1234567.89",
"rail": "faster_payments",
"estimatedSettlement": "instant",
"providerFee": "1234567.89",
"ourFee": "1234567.89",
"expiresAt": "2026-09-08T17:44:12.000Z"
}{
"environment": "sandbox",
"error": {
"code": "invalid_request",
"message": "amount must be a decimal string of the token's smallest unit.",
"fields": {
"applicantInfo.nationality": "iso3166_1_alpha2"
}
}
}{
"environment": "sandbox",
"error": {
"code": "invalid_request",
"message": "amount must be a decimal string of the token's smallest unit.",
"fields": {
"applicantInfo.nationality": "iso3166_1_alpha2"
}
}
}{
"environment": "sandbox",
"error": {
"code": "invalid_request",
"message": "amount must be a decimal string of the token's smallest unit.",
"fields": {
"applicantInfo.nationality": "iso3166_1_alpha2"
}
}
}{
"environment": "sandbox",
"error": {
"code": "invalid_request",
"message": "amount must be a decimal string of the token's smallest unit.",
"fields": {
"applicantInfo.nationality": "iso3166_1_alpha2"
}
}
}{
"environment": "sandbox",
"error": {
"code": "invalid_request",
"message": "amount must be a decimal string of the token's smallest unit.",
"fields": {
"applicantInfo.nationality": "iso3166_1_alpha2"
}
}
}network from GET /v1/config). Known limits: only the EUR/IBAN rail is wired for the simulated pay-in, and identity checks run on test-mode applicants. Every response says which environment answered in its environment field.mock: true: ids, shapes and statuses are real and deterministic from your input, every money figure is the placeholder 1234567.89, and nothing is sent to a provider. Integrate against the shape; do not compute anything from the figures.Authorizations
Your API key, issued by us and shown once at creation.
Body
Anonymous: no account, no identity - the price can be shown before anyone commits.
Symbol of the stablecoin the user pays out with, as GET /v1/currencies lists it on chain.
"USDC"
Chain id the stablecoins are sent from. Must be one your key may pay FROM (403 chain_not_allowed otherwise) and one the catalogue lists.
x <= 900719925474099142161
ISO 4217 code the bank account is credited in.
^[A-Za-z]{3}$"GBP"
ISO 3166-1 alpha-2 of the destination bank. The same currency reaches different countries over different rails, so it is priced per country.
^[A-Za-z]{2}$"GB"
What the user gives up, decimal string in major units of cryptoCurrency. Send this OR fiatAmount, never both.
^\d+(\.\d+)?$"1000.00"
What must arrive, decimal string in major units of fiatCurrency, solved backwards. Send this OR cryptoAmount, never both.
^\d+(\.\d+)?$"100"
Force a rail, named as GET /v1/limits names it (e.g. faster_payments, sepa_instant, pix). Omitted: the fastest published payout rail for the currency is chosen. A rail that does not serve the currency is refused with no_route.
"faster_payments"
Response
The quote, with the rail it is for.
Which environment answered. sandbox: at least one money upstream is the provider's sandbox - no real money moves there, and the card corridor is the sandbox's asset (read GET /v1/config), not the documented production one. production: every configured upstream is real. Derived from the configured upstream hosts at boot, never a flag.
sandbox, production "sandbox"
Always true on this endpoint: the provider behind it is currently being connected, docs updating. Ids, shapes and statuses are real and deterministic from your input; every money figure is the placeholder 1234567.89; nothing is sent to a provider. The field disappears the day the provider is wired, so branch on its presence, not its value.
true
Pass to POST /v1/bank/payout. Deterministic for the same request from the same key.
"bpq_42161_2e90c4a71f6d0b83"
Placeholder while the provider is being connected: always 1234567.89, never a price. Do not compute anything from it. When the provider is wired this becomes a decimal string in major units.
"1234567.89""1234567.89"
Placeholder while the provider is being connected: always 1234567.89, never a price. Do not compute anything from it. When the provider is wired this becomes a decimal string in major units.
"1234567.89""1234567.89"
Placeholder while the provider is being connected: always 1234567.89, never a price. Do not compute anything from it. When the provider is wired this becomes a decimal string in major units.
"1234567.89""1234567.89"
The rail this price is for, as GET /v1/limits names it. Read it: an omitted rail may resolve to something slower than you assumed.
"faster_payments"
The rail's published settlement time, in the notation GET /v1/limits explains. The rail's normal behaviour, never a commitment.
"instant"
Placeholder while the provider is being connected: always 1234567.89, never a price. Do not compute anything from it. When the provider is wired this becomes a decimal string in major units.
"1234567.89""1234567.89"
Placeholder while the provider is being connected: always 1234567.89, never a price. Do not compute anything from it. When the provider is wired this becomes a decimal string in major units.
"1234567.89""1234567.89"
ISO 8601. Execute before this. A quote past it is refused as expired rather than silently repriced.
"2026-09-08T17:44:12.000Z"