International payments
Use an international payment intent to send a cross-border payment from your business. The workflow is quote-first: a quote fixes the available route, pricing, and payment requirements for a short time, then you create an intent from the selected quote option.
These Merchant API endpoints require an active merchant API key for an
approved business. Send the key from your backend in the x-api-key header.
The existing dashboard-session endpoints remain available for dashboard and
mobile clients, but integrations should use the /api/merchant/... routes
below.
Before you begin
Your business must be KYB-approved. You should also make sure you have enough funds in the selected source to fund the quote:
- Use the quote's
totalAmountToPay.amountNgnwhen you will fund in Naira. - Use the quote's
totalAmountToPay.amountUsdcwhen you will fund on-chain.
A quote does not reserve funds
Balance availability is a readiness check for your integration today; the API does not reserve or enforce that balance when an intent is created. Treat the quote expiry as authoritative and request a new quote when it has expired.
Build your destination selector
Do not hard-code a country list. Fetch the currently supported destination
corridors and use each countryCode as the value stored by your integration;
use countryName as the label shown to your user. Country codes are uppercase
ISO 3166-1 alpha-2 codes, for example US, GB, and CA.
curl "https://api.example.com/api/public/quote/corridors"The endpoint is public and returns the currently available countries, including the supported destination currencies and each currency's amount limits:
{
"message": "intl payment corridors fetched",
"response": {
"countries": [
{
"countryCode": "US",
"countryName": "United States",
"currencies": [
{
"currencyCode": "USD",
"currencySymbol": "$",
"destinationAmount": { "min": 1, "max": 10000 }
}
]
}
],
"updatedAt": "2026-08-25T10:00:00.000Z",
"stale": false
}
}Populate the currency selector from the selected country's currencies list,
validate the entered amount against destinationAmount, then pass the selected
countryCode and currencyCode as destinationCountry and
destinationCurrency when requesting a quote. Refresh the catalog regularly:
available corridors and limits can change. If stale is true, the response
is a cached fallback and should be refreshed before a new payment is started.
Make an international payment
Get a quote
Create a quote for the destination amount and corridor. The response includes
one or more options; save the returned quoteId, select an option's
optionId, and note expiresAt.
curl -X POST "https://api.example.com/api/merchant/international-payment-intents/quote" \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_MERCHANT_API_KEY" \
-d '{
"routeType": "usdc",
"sourceChain": "arbitrum",
"sourceAsset": "USDC",
"destinationCountry": "US",
"destinationCurrency": "USD",
"destinationAmount": 250
}'Review the quote before continuing. In particular, use the selected option's
expiry and the quote's total payable amount; prices and available routes can
change after expiry. Each option also includes fee_included_rate: total to
pay divided by the destination amount, expressed in the funding currency per
one destination-currency unit. It is the all-in rate, including the quote's
exchange-rate and fee effects.
The selected option also returns requirementsSchema: the live JSON Schema
for that option's destinationPayload. Read it from the quote response before
you build the intent request. Do not reuse a payload shape from another option
or corridor.
Use the selected option's live schema
requirementsSchema is returned inside response.options[], alongside its
optionId. Its fields can differ by route, country, currency, and payout
method.
Choose the funding source
Before creating the intent, select its funding source. For onchain, select
a supported fundingNetwork and compatible fundingAsset:
Arbitrum supports USDC and USDT; Base, Polygon, Arc, and Solana support
USDC. For ordinary merchant intents, naira remains available where the
route supports it. POBO entity intents must use onchain.
Confirm the selected account or wallet can cover the quote. The platform validates that the quote and option are active, but a quote does not lock funds.
Create the payment intent
Create the intent before the selected quote option expires. Send the quoteId,
the selected quoteOptionId, your invoice and payment-instruction URLs, and
the destination details required by the selected option's requirementsSchema.
curl -X POST "https://api.example.com/api/merchant/international-payment-intents" \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_MERCHANT_API_KEY" \
-H "Idempotency-Key: 23e0e2ef-9b8e-44ce-a090-d39d94eb97f3" \
-d '{
"quoteId": "quote_123",
"quoteOptionId": "option_123",
"fundingMethod": "onchain",
"fundingNetwork": "arbitrum",
"fundingAsset": "USDC",
"invoiceUrl": "https://merchant.example/invoices/INV-2048",
"paymentInstructionsUrl": "https://merchant.example/payments/INV-2048",
"recipientFullName": "Alex Morgan",
"recipientEmail": "alex@example.com",
"bankCodeType": "routing_number",
"bankCode": "021000021",
"accountNumber": "123456789",
"purposeOfTransfer": "Supplier payment",
"destinationPayload": {
"beneficiary_info": {
"beneficiary_name": "Alex Morgan",
"account_number": "123456789"
}
}
}'If the quote or option has expired, the request is rejected. Get a fresh quote
instead of retrying an expired one. Store the returned intentId with your
order or invoice reference. Reuse the same Idempotency-Key only if the same
create request must be retried after a timeout or network failure.
Read status updates
List your business's international payment intents to read the current status,
or check a single saved intentId for efficient status updates. The
response contains merchant-safe quote, payment-reference, and settlement data.
curl "https://api.example.com/api/merchant/international-payment-intents/intlpi_abc123" \
-H "x-api-key: YOUR_MERCHANT_API_KEY"Check the single-intent endpoint from your server while a payment is
unresolved. Do not assume intent creation means funds have been received,
processed, or settled; use the returned status as the source of truth.
If response.actionRequired is retry_funding, top up the originally selected
wallet or account and call:
POST /api/merchant/international-payment-intents/:intentId/retry-fundingUse a new Idempotency-Key for that retry. The payment is not retried automatically.