How to add a "Send to Mexico by SPEI" feature to your neobank app

Build a Send to Mexico by SPEI feature: CLABE check-digit validation, the quote screen, payout, tracking keys, Pix vs SPEI, and CLABEs for receiving.

To add a "Send to Mexico by SPEI" feature, your app collects the recipient's 18-digit CLABE, validates its check digit, saves it as a SPEI bank account, requests a live quote, and executes a payout. BlindPay converts the stablecoins and pays MXN over SPEI through one API, and webhooks tell you when the pesos land.

This guide is the product view: screens, validation, and states. For the business payout mechanics, read how to send USDC to a bank account in Mexico. For the full build, start with how to build a neobank.

Key takeaways

  • A CLABE has a check digit. Validate it on the device and most typos never reach the payout.
  • The first three digits name the bank. Show the bank name, so the user sees where the money goes before sending.
  • Lock the price with a quote and show the MXN amount the recipient gets.
  • SPEI runs 24/7 and gives every payment a tracking key the recipient can look up.
  • From the same API, Mexican users can also get their own CLABE to receive SPEI deposits.

What is SPEI?

SPEI is Mexico's interbank electronic payment system, run by the central bank. Banco de México describes it as a real-time settlement system operating on a 24/7 schedule since 2004.

Its user guide says a SPEI payment should not take more than 30 seconds. The guide also says a payer can address the account by its 18-digit CLABE, a 16-digit debit card number, or a 10-digit phone number, and that a reference number (up to seven digits) and a payment description (up to 40 characters) reach the recipient.

That last detail matters for your app. Use the description to say who sent the money, in words the recipient recognizes.

What is a CLABE, and how is it built?

A CLABE (Clave Bancaria Estandarizada) is the standardized 18-digit account number for Mexican bank accounts. It has four parts:

DigitsPartWhat it tells you
1 to 3Bank codeWhich bank holds the account
4 to 6Branch (plaza) codeThe city or branch area
7 to 17Account numberThe account itself
18Check digitCatches typos in the first 17 digits

The bank code lets you show the bank's name on the confirmation screen. Keep a lookup table of bank codes in your app and refresh it when banks join or merge.

How do you validate a CLABE before sending?

Run four checks on the device, before any API call:

  1. Digits only. Strip spaces and dashes the user pasted.
  2. Exactly 18 digits. Not 16 (that is a card), not 10 (that is a phone).
  3. Known bank code. The first three digits match a bank in your table.
  4. Check digit. Multiply each of the first 17 digits by the weights 3, 7, 1, repeating. Keep only the last digit of each product. Add them. Take the sum modulo 10, subtract from 10, then take modulo 10 again. The result must equal digit 18.

Worked example with the commonly cited sample CLABE 002010077777777771:

Digit00201007777777777
Weight37137137137137137
Last digit of product00207009719719719

The sum is 69. 69 modulo 10 is 9. 10 minus 9 is 1, and 1 modulo 10 is 1. Digit 18 is 1, so the CLABE passes.

A passing check digit means the number is well formed. It doesn't prove the account belongs to the person the user named. That is why the confirmation screen repeats the recipient's name. The guide to verification of payee explains what rails can and can't check.

How do you build the feature step by step?

  1. Verify the sender. Terms of service and KYC, once per user.
  2. Collect the CLABE and name. One numeric input with an 18-digit mask, plus the recipient's full name. Run the four checks as the user types.
  3. Save the recipient. Store it as a SPEI bank account for the customer. The bank accounts docs list the fields: name, protocol, CLABE, and beneficiary name. Debit card and phone protocols also take the institution code.
  4. Request a live quote. The user types USD to send or MXN to arrive. The quote locks rate and fees for 5 minutes (payout quotes).
  5. Confirm and execute. Show recipient name, bank, MXN amount, fee, rate, and a countdown. On confirm, create the payout with an Idempotency-Key header (idempotency).
  6. Track and share proof. Update the transfer from payout webhooks. When it completes, the receipt shows the amount, rate, time, and a reference the recipient can use.

