quoteId that you must supply when you create the payout.
Endpoint
POST{{baseURL}}/v1/quote
Quotes expire after the duration returned in
expiresInSeconds. Create the payout before it expires or request a fresh quote.Request body
copy
{
"paymentChannel": "BANK_TRANSFER",
"source": {
"amount": 150000,
"country": "NG",
"currency": "NGN"
},
"target": {
"country": "US",
"currency": "USD"
}
}
Body fields
| Field | Type | Description | Required | Example |
|---|---|---|---|---|
paymentChannel | String | Payment channel used to settle the payout (e.g. BANK_TRANSFER, MOBILE_MONEY). | ✅ Yes | BANK_TRANSFER |
source.amount | Number | Amount you want to convert in the source currency. | ✅ Yes | 150000 |
source.country | String | ISO 3166-1 alpha-2 code for the sender country. | ✅ Yes | NG |
source.currency | String | ISO 4217 code for the sender currency. | ✅ Yes | NGN |
target.country | String | ISO 3166-1 alpha-2 code for the recipient country. | ✅ Yes | US |
target.currency | String | ISO 4217 code for the recipient currency. | ✅ Yes | USD |
Request headers
| Header | Type | Description | Required | Example |
|---|---|---|---|---|
x-api-key | String | API key associated with your workspace. | ✅ Yes | YOUR_API_KEY |
Content-Type | String | Media type of the request body. | ✅ Yes | application/json |
Request examples
curl --request POST '{{baseURL}}/v1/quote' \
--header 'x-api-key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"paymentChannel": "BANK_TRANSFER",
"source": {
"amount": 150000,
"country": "NG",
"currency": "NGN"
},
"target": {
"country": "US",
"currency": "USD"
}
}'
const payload = {
paymentChannel: 'BANK_TRANSFER',
source: {
amount: 150000,
country: 'NG',
currency: 'NGN'
},
target: {
country: 'US',
currency: 'USD'
}
};
fetch('{{baseURL}}/v1/quote', {
method: 'POST',
headers: {
'x-api-key': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify(payload)
})
.then((res) => {
if (!res.ok) {
throw new Error(`Request failed with status ${res.status}`);
}
return res.json();
})
.then((body) => console.log(body))
.catch((error) => console.error('Failed to create quote', error));
import requests
url = "{{baseURL}}/v1/quote"
headers = {
"x-api-key": "YOUR_API_KEY",
"Content-Type": "application/json",
}
payload = {
"paymentChannel": "BANK_TRANSFER",
"source": {
"amount": 150000,
"country": "NG",
"currency": "NGN",
},
"target": {
"country": "US",
"currency": "USD",
},
}
response = requests.post(url, json=payload, headers=headers, timeout=30)
response.raise_for_status()
print(response.json())
const axios = require('axios');
axios.post('{{baseURL}}/v1/quote', {
paymentChannel: 'BANK_TRANSFER',
source: {
amount: 150000,
country: 'NG',
currency: 'NGN'
},
target: {
country: 'US',
currency: 'USD'
}
}, {
headers: {
'x-api-key': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
timeout: 30000
})
.then((response) => {
console.log(response.data);
})
.catch((error) => {
if (error.response) {
console.error('API error:', error.response.data);
} else {
console.error('Request error:', error.message);
}
});
Successful response
copy
{
"message": "quote successfully created",
"status": "success",
"data": {
"id": "e5eec724-38f9-40e2-9i86-xxxxxxxxxxxxx",
"source": {
"currency": "NGN",
"country": "NG",
"amount": 150000
},
"target": {
"currency": "USD",
"country": "US",
"amount": 81.97
},
"rate": 1830,
"fee": {
"amount": 0
},
"summary": {
"total": 150000
},
"rules": [
{
"category": "LIMIT",
"appliedCurrency": "USD",
"transaction": {
"minimum": 1,
"maximum": 200000
}
}
],
"expiresInSeconds": 600,
"settlementTime": "1 hr"
}
}
Field reference
| Field | Type | Description |
|---|---|---|
id | String | Quote identifier to reuse in payout requests. |
rate | Number | Exchange rate applied to the conversion. |
summary.total | Number | Amount to debit in the source currency. |
fee.amount | Number | Total fees charged for the quote. |
expiresInSeconds | Number | Time remaining before the quote becomes invalid. |
rules | Array | Corridor rules that were evaluated (limits, compliance, etc.). |
Error responses
| Status | Message | Cause | How to handle |
|---|---|---|---|
| 400 | Invalid country or currency ISO code | The source/target country or currency combination is not supported. | Use valid ISO codes for corridors enabled on your workspace. |
| 400 | Invalid Payment Channel, check docs or contact support | paymentChannel is not valid for the selected corridor. | Choose a supported channel for the corridor and amount. |
| 400 | Required field missing or invalid request | Mandatory fields are missing or have invalid formats. | Validate source, target, paymentChannel, and metadata before sending. |
| 400 | Minimum target amount for transaction is {minimum_transaction_amount} | Requested target amount is below the corridor’s minimum. | Increase the target amount to at least the stated minimum. |
| 400 | Maximum target amount for transaction is {maximum_transaction_amount} | Requested target amount exceeds the corridor’s limit. | Reduce the target amount below the maximum threshold. |
| 400 | Transaction target amount {transaction_amount} requires invoice | Amount surpasses invoice thresholds that require documentation. | Collect and attach the required invoice before retrying. |
| 401 | API key missing or incorrect | x-api-key header missing, invalid, or expired. | Include the correct API key for sandbox/production. |
| 403 | Quote route not available, contact support | Endpoint disabled for your workspace or environment. | Reach out to support to enable quotes for the corridor. |
| 403 | Access denied: IP address not whitelisted | Request originated from an IP that isn’t on your allowlist. | Add your server IP in the dashboard. |
| 429 | API rate limit exceeded | Too many quote requests in a short window. | Apply exponential backoff and distribute requests. |
| 500 | Service temporarily unavailable | Temporary outage or maintenance event. | Retry after a delay; contact support if persistent. |
Best practices
- Cache quotes temporarily so the user can confirm without re-requesting.
- Surface the quote expiry countdown in your UI to encourage timely confirmation.
- Use the
Get Quote APIif you need to display the quote again before payout. - Pass the
quoteIdtoPOST /v2/payoutto execute the transfer.

