---
title: "How to invoice in BRL or MXN and settle in USDC: FX between invoice and payment"
seoTitle: "How to invoice in BRL or MXN and settle in USDC"
description: "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."
date: "2026-10-07"
updated: "2026-10-07"
category: "payments"
author: "BlindPay Team"
faq:
  - q: "Can I send an invoice in BRL and get paid in USDC?"
    a: "Yes. Issue the invoice in reais, and when the client is ready to pay, create a payin quote for the invoice amount with payment_method pix. The client pays the Pix code, and BlindPay converts the reais and delivers USDC to the wallet set on the quote. The rate is fixed when the quote is created, not when the invoice was issued."
  - q: "When is the exchange rate fixed on a local currency invoice?"
    a: "At payin quote time. A payin quote locks the amounts and the fee split and expires after 5 minutes, so you create it when the payer is about to pay, not on the invoice date. Any move in BRL or MXN between the invoice date and that moment changes how much USDC you receive."
  - q: "Who carries the FX risk between the invoice date and the payment date?"
    a: "Whoever's amount is fixed in the other currency. If the invoice is a fixed BRL or MXN amount, you carry the risk, because the USDC you receive floats. If the invoice is a fixed USD amount and the payer pays whatever local amount the quote says, the payer carries it."
  - q: "Does the payer pay more if I set cover_fees to true?"
    a: "Yes. On a payin quote, cover_fees true adds the fee on top of the fiat amount the sender pays, so the payer sends more than the invoice total. With cover_fees false, the payer pays the invoice amount exactly and the fee comes out of the stablecoins you receive. Most invoice flows use false."
  - q: "Can a Mexican invoice include centavos?"
    a: "Not if you quote the peso side. When currency_type is sender and the currency is MXN, COP, or ARS, request_amount must be a whole peso, a multiple of 100 in minor units. Round the invoice total to whole pesos before you quote, or the quote is rejected."
---

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**

- A payin quote locks the numbers for 5 minutes. Create it when the client is ready to pay, not when you issue the invoice.
- On a local currency invoice, the USDC you receive floats until payment. That's your FX exposure.
- Fix the side that matters: invoice in BRL or MXN and accept a floating USDC amount, or invoice in USD and let the payer's local amount float.
- Use `cover_fees: false` so the payer pays the invoice total exactly.
- MXN, COP, and ARS amounts must be whole pesos when you quote the local side.

## Why can't the invoice lock the exchange rate?

Because a payin quote expires 5 minutes after creation, and the invoice is open for weeks. BlindPay's [payin quotes](/docs/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](/resources/more/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](/resources/more/fx-gap-between-sale-and-payout). Same mechanics, opposite direction.

## Who carries FX risk between invoice and payment?

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](/resources/more/live-quotes-volatile-currencies-latin-america) shows how quotes behave when they do.

## How do you price the invoice in each setup?

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.

## Illustrative example: what does a 19-day delay cost on a BRL invoice?

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:

- FX move between invoice and payment: 5,000.00 - 4,864.86 = 135.14 USDC.
- Rate margin at payment: 4,864.86 - 4,838.71 = 26.15 USDC.
- Flat fee: 1.00 USDC.

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](/resources/more/natural-fx-hedge-stablecoin-rails) against BRL costs you already pay.

## What does the payment flow look like for Pix and SPEI?

Three calls, timed to the payer, not the invoice.

1. **Create the payin quote when the client clicks pay.** Pass the destination (`blockchain_wallet_id` or `wallet_id`), `payment_method`, `currency_type`, `cover_fees`, `request_amount`, and `token`.
2. **Create the payin from the quote within 5 minutes.** `POST /v1/instances/{instance_id}/payins/evm` with the quote id. The path name is historical and works for every rail ([payins](/docs/payins)).
3. **Show the instructions.** For Pix, the response carries a `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](/docs/kb/cut-off-times)). Pix runs every day of the year ([Banco Central do Brasil](https://www.bcb.gov.br/en/financialstability/pix_en)), and Banco de México says SPEI transfers should not take more than 30 seconds after approval ([Banxico](https://www.banxico.org.mx/services/interbanking-electronic-payme.html)).

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.

## Which API details break invoice flows?

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](/resources/more/why-crypto-on-ramp-deposits-fail) covers what happens when a payer sends the wrong amount or pays late.

## Should you just quote at invoice time and hope?

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](https://www.banxico.org.mx/tipcamb/tipCamMIAction.do?idioma=sp)), 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](/resources/more/how-to-on-ramp-local-currency-latin-america), and for the virtual account route on USD receivables, [how to accept bank transfers and settle in stablecoins](/resources/more/accept-bank-transfers-settle-in-stablecoins).

## What to do next

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](/docs/payin-quotes) have the exact request body.
