Integrating Peruvian Payment Rails: Yape, PagoEfectivo, and Beyond
A developer's guide to connecting with Peru's most popular payment methods. Technical patterns, common pitfalls, and lessons from our integrations.
The Peruvian Payment Landscape
Peru has one of the most interesting payment ecosystems in Latin America. While bank penetration is relatively low, mobile payment adoption has exploded—particularly with Yape, which has over 12 million users.
For fintech builders, this presents both opportunity and complexity.
Key Payment Methods
Yape (BCP)
- Peru's dominant P2P payment app
- Linked to phone numbers
- Instant transfers within the Yape network
- API access requires partnership with BCP
PagoEfectivo
- Cash payment network
- Users receive a code, pay at physical locations
- Settlement typically T+1
- Good API documentation
Interbank transfers (CCI)
- Standard bank transfers
- Works across all Peruvian banks
- Slower but widely accepted
Integration Patterns
1. Aggregate through a PSP
The simplest approach is to work with a payment service provider that aggregates multiple methods. Niubiz and Culqi are popular options. You get one integration, multiple payment methods.
2. Direct integrations
For higher volume or specific needs, direct integrations give you more control. But each method has its own:
- Authentication flow
- Webhook format
- Reconciliation process
- Error handling requirements
3. Hybrid approach
We typically recommend starting with a PSP, then adding direct integrations for your highest-volume methods as you scale.
Common Pitfalls
- Yape timeouts: The API can be slow during peak hours. Build generous timeouts and retry logic.
- PagoEfectivo expiration: Codes expire. Make sure your UX handles expired payments gracefully.
- Reconciliation gaps: Different providers have different settlement schedules. Your accounting needs to handle this.
Our Architecture
For our wallet product, we built an abstraction layer that normalizes different payment providers. Each provider is a plugin that implements a common interface:
interface PaymentProvider {
createPayment(amount: number, currency: string): Promise<PaymentIntent>
checkStatus(paymentId: string): Promise<PaymentStatus>
handleWebhook(payload: unknown): Promise<void>
}
This lets us add new providers without changing our core payment logic.
Building payment integrations in Peru? We can help.
