Legacy: Create an offramp
curl --request POST \
--url https://api.daya.co/v1/offramps \
--header 'Content-Type: application/json' \
--header 'X-Api-Key: <x-api-key>' \
--header 'X-Idempotency-Key: <x-idempotency-key>' \
--data '
{
"type": "<string>",
"customer": {
"customer.customer_id": "<string>",
"customer.email": "<string>",
"customer.first_name": "<string>",
"customer.last_name": "<string>"
},
"chain": "<string>",
"asset": "<string>",
"developer_fee": {
"developer_fee.percentage": "<string>"
},
"settlement": {
"settlement.mode": "<string>",
"settlement.rate_id": "<string>",
"settlement.destination_bank": {
"settlement.destination_bank.account_name": "<string>",
"settlement.destination_bank.account_number": "<string>",
"settlement.destination_bank.bank_code": "<string>"
}
}
}
'import requests
url = "https://api.daya.co/v1/offramps"
payload = {
"type": "<string>",
"customer": {
"customer.customer_id": "<string>",
"customer.email": "<string>",
"customer.first_name": "<string>",
"customer.last_name": "<string>"
},
"chain": "<string>",
"asset": "<string>",
"developer_fee": { "developer_fee.percentage": "<string>" },
"settlement": {
"settlement.mode": "<string>",
"settlement.rate_id": "<string>",
"settlement.destination_bank": {
"settlement.destination_bank.account_name": "<string>",
"settlement.destination_bank.account_number": "<string>",
"settlement.destination_bank.bank_code": "<string>"
}
}
}
headers = {
"X-Api-Key": "<x-api-key>",
"X-Idempotency-Key": "<x-idempotency-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'X-Api-Key': '<x-api-key>',
'X-Idempotency-Key': '<x-idempotency-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
type: '<string>',
customer: {
'customer.customer_id': '<string>',
'customer.email': '<string>',
'customer.first_name': '<string>',
'customer.last_name': '<string>'
},
chain: '<string>',
asset: '<string>',
developer_fee: {'developer_fee.percentage': '<string>'},
settlement: {
'settlement.mode': '<string>',
'settlement.rate_id': '<string>',
'settlement.destination_bank': {
'settlement.destination_bank.account_name': '<string>',
'settlement.destination_bank.account_number': '<string>',
'settlement.destination_bank.bank_code': '<string>'
}
}
})
};
fetch('https://api.daya.co/v1/offramps', 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.daya.co/v1/offramps",
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([
'type' => '<string>',
'customer' => [
'customer.customer_id' => '<string>',
'customer.email' => '<string>',
'customer.first_name' => '<string>',
'customer.last_name' => '<string>'
],
'chain' => '<string>',
'asset' => '<string>',
'developer_fee' => [
'developer_fee.percentage' => '<string>'
],
'settlement' => [
'settlement.mode' => '<string>',
'settlement.rate_id' => '<string>',
'settlement.destination_bank' => [
'settlement.destination_bank.account_name' => '<string>',
'settlement.destination_bank.account_number' => '<string>',
'settlement.destination_bank.bank_code' => '<string>'
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Api-Key: <x-api-key>",
"X-Idempotency-Key: <x-idempotency-key>"
],
]);
$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.daya.co/v1/offramps"
payload := strings.NewReader("{\n \"type\": \"<string>\",\n \"customer\": {\n \"customer.customer_id\": \"<string>\",\n \"customer.email\": \"<string>\",\n \"customer.first_name\": \"<string>\",\n \"customer.last_name\": \"<string>\"\n },\n \"chain\": \"<string>\",\n \"asset\": \"<string>\",\n \"developer_fee\": {\n \"developer_fee.percentage\": \"<string>\"\n },\n \"settlement\": {\n \"settlement.mode\": \"<string>\",\n \"settlement.rate_id\": \"<string>\",\n \"settlement.destination_bank\": {\n \"settlement.destination_bank.account_name\": \"<string>\",\n \"settlement.destination_bank.account_number\": \"<string>\",\n \"settlement.destination_bank.bank_code\": \"<string>\"\n }\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Api-Key", "<x-api-key>")
req.Header.Add("X-Idempotency-Key", "<x-idempotency-key>")
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.daya.co/v1/offramps")
.header("X-Api-Key", "<x-api-key>")
.header("X-Idempotency-Key", "<x-idempotency-key>")
.header("Content-Type", "application/json")
.body("{\n \"type\": \"<string>\",\n \"customer\": {\n \"customer.customer_id\": \"<string>\",\n \"customer.email\": \"<string>\",\n \"customer.first_name\": \"<string>\",\n \"customer.last_name\": \"<string>\"\n },\n \"chain\": \"<string>\",\n \"asset\": \"<string>\",\n \"developer_fee\": {\n \"developer_fee.percentage\": \"<string>\"\n },\n \"settlement\": {\n \"settlement.mode\": \"<string>\",\n \"settlement.rate_id\": \"<string>\",\n \"settlement.destination_bank\": {\n \"settlement.destination_bank.account_name\": \"<string>\",\n \"settlement.destination_bank.account_number\": \"<string>\",\n \"settlement.destination_bank.bank_code\": \"<string>\"\n }\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.daya.co/v1/offramps")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Api-Key"] = '<x-api-key>'
request["X-Idempotency-Key"] = '<x-idempotency-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"type\": \"<string>\",\n \"customer\": {\n \"customer.customer_id\": \"<string>\",\n \"customer.email\": \"<string>\",\n \"customer.first_name\": \"<string>\",\n \"customer.last_name\": \"<string>\"\n },\n \"chain\": \"<string>\",\n \"asset\": \"<string>\",\n \"developer_fee\": {\n \"developer_fee.percentage\": \"<string>\"\n },\n \"settlement\": {\n \"settlement.mode\": \"<string>\",\n \"settlement.rate_id\": \"<string>\",\n \"settlement.destination_bank\": {\n \"settlement.destination_bank.account_name\": \"<string>\",\n \"settlement.destination_bank.account_number\": \"<string>\",\n \"settlement.destination_bank.bank_code\": \"<string>\"\n }\n }\n}"
response = http.request(request)
puts response.read_body{
"id": "a50e8400-e29b-41d4-a716-446655440000",
"type": "PERMANENT",
"customer_id": "650e8400-e29b-41d4-a716-446655440000",
"address": "0x1a2b3c4d5e6f7890abcdef1234567890abcdef12",
"chain": "ETHEREUM",
"asset": "USDC",
"status": "ACTIVE",
"developer_fee": {
"percentage": "2.5"
},
"settlement": {
"mode": "INTERNAL_BALANCE",
"rate_id": null,
"destination_bank": null
},
"created_at": "2026-01-05T15:04:05Z",
"updated_at": "2026-01-05T15:04:05Z"
}
{
"id": "b60e8400-e29b-41d4-a716-446655440000",
"type": "PERMANENT",
"customer_id": "650e8400-e29b-41d4-a716-446655440000",
"address": "TN3W4H6rK2ce4vX9YnFQHwKENnHjoxb3m9",
"chain": "TRON",
"asset": "USDT",
"status": "ACTIVE",
"settlement": {
"mode": "NGN_PAYOUT",
"rate_id": "rate_8x7k2mq9p",
"destination_bank": {
"account_name": "John Doe",
"account_number": "0123456789",
"bank_code": "058"
}
},
"created_at": "2026-01-05T15:04:05Z",
"updated_at": "2026-01-05T15:04:05Z"
}
Offramps
Legacy: Create an offramp
Legacy route for creating a crypto receive flow
POST
/
v1
/
offramps
Legacy: Create an offramp
curl --request POST \
--url https://api.daya.co/v1/offramps \
--header 'Content-Type: application/json' \
--header 'X-Api-Key: <x-api-key>' \
--header 'X-Idempotency-Key: <x-idempotency-key>' \
--data '
{
"type": "<string>",
"customer": {
"customer.customer_id": "<string>",
"customer.email": "<string>",
"customer.first_name": "<string>",
"customer.last_name": "<string>"
},
"chain": "<string>",
"asset": "<string>",
"developer_fee": {
"developer_fee.percentage": "<string>"
},
"settlement": {
"settlement.mode": "<string>",
"settlement.rate_id": "<string>",
"settlement.destination_bank": {
"settlement.destination_bank.account_name": "<string>",
"settlement.destination_bank.account_number": "<string>",
"settlement.destination_bank.bank_code": "<string>"
}
}
}
'import requests
url = "https://api.daya.co/v1/offramps"
payload = {
"type": "<string>",
"customer": {
"customer.customer_id": "<string>",
"customer.email": "<string>",
"customer.first_name": "<string>",
"customer.last_name": "<string>"
},
"chain": "<string>",
"asset": "<string>",
"developer_fee": { "developer_fee.percentage": "<string>" },
"settlement": {
"settlement.mode": "<string>",
"settlement.rate_id": "<string>",
"settlement.destination_bank": {
"settlement.destination_bank.account_name": "<string>",
"settlement.destination_bank.account_number": "<string>",
"settlement.destination_bank.bank_code": "<string>"
}
}
}
headers = {
"X-Api-Key": "<x-api-key>",
"X-Idempotency-Key": "<x-idempotency-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'X-Api-Key': '<x-api-key>',
'X-Idempotency-Key': '<x-idempotency-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
type: '<string>',
customer: {
'customer.customer_id': '<string>',
'customer.email': '<string>',
'customer.first_name': '<string>',
'customer.last_name': '<string>'
},
chain: '<string>',
asset: '<string>',
developer_fee: {'developer_fee.percentage': '<string>'},
settlement: {
'settlement.mode': '<string>',
'settlement.rate_id': '<string>',
'settlement.destination_bank': {
'settlement.destination_bank.account_name': '<string>',
'settlement.destination_bank.account_number': '<string>',
'settlement.destination_bank.bank_code': '<string>'
}
}
})
};
fetch('https://api.daya.co/v1/offramps', 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.daya.co/v1/offramps",
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([
'type' => '<string>',
'customer' => [
'customer.customer_id' => '<string>',
'customer.email' => '<string>',
'customer.first_name' => '<string>',
'customer.last_name' => '<string>'
],
'chain' => '<string>',
'asset' => '<string>',
'developer_fee' => [
'developer_fee.percentage' => '<string>'
],
'settlement' => [
'settlement.mode' => '<string>',
'settlement.rate_id' => '<string>',
'settlement.destination_bank' => [
'settlement.destination_bank.account_name' => '<string>',
'settlement.destination_bank.account_number' => '<string>',
'settlement.destination_bank.bank_code' => '<string>'
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Api-Key: <x-api-key>",
"X-Idempotency-Key: <x-idempotency-key>"
],
]);
$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.daya.co/v1/offramps"
payload := strings.NewReader("{\n \"type\": \"<string>\",\n \"customer\": {\n \"customer.customer_id\": \"<string>\",\n \"customer.email\": \"<string>\",\n \"customer.first_name\": \"<string>\",\n \"customer.last_name\": \"<string>\"\n },\n \"chain\": \"<string>\",\n \"asset\": \"<string>\",\n \"developer_fee\": {\n \"developer_fee.percentage\": \"<string>\"\n },\n \"settlement\": {\n \"settlement.mode\": \"<string>\",\n \"settlement.rate_id\": \"<string>\",\n \"settlement.destination_bank\": {\n \"settlement.destination_bank.account_name\": \"<string>\",\n \"settlement.destination_bank.account_number\": \"<string>\",\n \"settlement.destination_bank.bank_code\": \"<string>\"\n }\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Api-Key", "<x-api-key>")
req.Header.Add("X-Idempotency-Key", "<x-idempotency-key>")
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.daya.co/v1/offramps")
.header("X-Api-Key", "<x-api-key>")
.header("X-Idempotency-Key", "<x-idempotency-key>")
.header("Content-Type", "application/json")
.body("{\n \"type\": \"<string>\",\n \"customer\": {\n \"customer.customer_id\": \"<string>\",\n \"customer.email\": \"<string>\",\n \"customer.first_name\": \"<string>\",\n \"customer.last_name\": \"<string>\"\n },\n \"chain\": \"<string>\",\n \"asset\": \"<string>\",\n \"developer_fee\": {\n \"developer_fee.percentage\": \"<string>\"\n },\n \"settlement\": {\n \"settlement.mode\": \"<string>\",\n \"settlement.rate_id\": \"<string>\",\n \"settlement.destination_bank\": {\n \"settlement.destination_bank.account_name\": \"<string>\",\n \"settlement.destination_bank.account_number\": \"<string>\",\n \"settlement.destination_bank.bank_code\": \"<string>\"\n }\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.daya.co/v1/offramps")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Api-Key"] = '<x-api-key>'
request["X-Idempotency-Key"] = '<x-idempotency-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"type\": \"<string>\",\n \"customer\": {\n \"customer.customer_id\": \"<string>\",\n \"customer.email\": \"<string>\",\n \"customer.first_name\": \"<string>\",\n \"customer.last_name\": \"<string>\"\n },\n \"chain\": \"<string>\",\n \"asset\": \"<string>\",\n \"developer_fee\": {\n \"developer_fee.percentage\": \"<string>\"\n },\n \"settlement\": {\n \"settlement.mode\": \"<string>\",\n \"settlement.rate_id\": \"<string>\",\n \"settlement.destination_bank\": {\n \"settlement.destination_bank.account_name\": \"<string>\",\n \"settlement.destination_bank.account_number\": \"<string>\",\n \"settlement.destination_bank.bank_code\": \"<string>\"\n }\n }\n}"
response = http.request(request)
puts response.read_body{
"id": "a50e8400-e29b-41d4-a716-446655440000",
"type": "PERMANENT",
"customer_id": "650e8400-e29b-41d4-a716-446655440000",
"address": "0x1a2b3c4d5e6f7890abcdef1234567890abcdef12",
"chain": "ETHEREUM",
"asset": "USDC",
"status": "ACTIVE",
"developer_fee": {
"percentage": "2.5"
},
"settlement": {
"mode": "INTERNAL_BALANCE",
"rate_id": null,
"destination_bank": null
},
"created_at": "2026-01-05T15:04:05Z",
"updated_at": "2026-01-05T15:04:05Z"
}
{
"id": "b60e8400-e29b-41d4-a716-446655440000",
"type": "PERMANENT",
"customer_id": "650e8400-e29b-41d4-a716-446655440000",
"address": "TN3W4H6rK2ce4vX9YnFQHwKENnHjoxb3m9",
"chain": "TRON",
"asset": "USDT",
"status": "ACTIVE",
"settlement": {
"mode": "NGN_PAYOUT",
"rate_id": "rate_8x7k2mq9p",
"destination_bank": {
"account_name": "John Doe",
"account_number": "0123456789",
"bank_code": "058"
}
},
"created_at": "2026-01-05T15:04:05Z",
"updated_at": "2026-01-05T15:04:05Z"
}
Overview
Create an offramp through the legacy compatibility route. New integrations should usePOST /v1/funding-accounts with rail: CRYPTO_ADDRESS, asset, and chain.
Authentication
string
required
Your merchant API key
string
required
Unique idempotency key to prevent duplicate offramp creation
Request Body
string
required
Offramp typeAllowed values:
TEMPORARY, PERMANENTTEMPORARY: Short-lived deposit address, locked torate_id. Must useNGN_PAYOUTsettlement.PERMANENT: Long-lived deposit address, uses current rate at settlement. Supports bothINTERNAL_BALANCEandNGN_PAYOUTsettlement.
object
required
Customer information. Either
customer_id or email must be provided.Show customer properties
Show customer properties
string
required
Blockchain network for the deposit addressAllowed values:
APTOS, BASE, BSC, CELO, ETHEREUM, POLYGON, SOLANA, SUI, TEMPO, TRONSee Supported Chains for details on which assets are available on each chain.string
required
Stablecoin asset to receiveAllowed values:
USDC, USDTobject
Optional fee that your merchant account keeps from each offramp deposit. Omit to use
0%.Show developer_fee properties
Show developer_fee properties
string
required
Percentage of each received deposit that your merchant account keeps. Use a decimal string from
0 to 50. This is a percentage value, not basis points: 0.5 means 0.5%, 2 means 2%, and 50 means 50%.Example: "2.5"object
required
Settlement configuration
Show settlement properties
Show settlement properties
string
required
Settlement modeAllowed values:
INTERNAL_BALANCE- Credit merchant USD balance (only valid whentypeisPERMANENT)NGN_PAYOUT- Settle as NGN to a bank account
string
Rate identifier from
GET /v1/ratesExample: rate_8x7k2mq9pRequired for
NGN_PAYOUT mode. Not used for INTERNAL_BALANCE.Request Examples
{
"type": "TEMPORARY",
"customer": {
"customer_id": "650e8400-e29b-41d4-a716-446655440000"
},
"chain": "BASE",
"asset": "USDC",
"developer_fee": {
"percentage": "2.5"
},
"settlement": {
"mode": "NGN_PAYOUT",
"rate_id": "rate_8x7k2mq9p",
"destination_bank": {
"account_name": "John Doe",
"account_number": "0123456789",
"bank_code": "058"
}
}
}
{
"type": "PERMANENT",
"customer": {
"email": "user@example.com",
"first_name": "John",
"last_name": "Doe"
},
"chain": "SOLANA",
"asset": "USDT",
"settlement": {
"mode": "INTERNAL_BALANCE"
}
}
{
"type": "PERMANENT",
"customer": {
"customer_id": "650e8400-e29b-41d4-a716-446655440000"
},
"chain": "TRON",
"asset": "USDT",
"settlement": {
"mode": "NGN_PAYOUT",
"rate_id": "rate_8x7k2mq9p",
"destination_bank": {
"account_name": "John Doe",
"account_number": "0123456789",
"bank_code": "058"
}
}
}
curl --request POST \
--url https://api.daya.co/v1/offramps \
--header 'X-Api-Key: YOUR_API_KEY' \
--header 'X-Idempotency-Key: unique-key-456' \
--header 'Content-Type: application/json' \
--data '{
"type": "PERMANENT",
"customer": {
"customer_id": "650e8400-e29b-41d4-a716-446655440000"
},
"chain": "TRON",
"asset": "USDT",
"settlement": {
"mode": "NGN_PAYOUT",
"rate_id": "rate_8x7k2mq9p",
"destination_bank": {
"account_name": "John Doe",
"account_number": "0123456789",
"bank_code": "058"
}
}
}'
const response = await fetch('https://api.daya.co/v1/offramps', {
method: 'POST',
headers: {
'X-Api-Key': 'YOUR_API_KEY',
'X-Idempotency-Key': 'unique-key-123',
'Content-Type': 'application/json'
},
body: JSON.stringify({
type: 'PERMANENT',
customer: {
email: 'user@example.com'
},
chain: 'ETHEREUM',
asset: 'USDC',
settlement: {
mode: 'INTERNAL_BALANCE'
}
})
});
const offramp = await response.json();
Response
string
required
Unique offramp identifier (UUID)
string
required
Offramp type:
TEMPORARY or PERMANENTstring
required
Associated customer ID (UUID)
string
required
Generated crypto deposit address
string
required
Blockchain network:
APTOS, BASE, BSC, CELO, ETHEREUM, POLYGON, SOLANA, SUI, TEMPO, or TRONstring
required
Stablecoin asset:
USDC or USDTstring
required
Current offramp status. New offramps start as
ACTIVE.object
required
Developer fee percentage used for deposits received through this offramp.
Show developer_fee properties
Show developer_fee properties
string
Configured percentage as a decimal string.
object
required
Settlement configuration
Show settlement properties
Show settlement properties
string
required
When the offramp was created (ISO 8601 timestamp)
string
required
When the offramp was last updated (ISO 8601 timestamp)
Success Responses
{
"id": "a50e8400-e29b-41d4-a716-446655440000",
"type": "PERMANENT",
"customer_id": "650e8400-e29b-41d4-a716-446655440000",
"address": "0x1a2b3c4d5e6f7890abcdef1234567890abcdef12",
"chain": "ETHEREUM",
"asset": "USDC",
"status": "ACTIVE",
"developer_fee": {
"percentage": "2.5"
},
"settlement": {
"mode": "INTERNAL_BALANCE",
"rate_id": null,
"destination_bank": null
},
"created_at": "2026-01-05T15:04:05Z",
"updated_at": "2026-01-05T15:04:05Z"
}
{
"id": "b60e8400-e29b-41d4-a716-446655440000",
"type": "PERMANENT",
"customer_id": "650e8400-e29b-41d4-a716-446655440000",
"address": "TN3W4H6rK2ce4vX9YnFQHwKENnHjoxb3m9",
"chain": "TRON",
"asset": "USDT",
"status": "ACTIVE",
"settlement": {
"mode": "NGN_PAYOUT",
"rate_id": "rate_8x7k2mq9p",
"destination_bank": {
"account_name": "John Doe",
"account_number": "0123456789",
"bank_code": "058"
}
},
"created_at": "2026-01-05T15:04:05Z",
"updated_at": "2026-01-05T15:04:05Z"
}
Error Responses
{
"error": {
"code": "VALIDATION_FAILED",
"message": "either customer.customer_id or customer.email is required",
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"validation": "customer.customer_id or customer.email is required"
}
}
{
"error": {
"code": "VALIDATION_FAILED",
"message": "Validation failed",
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"validation": "chain must be one of APTOS, BASE, BSC, CELO, ETHEREUM, POLYGON, SOLANA, SUI, TEMPO, TRON"
}
}
{
"error": {
"code": "VALIDATION_FAILED",
"message": "Validation failed",
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"validation": "rate_id is required for NGN_PAYOUT settlement mode"
}
}
{
"error": {
"code": "RATE_EXPIRED",
"message": "The specified rate_id has expired. Request a new rate via GET /v1/rates",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}
{
"error": {
"code": "VALIDATION_FAILED",
"message": "Validation failed",
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"validation": "destination_bank is required for NGN_PAYOUT settlement mode"
}
}
{
"error": {
"code": "VALIDATION_FAILED",
"message": "Validation failed",
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"validation": "account_number must be between 6 and 32 characters"
}
}
{
"error": {
"code": "UNAUTHORIZED",
"message": "Unauthorized",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}
{
"error": {
"code": "RATE_LIMITED",
"message": "Merchant has exceeded daily offramp creation limit",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}
Validation Rules
Customer identification
Customer identification
Either
customer.customer_id or customer.email must be provided (not both optional, at least one required).Temporary offramp rules
Temporary offramp rules
- Generates a short-lived crypto deposit address
- Settlement mode must be
NGN_PAYOUT—INTERNAL_BALANCEis not supported on temporary offramps settlement.rate_idandsettlement.destination_bankare required
Permanent offramp rules
Permanent offramp rules
- Generates a long-lived crypto deposit address
- Uses the current rate at the time of deposit settlement
- Supports both
INTERNAL_BALANCEandNGN_PAYOUTsettlement modes - For
NGN_PAYOUT:settlement.rate_idandsettlement.destination_bankare required - For
INTERNAL_BALANCE:settlement.rate_idandsettlement.destination_bankmust NOT be set
NGN payout bank details
NGN payout bank details
When
settlement.mode is NGN_PAYOUT:destination_bank.account_nameis requireddestination_bank.account_numbermust be 6-32 charactersdestination_bank.bank_codemust be 3-16 characters
Always resolve the bank account first using
POST /v1/banks/resolve before creating the offramp. Invalid bank accounts will be rejected.Best Practices
1
Resolve bank account before creation (NGN payout)
Always call
POST /v1/banks/resolve to verify the account number and get the account holder’s name before creating an offramp with NGN_PAYOUT. Invalid accounts will be rejected.2
Get fresh rate before creation (NGN payout)
Call
GET /v1/rates?side=SELL immediately before creating an offramp with NGN_PAYOUT to ensure maximum validity window.3
Use customer_id for returning customers
Create customers once via
POST /v1/customers, then reference them by customer_id in subsequent offramp requests.4
Use idempotency keys
Always include a unique
X-Idempotency-Key header to prevent duplicate offramp creation on retries.5
Choose the right chain
Consider transaction fees and confirmation times when selecting a chain. See Supported Chains for details.
Next Steps
List Offramps
Query offramps with filters
Get Rates
Fetch current exchange rates before creating an offramp
Customer API
Pre-create customers before offramp requests
Webhooks
Listen for deposit and settlement events