---
title: "Bank transfer checkout UX: showing Pix codes, CLABEs, and memos"
seoTitle: "Bank transfer checkout UX: Pix codes, CLABEs, and memos"
description: "How to design the instructions screen of a bank transfer checkout in 2026: Pix QR codes, CLABEs, CBUs, PSE links, US memo codes, timers, and status."
date: "2026-10-19"
updated: "2026-10-19"
category: "payments"
author: "BlindPay Team"
faq:
  - q: "What should a bank transfer checkout show the shopper?"
    a: "Show only what the shopper's rail needs, each value with a copy button: a Pix code as a QR code and text, a CLABE with the exact MXN amount, a CBU or CVU with the exact ARS amount, a PSE button that opens their bank, or US routing and account numbers with the memo code. Add the total in their currency and a live status line."
  - q: "Why does the US memo code matter at checkout?"
    a: "The memo code is how the deposit gets matched to the right payment when the shopper sends money to shared bank details. Without it, the transfer can land with no way to tie it to the order. Show the memo next to the account number, mark it as required in bold, and give it its own copy button."
  - q: "What happens if the payment quote expires on the checkout page?"
    a: "Quote again on the next click and show the new amount, with no error message. A BlindPay payin quote locks the rate and fees for 5 minutes. Once the shopper confirms and the payin is created, the instructions stay valid and the quote no longer matters, so the timer should only run on the price screen."
  - q: "How should the checkout handle a payment held for review?"
    a: "Keep the order open and tell the shopper the payment is being reviewed. A BlindPay payin in on_hold status is waiting for a manual risk or compliance check and is not final. Do not show a failure screen, and do not ask the shopper to pay again, or you may collect twice."
  - q: "Can I give the shopper a receipt or tracking page?"
    a: "Yes. BlindPay exposes GET /v1/e/payins/{id}, which returns the payin's fields without an API key, so a payer-facing receipt or status page can call it with just the payin id. Use it for a link in the confirmation email so the shopper can check the status without logging in."
---

A bank transfer checkout succeeds or fails on one screen: the payment instructions. Show only the values the shopper's rail needs, each with a copy button, the exact amount in their currency, and a live status line. Pix needs a QR code, SPEI a CLABE, Argentina a CBU or CVU, PSE a bank button, and US transfers a memo code.

Cards hide all of this behind a form. Bank rails push it to the shopper, so the layout decides whether money arrives. For how this screen fits in the stack, read [what a global payments checkout is](/resources/more/what-is-a-global-payments-checkout).

**Key takeaways**

- Each rail shows one primary value: a Pix code, an 18-digit CLABE, a CBU or CVU, a PSE payment link, or US bank details plus a memo code.
- Baymard's research puts average cart abandonment at 70.22% across 50 studies, and 17% of shoppers leave over a long or complicated checkout.
- A BlindPay payin quote lasts 5 minutes, so the timer belongs on the price step, not the instructions step.
- MXN, ARS, and COP amounts are always whole units, which makes the exact amount easier to type.
- Statuses to design for: processing, on hold, completed, failed, refunded.

## What should the instructions screen show for each rail?

One primary value per rail, the exact amount, and who receives it. Everything else is noise.

| Rail | Country | What to show | Shopper's action | Most common mistake |
| --- | --- | --- | --- | --- |
| Pix | Brazil | QR code plus copyable Pix code | Scan or paste in the bank app | Opening the code on the same phone and not finding the QR |
| SPEI | Mexico | 18-digit CLABE, exact MXN amount, beneficiary | New transfer in the bank app | Sending a rounded or different amount |
| Transfers 3.0 | Argentina | CBU or CVU (or alias), exact ARS amount | Transfer from a bank or wallet app | Paying from an account in someone else's name |
| PSE | Colombia | "Continue to your bank" button with the payment link | Approve in the bank's own site | Abandoning at the bank's two-factor step |
| ACH, wire, RTP | United States | Routing number, account number, beneficiary, bank, memo code | Bank transfer from online banking | Leaving out the memo code |

Put the value the shopper copies first, in large tabular numerals, with a copy button next to each field. On mobile, show the Pix copy text above the QR code, since a shopper paying on their phone cannot scan their own screen. [The details needed to pay in Brazil or Mexico](/resources/more/pix-key-cpf-clabe-payout-details) explains CPF and CLABE formats.

## Why do bank transfer checkouts lose shoppers?

Mostly at the moment the shopper leaves your page for their bank. Your job is to make that trip short and easy to resume.

