Sign in
An image of the Stripe logo
Create account
Sign in
Home
Payments
Business operations
Financial services
Developer tools
No-code
All products
Home
Payments
Business operations
Home
Payments
Business operations
Financial services
Developer tools
Support
Overview
Online payments
Products and prices
Invoicing
Subscriptions
Quotes
In-person payments
Multiparty payments
After the payment
Add payment methods
Payment Links
Stripe Checkout
Stripe Elements
About the APIs
Regulation support
    SCA readiness
    India recurring payments
Implementation guides
Testing
HomePayments

India recurring payments

Learn how to update an integration to support RBI e-mandates.

The Reserve Bank of India (RBI) issued a directive (as amended subsequently in December 2020 and March 2021) to the card issuing banks, card networks, and prepaid payment instrument issuers for the processing of e-mandates, that introduce measures to provide additional security measures for card payments. These measures include:

  • Cardholders who want to create an e-mandate must register through additional factor authentication (AFA) using 3D Secure (3DS).
  • Card issuers must alert cardholders at least 24 hours prior to charges taking place and give them the ability to opt out of transactions.
  • In addition to the first registration, recurring transactions over 15,000 Indian rupees (INR)—or the equivalent in other currencies—need to go through AFA each time.

These rules were effective April 1, 2021 for new subscriptions and September 30, 2021 for existing subscriptions. We’ve worked with our financial partners to provide you APIs to enable AFA-compliant recurring transactions on India-issued cards.

Stripe Checkout

If you’re a Stripe Checkout user in India presenting in INR currency or a Stripe Checkout international user (not in India) presenting in INR currency or one of the supported currencies below, Stripe automatically creates a corresponding mandate taking the parameters from the payment plan. In this scenario, mandate creation works as expected.

E-mandates for non-INR currencies

As of January 2023, Stripe supports cross-border e-mandates for recurring payments on cards issued in India for 12 non-INR currencies. These currencies include:

  • USD
  • EUR
  • GPB
  • SGD
  • CAD
  • CHF
  • SEK
  • AED
  • JPY
  • NOK
  • MYR
  • HKD

This functionality is supported only for international (non-IN) merchants.

For Stripe Billing users, Stripe automatically creates e-mandates on the next subscription renewal or new subscription creation. Users that directly integrate with PaymentIntents or SetupIntents can pass any of these currencies along with the mandate parameters to create e-mandates.

Support for non-INR e-mandates is only available for about 75% of Indian card issuers. For issuers that are not supported, Stripe ignores the mandate parameters and won’t generate e-mandates for those payments.

Effect on transactions

First, there’s no change in either the customer flow or the funds flow while setting up recurring payments. Your customer gets redirected to undergo AFA (3DS is one type of AFA) after which the subscription gets activated and funds get settled to your account based on your payout schedule. However, you need to send Stripe some additional information to set up the mandate.

Subsequent payments or auto-debits for subscription renewals undergo a significant change. Users need to receive a pre-debit notification at least 24 hours before the actual charge with the exact debit amount mentioned. The pre-debit notification contains information about the subscription and an option to cancel the subscription. If the recurring amount of the subscription is above 15000 INR, the pre-debit notification contains a link to undergo AFA for authorizing the transaction.

Because Stripe is integrating with a partner platform, we wait 72 hours before charging the customer after receiving a payment request for a renewal (we add a buffer for possible downstream issues, which necessitates the 72 hours advance notification). This means that Stripe delays collecting payment for renewals by 3 days, and we schedule your payouts accordingly.

After migrating to the new AFA compliant APIs, you must create mandates for all of your existing subscriptions to avoid card declines. As part of this process, you must bring your customers on-session and go through an AFA flow.

India cardholders and recurring payments

To support India cardholder recurring payments:

  1. Determine if your business is impacted:

    • You process off-session payments paid with cards issued by Indian banks. Off-session payments include recurring transactions, subscriptions, and payments where the user isn’t present (on your website or application) at the time of payment authorization.
  2. Decide which one of the India recurring-ready products is right for your business.

  3. If required, make changes to your integration to avoid declined recurring payments.

Impact on Subscriptions

If you’re a Stripe Subscriptions user, learn how the RBI regulations affect you.

Subscription creation

The RBI regulations impact the creation of subscriptions. Specifically, it affects subscriptions that are set to automatically charge (charge_automatically) India-issued cards. For these types of subscriptions, Stripe handles the internal logic eliminating the need to pass in extra parameters when you create a subscription. To create a new subscription, see Build a subscriptions integration.

Subscription updates

With the RBI regulations in place, you can’t:

  • Update the subscription renewal amount for a fixed price subscription (amount_type=fixed or amount_type=maximum).
  • Update the default payment method used for the subscription.
  • Update the renewal frequency of the subscription.

To perform any of the aforementioned updates to an existing subscription, Stripe recommends that you cancel the original subscription and create a new one.

Subscription migration

