Bill clients in reais or pesos and receive USDC. Where the rate gets fixed, who carries FX between invoice and payment, and three ways to price an invoice.
To invoice in BRL or MXN and settle in USDC, issue the invoice in local currency, then create a payin quote for that amount at the moment the client pays. The client pays by Pix or SPEI, and the reais or pesos convert to USDC at the quoted rate. The rate is set at payment time, so you carry FX between invoice and payment.
That gap is the whole problem. An invoice lives for 15, 30, or 60 days. A quote lives for 5 minutes. This guide covers where the rate actually gets fixed, three ways to price the invoice, and the API details that trip up invoice flows.
Key takeaways
cover_fees: false so the payer pays the invoice total exactly.Because a payin quote expires 5 minutes after creation, and the invoice is open for weeks. BlindPay's payin quotes lock how much fiat the sender pays, how much stablecoin the destination receives, and the fee split, but only for that short window. You then create the payin from the quote and show the payer their instructions.
So the rate on an invoice is never the rate on the day you sent it. It's the rate on the day the client pays. If you need a refresher on which number in a quote is the rate and which way it points, how to read an FX quote covers base and quote currency.
This is the on-ramp version of a problem payout teams know well: the FX gap between a sale and a payout. Same mechanics, opposite direction.
Whoever has a fixed amount in the other currency. The table shows the three common setups.
| Invoice setup | What is fixed | What floats | Who carries the FX move |
|---|---|---|---|
| Invoice in BRL or MXN, quote the local side | The local amount the client pays | USDC you receive | You |
| Invoice in USD, quote the stablecoin side | USDC you receive | Local amount the client pays | The client |
| Invoice in local currency with a re-price clause | Local amount, inside a band | USDC, inside the band | Shared |
Local clients usually prefer the first setup. Their accounting is in reais or pesos, and a fixed local total is easy to approve. You pay for that convenience with exposure. Brazil's and Mexico's currencies can move several percent in a month, and live quotes on volatile currencies shows how quotes behave when they do.
Pick the currency_type that matches the side you fixed. On a payin quote, the convention is the opposite of a payout quote, which catches people.
currency_type on a payin quote | request_amount is in | Use it when |
|---|---|---|
sender | The fiat the payer sends (BRL for Pix, MXN for SPEI) | The invoice total is in local currency |
receiver | The stablecoin the destination wallet receives | The invoice total is in USD |
Setup one, a BRL invoice of R$ 27,000.00: quote with currency_type: "sender", request_amount: 2700000, payment_method: "pix". The payer pays exactly R$ 27,000.00 and you receive whatever USDC the quote returns.
Setup two, a USD invoice of $5,000.00: quote with currency_type: "receiver", request_amount: 500000. The quote tells the payer how many reais to send for you to receive 5,000.00 USDC.
Amounts are integers in minor units, so 2700000 is R$ 27,000.00. Floats are rejected.
You invoice a Brazilian client R$ 27,000.00 on October 1. The market sits at 5.40 BRL per USD, so you expect about $5,000. The client pays on October 20, when the market is at 5.55. All rates below are illustrative and expressed as BRL per USDC.
| Line | Value |
|---|---|
| Invoice total | R$ 27,000.00 |
| Expected at invoice date (27,000 / 5.40) | 5,000.00 USDC |
| Market value at payment date (27,000 / 5.55) | 4,864.86 USDC |
| Quoted rate after margin | 5.58 BRL per USDC |
| Converted at quoted rate (27,000 / 5.58) | 4,838.71 USDC |
Flat fee, paid by you (cover_fees: false) | 1.00 USDC |
receiver_amount | 4,837.71 USDC |
Break down the 162.29 USDC shortfall against the 5,000 you expected:
Total: 135.14 + 26.15 + 1.00 = 162.29 USDC. The quote's cost is visible and small. The FX move is the real exposure, and the quote can't protect you from a move that happened before it existed.
If that exposure bothers you, the honest fixes are setup two (bill in USD), a shorter payment term, or a natural hedge against BRL costs you already pay.
Three calls, timed to the payer, not the invoice.
blockchain_wallet_id or wallet_id), payment_method, currency_type, cover_fees, request_amount, and token.POST /v1/instances/{instance_id}/payins/evm with the quote id. The path name is historical and works for every rail (payins).pix_code to show as copyable text or a QR code. For SPEI, it carries a CLABE.Once the payin exists, BlindPay waits for the deposit. Pix and SPEI typically settle within minutes, and BlindPay waits up to 30 minutes before marking a standard payin failed (cut-off times). Pix runs every day of the year (Banco Central do Brasil), and Banco de México says SPEI transfers should not take more than 30 seconds after approval (Banxico).
A payin can't be canceled after creation. Create it only when the client is actually paying, which is one more reason to quote at the pay button, not at invoice time.
Four, in order of how often they show up.
Fees on top of the invoice. On a payin quote, cover_fees: true adds the fee to the fiat the sender pays. The client then sends more than the invoice total, and their accounts payable team flags it. Use cover_fees: false and the fee comes out of the USDC you receive.
Centavos on Mexican invoices. When currency_type is sender and the currency is MXN, COP, or ARS, request_amount must be a multiple of 100. 10050 fails with request_amount_must_be_a_whole_currency_unit. Round invoice totals to whole pesos. On the receiver side, BlindPay rounds the computed peso amount down to a whole peso for you.
The wrong payer. Pix quotes accept payer_rules.pix_allowed_tax_ids, a list of CPF or CNPJ numbers allowed to pay. Put the client's CNPJ there, and a payment from some other account won't be matched to your invoice. BlindPay checks the tax id's check digits at quote time.
Amount limits. Each currency has a minimum and maximum, and the quote enforces them with an error that names the range. Don't hardcode a floor. Why on-ramp deposits fail covers what happens when a payer sends the wrong amount or pays late.
No. A quote created on invoice day expires 5 minutes later, so there's nothing to hope for. Any flow that "locks" a rate at invoice time without a hedge is really an indicative price.
What you can do is show an indicative USDC estimate on the invoice for your own planning, clearly labeled, and quote for real at payment. Banco de México publishes its FIX reference rate on banking days (Banxico), which works for that kind of estimate. It's a reference, not a price you can trade at.
For the full on-ramp mechanics by country, see how to on-ramp BRL, MXN, ARS, and COP, and for the virtual account route on USD receivables, how to accept bank transfers and settle in stablecoins.
Create one Pix payin quote on a development instance with currency_type: "sender", cover_fees: false, and your typical invoice total, then read receiver_amount and expires_at. The payin quotes docs have the exact request body.
Seven places blockchain payments beat bank rails: contractor payroll, remittances, B2B suppliers, marketplaces, 24/7 treasury, bill pay, and PSP payouts.
Push means the payer sends an ACH transfer. Pull means you debit a connected account. How each funds a USD to USDC on-ramp, the fees, and the return risk.
AP2, ACP, and x402 each verify that an AI agent had permission to spend. Here is what every protocol covers, who backs it, and the reconciliation gap none of them close.