Accept UPI and all Indian-issued cards in India with RBI-compliant subscription mandates. Understand the 48-hour processing delay, mandate limits, and webhook handling.
India has unique payment infrastructure dominated by UPI (60%+ of digital transactions) and Indian-issued cards (Visa, Mastercard, Rupay, etc.). Dodo Payments supports all of these with full RBI compliance for subscription mandates.
The amount registered with the customer’s bank is max(mandate_floor, billing_amount). So the floor is effectively the customer-facing authorization ceiling whenever billing is lower than the floor.Important for plan changes: If an upgrade results in a charge exceeding the existing mandate limit, the charge will fail and the customer must re-authorize.
The mandate floor for INR e-mandates is configurable via the mandate_min_amount_inr_paise field (in INR paise — 1 INR = 100 paise). You can override the system default of ₹15,000 at three levels:
Level
Where to set
Scope
Per request
mandate_min_amount_inr_paise on a checkout session, payment, or subscription
One transaction
Merchant
Business settings
All your INR subscriptions
System
—
₹15,000 default
Resolution priority: per-request override → merchant setting → system default.
Indian-card INR subscriptions on non-Airwallex connectors
Setting a higher floor lets you support larger one-off charges later (for example, plan upgrades or usage-based overages) without forcing customers to re-authorize. Setting a lower floor brings the customer’s authorization closer to the actual billing amount but limits headroom for future variable charges.
This setting only affects e-mandates registered for Indian-issued cards (Visa, Mastercard, RuPay) on INR subscriptions. UPI subscriptions follow their own AutoPay flow and are unaffected.
// DON'T do this:async function handleSubscriptionRenewal(subscription) { // ❌ Bad: Granting access immediately when charge is initiated grantPremiumAccess(subscription.customer_id);}// DO this:async function handlePaymentWebhook(event) { if (event.type === 'payment.succeeded') { // ✅ Good: Only grant access after payment is confirmed grantPremiumAccess(event.data.customer_id); } if (event.type === 'payment.failed') { // Handle failed payment (mandate cancelled, insufficient funds) revokePremiumAccess(event.data.customer_id); }}
Build your application to handle the gap between charge initiation and actual payment. Consider:
Grace periods for subscription access
Clear communication to customers about processing time
Webhook-driven fulfillment, not date-driven
Handle mandate cancellations
Customers can cancel mandates via their bank apps at any time. Monitor subscription.on_hold webhooks and prompt customers to re-subscribe or update payment methods.
Set appropriate mandate amounts
For variable pricing (e.g., usage-based), consider whether a Rs 15,000 on-demand mandate is sufficient. If charges might exceed this, customers will need to re-authorize.
Offer UPI prominently
For Indian customers, UPI should be the primary payment option. Many users prefer it over cards due to familiarity and lower friction.
If non-Indian merchant: Adaptive Currency enabled?
upi_collect included in allowed_payment_method_types?
Solution: Verify billing address has country: "IN" and billing_currency: "INR".
Subscription charge failed after upgrade
Cause: New charge amount exceeds existing mandate limit (Rs 15,000 threshold).Solution: Customer must update payment method to establish a new mandate with the correct limit.
Subscription on hold but customer claims they didn't cancel
Cause: Customer may have cancelled the mandate during the 48-hour window, or their bank declined the debit.Solution: Customer needs to re-authorize the mandate or update their payment method.
Payment deduction delayed beyond 48 hours
Cause: Bank API delays can extend processing by 2-3 additional hours.Solution: This is expected. Build your system to handle variable delays up to ~51 hours total.
Mandate cancelled but subscription still active
Cause: Edge case in RBI regulations — mandate cancellation during processing window doesn’t immediately cancel subscription.Solution: The next charge will fail and subscription will move to on_hold. Monitor webhooks for payment.failed.