BRL to USD
Move funds from Brazilian Reais to US Dollars using a PIX on-ramp and an off-loader wallet for automated stablecoin-to-fiat conversion.
Overview
Using Sphere's flexible payment infrastructure, integrators can offer end-users BRL → USD transfers that settle fast. This guide uses a stablecoin sandwich — routing funds through a stablecoin intermediary — to bridge the two currencies:
- Leg 1 (On-ramp): BRL → USDC or USDT via PIX
- Leg 2 (Auto-conversion): USDC or USDT → USD via an Off-loader Wallet
An Off-loader Wallet is a Sphere-managed on-chain address tied to a USD bank account. Any stablecoin sent to it is automatically converted and forwarded to the destination bank account — no second transfer API call required. Your integration makes a single transfer request, and Sphere handles the rest.
The choice of stablecoin determines which networks are available. USDC is supported on Arbitrum, Avalanche, Base, Ethereum, and Polygon. USDT is supported on Ethereum and Tron. The examples in this guide use USDC on Polygon.
Because both legs are standard Sphere primitives, your integration can present the entire flow to your end users as a single BRL → USD operation.
You orchestrate, SpherePay converts
SpherePay handles the currency conversion and settlement on each leg. Your integration is responsible for setting up the instruments and initiating the on-ramp transfer.
Use cases
This pattern is well-suited for cross-border payments where one party transacts in BRL and the other receives USD, including:
- Import/export payments — Brazilian importers paying USD invoices to international suppliers, or exporters receiving USD proceeds from foreign buyers.
- Loan repayments — Borrowers holding BRL servicing USD-denominated debt without manual FX conversion.
- Real estate transactions — Buyers or sellers in Brazilian property deals settling in USD for international counterparties.
What you handle vs. what SpherePay handles
| Responsibility | Owner |
|---|---|
| Creating the customer, bank accounts, and wallet objects | You (integrator) |
| Creating and managing the Off-loader Wallet | You (integrator) |
| Initiating the BRL → USDC on-ramp transfer | You (integrator) |
| PIX payment collection and BRL → USDC conversion | SpherePay |
| USDC → USD conversion and wire delivery | SpherePay (via Off-loader Wallet) |
| Handling failures on either leg | You (integrator) |
Prerequisites
This flow requires the customer to be approved for both verification profiles:
kyc_profile_a/kyb_profile_a(individuals / businesses) — required for USD transferskyc_profile_b/kyb_profile_b(individuals / businesses) — required for BRL/PIX transfers
See the Individual Customer guide and Business Customer guide for KYC/KYB setup instructions.
Before starting you will need:
- A customer with KYC/KYB
approvedfor both verification profiles - A USD bank account to receive the final payout — registered in Step 1
- A BRL bank account with a valid PIX key — registered in Step 4
Passing "network": "sol" on a BRL transfer will result in a rejected request. For USDC use ethereum, polygon, arbitrum, base, or avalanche. For USDT use ethereum or tron.
Flow Diagram
Step 1: Create a USD Bank Account
Register the USD destination account where the final payout will be delivered.
POST https://api.spherepay.co/v2/bank-account
{
"customerId": "{{customer_id}}",
"bankName": "Chase",
"accountName": "My USD Account",
"accountOwner": "Alice Johnson",
"currency": "usd",
"accountDetails": {
"accountNumber": "1234567890",
"routingNumber": "021000021",
"accountType": "checking"
},
"networks": ["wire"]
}Store the returned id as {{usd_bank_account_id}}.
Step 2: Create an Off-loader Wallet
Create an Off-loader Wallet linked to the USD bank account from Step 1. Sphere provisions a dedicated on-chain address — any stablecoin sent to it is automatically converted and wired to the destination bank account. Set currency to usdc or usdt depending on which stablecoin you want to use as the intermediary.
POST https://api.spherepay.co/v2/offloader-wallet
{
"customerId": "{{customer_id}}",
"currency": "usdc",
"network": "polygon",
"destination": {
"bankAccountId": "{{usd_bank_account_id}}",
"currency": "usd",
"network": "wire"
}
}Choosing your fiat rail
The network field in destination controls how USD is delivered. Wire (wire) settles faster — typically within a few hours on the same business day — but incurs higher fees. ACH (ach) is cheaper but slower, typically settling in 1–2 business days. Choose based on the speed vs. cost trade-off that fits your use case.
The response includes an address field — the on-chain wallet address. Store it as {{offloader_address}}.
Step 3: Register the Off-loader Address as a Wallet Object
The Transfers API requires a wallet object (with a Sphere-assigned ID) as the transfer destination, not a raw on-chain address. Register the off-loader address to get one.
POST https://api.spherepay.co/v2/wallet
{
"customerId": "{{customer_id}}",
"network": "polygon",
"address": "{{offloader_address}}"
}Store the returned id as {{wallet_id}}. Steps 2 and 3 only need to be completed once per customer — reuse {{wallet_id}} for all subsequent BRL → USD transfers for this customer.
Step 4: Create a BRL Bank Account
Register the BRL source account using currency: "brl" and PIX-specific details in accountDetails.
POST https://api.spherepay.co/v2/bank-account
{
"currency": "brl",
"bankName": "Banco do Brasil",
"accountName": "My BRL Account",
"accountDetails": {
"pixKey": "alice@example.com",
"pixKeyType": "email"
},
"accountOwner": {
"accountHolderName": "Alice Johnson",
"address": {
"line1": "Rua das Flores 123",
"city": "São Paulo",
"state": "SP",
"postalCode": "01310-100",
"country": "BRA"
}
},
"networks": ["pix"]
}The pixKeyType field accepts email, phone, cnpj, or random. The format of pixKey must match the specified type.
Step 5: Create the BRL → USDC Transfer
With all instruments in place, create the on-ramp transfer. The destination is the wallet object registered in Step 3 — backed by the off-loader wallet that will auto-convert to USD.
POST https://api.spherepay.co/v2/transfer
{
"customer": "{{customer_id}}",
"amount": "100.00",
"source": {
"type": "bank_account",
"id": "{{brl_bank_account_id}}",
"currency": "brl",
"network": "pix"
},
"destination": {
"type": "wallet",
"id": "{{wallet_id}}",
"currency": "usdc",
"network": "polygon"
},
"integratorBpsFeeRate": "50"
}BRL transfer constraints
integratorBpsFeeRate is required for BRL transfers (fixed fees are not supported), and Solana is not supported. See BRL/PIX transfer constraints for the full list.
Step 6: Fund the Transaction
The response from Step 5 includes an instructions field with the PIX key your customer should use to send BRL. Present this to your end user.
Once they initiate the PIX payment:
- Sphere receives the BRL and converts it to USDC
- USDC is delivered to the off-loader wallet address
- The off-loader wallet automatically converts USDC to USD and wires it to
{{usd_bank_account_id}}
Error Handling
| Scenario | What happens | What to do |
|---|---|---|
| On-ramp fails | BRL is returned via PIX. No USDC is minted. | Retry the transfer or surface the failure to your user. |
| On-ramp succeeds, off-loader conversion fails | USDC sits in the off-loader wallet. No USD is sent. | Contact SpherePay support — the off-loader wallet handles conversion automatically and any failure is on Sphere's side. |
| Customer sends wrong amount via PIX | Partial or excess USDC lands in the off-loader wallet. | The off-loader wallet will convert whatever USDC arrives. Handle reconciliation on your side. |
Constraints
- PIX runs 24/7 and is near-instant. USD wires only process during banking hours with a 5pm EST cutoff, and can take up to an hour depending on processing times.
- Off-loader Wallets do not support webhooks. Track the on-ramp transfer status via
GET /v2/transfer/{{transfer_id}}. - Both legs are billed as separate transfers.
- Both verification profiles (A and B) must be approved before either transfer can be initiated.
- Solana (
sol) is explicitly blocked as the intermediary network for BRL transfers — the API will reject requests using it regardless of stablecoin.
Looking ahead
Today this flow requires setting up an Off-loader Wallet and a separate transfer API call. SpherePay is working toward a single-call cross-currency transfer that abstracts the intermediate stablecoin hop — you would send one request with BRL as the source currency and USD as the destination currency, and SpherePay would handle the routing internally.
When that API is available, the pattern in this guide will still work, but you'll have the option to simplify your integration to a single call.
Related
- Off-loader Wallets — How automated stablecoin-to-fiat conversion works
- Transfers API Guide — Full transfer creation and tracking reference
- Bank Accounts — Registering PIX and USD bank accounts
- Transfer Lifecycle — Status definitions and state machine
- Supported Rails & Currencies — Full compatibility matrix
Last updated on