How do Pix and SPEI compare for a neobank feature?

If you built the Pix transfer feature, most of the flow carries over. The differences are in the recipient details and the proof.

Pix (Brazil)SPEI (Mexico)
OperatorBanco Central do BrasilBanco de México
HoursAny time, including non-business days24/7
BlindPay arrivalInstantInstant
How users address the recipientPix key: CPF, CNPJ, phone, email, or random key18-digit CLABE (or debit card, or phone)
Built-in typo checkFormat per key typeCLABE check digit
What to show on confirmRecipient name, masked keyRecipient name, bank from the CLABE
Proof for the recipientEnd-to-end ID in the bank appTracking key and CEP from Banxico
Receiving deposits on BlindPayPix payinsSPEI payins and SPEI CLABE virtual accounts

For the rail-level comparison (returns, references, failure modes), see Pix vs SPEI.

How does the recipient prove the money arrived?

With the CEP. Banco de México's CEP lookup gives an electronic proof of payment for a SPEI transfer. The recipient enters the date, the tracking key or reference, the banks, the receiving account, and the amount.

Put a "Share proof" button on the receipt that copies those fields. It saves a support ticket every time a recipient says "I didn't get it".

Can Mexican users receive SPEI deposits too?

Yes. From October 2026, BlindPay issues SPEI CLABE virtual accounts. Each customer gets a permanent 18-digit CLABE. Anyone with a Mexican bank account can send MXN to it by SPEI, any time and any amount, without a quote first. Each deposit creates a payin at the live MXN rate and settles to the wallet linked to the account.

The account is active as soon as it is created. It is not a named account: payers see a pooled recipient name, which the API returns so you can tell payers what to expect. Details are in the virtual accounts docs.

For a neobank, that closes the loop. A user in Mexico can receive pesos into the app and send pesos out, both over SPEI.

What does one transfer look like?

Illustrative example, with invented numbers. Diego, in Houston, pays a freelance designer in Guadalajara.

  1. Diego taps "Send to Mexico" and types the designer's CLABE. The check digit passes and the app shows the bank name.
  2. He types US$ 300. The quote shows MX$ 5,460.00 arriving, a US$ 3.00 fee, and a 5-minute countdown.
  3. He confirms. The backend creates the payout with an idempotency key and the description "Diego Ruiz invoice 14".
  4. Webhooks move the transfer to completed. Diego shares the proof fields with the designer, who pulls the CEP.

What are the common SPEI mistakes?

  • No check-digit validation. It is a ten-line function and it catches most typos.
  • Accepting 16 digits in the CLABE field. That is a card number. Route it to the debit card protocol or reject it.
  • A vague payment description. The recipient sees it. "Transfer" tells them nothing.
  • Showing only USD. Show the MXN amount from the quote.
  • Executing an expired quote. Requote and show the new numbers.
  • No proof on the receipt. Recipients need the tracking key or reference for the CEP.
  • Assuming deposit accounts carry the user's name. CLABE virtual accounts show a pooled name. Tell payers.

How BlindPay fits

BlindPay gives a neobank one API for Mexico in both directions. Out: add the recipient as a SPEI bank account, request a quote that locks rate and fees for 5 minutes, and execute a payout that BlindPay lists as instant. In: issue a SPEI CLABE virtual account per customer, and every deposit becomes a payin that settles to the linked wallet.

Payouts are funded in USDC or USDT from the wallet you choose, so there is no peso balance to pre-fund. On non-USD local rails like SPEI, 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. KYC and sanctions screening run inside the API. BlindPay is the best fit for a neobank sending stablecoin-funded transfers into Mexico that wants SPEI speed and compliance handled in the same integration. To decide which rails come next, see which payout rails to launch first.

What to do next

Ship the CLABE validator first, it pays off even before payouts go live. Then run one SPEI payout end to end on a development instance with the payout quickstart.

FAQ