---
title: "How to add a \"Send to Brazil by Pix\" feature to your neobank app"
seoTitle: "How to add Pix transfers to your neobank app"
description: "Build a Send to Brazil by Pix feature: Pix key entry, recipient check, live quote screen, payout, webhooks, receipts, and the mistakes that cause failures."
date: "2026-10-14"
updated: "2026-10-14"
category: "payments"
author: "BlindPay Team"
howto:
  name: "How to add a Send to Brazil by Pix feature to a neobank app"
  steps:
    - name: "Verify the sender"
      text: "Make sure the user sending money has accepted the terms of service and passed KYC, so payouts can be created for them."
    - name: "Collect the recipient's Pix key"
      text: "Ask for the Pix key type first (CPF, CNPJ, phone, email, or random key), validate the format on the device, and save it as a Pix bank account for the customer."
    - name: "Request a live quote"
      text: "Create a payout quote for the amount in USD or in BRL. The quote locks the exchange rate and fees for 5 minutes."
    - name: "Show the confirmation screen"
      text: "Display the recipient name, the BRL amount they receive, the fee, the rate, and a countdown to quote expiry. Ask the user to confirm."
    - name: "Execute the payout"
      text: "Create the payout with the quote ID before it expires, sending an idempotency key so a retry never creates a second transfer."
    - name: "Track status and send a receipt"
      text: "Listen for payout webhooks, update the transfer in the app, and send the user a receipt with the amount, rate, and reference when the payout completes."
faq:
  - q: "How do I add Pix transfers to my app?"
    a: "Use a payout API that pays out over Pix. Your app collects the recipient's Pix key, your backend saves it as a Pix bank account, requests a quote that locks the rate and fees, shows the user the BRL amount, and executes the payout. Webhooks tell you when the reais arrive. With BlindPay, the whole flow is a handful of REST calls."
  - q: "Which Pix keys can a recipient use?"
    a: "A Pix key can be a CPF (individual tax ID), a CNPJ (company tax ID), a phone number, an email address, or a random key the bank generates. Ask the user which type they have before they type it, because each type has a different format to validate. If the recipient has no key, bank and branch details can go over PIX Safe or TED instead."
  - q: "How fast does a Pix transfer from a US app arrive?"
    a: "Pix itself moves money in a few seconds, at any time, including weekends and holidays, according to Banco Central do Brasil. BlindPay lists Pix payouts as instant once the payout executes. Show users a short arrival window such as usually within minutes, and send a push notification when the payout webhook reports it as completed."
  - q: "What happens if a Pix payout fails?"
    a: "On Pix and other non-USD local rails, if BlindPay can't deliver a payout after collecting the stablecoins, it refunds them automatically to the quote's refund wallet, or to the sending wallet when none is set. Your app should mark the transfer as failed or refunded, tell the user why, and let them fix the Pix key and try again."
  - q: "Does the user see the exchange rate before sending?"
    a: "They should. A BlindPay payout quote returns the exchange rate, the fees, and the exact BRL amount the recipient receives, locked for 5 minutes. Put all three on the confirmation screen with a countdown. If the quote expires, request a new one and show the new numbers before the user confirms again."
  - q: "Can a neobank send Pix payouts without a Brazilian entity?"
    a: "Yes, through a provider that pays out over Pix. The neobank calls the provider's API, and the provider delivers the reais through its own Pix access in Brazil. You still own your obligations toward your users, such as KYC on the sender and clear disclosures about cost and arrival time."
---

To add a "Send to Brazil by Pix" feature, your app collects the recipient's Pix key, your backend saves it as a Pix bank account, requests a live quote, shows the BRL amount, and executes a payout. BlindPay handles the conversion and the Pix delivery through one API, and webhooks tell you when the reais land.

This guide is about the product feature inside a neobank: the screens, the states, and the messages. For the payout mechanics from a business wallet, see [how to send USDC to a bank account in Brazil](/resources/more/how-to-send-usdc-to-bank-account-brazil). For where this feature sits in the whole build, start with [how to build a neobank](/resources/more/how-to-build-a-neobank).

**Key takeaways**

- Ask for the Pix key type before the key. Each type has its own format and validation.
- Lock the price with a quote and show the BRL amount the recipient gets, not only the USD you send.
- Send an idempotency key on every payout so a timeout never doubles a transfer.
- Pix runs 24/7, so your support and notifications should too.
- Store the payout ID and rail reference on every transfer. Support needs them for every "where is my money" ticket.