You can’t migrate any subscriptions that you created before October 1, 2021 unless they have a mandate that’s registered in compliance with the new regulation. You need to bring the user on-session to re-register the subscription. However, you don’t need to change the renewal date for your end user. The suggested (and non-disruptive way) to do this is to piggyback on subscription’s renewal date.

Impact on other products

If you use the PaymentIntents or SetupIntents APIs to directly create recurring payments, you must update your integration.

Create a mandate

The following diagram shows the mandate creation flow:

The mandate creation flow

Per the RBI regulation, when you set up a new subscription, you need to register a mandate. To facilitate the creation of a mandate, populate the following parameters on the PaymentIntent or SetupIntent objects (in addition to the existing parameters).

ParameterRequiredDescription
payment_method_options[card][mandate_options][reference]YesUnique identifier for the mandate or subscription.
payment_method_options[card][mandate_options][description]NoA description of the mandate or subscription that is meant to be displayed to the customer. If not passed, Stripe populates it with {merchant_name} - {reference}.
payment_method_options[card][mandate_options][amount_type]YesOne of fixed, maximum. If fixed, the amount parameter refers to the exact amount to be charged in future payments. If maximum, the amount charged can be up to the value passed for the amount parameter.
payment_method_options[card][mandate_options][amount]YesAmount to be charged for future payments.
payment_method_options[card][mandate_options][start_date]YesStart date of the mandate or subscription, specified as the epoch timestamp. Start date must be later than yesterday.
payment_method_options[card][mandate_options][end_date]NoEnd date of the mandate or subscription, specified as the epoch timestamp. If not provided, the mandate remains active until canceled.
payment_method_options[card][mandate_options][interval]YesSpecifies payment frequency. One of day, week, month, year, sporadic
payment_method_options[card][mandate_options][interval_count]NoThe number of intervals between payments. For example, interval=month and interval_count=3 indicates one payment every three months. Intervals have a maximum of one year (1 year, 12 months, or 52 weeks). This parameter is optional only when interval=sporadic.
payment_method_options[card][mandate_options][supported_types]YesAn array specifying the mandate types supported for this payment. Possible values are [‘india’]

Learn how to create a mandate using a PaymentIntent or SetupIntent:

Command Line
curl https://api.stripe.com/v1/payment_intents \ -u
sk_test_4eC39HqLyjWDarjtT1zdp7dc
: \ -d amount=1099 \ -d currency=inr \ -d customer=
{{CUSTOMER_ID}}
\ -d confirm=true \ -d setup_future_usage=off_session \ -d "payment_method_types[]"=card \ -d payment_method=
{{PAYMENT_METHOD_ID}}
\ -d "payment_method_options[card][mandate_options][reference]"="{{REFERENCE}}" \ -d "payment_method_options[card][mandate_options][description]"="{{DESCRIPTION}}" \ -d "payment_method_options[card][mandate_options][amount]"=1099 \ -d "payment_method_options[card][mandate_options][start_date]"=1675238400 \ -d "payment_method_options[card][mandate_options][end_date]"=1738396800 \ -d "payment_method_options[card][mandate_options][amount_type]"=fixed \ -d "payment_method_options[card][mandate_options][interval]"=month \ -d "payment_method_options[card][mandate_options][interval_count]"=1 \ -d "payment_method_options[card][mandate_options][supported_types][]"=india

Confirming the PaymentIntent transitions it to a requires_action state with the next_action property describing what action needs to be taken for completing the payment.