[Baymard](https://baymard.com/lists/cart-abandonment-rate) reports an average documented cart abandonment rate of 70.22% across 50 studies. Among US shoppers who left for reasons other than browsing, 17% blamed a long or complicated checkout and 12% could not see or calculate the total cost up front. Both apply directly to bank transfers.

Three design rules follow:

- **Show the total in the shopper's currency before they confirm.** "You pay R$ 467,04, includes fees and exchange" removes the surprise.
- **Keep the page alive while they are in the bank app.** The shopper switches apps and comes back. The page should still show the instructions and a status line, not a timeout.
- **Speak their language.** Stripe's [localization guide](https://stripe.com/resources/more/payment-localization-best-practices-a-guide-for-scaling-payments-worldwide) recommends the local language for field labels, error messages, and buttons. "Pague com Pix" beats "Pay with Pix" in Brazil.

## How should the checkout flow be ordered?

Price first, payer details second, instructions third, status last. Here is the sequence that works across all rails:

1. **Pick country and rail.** Show flags and one hint per rail, such as "Pay from any Brazilian bank app" or "Takes 1 to 3 business days" for ACH.
2. **Collect only the payer details the rail needs.** CPF or CNPJ for Pix, CUIT or CUIL for Argentina, and for PSE the document type (CC or NIT), document number, email, phone, and bank. SPEI and US rails need nothing extra.
3. **Show the price.** Request the payin quote and display the local amount large. Add a countdown to the quote's expiry. If it runs out, quote again on the next click without an error.
4. **Confirm.** Create the payin with an Idempotency-Key tied to the order, so a double click never creates two payments. From here the rail is fixed.
5. **Show the instructions.** One primary value, the exact amount, copy buttons, and for US rails a bold note that the memo is required.
6. **Wait with a live status.** "Waiting for your transfer", then "Payment received". Poll your own backend, not the payment provider, from the browser.
7. **Finish.** A success screen with the amount, the merchant, and a reference, then redirect to the merchant's success URL.

[How long a payment quote lasts](/resources/more/how-long-does-a-payment-quote-last) compares quote windows if you need to tune step 3.

## How do you prevent the most common payer mistakes?

Make the wrong action hard. Most bank transfer errors are typing errors or wrong-account errors.

- **Wrong amount.** Show the exact amount with a copy button. MXN, ARS, and COP amounts come back in whole units, which is easier to type correctly. SPEI is fast: Banco de México says a [SPEI payment should take no more than 30 seconds](https://www.banxico.org.mx/services/interbanking-electronic-payme.html) after approval, so a wrong amount shows up quickly.
- **Wrong payer.** Pix and Transfers 3.0 payins match the sender's tax id. Tell the shopper to pay from an account in their own name, with the CPF or CUIT they entered. In Argentina, BlindPay revives a Transfers payin whose funding arrived after it was marked failed, once it matches the sender's tax id and amount.
- **Missing memo.** On ACH, wire, and RTP, the memo code ties the deposit to the order. Repeat it in the confirmation email.
- **PSE drop-off.** [PSE](https://www.pse.com.co/persona) debits the shopper's savings, checking, or electronic deposit account after they approve in their bank. Open the payment link in the same tab and tell the shopper to expect a two-factor step.

[Why a deposit gets delayed, held, or returned](/resources/more/virtual-account-deposit-not-received) covers what happens on the back end when a payer still gets it wrong.

## Which statuses does the checkout need to design for?

Five, and two of them are not final. Map each one to a screen before you write any code.

- **Processing.** The payin exists and BlindPay is waiting for the deposit. Show the instructions and "Waiting for your transfer".
- **On hold.** Held for manual risk or compliance review. Show "Your payment is being reviewed" and keep the order open.
- **Completed.** The money arrived and the stablecoins were delivered. Show success.
- **Failed.** The payin did not go through. Show "This payment did not go through" and a way back to the merchant.
- **Refunded.** The deposit was returned to the sender. Treat it like failed, and say the money is on its way back.

A payin cannot be canceled once created, so never expire the instructions screen after the shopper confirmed. If they never pay, the payin stays processing until it is cleaned up on BlindPay's side.

## How does BlindPay fit behind the instructions screen?

BlindPay returns every value this screen needs in the payin response. You build the page, and BlindPay moves the money.

One endpoint creates payins for every rail. The response populates only the field for the chosen method: `pix_code` for Pix, `clabe` for SPEI, `tracking_transaction.transfers_instruction` for Argentina, `tracking_transaction.pse_instruction.payment_link` for PSE, and `memo_code` plus `blindpay_bank_details` for ACH, wire, and RTP.

Payin quotes validate payer details before money moves. A CPF or CNPJ is checked against the Receita Federal check digits at quote time, so a typo fails on your page instead of at the bank. Pix, SPEI, Transfers, and PSE typically settle within minutes. ACH and wire can take up to 5 business days to arrive.

For status, subscribe to `payin.new`, `payin.update`, and `payin.complete`, then read the payin's `status`. Verify the `svix-signature` header on every call. For receipts, `GET /v1/e/payins/{id}` returns the payin without an API key, so the shopper's tracking link works without a login. Merchants receive USD stablecoins and withdraw to a bank account with a payout quote.

## Methodology and sources

External facts: [Baymard's cart abandonment research](https://baymard.com/lists/cart-abandonment-rate) (updated September 22, 2025), [Stripe's payment localization guide](https://stripe.com/resources/more/payment-localization-best-practices-a-guide-for-scaling-payments-worldwide), [Banco de México on SPEI](https://www.banxico.org.mx/services/interbanking-electronic-payme.html), and [PSE](https://www.pse.com.co/persona). BlindPay facts come from the [payins](/docs/payins), [payin quotes](/docs/payin-quotes), and [webhooks](/docs/learn/webhooks) docs.

## What to do next

Sketch the instructions screen for your top two rails, with one primary value and a copy button each. Then create a test payin in a BlindPay development instance with the [payin quickstart](/docs/quickstart-payin) and map every status in the response to a screen.