## What is Pix, and why do users in Brazil expect it?

Pix is Brazil's instant payment scheme, created by the central bank. According to [Banco Central do Brasil](https://www.bcb.gov.br/en/financialstability/pix_en), it lets people, companies, and government entities send or receive transfers in a few seconds at any time, including non-business days.

That sets the bar. A Brazilian recipient compares your transfer to the Pix they get from friends every day. If your feature takes two days, it feels broken, even if it is cheaper than a wire.

## What do you need before the first Pix transfer?

You need a verified sender, a recipient's Pix details, and a funding source for the payout.

| Requirement | Who provides it | Where it lives in BlindPay |
| --- | --- | --- |
| Terms of service acceptance | Your user, on a hosted page | `tos_id` passed when creating the customer |
| KYC on the sender | Your user | Customer object, status `approved` |
| Pix key and recipient name | Your user, about the recipient | Bank account of type `pix` |
| Bank and branch details (no key) | Your user, about the recipient | Bank account of type `pix_safe` or `ted` |
| Funds to send | Your treasury or the user's balance | USDC or USDT in the funding wallet |

The [onboarding guide for neobanks](/resources/more/neobank-kyc-kyb-onboarding-flow) covers the KYC side. The [bank accounts docs](/docs/bank-accounts) list the exact fields per rail.

## How do you build the feature step by step?

Six steps, from the sender's first tap to the receipt.

1. **Verify the sender.** The user accepts terms of service and passes KYC once. After that, every transfer reuses the same customer.
2. **Collect the Pix key.** Show a picker first: CPF, CNPJ, phone, email, or random key. Then show one input with the right keyboard and mask for that type. Save it as a `pix` bank account for the customer.
3. **Request a live quote.** Your backend creates a payout quote for the amount. The user can type USD to send or BRL to arrive. The quote locks the rate and fees for 5 minutes. See the [payout quotes docs](/docs/payout-quotes).
4. **Show the confirmation screen.** Recipient name, Pix key (partly masked), BRL amount received, fee, rate, and a countdown.
5. **Execute the payout.** On confirm, create the payout with the quote ID and an `Idempotency-Key` header ([idempotency docs](/docs/learn/idempotency)). A retry after a timeout then returns the same payout instead of a second one.
6. **Track and notify.** Listen for `payout.new`, `payout.update`, and `payout.complete` ([webhook events](/docs/learn/webhooks-events)). Update the transfer row, send a push notification, and email a receipt.

## How should the Pix key screen work?

Validate early and show who the money goes to before the user commits.

- **Type picker first.** "Which Pix key does your recipient use?" removes most format errors.
- **Format checks on the device.** A CPF has 11 digits, a CNPJ has 14. A phone needs the country code. An email needs an @. A random key is long and gets pasted, so offer a paste button.
- **Show the recipient name.** Ask the user to type the recipient's full name and show it again on the confirmation screen. People catch wrong keys when they read a name they don't recognize. The guide on [verification of payee in instant payments](/resources/more/verification-of-payee-instant-payments) explains how rails check recipients.
- **Save favorites.** Most remittance users send to the same two or three people. Let them pick a saved recipient instead of retyping a key.

## What should the confirmation screen show?

Everything the user needs to say yes, and nothing they need to calculate.

| Field | Example (illustrative) | Why it matters |
| --- | --- | --- |
| Recipient | Ana Souza | Catches a wrong key |
| Arrives as | R$ 2,710.00 | The number the recipient will see |
| You send | US$ 500.00 | The number leaving the user's balance |
| Fee | US$ 4.50 | Shown separately, never buried in the rate |
| Rate | 1 USD = 5.47 BRL | Lets users compare |
| Price locked for | 4:32 | The quote expiry, counting down |
| Arrives | Usually within minutes | Sets expectations |

The numbers above are invented. In production, every one of them comes from the quote response. Some users check your rate against the central bank's PTAX reference, which [Banco Central do Brasil publishes](https://dadosabertos.bcb.gov.br/dataset/dolar-americano-usd-todos-os-boletins-diarios) as the average of four daily dealer consultations. A quote includes spread and fees, so it won't match PTAX exactly. Show both the rate and the fee so the comparison is fair. The [quote screen and fee disclosure guide](/resources/more/cross-border-quote-screen-fee-disclosure) covers the layout in more detail.