{ "payment_method_options": { "card" : { "mandate_options" : { "reference" : "{{REFRENCE}}", "description" : "{{DESCRIPTION}}", "amount" : "{{AMOUNT}}", "type" : "{{AMOUNT_TYPE}}", "start_date" : "{{START_DATE}}", "end_date" : "{{END_DATE}}", "interval" : "{{INTERVAL}}", "interval_count" : "{{INTERVAL_COUNT}}" } } }, "status": "requires_action", "next_action": { "type": "use_stripe_sdk", "use_stripe_sdk": { "type": "three_d_secure_redirect", "stripe_js": "https://hooks.stripe.com/redirect/authenticate/src_xxxxxxxxxxx", "source": "src_xxxxxxxx" } }, // Other existing PaymentIntent params }

Upon the successful completion of AFA (3DS) by the cardholder, the PaymentIntent transitions to a succeeded state and a mandate is created. The mandate is available on the PaymentIntent object.

{ "payment_method_options": { "card" : { "mandate_options" : { "india": { "reference" : "{{REFRENCE}}", "description" : "{{DESCRIPTION}}", "amount" : "{{AMOUNT}}", "type" : "{{AMOUNT_TYPE}}", "start_date" : "{{START_DATE}}", "end_date" : "{{END_DATE}}", "interval" : "{{INTERVAL}}", "interval_count" : "{{INTERVAL_COUNT}}" } } } }, "charges": { "object": "list", "data": [ { "id": "{{CHARGE_ID}}", "object": "charge", "amount": 1099, "currency": "inr", "payment_method_details": { "card": { "mandate": "{{MANDATE_ID}}" // id of the mandate created by the charge }, }, "status": "succeeded", } ], "has_more": false, "url": "/v1/charges?payment_intent={{PAYMENT_INTENT_ID}}" }, "status": "succeeded", // Other existing PaymentIntent parameters }

Off-session and recurring charges

Learn about off-session and recurring charges.

Trigger pre-debit notification

The following diagrams show how pre-debit notifications are triggered for off-session and recurring charges:

Recurring payment amount less than INR 15000

Recurring payment equal to or greater than INR 15000

The regulation requires that a pre-debit notification be sent by the card issuer to the customer at least 24 hours prior to attempting a charge. To initiate the pre-debit notification, you need to confirm a PaymentIntent with off_session=true and specify the mandate to use for this recurring payment.

Command Line
curl https://api.stripe.com/v1/payment_intents \ -u
sk_test_4eC39HqLyjWDarjtT1zdp7dc
: \ -d amount=1099 \ -d currency=inr \ -d customer=
{{CUSTOMER_ID}}
\ -d confirm=true \ -d "payment_method_types[]"=card \ -d payment_method=
{{PAYMENT_METHOD_ID}}
\ -d mandate=
{{MANDATE_ID}}
\ -d off_session=true

Upon confirmation, the issuing bank sends a pre-debit notification to the customer and the PaymentIntent transitions to a processing state for a duration of 72 hours.

{ "object": "payment_intent", "amount": 1099, "mandate": "{{MANDATE_ID}}", "payment_method_types": [ "card" ], "status": "processing", "processing": { "type": "card", "card": { "customer_notification": { "approval_requested": "{{APPROVAL_REQUESTED}}", "completes_at": "{{COMPLETES_AT}}" } } }, // Other existing PaymentIntent params }

The processing attribute on the PaymentIntent provides details on the state of the payment.

processing.card.customer_notification

processing.card.customer_notification.approval_requested—If this property is set to true, the customer needs to authenticate the payment using the pre-debit notification sent to them by their card-issuing bank. You can send this notification to your customers informing them of the action they need to take.

processing.card.customer_notification.completes_at—Specifies the time that the authorization for the payment is going be attempted. If customer approval is required for successfully processing the payment, your customer needs to act on the pre-debit notification by the specified time.

After the time specified by the processing.card.customer_notification.completes_at parameter passes, the charge is attempted and the final status of the payment is notified using a webhook.

Webhooks

Stripe creates the Mandates object (returned as part of the mandate setup) in the pending state. When the mandate transitions to an active state (approximately 60-90 seconds), a mandate.updated webhook is emitted. If the user cancels the mandate during a recurring payment, Stripe emits a mandate.updated webhook that indicates it’s canceled. For more information on receiving webhooks, see Steps to receive webhooks.

Cancel a payment

You can’t cancel a PaymentIntent while it’s processing. PaymentIntents are in a processing state for the entire duration of the pre-debit notification period (72 hours).

Limitations

  • The Charges and Sources APIs are unavailable for recurring payments. If you want to use recurring payments, you must use the PaymentIntent or SetupIntent APIs.

  • Currently, all issuing banks only support INR for subscriptions.

  • Updates to existing mandates aren’t supported at this time. If an update to your subscription invalidates its mandate, you must cancel the existing subscription and create a new one.

Consider setting up a variable amount or an ad-hoc subscription frequency to perform dynamic updates of a mandate. Let’s say, for example, your subscription charges 1000 INR and you know you’re going to update it to 2000 INR in the future. In this case, when you create the subscription, pass in amount_type=maximum and amount=200000 (amount is in paise) to ensure a valid mandate for both the original and updated subscriptions.

Test your mandate setup

You can use these unique test card numbers to simulate different test scenarios related to mandate setup. For each test scenario, the table shows the final statuses and errors returned by the Payment Intents API.

In testmode, it takes recurring payments approximately 15 minutes to transition out of the processing state instead of the 72 hours in livemode.

As of October of 2022, Stripe has stopped supporting 3D Secure 1, except for IN accounts. If you have a non-IN account, you must update your test mode integration to use 3D Secure 2.

Test card numberScenario
Simulates successful mandate setup and renewals.
Simulates a cardholder receiving a pre-debit notification for a recurring payment and choosing to either cancel or pause the payment for a mandate of any amount.
Simulates the issuing bank’s failure to send a pre-debit notification to the cardholder during recurring payment for a mandate of any amount.
Simulates a cardholder canceling a mandate of any amount.
Was this page helpful?
Questions? Contact us.
Watch our developer tutorials.
Check out our product changelog.
Powered by Markdoc
You can unsubscribe at any time. Read our privacy policy.
On this page
Effect on transactions
Impact on Subscriptions
Impact on other products
Test your mandate setup
Stripe Shell
Test mode
Welcome to the Stripe Shell! Stripe Shell is a browser-based shell with the Stripe CLI pre-installed. Login to your Stripe account and press Control + Backtick on your keyboard to start managing your Stripe resources in test mode. - View supported Stripe commands: - Find webhook events: - Listen for webhook events: - Call Stripe APIs: stripe [api resource] [operation] (e.g. )
The Stripe Shell is best experienced on desktop.
$