# Create beneficiary Source: https://docs.onswitch.xyz/api-reference/beneficiary/create-beneficiary /openapi.json post /beneficiary/create Create and save a beneficiary details for future payments. # Get beneficiaries Source: https://docs.onswitch.xyz/api-reference/beneficiary/get-beneficiaries /openapi.json get /beneficiary/fetch Returns paginated beneficiaries previously used as payment destination. # Get requirements Source: https://docs.onswitch.xyz/api-reference/beneficiary/get-requirements /openapi.json get /beneficiary/requirement Retrieve the required fields and validation rules for creating a beneficiary. # AML histories Source: https://docs.onswitch.xyz/api-reference/compliance/aml-histories /openapi.json get /compliance/aml/history Returns paginated previous AML lookup history. # AML lookup Source: https://docs.onswitch.xyz/api-reference/compliance/aml-lookup /openapi.json post /compliance/aml/lookup Screen an individual, business or crypto wallet against global compliance data. # Get payments Source: https://docs.onswitch.xyz/api-reference/history/get-payments /openapi.json get /payment/history Returns paginated payments history. # Get summary Source: https://docs.onswitch.xyz/api-reference/history/get-summary /openapi.json get /payment/summary Returns aggregated payment statistics. # Get institution Source: https://docs.onswitch.xyz/api-reference/institution/get-institution /openapi.json get /institution Retrieve institution-related data for the authenticated service. When `country` is provided, returns institutions (e.g. banks). # Lookup institution Source: https://docs.onswitch.xyz/api-reference/institution/lookup-institution /openapi.json post /institution/lookup Resolve bank or payment institution details from country-specific identifiers. # Get assets Source: https://docs.onswitch.xyz/api-reference/miscellaneous/get-assets /openapi.json get /asset Retrieve a list of all supported stablecoin assets. # Get coverage Source: https://docs.onswitch.xyz/api-reference/miscellaneous/get-coverage /openapi.json get /coverage Retrieve information about supported countries, currencies, and payment rails. # Get rates Source: https://docs.onswitch.xyz/api-reference/miscellaneous/get-rates /openapi.json get /rates Retrieve exchange rates for all supported currencies. # Get quote Source: https://docs.onswitch.xyz/api-reference/offramp/get-quote /openapi.json post /offramp/quote Get a real-time quote for an offramp transaction including exchange rate, settlement time, and payment rail information. # Get rate Source: https://docs.onswitch.xyz/api-reference/offramp/get-rate /openapi.json post /offramp/rate Get the current exchange rate for an offramp transaction. # Initiate Source: https://docs.onswitch.xyz/api-reference/offramp/initiate /openapi.json post /offramp/initiate Initiate a stablecoin to local currency transaction. # Get quote Source: https://docs.onswitch.xyz/api-reference/onramp/get-quote /openapi.json post /onramp/quote Get a real-time quote for an onramp transaction including exchange rate, settlement time, and payment rail information. # Get rate Source: https://docs.onswitch.xyz/api-reference/onramp/get-rate /openapi.json post /onramp/rate Get the current exchange rate for an onramp transaction. # Initiate Source: https://docs.onswitch.xyz/api-reference/onramp/initiate /openapi.json post /onramp/initiate Initiate a local currency to stablecoin transaction. # Confirm deposit Source: https://docs.onswitch.xyz/api-reference/payment/confirm-deposit /openapi.json post /payment/confirm Manually confirm a payment deposit. # Get status Source: https://docs.onswitch.xyz/api-reference/payment/get-status /openapi.json get /payment/status Retrieve the current status and details of a payment. # Get quote Source: https://docs.onswitch.xyz/api-reference/swap/get-quote /openapi.json post /swap/quote Get a real-time quote for swapping between two stablecoin assets including exchange rate and fees. # Initiate Source: https://docs.onswitch.xyz/api-reference/swap/initiate /openapi.json post /swap/initiate Initiate a swap transaction between two stablecoin assets. # Create wallet Source: https://docs.onswitch.xyz/api-reference/wallet/create-wallet /openapi.json post /wallet/create Create a new wallet with unified balance across multiple chains. One account, one balance, any chain. # Estimate fee Source: https://docs.onswitch.xyz/api-reference/wallet/estimate-fee /openapi.json post /wallet/fee Estimate the network fee for transferring a specific asset from a wallet. # Export wallet Source: https://docs.onswitch.xyz/api-reference/wallet/export-wallet /openapi.json post /wallet/export Export wallet private key. Use with caution; the private key grants full control of the wallet. # Get balance Source: https://docs.onswitch.xyz/api-reference/wallet/get-balance /openapi.json get /wallet/{wallet_id}/balance Get unified spendable wallet balance and breakdown by chain. # Get transactions Source: https://docs.onswitch.xyz/api-reference/wallet/get-transactions /openapi.json get /wallet/{wallet_id}/transactions List transactions for a wallet with optional pagination. # Get wallet Source: https://docs.onswitch.xyz/api-reference/wallet/get-wallet /openapi.json get /wallet/{wallet_id} Retrieve the details of an existing wallet # Get wallets Source: https://docs.onswitch.xyz/api-reference/wallet/get-wallets /openapi.json get /wallets Returns paginated stablecoin wallets # Lookup transaction Source: https://docs.onswitch.xyz/api-reference/wallet/lookup-transaction /openapi.json get /wallet/{wallet_id}/transaction/{reference} Get details of a single transaction by its reference (UUID). # Rescue token Source: https://docs.onswitch.xyz/api-reference/wallet/rescue-token /openapi.json post /wallet/rescue Transfer a specific token (by contract address) from the wallet to a recipient address. Use to recover tokens that are not part of the unified balance (e.g. unsupported or airdropped tokens). Supports EVM and Solana token addresses. # Transfer funds Source: https://docs.onswitch.xyz/api-reference/wallet/transfer-funds /openapi.json post /wallet/transfer Send assets to any address across supported chains. No bridging, no swapping or gas tokens required. # Update wallet Source: https://docs.onswitch.xyz/api-reference/wallet/update-wallet /openapi.json patch /wallet/{wallet_id} Update wallet details (e.g. callback URL for wallet notifications). # Get webhooks Source: https://docs.onswitch.xyz/api-reference/webhook/get-webhooks /openapi.json get /webhook/history Returns paginated webhooks history. # Resend webhook Source: https://docs.onswitch.xyz/api-reference/webhook/resend-webhook /openapi.json post /webhook/resend Resend any webhook notification for a previous transactions. # Authentication Source: https://docs.onswitch.xyz/authentication Authenticate the Switch REST API with your service key (x-service-key) for sandbox and production crypto payment and settlement requests. You can view both keys anytime in the Switch dashboard. Both keys works with the same base URL `https://api.onswitch.xyz`. ## Example request ```bash curl theme={"dark"} curl https://api.onswitch.xyz/asset \ -H "x-service-key: $YOUR_SERVICE_KEY" \ -H "Accept: application/json" ``` ```javascript Node.js theme={"dark"} const res = await fetch('https://api.onswitch.xyz/asset', { headers: { 'x-service-key': process.env.YOUR_SERVICE_KEY, 'Accept': 'application/json', }, }); ``` ```python Python theme={"dark"} import os, urllib.request req = urllib.request.Request( "https://api.onswitch.xyz/asset", headers={ "x-service-key": os.environ["YOUR_SERVICE_KEY"], "Accept": "application/json", }, ) urllib.request.urlopen(req, timeout=30) ``` Use your *live key* only when it's production environment, as this might involve live onchain transactions and actual money movement. If your key may is exposed or compromised, quickly rotate it from the dashboard or contact support at [contact@onswitch.xyz](mailto:contact@onswitch.xyz) for assistance. ## Need Help? Send us a message Book a call with us # Changelog Source: https://docs.onswitch.xyz/changelog Release notes and updates for Switch. **Collect multiple local currencies** to stablecoin in a single transaction. You can collect **NGN**, **GHS**, **CDF**, **GMD**, **KES**, **LRD**, **MWK**, **RWF**, **SLE**, **TZS**, **UGX**, **XAF**, **XOF**, and **ZMW**. See [Initiate onramp](/api-reference/onramp/initiate) for guides. You can run **AML lookup** against individuals, businesses, and crypto wallet addresses, and retrieve PEP, sanctions, and other compliance and regulatory details. See [Lookup AML](/api-reference/compliance/aml-lookup) for guides. The Switch **partners** dashboard is live, seamlessly built to enable businesses to easily manage and monitor all stablecoin collection and settlement activities from one place. Use your **Switch wallet** to fund offramp payments. Use it when the offramp deposit should be taken from your Switch wallet balance instead of sending from an external wallet. **Onramp** and **Offramp** can now reuse a previous payment beneficiary by just passing the **`beneficiary.id`** instead of entering the full beneficiary details every time. Easily query and retrieve all previous payment beneficiaries you have used as payout destinations. See [Get beneficiaries](/api-reference/beneficiary/get-beneficiaries) for guides. Static deposit address is now supported on **Solana** — use the **`static`** parameter on initiate flows where you need a reusable deposit address for the same beneficiary details. We’ve launched improved **developer documentation** with clearer structure, refreshed guides, and easier navigation so you can integrate faster and find answers without digging. We’ve added support for `USDC` on the `Stellar` network, significantly expanding our platform’s stabelcoin coverage. Supported functionality includes: * Offramp: Convert stablecoins to local currencies * Onramp: Convert local currencies to stablecoins * Swap: Swap between different stablecoins Developer fees collected on payments are now paid out automatically. The collected fee is sent instantly to the **`developer_recipient`** address you specify on each transaction—no separate settlement step. Support for the **`CNGN`** stablecoin on **BNB Smart Chain (BSC)** and **Base** is live. Enabling coverage for growing local stablecoin usage. Supported functionality includes: * Offramp: Convert stablecoins to local currencies We’ve launched a refreshed and improved Switch marketing site with clearer product information and a smoother experience for visitors exploring what Switch can do. **Switch Stablecoin Wallets** - One balance. Any chain. Switch now lets you create **non-custodial stablecoin wallets** — you own your keys, and your funds can move anywhere. What’s included: * **Multi chain support**: Solana, Ethereum, Base, BSC, Arbitrum, Optimism, Polygon, Avalanche, Sonic, Berachain, Mantle, Monad, Linea, HyperEVM, Plasma, Blast, Manta, and Mode. * **Unified balance** — no bridging, no swapping, no network switching, just transfer when you want. * **Pay fees in any stablecoin** — as low as \$0.05 (Depending on the chain and amount) per transaction, with no native gas tokens required. * **Send anywhere, instantly** — transfer to any supported chain, regardless of which chain holds your funds. * **Deep liquidity across chains** — Withdraw and deposit to any supported chain, regardless of which chain holds your funds. See [Create wallet](/guides/create-wallet) for guides. # Supported countries Source: https://docs.onswitch.xyz/countries List of countries where you can settle stablecoin payouts in local currency using domestic payment rails. Payouts are typically settled in real-time or within minutes, depending on the country and payment method. Switch supports the following countries and currencies. ## Africa | Country | Code | Currency | Channels | | :-------------------------------- | :--- | :------- | :----------------- | | 🇧🇯 Benin | BJ | XOF | Mobile money | | 🇨🇲 Cameroon | CM | XAF | Mobile money | | 🇨🇮 Côte d'Ivoire | CI | XOF | Mobile money | | 🇨🇩 Democratic Republic of Congo | CD | CDF | Mobile money | | 🇪🇹 Ethiopia | ET | ETB | Mobile money | | 🇬🇦 Gabon | GA | XAF | Mobile money | | 🇬🇲 Gambia | GM | GMD | Mobile money | | 🇬🇭 Ghana | GH | GHS | Mobile money | | 🇬🇳 Guinea | GN | GNF | Mobile money | | 🇰🇪 Kenya | KE | KES | Mobile money, Bank | | 🇱🇷 Liberia | LR | LRD | Mobile money | | 🇲🇼 Malawi | MW | MWK | Mobile money | | 🇲🇱 Mali | ML | XOF | Mobile money | | 🇳🇬 Nigeria | NG | NGN | Bank | | 🇷🇼 Rwanda | RW | RWF | Mobile money | | 🇸🇳 Senegal | SN | XOF | Mobile money | | 🇸🇱 Sierra Leone | SL | SLE | Mobile money | | 🇿🇦 South Africa | ZA | ZAR | Bank | | 🇹🇿 Tanzania | TZ | TZS | Mobile money, Bank | | 🇺🇬 Uganda | UG | UGX | Mobile money | | 🇿🇲 Zambia | ZM | ZMW | Mobile money | ## Need help? Send us a message Book a call with us # Developer fee Source: https://docs.onswitch.xyz/developer_fee Take a percentage of each payment amount as a fee Developer fees let you charge a share of each payment amount and route it to a beneficiary wallet you control. Switch calculates the fee from the stablecoin side of the transaction when you add `developer_fee` and `developer_recipient` on quote and initiate requests. When the offramp completes, Switch sends your fee to **`developer_recipient`** automatically. To see how a fee changes output amounts before you initiate a payment, use [Get quote](/guides/get-quote) endpoint with the same payment request payload. ## How developer fees work On [POST `/offramp/quote`](/guides/get-quote) and **POST `/offramp/initiate`**, pass **`developer_fee`** and **`developer_recipient`**. Omit them or set `developer_fee` to `0` if you are not charging a fee. After the payment completes, Switch pays your **`developer_fee`** portion to **`developer_recipient`** automatically — no separate action required. ## Fee model Switch enables you to charge any **percentage** as a developer fee on the incoming stablecoin payment amount: * **`developer_fee`** — Number from **0** to **100**: the percentage of the payment amount taken as your fee (for example, `0.5` for 0.5%, `2` for 2%). * **`developer_recipient`** — Blockchain address that should receive the developer fee. **`developer_recipient`** wallet address must be able to receive the stablecoin and network of the payment. ### Calculation example Payment of **100 USDC** with **`developer_fee`: `0.2`** (0.2%, i.e. 20 bps): * Your fee: 100 × 0.002 = **0.2 USDC** to `developer_recipient`. With **`developer_fee`: `0.5`**: * Your fee: **0.5 USDC** on a 100 USDC payment (0.5% of 100). ## Need help? Send us a message and we will get back to you shortly. Hop on a call with us. # Check status Source: https://docs.onswitch.xyz/guides/check-status Look up the status of a payment by its reference. **GET `/payment/status`** returns the current state of a stablecoin transaction using the `reference` used to initiate the payment. This enables you to track the progress of any payment if not using the [Webhook](/webhook) endpoint. ## Example Request ```bash cURL theme={"dark"} curl -L \ --request GET \ --url 'https://api.onswitch.xyz/payment/status?reference=ccdd7666-8cb6-45d6-9caf-498b94d10929' \ --header 'x-service-key: '"$YOUR_SERVICE_KEY" \ --header 'Accept: */*' ``` ```javascript Node.js theme={"dark"} const reference = 'ccdd7666-8cb6-45d6-9caf-498b94d10929'; const params = new URLSearchParams({ reference }); const res = await fetch(`https://api.onswitch.xyz/payment/status?${params}`, { method: 'GET', headers: { 'x-service-key': process.env.YOUR_SERVICE_KEY, Accept: '*/*', }, }); const json = await res.json(); console.log(json.data?.status, json.data?.reference); ``` ```python Python theme={"dark"} import os, json, urllib.parse, urllib.request reference = "ccdd7666-8cb6-45d6-9caf-498b94d10929" q = urllib.parse.urlencode({"reference": reference}) req = urllib.request.Request( f"https://api.onswitch.xyz/payment/status?{q}", method="GET", headers={ "x-service-key": os.environ["YOUR_SERVICE_KEY"], "Accept": "*/*", }, ) with urllib.request.urlopen(req, timeout=60) as r: payload = json.load(r) data = payload.get("data") or {} print(data.get("status"), data.get("reference")) ``` `reference` is required and must be the UUID used to create the payment. ### Example Response ```json theme={"dark"} { "success": true, "message": "Payment status fetched successfully", "timestamp": "2026-03-31T03:52:50.776Z", "data": { "status": "COMPLETED", "type": "OFFRAMP", "reference": "ccdd7666-8cb6-45d6-9caf-498b94d10929", "rate": 1408.761, "source": { "amount": 1.745636, "network": "BASE", "currency": "USDC" }, "destination": { "amount": 2459.183917, "network": "FIAT", "currency": "NGN" }, "deposit": { "amount": 1.745636, "address": "0x73E60786CA161d1BfabbaF7c7d467a0A677997aC", "asset": "base:usdc", "note": [ "Kindly send the exact amount to the wallet address to complete the transaction.", "This dynamic wallet address has a 30 minutes expiry window and can only be used once." ] } } } ``` **`status`** may be values such as `AWAITING_DEPOSIT`, `PROCESSING`, `COMPLETED`, `FAILED`, `REVERSED`, `SCHEDULED`, depending on the state of the transaction. ## Need Help? Send us a message. Hop on a call with us. # Create stablecoin wallet Source: https://docs.onswitch.xyz/guides/create-wallet Create a unified balance, non-custodial stablecoin wallet. **POST `/wallet/create`** creates a **non-custodial** stablecoin wallet: one unified balance across supported chains, with deposit addresses per network. You receive the **`private_key`** only in this response—store it securely; Switch cannot show it again later except via **POST `/wallet/export`** when you explicitly request recovery. Use **GET `/asset`** to see which stablecoins support the wallet product (`wallet_supported`). See [Get stablecoins](/guides/get-stablecoins). ## Example request ```bash cURL theme={"dark"} curl https://api.onswitch.xyz/wallet/create \ --request POST \ --header 'Content-Type: application/json' \ --header 'x-service-key: '"$YOUR_SERVICE_KEY" \ --data '{ "name": "My Wallet", "callback_url": "https://your-app.com/webhook" }' ``` ```javascript Node.js theme={"dark"} const res = await fetch('https://api.onswitch.xyz/wallet/create', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-service-key': process.env.YOUR_SERVICE_KEY, }, body: JSON.stringify({ name: 'My Wallet', callback_url: 'https://your-app.com/webhook', }), }); const json = await res.json(); const data = json.data ?? {}; console.log(data.id, Object.keys(data.address ?? {})); ``` ```python Python theme={"dark"} import json import os import urllib.request payload = { "name": "My Wallet", "callback_url": "https://your-app.com/webhook", } req = urllib.request.Request( "https://api.onswitch.xyz/wallet/create", method="POST", data=json.dumps(payload).encode("utf-8"), headers={ "Content-Type": "application/json", "x-service-key": os.environ["YOUR_SERVICE_KEY"], }, ) with urllib.request.urlopen(req, timeout=60) as r: out = json.load(r) data = out.get("data") or {} print(data.get("id"), list((data.get("address") or {}).keys())) ``` ## Frequently Asked Questions Set **`callback_url`** to receive wallet-related notifications at your server. For general webhook behaviour and security practices, see [Webhooks](/webhook). ```json theme={"dark"} { "callback_url": "https://your-app.com/webhook" } ``` After creation, store only **`data.id`** (for subsequent wallet related API calls) and **`data.private_key`** (for custody and signing) using your own secure storage. Store **`data.address`** if you want to show per-chain deposit addresses without calling **GET `/wallet/{wallet_id}`** again. ### Example response ```json theme={"dark"} { "success": true, "message": "Wallet created successfully", "timestamp": "2026-04-01T12:00:00.000Z", "data": { "id": "699a6555fd4cab59e6175f79", "name": "My Wallet", "private_key": "0xb8ce59fc3717ada4c02eadf9682a9e934f625ebb", "address": { "BASE": "0xA3B3b28d8E3ec225f555f4AB9fC3607De545Ff49", "ETHEREUM": "0xA3B3b28d8E3ec225f555f4AB9fC3607De545Ff49", "POLYGON": "0xA3B3b28d8E3ec225f555f4AB9fC3607De545Ff49", "BSC": "0xA3B3b28d8E3ec225f555f4AB9fC3607De545Ff49", "ARBITRUM": "0xA3B3b28d8E3ec225f555f4AB9fC3607De545Ff49", "OPTIMISM": "0xA3B3b28d8E3ec225f555f4AB9fC3607De545Ff49", "GNOSIS": "0xA3B3b28d8E3ec225f555f4AB9fC3607De545Ff49", "AVALANCHE": "0xA3B3b28d8E3ec225f555f4AB9fC3607De545Ff49", "MONAD": "0xA3B3b28d8E3ec225f555f4AB9fC3607De545Ff49", "PLASMA": "0xA3B3b28d8E3ec225f555f4AB9fC3607De545Ff49", "LINEA": "0xA3B3b28d8E3ec225f555f4AB9fC3607De545Ff49", "MANTLE": "0xA3B3b28d8E3ec225f555f4AB9fC3607De545Ff49", "HYPEREVM": "0xA3B3b28d8E3ec225f555f4AB9fC3607De545Ff49", "BERACHAIN": "0xA3B3b28d8E3ec225f555f4AB9fC3607De545Ff49", "SONIC": "0xA3B3b28d8E3ec225f555f4AB9fC3607De545Ff49", "SOLANA": "2dTHot2BVjqqGD3S5Z2bzEVYnyEcJCdr9SawzqTdKo4h" }, "note": "Do not share your private key. This key grants full control of your account." } } ``` ## Security The **`private_key`** is returned **only when the wallet is created**. Anyone with the key can move funds. Do not log it, embed it in client-side code, or send it over insecure channels. If you lose it and never exported a backup, recovery may not be possible. ## Need Help? Send us a message. Hop on a call with us. # Get currencies Source: https://docs.onswitch.xyz/guides/get-currencies List supported local currencies, channels and limits. **GET `/coverage`** returns the supported local currencies you can use convert to or from stablecoin. Shows metadata such as country (ISO code), channels, the default channel, typical settlement times, transaction limits etc. ## Example Request ```bash cURL theme={"dark"} curl -L \ --request GET \ --url 'https://api.onswitch.xyz/coverage?direction=OFFRAMP' \ --header 'x-service-key: '"$YOUR_SERVICE_KEY" \ --header 'Accept: */*' ``` ```javascript Node.js theme={"dark"} const params = new URLSearchParams({ direction: 'OFFRAMP' }); const res = await fetch(`https://api.onswitch.xyz/coverage?${params}`, { method: 'GET', headers: { 'x-service-key': process.env.YOUR_SERVICE_KEY, Accept: '*/*', }, }); const json = await res.json(); console.log(json.data?.length, 'corridors'); ``` ```python Python theme={"dark"} import os, json, urllib.parse, urllib.request q = urllib.parse.urlencode({"direction": "OFFRAMP"}) req = urllib.request.Request( f"https://api.onswitch.xyz/coverage?{q}", method="GET", headers={ "x-service-key": os.environ["YOUR_SERVICE_KEY"], "Accept": "*/*", }, ) with urllib.request.urlopen(req, timeout=60) as r: payload = json.load(r) print(len(payload.get("data", [])), "corridors") ``` Direction can be `ONRAMP` or `OFFRAMP`. `ONRAMP` returns currencies that can be converted to stablecoin. `OFFRAMP` returns currencies that stablecoin can be converted to. ### Example Response ```json theme={"dark"} { "success": true, "message": "Coverage fetched successfully", "timestamp": "2026-08-04T10:44:30.935Z", "data": [ { "country": "NG", "currency": ["NGN"], "continent": "AFRICA", "default_channel": "BANK", "channel": ["BANK"], "direction": ["ONRAMP", "OFFRAMP"], "settlement_time": { "BANK": "30-120 seconds", "MOBILEMONEY": "5-10 minutes" }, "payout_limit": { "BANK": { "min": "$1", "max": "$100,000" }, "note": "This represents the maximum USD value allowed per transaction." } }, { "country": "GH", "currency": ["GHS"], "continent": "AFRICA", "default_channel": "MOBILEMONEY", "channel": ["MOBILEMONEY"], "direction": ["OFFRAMP", "ONRAMP"], "settlement_time": { "MOBILEMONEY": "5-10 minutes" }, "payout_limit": { "MOBILEMONEY": { "min": "$10", "max": "$100,000" }, "note": "This represents the maximum USD value allowed per transaction." } }, { "country": "KE", "currency": ["KES"], "continent": "AFRICA", "default_channel": "MOBILEMONEY", "channel": ["MOBILEMONEY", "BANK"], "direction": ["OFFRAMP", "ONRAMP"], "settlement_time": { "BANK": "5-10 minutes", "MOBILEMONEY": "5-10 minutes" }, "payout_limit": { "MOBILEMONEY": { "min": "$10", "max": "$100,000" }, "BANK": { "min": "$10", "max": "$100,000" }, "note": "This represents the maximum USD value allowed per transaction." } }, { "country": "ZA", "currency": ["ZAR"], "continent": "AFRICA", "default_channel": "BANK", "channel": ["BANK"], "direction": ["OFFRAMP"], "settlement_time": { "BANK": "5-10 minutes" }, "payout_limit": { "BANK": { "min": "$100", "max": "$100,000" }, "note": "This represents the maximum USD value allowed per transaction." } }, { "country": "CD", "currency": ["CDF"], "continent": "AFRICA", "default_channel": "MOBILEMONEY", "channel": ["MOBILEMONEY"], "direction": ["OFFRAMP", "ONRAMP"], "settlement_time": { "MOBILEMONEY": "5-10 minutes" }, "payout_limit": { "MOBILEMONEY": { "min": "$10", "max": "$100,000" }, "note": "This represents the maximum USD value allowed per transaction." } }, { "country": "GN", "currency": ["GNF"], "continent": "AFRICA", "default_channel": "MOBILEMONEY", "channel": ["MOBILEMONEY"], "direction": ["OFFRAMP"], "settlement_time": { "MOBILEMONEY": "5-10 minutes" }, "payout_limit": { "MOBILEMONEY": { "min": "$10", "max": "$100,000" }, "note": "This represents the maximum USD value allowed per transaction." } }, { "country": "UG", "currency": ["UGX"], "continent": "AFRICA", "default_channel": "MOBILEMONEY", "channel": ["MOBILEMONEY"], "direction": ["OFFRAMP", "ONRAMP"], "settlement_time": { "MOBILEMONEY": "5-10 minutes" }, "payout_limit": { "MOBILEMONEY": { "min": "$10", "max": "$100,000" }, "note": "This represents the maximum USD value allowed per transaction." } }, { "country": "ET", "currency": ["ETB"], "continent": "AFRICA", "default_channel": "MOBILEMONEY", "channel": ["MOBILEMONEY"], "direction": ["OFFRAMP"], "settlement_time": { "MOBILEMONEY": "5-10 minutes" }, "payout_limit": { "MOBILEMONEY": { "min": "$10", "max": "$100,000" }, "note": "This represents the maximum USD value allowed per transaction." } }, { "country": "CI", "currency": ["XOF"], "continent": "AFRICA", "default_channel": "MOBILEMONEY", "channel": ["MOBILEMONEY"], "direction": ["OFFRAMP", "ONRAMP"], "settlement_time": { "MOBILEMONEY": "5-10 minutes" }, "payout_limit": { "MOBILEMONEY": { "min": "$1", "max": "$100,000" }, "note": "This represents the maximum USD value allowed per transaction." } }, { "country": "CM", "currency": ["XAF"], "continent": "AFRICA", "default_channel": "MOBILEMONEY", "channel": ["MOBILEMONEY"], "direction": ["OFFRAMP", "ONRAMP"], "settlement_time": { "MOBILEMONEY": "5-10 minutes" }, "payout_limit": { "MOBILEMONEY": { "min": "$10", "max": "$100,000" }, "note": "This represents the maximum USD value allowed per transaction." } }, { "country": "SN", "currency": ["XOF"], "continent": "AFRICA", "default_channel": "MOBILEMONEY", "channel": ["MOBILEMONEY"], "direction": ["OFFRAMP", "ONRAMP"], "settlement_time": { "MOBILEMONEY": "5-10 minutes" }, "payout_limit": { "MOBILEMONEY": { "min": "$10", "max": "$100,000" }, "note": "This represents the maximum USD value allowed per transaction." } }, { "country": "RW", "currency": ["RWF"], "continent": "AFRICA", "default_channel": "MOBILEMONEY", "channel": ["MOBILEMONEY"], "direction": ["OFFRAMP", "ONRAMP"], "settlement_time": { "MOBILEMONEY": "5-10 minutes" }, "payout_limit": { "MOBILEMONEY": { "min": "$10", "max": "$100,000" }, "note": "This represents the maximum USD value allowed per transaction." } }, { "country": "BJ", "currency": ["XOF"], "continent": "AFRICA", "default_channel": "MOBILEMONEY", "channel": ["MOBILEMONEY"], "direction": ["OFFRAMP", "ONRAMP"], "settlement_time": { "MOBILEMONEY": "5-10 minutes" }, "payout_limit": { "MOBILEMONEY": { "min": "$10", "max": "$100,000" }, "note": "This represents the maximum USD value allowed per transaction." } }, { "country": "GA", "currency": ["XAF"], "continent": "AFRICA", "default_channel": "MOBILEMONEY", "channel": ["MOBILEMONEY"], "direction": ["OFFRAMP"], "settlement_time": { "MOBILEMONEY": "5-10 minutes" }, "payout_limit": { "MOBILEMONEY": { "min": "$10", "max": "$100,000" }, "note": "This represents the maximum USD value allowed per transaction." } }, { "country": "ML", "currency": ["XOF"], "continent": "AFRICA", "default_channel": "MOBILEMONEY", "channel": ["MOBILEMONEY"], "direction": ["OFFRAMP", "ONRAMP"], "settlement_time": { "MOBILEMONEY": "5-10 minutes" }, "payout_limit": { "MOBILEMONEY": { "min": "$10", "max": "$100,000" }, "note": "This represents the maximum USD value allowed per transaction." } }, { "country": "TZ", "currency": ["TZS"], "continent": "AFRICA", "default_channel": "MOBILEMONEY", "channel": ["MOBILEMONEY", "BANK"], "direction": ["OFFRAMP", "ONRAMP"], "settlement_time": { "MOBILEMONEY": "5-10 minutes", "BANK": "5-10 minutes" }, "payout_limit": { "MOBILEMONEY": { "min": "$10", "max": "$100,000" }, "BANK": { "min": "$10", "max": "$100,000" }, "note": "This represents the maximum USD value allowed per transaction." } }, { "country": "ZM", "currency": ["ZMW"], "continent": "AFRICA", "default_channel": "MOBILEMONEY", "channel": ["MOBILEMONEY"], "direction": ["OFFRAMP", "ONRAMP"], "settlement_time": { "MOBILEMONEY": "5-10 minutes" }, "payout_limit": { "MOBILEMONEY": { "min": "$10", "max": "$100,000" }, "note": "This represents the maximum USD value allowed per transaction." } }, { "country": "SL", "currency": ["SLE"], "continent": "AFRICA", "default_channel": "MOBILEMONEY", "channel": ["MOBILEMONEY"], "direction": ["OFFRAMP", "ONRAMP"], "settlement_time": { "MOBILEMONEY": "5-10 minutes" }, "payout_limit": { "MOBILEMONEY": { "min": "$10", "max": "$100,000" }, "note": "This represents the maximum USD value allowed per transaction." } }, { "country": "MW", "currency": ["MWK"], "continent": "AFRICA", "default_channel": "MOBILEMONEY", "channel": ["MOBILEMONEY"], "direction": ["OFFRAMP", "ONRAMP"], "settlement_time": { "MOBILEMONEY": "5-10 minutes" }, "payout_limit": { "MOBILEMONEY": { "min": "$10", "max": "$100,000" }, "note": "This represents the maximum USD value allowed per transaction." } }, { "country": "LR", "currency": ["LRD"], "continent": "AFRICA", "default_channel": "MOBILEMONEY", "channel": ["MOBILEMONEY"], "direction": ["OFFRAMP", "ONRAMP"], "settlement_time": { "MOBILEMONEY": "5-10 minutes" }, "payout_limit": { "MOBILEMONEY": { "min": "$10", "max": "$100,000" }, "note": "This represents the maximum USD value allowed per transaction." } }, { "country": "GM", "currency": ["GMD"], "continent": "AFRICA", "default_channel": "MOBILEMONEY", "channel": ["MOBILEMONEY"], "direction": ["OFFRAMP", "ONRAMP"], "settlement_time": { "MOBILEMONEY": "5-10 minutes" }, "payout_limit": { "MOBILEMONEY": { "min": "$10", "max": "$100,000" }, "note": "This represents the maximum USD value allowed per transaction." } } ] } ``` **`payout_limit`** represents the maximum USD value that is allowed in a single transaction and varies by channel and currency. ## Need Help? Send us a message. Hop on a call with us. # Get quote Source: https://docs.onswitch.xyz/guides/get-quote Get a priced off-ramp quote with source and destination amounts **POST `/offramp/quote`** endpoint returns a quote for converting a supported stablecoin to local currency, including the applied rate, how much the user sends and receives, settlement timing, and when the quote expires. ## Example Request ```bash cURL theme={"dark"} curl -L \ --request POST \ --url 'https://api.onswitch.xyz/offramp/quote' \ --header 'x-service-key: YOUR_SERVICE_KEY' \ --header 'Content-Type: application/json' \ --data '{ "amount": 100, "country": "NG", "asset": "base:usdc", "currency": "NGN", "channel": "BANK", "exact_output": false, "developer_fee": 0.5 }' ``` ```javascript Node.js theme={"dark"} const res = await fetch('https://api.onswitch.xyz/offramp/quote', { method: 'POST', headers: { 'x-service-key': process.env.YOUR_SERVICE_KEY, 'Content-Type': 'application/json', }, body: JSON.stringify({ amount: 100, country: 'NG', asset: 'base:usdc', currency: 'NGN', channel: 'BANK', exact_output: false, developer_fee: 0.5, developer_recipient: '0x1234567890123456789012345678901234567890', }), }); const body = await res.json(); const { data } = body; console.log( `${data.source.amount} ${data.source.currency} → ${data.destination.amount} ${data.destination.currency} (rate ${data.rate}, expires ${data.expiry})` ); ``` ```python Python theme={"dark"} import os, json, urllib.request payload = { "amount": 100, "country": "NG", "asset": "base:usdc", "currency": "NGN", "channel": "BANK", "exact_output": False, "developer_fee": 0.5, "developer_recipient": "0x1234567890123456789012345678901234567890", } req = urllib.request.Request( "https://api.onswitch.xyz/offramp/quote", data=json.dumps(payload).encode(), method="POST", headers={ "x-service-key": os.environ["YOUR_SERVICE_KEY"], "Content-Type": "application/json", }, ) with urllib.request.urlopen(req, timeout=30) as r: body = json.load(r) d = body["data"] print( f"{d['source']['amount']} {d['source']['currency']} → " f"{d['destination']['amount']} {d['destination']['currency']} " f"(rate {d['rate']}, expires {d['expiry']})" ) ``` `exact_output` (optional, default `false`) controls how `amount` is interpreted.

