If you're building fintech products for Brazil, you're entering one of the most exciting — and complex — payment ecosystems in the world. Pix processed over R$17 trillion in 2023. Credit card installments are a cultural institution. Boleto bancário refuses to die. And the Central Bank keeps launching new features that reshape the landscape every few months.
At Mind Group Technologies, we've built payment systems for fintech clients across Brazil since 2016. From processing Pix payments in real-time to handling credit card installments across multiple acquirers, we've learned that Brazilian payments are a world unto themselves.
Here's the practical guide I wish someone had given me when we started.
Understanding the Brazilian Payment Landscape
Pix: The Game Changer
Pix launched in November 2020 and fundamentally changed how Brazilians move money. Within three years, it became the most-used payment method in the country. The numbers are staggering:
- 150+ million registered Pix keys
- R$17+ trillion processed in 2023
- Average transaction time: 3-10 seconds
- Available: 24/7/365, including holidays
- Cost to merchants: Free for individuals, near-zero for businesses
For developers, Pix is accessed through the banking APIs of authorized Payment Service Providers (PSPs). The Central Bank defines the standard, but each PSP implements it slightly differently.
// Simplified Pix payment flow
async function createPixPayment(amount, description, tenantId) {
// 1. Generate a unique transaction ID
const txId = generateTxId(); // Max 35 chars, alphanumeric
// 2. Create the charge via PSP API
const charge = await pspClient.createCharge({
calendario: { expiracao: 3600 }, // 1 hour expiration
devedor: { cpf: customerCPF, nome: customerName },
valor: { original: amount.toFixed(2) },
chave: merchantPixKey, // Merchant's Pix key
solicitacaoPagador: description,
infoAdicionais: [
{ nome: 'tenant_id', valor: tenantId },
{ nome: 'order_id', valor: orderId }
]
});
// 3. Generate QR Code
const qrCode = await pspClient.generateQRCode(charge.loc.id);
return {
txId,
qrCodeImage: qrCode.imagemQrcode, // Base64 PNG
qrCodePayload: qrCode.qrcode, // Copy-paste string
expiresAt: new Date(Date.now() + 3600000)
};
}
Critical implementation detail: Pix confirmations come via webhooks. You MUST implement idempotent webhook handlers because the Central Bank may send duplicate notifications.
// Idempotent Pix webhook handler
async function handlePixWebhook(payload) {
const { txid, valor, horario } = payload.pix[0];
// Check if already processed (idempotency)
const existing = await db.query(
'SELECT id FROM pix_transactions WHERE txid = $1',
[txid]
);
if (existing.rows.length > 0) {
return { status: 'already_processed' };
}
// Process within a transaction
await db.transaction(async (trx) => {
await trx.query(
'INSERT INTO pix_transactions (txid, amount, timestamp) VALUES ($1, $2, $3)',
[txid, valor.original, horario]
);
await trx.query(
'UPDATE orders SET payment_status = $1 WHERE pix_txid = $2',
['confirmed', txid]
);
});
// Notify customer in real-time
await notifyPaymentConfirmed(txid);
return { status: 'processed' };
}
Credit Card Installments (Parcelamento)
This is where Brazilian payments get uniquely complex. In most countries, you charge a credit card once. In Brazil, customers expect to split purchases into monthly installments — and they get upset if you don't offer it.
There are two types:
- Parcelamento sem juros (interest-free installments): The merchant absorbs the cost. The customer pays R$100 in 3x of R$33.33.
- Parcelamento com juros (installments with interest): The customer pays interest. R$100 becomes 3x of R$35.50.
// Calculate installment options
function calculateInstallments(totalAmount, maxInstallments = 12) {
const options = [];
for (let i = 1; i <= maxInstallments; i++) {
if (i === 1) {
options.push({
installments: 1,
installmentAmount: totalAmount,
totalAmount: totalAmount,
interestFree: true,
label: `1x de R$ ${totalAmount.toFixed(2)} (à vista)`
});
} else if (i <= 3) {
// Interest-free up to 3x (merchant absorbs MDR)
const installmentAmount = totalAmount / i;
options.push({
installments: i,
installmentAmount: installmentAmount,
totalAmount: totalAmount,
interestFree: true,
label: `${i}x de R$ ${installmentAmount.toFixed(2)} sem juros`
});
} else {
// With interest (typically 1.99% per month)
const monthlyRate = 0.0199;
const installmentAmount = totalAmount *
(monthlyRate * Math.pow(1 + monthlyRate, i)) /
(Math.pow(1 + monthlyRate, i) - 1);
const totalWithInterest = installmentAmount * i;
options.push({
installments: i,
installmentAmount: installmentAmount,
totalAmount: totalWithInterest,
interestFree: false,
label: `${i}x de R$ ${installmentAmount.toFixed(2)} (total: R$ ${totalWithInterest.toFixed(2)})`
});
}
}
return options;
}
Business consideration: The number of interest-free installments you offer directly impacts your conversion rate. Offering 3x sem juros is nearly standard in Brazilian e-commerce. Offering 6x or 12x sem juros can increase conversion 20-40% but eats into your margins.
Boleto Bancário: The Undead Payment Method
Boleto is a uniquely Brazilian payment slip that can be paid at any bank, lottery house, or through banking apps. It's been "dying" for a decade but still processes billions in transactions because:
- ~30 million Brazilians don't have credit cards
- Businesses use it for B2B transactions
- Some customers prefer it for large purchases
// Generate a boleto
async function generateBoleto(amount, customer, dueDate) {
const boleto = await boletoProvider.create({
amount: amount,
dueDate: dueDate,
customer: {
name: customer.name,
cpf: customer.cpf,
address: customer.address
},
instructions: [
'Não receber após o vencimento',
'Multa de 2% após vencimento'
],
fine: { percentage: 2.0 }, // Late fee
interest: { percentage: 1.0 } // Monthly interest on late payment
});
return {
barcode: boleto.barcode,
digitableLine: boleto.digitableLine, // Typeable line
pdfUrl: boleto.pdfUrl,
dueDate: dueDate,
// Important: boletos take 1-3 business days to confirm
expectedConfirmation: addBusinessDays(new Date(), 3)
};
}
Key difference from other methods: Boleto confirmation is NOT real-time. It can take 1-3 business days. Your system needs to handle this async flow gracefully — hold the order, send reminders, and handle expiration.
Building a Multi-Method Payment Service
At Mind Group, we built a payment abstraction layer that handles all Brazilian payment methods through a unified interface. Here's the architecture:
┌──────────────────────────────────────────┐
│ Payment Gateway Service │
│ │
│ ┌──────────────────────────────────┐ │
│ │ Unified Payment Interface │ │
│ │ createPayment(method, amount) │ │
│ │ getStatus(paymentId) │ │
│ │ refund(paymentId, amount) │ │
│ └──────────────────────────────────┘ │
│ │ │ │ │
│ ┌────────┤ ┌───────┤ ┌─────┤ │
│ ▼ ▼ ▼ ▼ ▼ ▼ │
│ ┌────┐ ┌────┐ ┌──────┐ ┌──────┐ │
│ │Pix │ │Card│ │Boleto│ │Wallet│ │
│ │Adpt│ │Adpt│ │Adapt │ │Adapt │ │
│ └────┘ └────┘ └──────┘ └──────┘ │
│ │ │ │ │ │
├───┼──────┼───────┼────────┼──────────────┤
│ ▼ ▼ ▼ ▼ │
│ PSP Acquirer Bank Digital │
│ API API API Wallet │
└──────────────────────────────────────────┘
Each adapter implements the same interface but handles the specifics of each payment method. This means our application code doesn't need to know whether a customer is paying with Pix or credit card — the payment service handles the differences.
Handling Multiple Acquirers
In Brazil, it's common to work with multiple credit card acquirers (Cielo, Rede, Stone, PagSeguro) for redundancy and better rates. We implemented an intelligent routing system:
// Acquirer routing logic
async function routeCardPayment(payment) {
const { amount, cardBrand, installments, tenantId } = payment;
// Get tenant's acquirer configuration
const config = await getTenantPaymentConfig(tenantId);
// Score each available acquirer
const scores = config.acquirers.map(acquirer => ({
acquirer,
score: calculateScore(acquirer, {
// Lower MDR = better score
mdr: acquirer.rates[cardBrand]?.[installments] || 999,
// Higher uptime = better score
uptime: acquirer.metrics.uptime30d,
// Lower latency = better score
latency: acquirer.metrics.avgLatencyMs,
// Current success rate matters
successRate: acquirer.metrics.successRate24h
})
}));
// Sort by score, try best first with fallback
const sorted = scores.sort((a, b) => b.score - a.score);
for (const { acquirer } of sorted) {
try {
const result = await acquirer.processPayment(payment);
return result;
} catch (error) {
logger.warn(`Acquirer ${acquirer.name} failed, trying next`, error);
continue;
}
}
throw new PaymentError('All acquirers failed');
}
Compliance: What You Can't Ignore
LGPD (Brazil's GDPR)
Financial data is the most sensitive category under LGPD. Requirements:
- Explicit consent for data collection and processing
- Data minimization — only collect what you need
- Right to deletion — customers can request data removal
- Breach notification — 72 hours to notify the authority (ANPD)
- DPO requirement — you need a Data Protection Officer
Central Bank Regulations
If you're processing payments, you need to comply with Central Bank of Brazil (BCB) regulations:
- Resolution 4,658: Cloud computing requirements for financial institutions
- Circular 3,978: Anti-money laundering (PLD/FT) requirements
- PIX regulations: Specific rules for Pix participants
PCI DSS
If you handle credit card data, PCI compliance is mandatory. Our recommendation: use tokenization through your acquirer's vault. Never store raw card numbers.
// NEVER do this
const payment = {
cardNumber: '4111111111111111', // RAW CARD NUMBER - VIOLATION
cvv: '123'
};
// DO this instead - tokenize through the acquirer
const token = await acquirer.tokenize({
encryptedCard: rsaEncrypt(cardData, acquirerPublicKey)
});
// Store and reuse the token
const payment = {
cardToken: token.id, // Safe to store
acquirerId: 'cielo'
};
Pix Innovations to Watch
The Central Bank keeps evolving Pix with new features that create opportunities for developers:
- Pix Automático (automatic recurring Pix) — subscription billing without credit cards
- Pix por Aproximação (contactless Pix) — NFC payments at physical stores
- Pix Garantido (guaranteed Pix) — installment payments via Pix, potentially replacing credit card parcelamento
- Pix Internacional — cross-border Pix payments
Each of these creates new integration requirements and business opportunities. At Mind Group, we're already building support for Pix Automático into our multi-tenant payment platform, as it could significantly reduce payment processing costs for our fintech clients.
Practical Tips From the Trenches
After 8+ years building payment systems in Brazil:
Always have a fallback acquirer. Single points of failure in payments cost real money.
Test with real money in sandbox. Brazilian payment sandbox environments are notoriously unreliable. Test with small real transactions before going live.
Handle CPF validation properly. CPF (Brazilian tax ID) is required for most payment methods. Validate the check digits, don't just check length.
Time zone matters. Brazil has multiple time zones and DST rules change. Payment deadlines (especially boleto) must account for this.
Reconciliation is harder than processing. Build automated reconciliation from day one. When you process thousands of transactions across multiple methods and acquirers, manual reconciliation is impossible.
Monitor chargebacks aggressively. Brazil has one of the highest chargeback rates in the world. Implement fraud detection (device fingerprinting, velocity checks, address verification) before you need it.
The Opportunity
Brazil's fintech sector attracted over $3 billion in investment in recent years. The Central Bank is one of the most innovation-friendly regulators in the world. And there are still massive gaps — 30+ million unbanked adults, SMBs struggling with payment infrastructure, and entire sectors that haven't digitized their payment flows.
For developers willing to navigate the complexity, Brazilian fintech is one of the most rewarding spaces to build in. The payment ecosystem is rich, the market is enormous, and the problems are real.
José Gonçalves is the Founder of Mind Group Technologies, a software company in Sorocaba, Brazil, specializing in fintech, healthcare, and SaaS platforms. We've been building payment systems and multi-tenant platforms since 2016. Learn more at mindconsulting.com.br.
Top comments (0)