Where AgriLokal was building a business from nothing, Zupee is the opposite problem: an existing payment stack, wallet, KYC, routing across PSPs, that has to stay trustworthy at a size where every edge case is a real user's money.
Every point of friction in a payments flow, KYC, retry logic, routing, a withdrawal status screen, costs either a deposit or a user's trust, and at Zupee's scale, both are measured in real money.
Went after five separate friction points across the deposit and withdrawal lifecycle: personalized deposit widgets, an Aadhaar-first KYC redesign, QR/PineLabs/QuickPay rollout, SR-based dynamic payment routing, and a high-value withdrawal status screen.
+2.37% average deposit, +11pp Aadhaar conversion, -21% failed payment attempts, -15% high-value withdrawal drop-off.
Deposits, KYC, and withdrawals each had their own friction point: generic (non-personalized) deposit prompts, a KYC flow with high fallback usage, limited QR/UPI coverage, static payment-mode ordering that didn't adapt to real-time success rates, and a withdrawal status screen that quietly lost users right after they'd won.
Useful to see the whole path before the rest of this makes sense: a user's tap doesn't go straight to a bank, it passes through several hops, and Zupee's own systems sit specifically at the routing and reconciliation layer, not inside the banks themselves.
Deposit personalization started from wallet balance and entry-fee pattern data per user, not a single generic prompt. Separately, KYC fallback usage (users dropping to a slower manual path) was traced to specific friction points in the existing Aadhaar flow, and payment failures were traced by success-rate (SR) band per mode, not just an aggregate failure count.
A fixed payment-mode order works until a specific mode's success rate degrades, at which point every user routed to it inherits that failure, regardless of their own history. Aadhaar-first KYC only converts well if the fallback path is rare, not a default users end up on. Both point at the same fix pattern: make the system respond to live signal instead of a fixed configuration.
If deposit prompts adapted to individual wallet/entry-fee behavior, if KYC reduced reliance on fallback through voice-led guidance, and if payment routing responded to real-time success rate instead of a static order, deposit completion and payment success would both improve without adding friction anywhere else.
Shipped first-time-deposit widgets personalized by each user's wallet balance and entry-fee trends, rather than a single generic deposit prompt. Result: average deposit +2.37%.
QR / Pine Labs / QuickPay: rolled out QR-based UPI flows to 30% of new users, integrated Pine Labs, and built QuickPay, a 1-click last-used-mode reuse flow with downtime-aware fallbacks, to streamline repeat payments specifically.
That year, government regulation made KYC mandatory, and Zupee's user base skewed heavily toward tier 2, 3, and 4 cities, where comfort with a text-heavy upload flow couldn't be assumed. Redesigned KYC to be Aadhaar-first, with both visual and audio cues at each step, and voice-led onboarding as a primary path rather than an accessibility afterthought, specifically to reduce how often users dropped into the slower manual fallback path. Result: Aadhaar conversion +11pp.
A static payment-mode order is simple to reason about and simple to debug. Dynamic, SR-based reordering is more resilient but means the "why did this user see this payment mode" question no longer has a fixed answer, every routing decision now depends on a live, changing signal. That's a real cost in debuggability traded for a real gain in success rate.
Banks and PSPs go down without warning, and a fixed payment-mode order has no way to react. Built success-rate-based fallback logic with three tiers, color-coded so the pattern is instantly legible: Critical (0–25% SR, red), Poor (26–50% SR, orange), Good (51–75% SR, green). A bank or PSP sliding into red gets dynamically deprioritized in real time, and the next-healthiest option moves to the top, instead of users continuing to be routed into a mode that's currently failing.
This ran specifically against a curated set of Zupee's top 10 banks, prioritized because we already had enough historical success-rate and downtime data on them to make the live scoring meaningful, rather than trying to score every possible bank with thin data.
Recommended payment method: alongside live routing, the system also looked at whether a user had paid with a specific UPI ID or VPA in roughly the last 3-6 months, and surfaced that as a "recommended" option. Live bank health decides what's safe to route to; recent personal usage decides what's fastest for that specific user, the two run together rather than one replacing the other.
Their own recently-used UPI ID shows up as "recommended," and whichever bank is healthiest right now is what they're routed to, without ever seeing a bank that's currently down.
Continuously recalculated each of the top-10 banks' live success rate, bucketed it red/orange/green, re-ordered routing accordingly, and separately checked the user's own 3-6 month payment history for a personalized recommendation.
A fixed order is a bet that today's best bank stays the best bank. That bet breaks exactly when a bank has unscheduled downtime, which is precisely when you can least afford it, and the color coding existed so the whole team, not just whoever built it, could reason about system health instantly.
Withdrawal, built for trust with power users: for users depositing over Rs.5k-10k, a slow or unclear withdrawal does more damage to trust than almost anything else, a win that's hard to cash out reads as a product that doesn't want to pay you. Revamped the high-value withdrawal status screen with animations and trust messaging, added a "maximize" button that auto-fills the maximum withdrawable amount in one tap, and an inline flow to switch to an alternate account if the primary one hit an issue, rather than leaving the user stuck. Result: drop-offs down 15% at exactly the moment users had the most reason to worry about their money.
| Initiative | Metric | Result |
|---|---|---|
| Personalized FTD widgets | Average deposit | +2.37% |
| Aadhaar-first KYC redesign | Aadhaar conversion | +11pp |
| QR / Pine Labs / QuickPay | New-user QR coverage | 30% |
| SR-based 3-tier routing | Failed payment attempts | −21% |
| Withdrawal status screen | High-value drop-off (>Rs.10k) | −15% |
Personalization, KYC, routing, and the withdrawal screen look like five unrelated tickets. They're the same problem in five places: a system that treated every user and every payment mode identically, when the underlying reality (wallet behavior, KYC readiness, gateway health) was never actually uniform. Once framed that way, "which fix next" stopped being a prioritization guess and became a search for the next place the system was still assuming uniformity that didn't exist.
Extend SR-based routing with per-user history, not just per-mode aggregate health.
Predict gateway degradation before it crosses into the Critical tier, instead of reacting once it does.
Extend the withdrawal trust-messaging pattern to more transaction types, not just high-value withdrawals.
Reduce Aadhaar fallback further by identifying exactly which user segments still default to it.