## What does one transfer look like end to end?

Illustrative example. Maria lives in Miami and uses a neobank app. She sends money to her sister Ana in Belo Horizonte.

1. Maria taps "Send to Brazil" and picks Ana from saved recipients (Pix key type: phone).
2. She types US$ 500. The app requests a quote and shows R$ 2,710.00 arriving, a US$ 4.50 fee, and a 5-minute countdown.
3. She confirms at 4:32 remaining. The backend creates the payout with an idempotency key.
4. The app shows "Sending". A `payout.new` webhook arrives, then `payout.complete`.
5. Maria gets a push: "R$ 2,710.00 arrived in Ana's account." The receipt includes the rate, fee, time, and a reference number.

Total time on Maria's side: under a minute. That is the experience Pix users expect.

## What are the common Pix mistakes?

- **One free-text field for every key type.** Users paste a phone without the country code or a CPF with dots in the wrong place. Use a type picker and masks.
- **Showing only the USD amount.** The recipient cares about reais. Show the BRL amount from the quote.
- **Executing an expired quote.** The 5-minute window passes while the user reads. Requote and show the new numbers.
- **No idempotency key.** A flaky mobile connection plus a retry can send money twice.
- **Treating "processing" as "failed".** Give the payout time and rely on webhooks instead of polling every second.
- **Silent failures.** If a payout fails or is refunded, say so in the app with a reason and a "fix and resend" button.
- **No reference on the receipt.** Store the payout ID and the rail reference. Without them, support can't trace anything.

## How should you handle failures and refunds?

Show the status the payout reports, explain it in plain words, and give one next step.

- **`processing`:** "Sending. Usually takes a few minutes."
- **`on_hold`:** "We're checking this transfer. We'll update you." Compliance reviews can happen on any rail.
- **`completed`:** "Arrived." Show the receipt.
- **`failed` or `refunded`:** "This transfer didn't go through. Your money is back." Then offer to fix the Pix key.

On Pix and other non-USD local rails, if BlindPay can't deliver a payout after the stablecoins are collected, it refunds them automatically to the quote's refund wallet, or to the sending wallet when none is set. Your ledger should then return the amount to the user's balance. The [payout statuses explainer](/resources/more/stablecoin-payout-statuses-explained) covers each state.

Pix also has a special return mechanism for fraud cases, run by the recipient's and payer's banks. The central bank's [guide to Pix returns and the MED](https://www.bcb.gov.br/content/estabilidadefinanceira/pix/Guia_MED.pdf) sets the rules, including an 80-day window from the original transaction to open a recovery.

## How do you test the feature before launch?

Run every branch on a development instance before real money moves.

1. Create a customer and add a Pix bank account with test details.
2. Request a quote and let it expire. Confirm your app requotes.
3. Execute a payout and confirm your webhook handler updates the transfer.
4. Send the amount 66600 to force a `failed` payout, and 77700 to force a `refunded` one. Check the messages users see.
5. Retry a payout call with the same idempotency key and confirm no second payout appears.
6. Kill the app mid-transfer and reopen it. The status should come from your backend, not from the screen.

## How BlindPay fits

BlindPay gives a neobank one API for Pix payouts. Your backend creates the customer after terms of service and KYC, adds the recipient as a `pix` bank account (or `pix_safe` and `ted` when the user has bank details instead of a key), requests a quote that locks the rate and fees for 5 minutes, and executes the payout. BlindPay converts USDC or USDT from the funding wallet into BRL and pays over Pix, which BlindPay lists as instant.

You don't pre-fund a Brazilian account or open a local entity to send. Webhooks, signed with Svix headers, report each status change. If you charge your own fee per transfer, [partner fees](/docs/learn/partner-fees) add it to the quote so users see one price. The same flow then extends to SPEI and other rails, as covered in [which payout rails a neobank should launch with](/resources/more/neobank-payout-rails-which-to-launch-first).

## What to do next

Sketch the three screens (recipient, confirm, receipt), then wire them to a development instance with the [payout quickstart](/docs/quickstart-payout). Send one test transfer that completes, one that fails, and one that is refunded before you show it to users.
