curl --request POST \
--url https://api.globalstack.io/v1/offramps/quotes \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"wallet_id": "<string>",
"beneficiary_id": "<string>",
"source_amount": "<string>",
"target_amount": "6.05",
"narration": "<string>"
}
'import requests
url = "https://api.globalstack.io/v1/offramps/quotes"
payload = {
"wallet_id": "<string>",
"beneficiary_id": "<string>",
"source_amount": "<string>",
"target_amount": "6.05",
"narration": "<string>"
}
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({
wallet_id: '<string>',
beneficiary_id: '<string>',
source_amount: '<string>',
target_amount: '6.05',
narration: '<string>'
})
};
fetch('https://api.globalstack.io/v1/offramps/quotes', 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.globalstack.io/v1/offramps/quotes",
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([
'wallet_id' => '<string>',
'beneficiary_id' => '<string>',
'source_amount' => '<string>',
'target_amount' => '6.05',
'narration' => '<string>'
]),
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.globalstack.io/v1/offramps/quotes"
payload := strings.NewReader("{\n \"wallet_id\": \"<string>\",\n \"beneficiary_id\": \"<string>\",\n \"source_amount\": \"<string>\",\n \"target_amount\": \"6.05\",\n \"narration\": \"<string>\"\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.globalstack.io/v1/offramps/quotes")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"wallet_id\": \"<string>\",\n \"beneficiary_id\": \"<string>\",\n \"source_amount\": \"<string>\",\n \"target_amount\": \"6.05\",\n \"narration\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.globalstack.io/v1/offramps/quotes")
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 \"wallet_id\": \"<string>\",\n \"beneficiary_id\": \"<string>\",\n \"source_amount\": \"<string>\",\n \"target_amount\": \"6.05\",\n \"narration\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"status": true,
"message": "Quote created successfully",
"code": "ok",
"data": {
"id": "quo_01KPBK123456789ABCDEFG",
"operation": "onramp",
"status": "active",
"wallet_id": "wal_seed_alice_usdc",
"customer_id": "cust_01HXYZABC1234567890ABCDEFG",
"source_amount": "10000.00",
"source_currency": "NGN",
"destination_amount": "6.046600",
"destination_currency": "USDC",
"rate": "0.000605",
"expires_at": "2026-04-22T02:30:00.000Z",
"created_at": "2026-04-22T02:00:00.000Z",
"updated_at": "2026-04-22T02:00:00.000Z",
"reference": "INV-2026-001",
"destination_wallet_id": "wal_seed_alice_ngn",
"received_amount": "6.046600",
"fee": {
"line_items": [
{
"name": "gateway",
"amount": "100",
"currency": "NGN"
},
{
"name": "network",
"amount": "0.5",
"currency": "USDC"
}
]
}
},
"meta": {
"request_id": "req_01HXYZ4K5ABCDEFGHJKLMNPQRS",
"timestamp": "2026-05-14T15:43:55.732Z",
"version": "1"
}
}{
"status": false,
"message": "Resource not found",
"code": "not_found",
"data": null,
"meta": {
"next_steps": {
"action": "Verify the resource identifier and retry.",
"docs_url": "https://docs.globalstack.io/errors#not_found"
},
"request_id": "req_01HXYZ4K5ABCDEFGHJKLMNPQRS",
"timestamp": "2026-05-14T15:43:55.732Z",
"version": "1"
}
}{
"status": false,
"message": "Resource not found",
"code": "not_found",
"data": null,
"meta": {
"next_steps": {
"action": "Verify the resource identifier and retry.",
"docs_url": "https://docs.globalstack.io/errors#not_found"
},
"request_id": "req_01HXYZ4K5ABCDEFGHJKLMNPQRS",
"timestamp": "2026-05-14T15:43:55.732Z",
"version": "1"
}
}{
"status": false,
"message": "Resource not found",
"code": "not_found",
"data": null,
"meta": {
"next_steps": {
"action": "Verify the resource identifier and retry.",
"docs_url": "https://docs.globalstack.io/errors#not_found"
},
"request_id": "req_01HXYZ4K5ABCDEFGHJKLMNPQRS",
"timestamp": "2026-05-14T15:43:55.732Z",
"version": "1"
}
}{
"status": false,
"message": "Resource not found",
"code": "not_found",
"data": null,
"meta": {
"next_steps": {
"action": "Verify the resource identifier and retry.",
"docs_url": "https://docs.globalstack.io/errors#not_found"
},
"request_id": "req_01HXYZ4K5ABCDEFGHJKLMNPQRS",
"timestamp": "2026-05-14T15:43:55.732Z",
"version": "1"
}
}Create an offramp quote
Creates an offramp quote — a short-lived, priced offer to convert the crypto
held by the wallet identified by wallet_id into fiat paid out to beneficiary_id.
The wallet’s own currency (e.g. USDC) is the source; the beneficiary’s currency
(e.g. NGN) is the destination. source_network is derived from a credential on
the wallet; destination_network is the beneficiary’s payout rail. The beneficiary
must belong to the same customer as the wallet. narration is optional and echoed
back as the quote reference.
The quote is created with status: active and an expires_at in the near future.
You can optionally pass source_currency and destination_currency as consistency checks — if they do not match the wallet or beneficiary, we reject the request immediately.
Specify either source_amount (the crypto amount converted) or target_amount
(the fiat amount the beneficiary receives) — exactly one, each a positive decimal string.
Providing both, or neither, is rejected with a 400. When target_amount is supplied, we
compute and return the required source_amount on the quote.
USDC amounts settle in whole US cents: source_amount may carry at most 2 significant
decimal places. Trailing zeros are fine — 2.980000 is accepted, 2.980228 is rejected
with 400 invalid_amount_precision. This precision check applies only when you supply
source_amount; a target_amount-driven quote is not constrained this way.
curl --request POST \
--url https://api.globalstack.io/v1/offramps/quotes \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"wallet_id": "<string>",
"beneficiary_id": "<string>",
"source_amount": "<string>",
"target_amount": "6.05",
"narration": "<string>"
}
'import requests
url = "https://api.globalstack.io/v1/offramps/quotes"
payload = {
"wallet_id": "<string>",
"beneficiary_id": "<string>",
"source_amount": "<string>",
"target_amount": "6.05",
"narration": "<string>"
}
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({
wallet_id: '<string>',
beneficiary_id: '<string>',
source_amount: '<string>',
target_amount: '6.05',
narration: '<string>'
})
};
fetch('https://api.globalstack.io/v1/offramps/quotes', 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.globalstack.io/v1/offramps/quotes",
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([
'wallet_id' => '<string>',
'beneficiary_id' => '<string>',
'source_amount' => '<string>',
'target_amount' => '6.05',
'narration' => '<string>'
]),
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.globalstack.io/v1/offramps/quotes"
payload := strings.NewReader("{\n \"wallet_id\": \"<string>\",\n \"beneficiary_id\": \"<string>\",\n \"source_amount\": \"<string>\",\n \"target_amount\": \"6.05\",\n \"narration\": \"<string>\"\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.globalstack.io/v1/offramps/quotes")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"wallet_id\": \"<string>\",\n \"beneficiary_id\": \"<string>\",\n \"source_amount\": \"<string>\",\n \"target_amount\": \"6.05\",\n \"narration\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.globalstack.io/v1/offramps/quotes")
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 \"wallet_id\": \"<string>\",\n \"beneficiary_id\": \"<string>\",\n \"source_amount\": \"<string>\",\n \"target_amount\": \"6.05\",\n \"narration\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"status": true,
"message": "Quote created successfully",
"code": "ok",
"data": {
"id": "quo_01KPBK123456789ABCDEFG",
"operation": "onramp",
"status": "active",
"wallet_id": "wal_seed_alice_usdc",
"customer_id": "cust_01HXYZABC1234567890ABCDEFG",
"source_amount": "10000.00",
"source_currency": "NGN",
"destination_amount": "6.046600",
"destination_currency": "USDC",
"rate": "0.000605",
"expires_at": "2026-04-22T02:30:00.000Z",
"created_at": "2026-04-22T02:00:00.000Z",
"updated_at": "2026-04-22T02:00:00.000Z",
"reference": "INV-2026-001",
"destination_wallet_id": "wal_seed_alice_ngn",
"received_amount": "6.046600",
"fee": {
"line_items": [
{
"name": "gateway",
"amount": "100",
"currency": "NGN"
},
{
"name": "network",
"amount": "0.5",
"currency": "USDC"
}
]
}
},
"meta": {
"request_id": "req_01HXYZ4K5ABCDEFGHJKLMNPQRS",
"timestamp": "2026-05-14T15:43:55.732Z",
"version": "1"
}
}{
"status": false,
"message": "Resource not found",
"code": "not_found",
"data": null,
"meta": {
"next_steps": {
"action": "Verify the resource identifier and retry.",
"docs_url": "https://docs.globalstack.io/errors#not_found"
},
"request_id": "req_01HXYZ4K5ABCDEFGHJKLMNPQRS",
"timestamp": "2026-05-14T15:43:55.732Z",
"version": "1"
}
}{
"status": false,
"message": "Resource not found",
"code": "not_found",
"data": null,
"meta": {
"next_steps": {
"action": "Verify the resource identifier and retry.",
"docs_url": "https://docs.globalstack.io/errors#not_found"
},
"request_id": "req_01HXYZ4K5ABCDEFGHJKLMNPQRS",
"timestamp": "2026-05-14T15:43:55.732Z",
"version": "1"
}
}{
"status": false,
"message": "Resource not found",
"code": "not_found",
"data": null,
"meta": {
"next_steps": {
"action": "Verify the resource identifier and retry.",
"docs_url": "https://docs.globalstack.io/errors#not_found"
},
"request_id": "req_01HXYZ4K5ABCDEFGHJKLMNPQRS",
"timestamp": "2026-05-14T15:43:55.732Z",
"version": "1"
}
}{
"status": false,
"message": "Resource not found",
"code": "not_found",
"data": null,
"meta": {
"next_steps": {
"action": "Verify the resource identifier and retry.",
"docs_url": "https://docs.globalstack.io/errors#not_found"
},
"request_id": "req_01HXYZ4K5ABCDEFGHJKLMNPQRS",
"timestamp": "2026-05-14T15:43:55.732Z",
"version": "1"
}
}Authorizations
API key issued during merchant onboarding.
Headers
Optional client-supplied key. Identical key + identical body within 24h replays the original response. Identical key + different body returns 409 idempotency_conflict. The hash is over raw bytes — clients retrying must send the byte-identical body; a re-serialised JSON payload will produce a different hash and a 409. Strongly recommended for retry-safe clients.
^[A-Za-z0-9_\-]{8,255}$Body
CreateOfframpQuoteDto
6464^\d+(\.\d+)?$Destination amount the recipient receives, as a decimal string. Provide exactly one of source_amount or target_amount.
^\d+(\.\d+)?$"6.05"
128Response
Quote created successfully