curl --request POST \
--url https://api.rheon.io/v1/card/purchase \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"email": "buyer@example.com",
"address": "0x1111111111111111111111111111111111111111",
"fiatCurrency": "EUR",
"fiatAmount": "100",
"billingAddress": {
"countryCode": "DE",
"streetLine1": "Main Street 1",
"streetLine2": "Apt 2",
"city": "Berlin",
"zipCode": "10115",
"stateCode": "BE"
},
"birthday": "1990-01-31",
"returnUrl": "https://example.com/return"
}
'import requests
url = "https://api.rheon.io/v1/card/purchase"
payload = {
"email": "buyer@example.com",
"address": "0x1111111111111111111111111111111111111111",
"fiatCurrency": "EUR",
"fiatAmount": "100",
"billingAddress": {
"countryCode": "DE",
"streetLine1": "Main Street 1",
"streetLine2": "Apt 2",
"city": "Berlin",
"zipCode": "10115",
"stateCode": "BE"
},
"birthday": "1990-01-31",
"returnUrl": "https://example.com/return"
}
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({
email: 'buyer@example.com',
address: '0x1111111111111111111111111111111111111111',
fiatCurrency: 'EUR',
fiatAmount: '100',
billingAddress: {
countryCode: 'DE',
streetLine1: 'Main Street 1',
streetLine2: 'Apt 2',
city: 'Berlin',
zipCode: '10115',
stateCode: 'BE'
},
birthday: '1990-01-31',
returnUrl: 'https://example.com/return'
})
};
fetch('https://api.rheon.io/v1/card/purchase', 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/card/purchase",
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([
'email' => 'buyer@example.com',
'address' => '0x1111111111111111111111111111111111111111',
'fiatCurrency' => 'EUR',
'fiatAmount' => '100',
'billingAddress' => [
'countryCode' => 'DE',
'streetLine1' => 'Main Street 1',
'streetLine2' => 'Apt 2',
'city' => 'Berlin',
'zipCode' => '10115',
'stateCode' => 'BE'
],
'birthday' => '1990-01-31',
'returnUrl' => 'https://example.com/return'
]),
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/card/purchase"
payload := strings.NewReader("{\n \"email\": \"buyer@example.com\",\n \"address\": \"0x1111111111111111111111111111111111111111\",\n \"fiatCurrency\": \"EUR\",\n \"fiatAmount\": \"100\",\n \"billingAddress\": {\n \"countryCode\": \"DE\",\n \"streetLine1\": \"Main Street 1\",\n \"streetLine2\": \"Apt 2\",\n \"city\": \"Berlin\",\n \"zipCode\": \"10115\",\n \"stateCode\": \"BE\"\n },\n \"birthday\": \"1990-01-31\",\n \"returnUrl\": \"https://example.com/return\"\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/card/purchase")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"email\": \"buyer@example.com\",\n \"address\": \"0x1111111111111111111111111111111111111111\",\n \"fiatCurrency\": \"EUR\",\n \"fiatAmount\": \"100\",\n \"billingAddress\": {\n \"countryCode\": \"DE\",\n \"streetLine1\": \"Main Street 1\",\n \"streetLine2\": \"Apt 2\",\n \"city\": \"Berlin\",\n \"zipCode\": \"10115\",\n \"stateCode\": \"BE\"\n },\n \"birthday\": \"1990-01-31\",\n \"returnUrl\": \"https://example.com/return\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.rheon.io/v1/card/purchase")
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 \"email\": \"buyer@example.com\",\n \"address\": \"0x1111111111111111111111111111111111111111\",\n \"fiatCurrency\": \"EUR\",\n \"fiatAmount\": \"100\",\n \"billingAddress\": {\n \"countryCode\": \"DE\",\n \"streetLine1\": \"Main Street 1\",\n \"streetLine2\": \"Apt 2\",\n \"city\": \"Berlin\",\n \"zipCode\": \"10115\",\n \"stateCode\": \"BE\"\n },\n \"birthday\": \"1990-01-31\",\n \"returnUrl\": \"https://example.com/return\"\n}"
response = http.request(request)
puts response.read_body{
"environment": "sandbox",
"status": "ready",
"redirectUrl": "<string>",
"transactionId": "<string>"
}{
"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"
}
}
}{
"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"
}
}
}Start a card purchase
Checks the buyer’s verification first. Not green: answers status: pending and no money moves - poll and retry. Green: sets the buyer’s profile and creates the purchase, answering the provider-hosted card page to redirect to. Card details are entered there, never on Rheon.
curl --request POST \
--url https://api.rheon.io/v1/card/purchase \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"email": "buyer@example.com",
"address": "0x1111111111111111111111111111111111111111",
"fiatCurrency": "EUR",
"fiatAmount": "100",
"billingAddress": {
"countryCode": "DE",
"streetLine1": "Main Street 1",
"streetLine2": "Apt 2",
"city": "Berlin",
"zipCode": "10115",
"stateCode": "BE"
},
"birthday": "1990-01-31",
"returnUrl": "https://example.com/return"
}
'import requests
url = "https://api.rheon.io/v1/card/purchase"
payload = {
"email": "buyer@example.com",
"address": "0x1111111111111111111111111111111111111111",
"fiatCurrency": "EUR",
"fiatAmount": "100",
"billingAddress": {
"countryCode": "DE",
"streetLine1": "Main Street 1",
"streetLine2": "Apt 2",
"city": "Berlin",
"zipCode": "10115",
"stateCode": "BE"
},
"birthday": "1990-01-31",
"returnUrl": "https://example.com/return"
}
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({
email: 'buyer@example.com',
address: '0x1111111111111111111111111111111111111111',
fiatCurrency: 'EUR',
fiatAmount: '100',
billingAddress: {
countryCode: 'DE',
streetLine1: 'Main Street 1',
streetLine2: 'Apt 2',
city: 'Berlin',
zipCode: '10115',
stateCode: 'BE'
},
birthday: '1990-01-31',
returnUrl: 'https://example.com/return'
})
};
fetch('https://api.rheon.io/v1/card/purchase', 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/card/purchase",
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([
'email' => 'buyer@example.com',
'address' => '0x1111111111111111111111111111111111111111',
'fiatCurrency' => 'EUR',
'fiatAmount' => '100',
'billingAddress' => [
'countryCode' => 'DE',
'streetLine1' => 'Main Street 1',
'streetLine2' => 'Apt 2',
'city' => 'Berlin',
'zipCode' => '10115',
'stateCode' => 'BE'
],
'birthday' => '1990-01-31',
'returnUrl' => 'https://example.com/return'
]),
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/card/purchase"
payload := strings.NewReader("{\n \"email\": \"buyer@example.com\",\n \"address\": \"0x1111111111111111111111111111111111111111\",\n \"fiatCurrency\": \"EUR\",\n \"fiatAmount\": \"100\",\n \"billingAddress\": {\n \"countryCode\": \"DE\",\n \"streetLine1\": \"Main Street 1\",\n \"streetLine2\": \"Apt 2\",\n \"city\": \"Berlin\",\n \"zipCode\": \"10115\",\n \"stateCode\": \"BE\"\n },\n \"birthday\": \"1990-01-31\",\n \"returnUrl\": \"https://example.com/return\"\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/card/purchase")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"email\": \"buyer@example.com\",\n \"address\": \"0x1111111111111111111111111111111111111111\",\n \"fiatCurrency\": \"EUR\",\n \"fiatAmount\": \"100\",\n \"billingAddress\": {\n \"countryCode\": \"DE\",\n \"streetLine1\": \"Main Street 1\",\n \"streetLine2\": \"Apt 2\",\n \"city\": \"Berlin\",\n \"zipCode\": \"10115\",\n \"stateCode\": \"BE\"\n },\n \"birthday\": \"1990-01-31\",\n \"returnUrl\": \"https://example.com/return\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.rheon.io/v1/card/purchase")
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 \"email\": \"buyer@example.com\",\n \"address\": \"0x1111111111111111111111111111111111111111\",\n \"fiatCurrency\": \"EUR\",\n \"fiatAmount\": \"100\",\n \"billingAddress\": {\n \"countryCode\": \"DE\",\n \"streetLine1\": \"Main Street 1\",\n \"streetLine2\": \"Apt 2\",\n \"city\": \"Berlin\",\n \"zipCode\": \"10115\",\n \"stateCode\": \"BE\"\n },\n \"birthday\": \"1990-01-31\",\n \"returnUrl\": \"https://example.com/return\"\n}"
response = http.request(request)
puts response.read_body{
"environment": "sandbox",
"status": "ready",
"redirectUrl": "<string>",
"transactionId": "<string>"
}{
"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"
}
}
}{
"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"
}
}
}completed (it stops at processing), the settlement asset is the sandbox’s, not production’s (read cryptoCurrency from GET /v1/config), and the EUR window is unpublished (GET /v1/card/limits says window: unpublished). Every response says which environment answered in its environment field.Authorizations
Your API key, issued by us and shown once at creation.
Body
Asset and chain come from the deployment's fixed corridor; there is no field to choose them.
Buyer email from the card form.
^[^\s@]+@[^\s@]+\.[^\s@]+$"buyer@example.com"
The user's EVM wallet - the non-custodial destination.
^0x[0-9a-fA-F]{40}$"0x1111111111111111111111111111111111111111"
ISO 4217 code to charge in. Must be one of the deployment's supported fiat currencies (see GET /v1/card/currencies); others are refused.
^[A-Za-z]{3}$"EUR"
Fiat to spend, decimal string in major units, greater than zero.
^\d+(\.\d+)?$"100"
Show child attributes
Show child attributes
Date of birth, ISO YYYY-MM-DD.
^\d{4}-\d{2}-\d{2}$"1990-01-31"
Where the hosted card page sends the user afterwards.
"https://example.com/return"
Response
Ready to pay, or verification still pending.
- Option 1
- Option 2
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"
"ready"Provider-hosted card entry page. Redirect the user here.
Provider transaction id to poll status with.