With `false`, `amount` is the stablecoin you send (`asset`); i.e. the quote computes how much local currency (`currency`) the user receives.

With `true`, `amount` is the local currency to deliver; i.e. the quote computes how much stablecoin must be sent.
`developer_fee` (optional) is a percentage between 0 and 100 taken as your fee from the payment amount.

Omit the fee or set it to 0 if you are not charging your own fee.
### Example Response ```json theme={"dark"} { "success": true, "message": "Offramp quote fetched successfully", "timestamp": "2026-03-31T03:05:43.257Z", "data": { "expiry": "2026-03-31T04:10:43+01:00", "settlement": "5-10 minutes", "channel": "BANK", "rate": 1409.758, "source": { "amount": 100, "currency": "USDC", "network": "BASE" }, "destination": { "amount": 140975.8, "currency": "NGN", "network": "FIAT" } } } ``` Quotes expire at `data.expiry`. Market conditions can change; create the transaction promptly after fetching a quote, or request a fresh quote if it has expired. ## Need Help? Send us a message. Hop on a call with us. # Get rate Source: https://docs.onswitch.xyz/guides/get-rate Fetch rate for stablecoin to local currency conversion. **POST `/offramp/rate`** endpoint returns the current exchange rate for converting a supported stablecoin to a local currency. Call this endpoint before creating an actual payment transaction to show users exactly how much they'll receive. ## Example Request ```bash cURL theme={"dark"} curl -L \ --request POST \ --url 'https://api.onswitch.xyz/offramp/rate' \ --header 'x-service-key: '"$YOUR_SERVICE_KEY" \ --header 'Content-Type: application/json' \ --data '{ "asset": "base:usdc", "country": "NG", "currency": "NGN" }' ``` ```javascript Node.js theme={"dark"} const res = await fetch('https://api.onswitch.xyz/offramp/rate', { method: 'POST', headers: { 'x-service-key': process.env.YOUR_SERVICE_KEY, 'Content-Type': 'application/json', }, body: JSON.stringify({ asset: 'base:usdc', country: 'NG', currency: 'NGN', }), }); const { rate } = await res.json(); console.log(`1 USDC = ${rate} NGN`); ``` ```python Python theme={"dark"} import os, json, urllib.request payload = { "asset": "base:usdc", "country": "NG", "currency": "NGN", } req = urllib.request.Request( "https://api.onswitch.xyz/offramp/rate", data=json.dumps(payload).encode(), method="POST", headers={ "x-service-key": os.environ["YOUR_SERVICE_KEY"], "Content-Type": "application/json", }, ) with urllib.request.urlopen(req, timeout=30) as r: data = json.load(r) print(f"1 USDC = {data['rate']} NGN") ``` ### Example Response ```json theme={"dark"} { "success": true, "message": "Offramp rate fetched successfully", "timestamp": "2024-01-01T00:00:00.000Z", "data": { "currency": "NGN", "channel": "BANK", "rate": 1408.761 } } ``` Rates reflect current market conditions and may change between the time you fetch them and when a transaction is submitted. Always re-fetch the rate immediately before creating a transaction. ## Need Help? Send us a message. Hop on a call with us. # Get stablecoins Source: https://docs.onswitch.xyz/guides/get-stablecoins List all supported stablecoins and metadata. **GET `/asset`** lists every stablecoin supported across all networks, including metadata such as token address, blockchain, decimals etc. and which payment flows (offramp, onramp, swap, wallet) each stablecoin supports. ## Example Request ```bash cURL theme={"dark"} curl -L \ --request GET \ --url 'https://api.onswitch.xyz/asset' \ --header 'x-service-key: '"$YOUR_SERVICE_KEY" \ --header 'Accept: */*' ``` ```javascript Node.js theme={"dark"} const res = await fetch('https://api.onswitch.xyz/asset', { method: 'GET', headers: { 'x-service-key': process.env.YOUR_SERVICE_KEY, Accept: '*/*', }, }); const json = await res.json(); console.log(json.data?.length, 'assets'); ``` ```python Python theme={"dark"} import os, json, urllib.request req = urllib.request.Request( "https://api.onswitch.xyz/asset", method="GET", headers={ "x-service-key": os.environ["YOUR_SERVICE_KEY"], "Accept": "*/*", }, ) with urllib.request.urlopen(req, timeout=60) as r: payload = json.load(r) print(len(payload.get("data", [])), "assets") ``` ### Example Response ```json theme={"dark"} { "success": true, "message": "Assets fetched successfully", "timestamp": "2026-03-31T03:15:12.304Z", "data": [ { "id": "base:usdc", "name": "USD Coin", "code": "USDC", "decimals": 6, "address": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913", "blockchain": { "id": 8453, "name": "BASE", "type": "EVM" }, "offramp_supported": true, "onramp_supported": true, "swap_supported": true, "wallet_supported": true }, { "id": "solana:usdc", "name": "USD Coin", "code": "USDC", "decimals": 6, "address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", "blockchain": { "id": 10000, "name": "SOLANA", "type": "SVM" }, "offramp_supported": true, "onramp_supported": true, "swap_supported": true, "wallet_supported": true } ] } ``` For a readable reference table, see [Stablecoins](/stablecoins). ## Need Help? Send us a message. Hop on a call with us. # Stablecoin to GHS Source: https://docs.onswitch.xyz/guides/stablecoin-to-ghs Convert stablecoin (USDC, USDT) to Ghanaian Cedi. **POST `/offramp/initiate`** endpoint creates an off-ramp transaction where the customer sends stablecoin and receives Ghanaian Cedi (GHS) instantly. Switch returns a deposit address — once the customer sends the amount in the speicifed asset to that address, the GHS payout is processed automatically. Before calling this endpoint to create a payment, call `GET /requirement` to retrieve the required beneficiary fields based on the country and channel. ## Example request ```bash cURL theme={"dark"} curl https://api.onswitch.xyz/offramp/initiate \ --request POST \ --header 'Content-Type: application/json' \ --header 'x-service-key: '"$YOUR_SERVICE_KEY" \ --data '{ "country": "GH", "currency": "GHS", "amount": 12, "asset": "base:usdc", "narration": "Mobile money transfer to John Doe", "channel": "MOBILEMONEY", "beneficiary": { "mobile_network": "MTN", "mobile_number": "0555927608", "holder_name": "John Doe", "holder_type": "INDIVIDUAL" } }' ``` ```javascript Node.js theme={"dark"} const res = await fetch('https://api.onswitch.xyz/offramp/initiate', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-service-key': process.env.YOUR_SERVICE_KEY, }, body: JSON.stringify({ country: 'GH', currency: 'GHS', amount: 12, asset: 'base:usdc', narration: 'Mobile money transfer to John Doe', channel: 'MOBILEMONEY', beneficiary: { mobile_network: 'MTN', mobile_number: '0555927608', holder_name: 'John Doe', holder_type: 'INDIVIDUAL', }, }), }); const json = await res.json(); console.log(json.data?.reference, json.data?.status); ``` ```python Python theme={"dark"} import json import os import urllib.request payload = { "country": "GH", "currency": "GHS", "amount": 12, "asset": "base:usdc", "narration": "Mobile money transfer to John Doe", "channel": "MOBILEMONEY", "beneficiary": { "mobile_network": "MTN", "mobile_number": "0555927608", "holder_name": "John Doe", "holder_type": "INDIVIDUAL", }, } req = urllib.request.Request( "https://api.onswitch.xyz/offramp/initiate", method="POST", data=json.dumps(payload).encode("utf-8"), headers={ "Content-Type": "application/json", "x-service-key": os.environ["YOUR_SERVICE_KEY"], }, ) with urllib.request.urlopen(req, timeout=60) as r: out = json.load(r) data = out.get("data") or {} print(data.get("reference"), data.get("status")) ``` ## Frequently Asked Questions Add exact\_output and amount if you want an exact amount to be received at the destination. e.g; if you want 10,000 GHS ```json theme={"dark"} { "exact_output": true, "amount": 10000 } ``` Add callback\_url to set the URL to receive webhook notifications when the payment status changes. ```json theme={"dark"} { "callback_url": "https://your-webhook-url.com" } ``` Add developer\_fee and developer\_recipient to set the developer fee you wish to charge from the payment amount. ```json theme={"dark"} { "developer_fee": 0.5, "developer_recipient": "0x1234567890123456789012345678901234567890" } ``` Include **`holder_type`** on **`beneficiary`** depending on the payout recipient; if Business, set to **`BUSINESS`** else **`INDIVIDUAL`**. ```json theme={"dark"} { "beneficiary": { "holder_type": "INDIVIDUAL" } } ``` Add reason to set the purpose of the payment. This is mostly required for transfers out of Nigeria. ```json theme={"dark"} { "reason": "CAPITAL_CONTRIBUTIONS" } ``` Allowed values are listed under [Reason](/reasons). Add refund\_address to set the wallet address to refund the stablecoin deposit to if the payment fails for any reason. ```json theme={"dark"} { "refund_address": "0x1234567890123456789012345678901234567890" } ``` Add channel to set the specific channel or settlement method to use for the payment, if not set, the default channel for the country will be used. ```json theme={"dark"} { "channel": "MOBILEMONEY" } ``` Allowed values are listed under [Countries](/countries). Add static if you want to always generate the same deposit address for the same local currency beneficiary details. ```json theme={"dark"} { "static": true } ``` ### Example response ```json theme={"dark"} { "success": true, "message": "Offramp initiated successfully", "timestamp": "2026-03-31T04:03:15.931Z", "data": { "status": "AWAITIGH_DEPOSIT", "type": "OFFRAMP", "reference": "6c01338d-67e5-4d0c-a394-9d3e367f46a5", "rate": 11.440874, "source": { "amount": 12, "currency": "USDC", "network": "BASE" }, "destination": { "amount": 137.290488, "currency": "GHS", "network": "FIAT" }, "deposit": { "amount": 12, "address": "0xcd257a5867B42556fa14c35de714154B277f70fD", "asset": "base:usdc", "note": [ "Kindly send the exact amount to the wallet address to complete the transaction.", "This dynamic wallet address has a 30 minutes expiry window and can only be used once." ] } } } ``` ## Completing the Deposit After initiating, you are expected to send **exactly** **`deposit.amount`** of **`deposit.asset`** to **`deposit.address`**. Check **`deposit.note`** for specific instructions. The deposit address is for **one-time use only** and expires after **30 minutes**. if not created with **`static`** set to **`true`**. If less or more amount than specified in **`deposit.amount`** is sent, the deposit will be processed based on the amount sent, so long as it is within the limits and the asset (**`deposit.asset`**) sent is supported. ## Need Help? Send us a message. Hop on a call with us. # Stablecoin to KES Source: https://docs.onswitch.xyz/guides/stablecoin-to-kes Convert stablecoin (USDC, USDT) to Kenyan shilling. **POST `/offramp/initiate`** endpoint creates an off-ramp transaction where the customer sends stablecoin and receives Kenyan shilling (KES) instantly. Switch returns a deposit address — once the customer sends the amount in the specified asset to that address, the KES payout is processed automatically. Before calling this endpoint to create a payment, call `GET /requirement` to retrieve the required beneficiary fields based on the country and channel. ## Example request ```bash cURL theme={"dark"} curl https://api.onswitch.xyz/offramp/initiate \ --request POST \ --header 'Content-Type: application/json' \ --header 'x-service-key: '"$YOUR_SERVICE_KEY" \ --data '{ "country": "KE", "currency": "KES", "amount": 12, "asset": "base:usdc", "narration": "Mobile money transfer to John Doe", "channel": "MOBILEMONEY", "beneficiary": { "mobile_network": "MPESA", "mobile_number": "254712345678", "holder_name": "John Doe", "holder_type": "INDIVIDUAL" } }' ``` ```javascript Node.js theme={"dark"} const res = await fetch('https://api.onswitch.xyz/offramp/initiate', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-service-key': process.env.YOUR_SERVICE_KEY, }, body: JSON.stringify({ country: 'KE', currency: 'KES', amount: 12, asset: 'base:usdc', narration: 'Mobile money transfer to John Doe', channel: 'MOBILEMONEY', beneficiary: { mobile_network: 'MPESA', mobile_number: '254712345678', holder_name: 'John Doe', holder_type: 'INDIVIDUAL', }, }), }); const json = await res.json(); console.log(json.data?.reference, json.data?.status); ``` ```python Python theme={"dark"} import json import os import urllib.request payload = { "country": "KE", "currency": "KES", "amount": 12, "asset": "base:usdc", "narration": "Mobile money transfer to John Doe", "channel": "MOBILEMONEY", "beneficiary": { "mobile_network": "MPESA", "mobile_number": "254712345678", "holder_name": "John Doe", "holder_type": "INDIVIDUAL", }, } req = urllib.request.Request( "https://api.onswitch.xyz/offramp/initiate", method="POST", data=json.dumps(payload).encode("utf-8"), headers={ "Content-Type": "application/json", "x-service-key": os.environ["YOUR_SERVICE_KEY"], }, ) with urllib.request.urlopen(req, timeout=60) as r: out = json.load(r) data = out.get("data") or {} print(data.get("reference"), data.get("status")) ``` ## Frequently Asked Questions Add exact\_output and amount if you want an exact amount to be received at the destination. e.g; if you want 10,000 KES ```json theme={"dark"} { "exact_output": true, "amount": 10000 } ``` Add callback\_url to set the URL to receive webhook notifications when the payment status changes. ```json theme={"dark"} { "callback_url": "https://your-webhook-url.com" } ``` Add developer\_fee and developer\_recipient to set the developer fee you wish to charge from the payment amount. ```json theme={"dark"} { "developer_fee": 0.5, "developer_recipient": "0x1234567890123456789012345678901234567890" } ``` Include **`holder_type`** on **`beneficiary`** depending on the payout recipient; if Business, set to **`BUSINESS`** else **`INDIVIDUAL`**. ```json theme={"dark"} { "beneficiary": { "holder_type": "INDIVIDUAL" } } ``` Add reason to set the purpose of the payment. This is mostly required for transfers out of Nigeria. ```json theme={"dark"} { "reason": "CAPITAL_CONTRIBUTIONS" } ``` Allowed values are listed under [Reason](/reasons). Add refund\_address to set the wallet address to refund the stablecoin deposit to if the payment fails for any reason. ```json theme={"dark"} { "refund_address": "0x1234567890123456789012345678901234567890" } ``` Add channel to set the specific channel or settlement method to use for the payment, if not set, the default channel for the country will be used. ```json theme={"dark"} { "channel": "MOBILEMONEY" } ``` Allowed values are listed under [Countries](/countries). Add static if you want to always generate the same deposit address for the same local currency beneficiary details. ```json theme={"dark"} { "static": true } ``` ### Example response ```json theme={"dark"} { "success": true, "message": "Offramp initiated successfully", "timestamp": "2026-03-31T04:03:15.931Z", "data": { "status": "AWAITING_DEPOSIT", "type": "OFFRAMP", "reference": "6c01338d-67e5-4d0c-a394-9d3e367f46a5", "rate": 128.5, "source": { "amount": 12, "currency": "USDC", "network": "BASE" }, "destination": { "amount": 1542, "currency": "KES", "network": "FIAT" }, "deposit": { "amount": 12, "address": "0xcd257a5867B42556fa14c35de714154B277f70fD", "asset": "base:usdc", "note": [ "Kindly send the exact amount to the wallet address to complete the transaction.", "This dynamic wallet address has a 30 minutes expiry window and can only be used once." ] } } } ``` ## Completing the Deposit After initiating, you are expected to send **exactly** **`deposit.amount`** of **`deposit.asset`** to **`deposit.address`**. Check **`deposit.note`** for specific instructions. The deposit address is for **one-time use only** and expires after **30 minutes**. if not created with **`static`** set to **`true`**. If less or more amount than specified in **`deposit.amount`** is sent, the deposit will be processed based on the amount sent, so long as it is within the limits and the asset (**`deposit.asset`**) sent is supported. ## Need Help? Send us a message. Hop on a call with us. # Stablecoin to NGN Source: https://docs.onswitch.xyz/guides/stablecoin-to-ngn Convert stablecoin (USDC, USDT) to Nigerian naira. **POST `/offramp/initiate`** endpoint creates an off-ramp transaction where the customer sends stablecoin and receives Nigerian Naira (NGN) instantly. Switch returns a deposit address — once the customer sends the amount in the speicifed asset to that address, the NGN payout is processed automatically. Before calling this endpoint to create a payment, call `GET /requirement` to retrieve the required beneficiary fields based on the country and channel. ## Example request ```bash cURL theme={"dark"} curl https://api.onswitch.xyz/offramp/initiate \ --request POST \ --header 'Content-Type: application/json' \ --header 'x-service-key: '"$YOUR_SERVICE_KEY" \ --data '{ "country": "NG", "currency": "NGN", "amount": 10, "asset": "base:usdc", "narration": "Bank transfer to John Doe", "channel": "BANK", "beneficiary": { "bank_code": "100004", "account_number": "8188216769", "holder_name": "John Doe", "holder_type": "INDIVIDUAL" } }' ``` ```javascript Node.js theme={"dark"} const res = await fetch('https://api.onswitch.xyz/offramp/initiate', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-service-key': process.env.YOUR_SERVICE_KEY, }, body: JSON.stringify({ country: 'NG', currency: 'NGN', amount: 10, asset: 'base:usdc', narration: 'Bank transfer to John Doe', channel: 'BANK', beneficiary: { bank_code: '100004', account_number: '8188216769', holder_name: 'John Doe', holder_type: 'INDIVIDUAL', }, }), }); const json = await res.json(); console.log(json.data?.reference, json.data?.status); ``` ```python Python theme={"dark"} import json import os import urllib.request payload = { "country": "NG", "currency": "NGN", "amount": 10, "asset": "base:usdc", "narration": "Bank transfer to John Doe", "channel": "BANK", "beneficiary": { "bank_code": "100004", "account_number": "8188216769", "holder_name": "John Doe", "holder_type": "INDIVIDUAL", }, } req = urllib.request.Request( "https://api.onswitch.xyz/offramp/initiate", method="POST", data=json.dumps(payload).encode("utf-8"), headers={ "Content-Type": "application/json", "x-service-key": os.environ["YOUR_SERVICE_KEY"], }, ) with urllib.request.urlopen(req, timeout=60) as r: out = json.load(r) data = out.get("data") or {} print(data.get("reference"), data.get("status")) ``` ## Frequently Asked Questions Add exact\_output and amount if you want an exact amount to be received at the destination. e.g; if you want 10,000 NGN ```json theme={"dark"} { "exact_output": true, "amount": 10000 } ``` Add sender\_name to set what the bank transfer will show as the sender name to the recipient. For Nigeria bank transfers only. ```json theme={"dark"} { "sender_name": "SwiftPay" } ``` Add callback\_url to set the URL to receive webhook notifications when the payment status changes. ```json theme={"dark"} { "callback_url": "https://your-webhook-url.com" } ``` Add developer\_fee and developer\_recipient to set the developer fee you wish to charge from the payment amount. ```json theme={"dark"} { "developer_fee": 0.5, "developer_recipient": "0x1234567890123456789012345678901234567890" } ``` Add refund\_address to set the wallet address to refund the stablecoin deposit to if the payment fails for any reason. ```json theme={"dark"} { "refund_address": "0x1234567890123456789012345678901234567890" } ``` Add channel to set the specific channel or settlement method to use for the payment, if not set, the default channel for the country will be used. ```json theme={"dark"} { "channel": "BANK" } ``` Allowed values are listed under [Countries](/countries). Add static if you want to always generate the same deposit address for the same local currency beneficiary details. ```json theme={"dark"} { "static": true } ``` ### Example response ```json theme={"dark"} { "success": true, "message": "Offramp initiated successfully", "timestamp": "2026-03-31T04:03:15.931Z", "data": { "status": "AWAITING_DEPOSIT", "type": "OFFRAMP", "reference": "6c01338d-67e5-4d0c-a394-9d3e367f46a5", "rate": 1409.758, "source": { "amount": 10, "currency": "USDC", "network": "BASE" }, "destination": { "amount": 14097.58, "currency": "NGN", "network": "FIAT" }, "deposit": { "amount": 10, "address": "0xcd257a5867B42556fa14c35de714154B277f70fD", "asset": "base:usdc", "note": [ "Kindly send the exact amount to the wallet address to complete the transaction.", "This dynamic wallet address has a 30 minutes expiry window and can only be used once." ] } } } ``` ## Completing the Deposit After initiating, you are expected to send **exactly** **`deposit.amount`** of **`deposit.asset`** to **`deposit.address`**. Check **`deposit.note`** for specific instructions. The deposit address is for **one-time use only** and expires after **30 minutes**. if not created with **`static`** set to **`true`**. If less or more amount than specified in **`deposit.amount`** is sent, the deposit will be processed based on the amount sent, so long as it is within the limits and the asset (**`deposit.asset`**) sent is supported. ## Need Help? Send us a message. Hop on a call with us. # Swap stablecoins Source: https://docs.onswitch.xyz/guides/swap-stablecoins Convert between supported stablecoins. **POST `/swap/initiate`** endpoint creates an swap transaction where the customer sends **`from_asset`** to the generated deposit address, the output is delivered to **`beneficiary.wallet_address`** on the destination (**`to_asset`**). Use **GET `/quote`** with the same payload (**`from_asset`**, **`to_asset`**, **`amount`**, **`exact_output`**) to preview the output without creating a swap. ## Example request ```bash cURL theme={"dark"} curl https://api.onswitch.xyz/swap/initiate \ --request POST \ --header 'Content-Type: application/json' \ --header 'x-service-key: '"$YOUR_SERVICE_KEY" \ --data '{ "amount": 100, "from_asset": "base:usdc", "to_asset": "bsc:usdt", "beneficiary": { "wallet_address": "0x1234567890123456789012345678901234567890" } }' ``` ```javascript Node.js theme={"dark"} const res = await fetch('https://api.onswitch.xyz/swap/initiate', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-service-key': process.env.YOUR_SERVICE_KEY, }, body: JSON.stringify({ amount: 100, from_asset: 'base:usdc', to_asset: 'bsc:usdt', beneficiary: { wallet_address: '0x1234567890123456789012345678901234567890', }, }), }); const json = await res.json(); console.log(json.data?.reference, json.data?.status); ``` ```python Python theme={"dark"} import json import os import urllib.request payload = { "amount": 100, "from_asset": "base:usdc", "to_asset": "bsc:usdt", "beneficiary": { "wallet_address": "0x1234567890123456789012345678901234567890", }, } req = urllib.request.Request( "https://api.onswitch.xyz/swap/initiate", method="POST", data=json.dumps(payload).encode("utf-8"), headers={ "Content-Type": "application/json", "x-service-key": os.environ["YOUR_SERVICE_KEY"], }, ) with urllib.request.urlopen(req, timeout=60) as r: out = json.load(r) data = out.get("data") or {} print(data.get("reference"), data.get("status")) ``` ## Frequently Asked Questions Add exact\_output and amount if you want an exact amount to be received at the destination. e.g; if you want 100 USDT ```json theme={"dark"} { "exact_output": true, "amount": 100 } ``` Add callback\_url to set the URL to receive webhook notifications when the payment status changes. ```json theme={"dark"} { "callback_url": "https://your-webhook-url.com" } ``` ### Example response ```json theme={"dark"} { "success": true, "message": "Swap initiated successfully", "timestamp": "2026-03-31T06:23:38.535Z", "data": { "status": "AWAITING_DEPOSIT", "type": "SWAP", "reference": "7ec6514e-d894-474e-87de-a796b1b96771", "rate": 0.999684, "source": { "amount": 100, "currency": "USDC", "network": "BASE" }, "destination": { "amount": 100.031644952349, "currency": "USDT", "network": "BSC" }, "deposit": { "amount": 100, "address": "0x24eAD3fe58DE7DbD031ADddd9f8E6199B9cC691e", "asset": "base:usdc", "note": [ "Kindly send the exact amount to the wallet address to complete the transaction.", "This dynamic wallet address has a 30 minutes expiry window and can only be used once." ] } } } ``` ## Completing the Deposit After initiating, you are expected to send **exactly** **`deposit.amount`** of **`deposit.asset`** to **`deposit.address`**. Check **`deposit.note`** for specific instructions. The deposit address is for **one-time use only** and expires after **30 minutes**. if not created with **`static`** set to **`true`**. If less or more amount than specified in **`deposit.amount`** is sent, the deposit will be processed based on the amount sent, so long as it is within the limits and the asset (**`deposit.asset`**) sent is supported. ## Need Help? Send us a message. Hop on a call with us. # Introduction Source: https://docs.onswitch.xyz/introduction Stablecoin collection and settlement layer.