# India recurring payments

Learn how to update an integration to support RBI e-mandates for cards and UPI.

> While the regulation refers to “recurring” payments, networks treat *any* off-session (that is, merchant-initiated) transaction as in scope, and so do we.

The Reserve Bank of India (RBI) issued a [directive](https://www.rbi.org.in/Scripts/NotificationUser.aspx?Id=11668) (amended subsequently in [December 2020](https://www.rbi.org.in/Scripts/NotificationUser.aspx?Id=12002) and [March 2021](https://www.rbi.org.in/Scripts/NotificationUser.aspx?Id=12051&Mode=0)) that introduces additional security measures for recurring payments on India-issued cards and other payment methods such as [UPI](https://docs.stripe.com/payments/upi.md). These measures include:

- Payment providers need to register customers and create an *e-mandate* (An e-mandate is a form of authorization provided by cardholders to issuing banks that grants permission for recurring payments on their card. Any recurring payment arrangements (for example, monthly subscriptions to OTT services) need an associated e-mandate to be successful. The e-mandate needs to be registered and then validated through AFA, such as 3DS) through a one-time process, using additional factor authentication (AFA) such as *3D Secure (3DS)* (3D Secure (3DS) provides an additional layer of authentication for credit card transactions that protects businesses from liability for fraudulent card payments) for cards or UPI PIN for UPI.
- Customers must be alerted at least 24 hours before charges take place and given the ability to opt out of transactions.
- Recurring transactions over 15,000 INR (or equivalent in other currencies) must go through AFA each time.

If you’re an India-based Stripe user or an international (non-IN) Stripe user, your business is impacted if you have customers who use India cards or UPI for:

- *Off-session* (A payment is described as off-session if it occurs without the direct involvement of the customer, using previously-collected payment information) payments
- Subscriptions or Invoices where the `collection_method` is set to `charge_automatically`

> For UPI-specific recurring payment details including mandate customization options, see [Recurring payments (UPI AutoPay)](https://docs.stripe.com/payments/upi/upi-autopay.md).

## How payments work with an e-mandate 

Stripe has worked with a partner platform to support registering e-mandates and issuing pre-debit notifications to customers. This applies to both card payments and UPI payments.

> We don’t currently offer the use of e-mandates to Stripe users in Mexico.

Depending on how you’ve integrated with Stripe, you might need to send Stripe additional information to set up a mandate. The customer must go through AFA (3DS for cards, or UPI PIN for UPI) to register the mandate.

Subsequent off-session payments or auto-debits for a Subscription undergo a significant change. Customers need to receive a pre-debit notification at least 24 hours before the actual payment with the exact debit amount mentioned. The pre-debit notification contains information about the payment and an option to cancel the mandate. For card payments, if the payment amount is above 15,000 INR or the mandate’s maximum amount, the pre-debit notification contains a link to perform AFA (3DS) to authorize the payment. UPI currently doesn’t support recurring transactions of greater than 15,000 INR in value.

For card payments, because Stripe is integrating with a partner platform, Stripe waits 26 hours before charging the customer after receiving a payment request (Stripe adds a buffer for possible downstream issues, which necessitates the 26-hour advance notification). This means that Stripe delays collecting card payments by 26 hours. For UPI payments, Stripe sends the pre-debit notification and charges the customer 1 day later.

Without a mandate for an off-session payment, the payment will be declined.

## Integration

Stripe doesn’t support e-mandates for India recurring payments with `PaymentIntents` or `SetupIntents`. To manage mandates for recurring payments, use Subscriptions.

> Your account already receives the improved mandate setup and validation behavior described in the [upgrade guide](https://docs.stripe.com/india-recurring-payments.md#upgrade-guide).

### Pre-debit notification  

When the off-session PaymentIntent is [confirmed](https://docs.stripe.com/api/payment_intents/confirm.md), the bank sends the customer the pre-debit notification. The PaymentIntent transitions to a `processing` state for the entire duration of the pre-debit notification period (26 hours) and can’t be canceled.

```json
{
  "object": "payment_intent",
  ...
  "processing": {
    "card": {
      "customer_notification": {
        "approval_requested": true,
        "completes_at": 1677307005
      }
    },
    "type": "card"
  },
  ...
  "status": "processing",
  ...
}
```

If [processing.card.customer_notification.approval_requested](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-processing-card-customer_notification-approval_requested) is `true`, the customer needs to authenticate the payment using the pre-debit notification sent to them by the bank.

The [processing.card.customer_notification.completes_at](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-processing-card-customer_notification-completes_at) attribute specifies the time that Stripe attempts to charge the payment method. If successfully processing the payment requires customer approval, they need to authenticate the payment by the specified time.

### Reasons for inactive mandates  

Mandate objects might be `inactive` at creation (for example, they might lack issuer support). They also might transition to an `inactive` state at a later time (for example, a customer might cancel the mandate). The [payment_method_details.card.india.inactive_reason](https://docs.stripe.com/api/mandates/object.md#mandate_object-payment_method_details-card-india-inactive_reason) field often provides additional details about why this happened (for card mandates).

| Reason | Description |
| --- | --- |
| `issuer_not_supported` | The issuer doesn’t yet support e-mandates. A payment method from a different issuer might succeed. |
| `currency_not_supported` | The issuer doesn’t yet support e-mandates for the given currency. Trying with INR currency instead might succeed. |
| `card_not_supported` | The card issuer doesn’t support the specific card that is used. Another card from the same issuer might succeed. |
| `processing_error` | We encountered a processing error, for instance due to downgraded partner availability. A future attempt might be successful without requiring any changes to parameters or card details. |
| `undetermined` | We encountered an unknown error or couldn’t determine why a mandate is inactivated. Reattempting setup is unlikely to succeed. |
| `canceled` | The customer canceled the mandate. |
| `expired` | The mandate expired. |

### Error and decline codes  

We return [error codes](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-last_payment_error-code) for the following scenarios:

| Error code | Description |
| --- | --- |
| `payment_intent_mandate_invalid` | Attempting a recurring payment using an inactive mandate returns this code. You can prevent this by checking the mandate status before attempting to charge. |
| `india_recurring_payment_mandate_canceled` | Attempting a recurring payment using a canceled mandate returns this code. This can happen when we only learn that a mandate has been canceled at this point. |
| `resource_already_exists` | Duplicate `reference` detection returns this code. |
| `processing_error` | Discovery of a (usually transient) processing error returns this code. |

In the context of e-mandates, certain [decline codes](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-last_payment_error-decline_code) have potentially more specific explanations than [in general scenarios](https://docs.stripe.com/declines/codes.md):

| Decline code | Description |
| --- | --- |
| `transaction_not_approved` | Attempting a subsequent payment when the customer has paused permissions to auto-debit, or doesn’t authenticate the payment when it’s required returns this code. |
| `debit_notification_undelivered` | The issuing bank couldn’t deliver the pre-debit notification to the customer. |

## Testing 

Use the following test card numbers to simulate different card mandate scenarios. Use any future expiration date and any three-digit CVC.

In a *sandbox* (A sandbox is an isolated test environment that allows you to test Stripe functionality in your account without affecting your live integration. Use sandboxes to safely experiment with new features and changes), it takes approximately 15 minutes for an off-session PaymentIntent to transition out of the `processing` state. The on-session PaymentIntent for an initial payment never enters the `processing` state.

#### Card numbers

| Number | Scenario |
| --- | --- |
| 4000003560000123 | Simulates successful mandate setup, pre-debit notification delivery, and renewals. |
| 4000003560000297 | Simulates a customer canceling or pausing an off-session payment after receiving the pre-debit notification. The mandate remains active. |
| 4000003560000248 | Simulates the issuing bank’s failure to send a pre-debit notification to the customer during off-session payment. |
| 4000003560000263 | Simulates a customer canceling a mandate. |

#### PaymentMethods

| PaymentMethod | Scenario |
| --- | --- |
| `pm_card_indiaRecurringMandateSetupAndRenewalsSuccess` | Simulates successful mandate setup, pre-debit notification delivery, and renewals. |
| `pm_card_indiaRecurringPaymentFailureAfterPreDebitNotification` | Simulates a customer canceling or pausing an off-session payment after receiving the pre-debit notification. The mandate remains active. |
| `pm_card_indiaRecurringPaymentFailureUndeliveredDebitNotification` | Simulates the issuing bank’s failure to send a pre-debit notification to the customer during off-session payment. |
| `pm_card_indiaRecurringPaymentFailureCanceledMandate` | Simulates a customer canceling a mandate. |

### Simulate mandate setup failures 

> #### API version requirement
> 
> This simulation is available for API versions `2026-09-30.endive` and later.

To test how your integration handles failed India recurring mandate setup, use test card 4000003560000032 in a sandbox and provide a [billing email](https://docs.stripe.com/api/payment_methods/object.md#payment_method_object-billing_details-email) that matches one of the following patterns. The pattern can have any nonempty domain and, optionally, any prefix.

| Billing email pattern | Inactive reason |
| --- | --- |
| `{prefix}issuer_not_supported@{domain}` | `issuer_not_supported` |
| `{prefix}currency_not_supported@{domain}` | `currency_not_supported` |
| `{prefix}card_not_supported@{domain}` | `card_not_supported` |
| `{prefix}processing_error@{domain}` | `processing_error` |
| `{prefix}undetermined@{domain}` | `undetermined` |
| `{prefix}canceled@{domain}` | `canceled` |
| `{prefix}expired@{domain}` | `expired` |

For example, use `customer_issuer_not_supported@example.com` as the billing email to simulate an `issuer_not_supported` reason. The resulting mandate has an `inactive` status and the selected [inactive_reason](https://docs.stripe.com/api/mandates/object.md#mandate_object-payment_method_details-card-india-inactive_reason). If the billing email doesn’t match one of these patterns, the card follows the normal test mode flow.

## Limitations 

Keep in mind the following limitations:

- Stripe attempts to automatically create mandates only on Subscriptions created after October 1, 2021. If you have a Subscription created before then, cancel and create a new Subscription to make sure a mandate is created.
- You can’t create a mandate using the [Charges](https://docs.stripe.com/api/charges.md) and [Sources](https://docs.stripe.com/api/sources.md) APIs.
- For Subscriptions with a non-INR currency, mandates are only registered if an India payment method is attached to the Customer at the time of subscription creation. If you create a non-INR subscription without a payment method and later add an India card, no mandate is created. To ensure proper mandate creation, attach an India payment method before creating the subscription.
- You can’t pass an existing mandate to a Subscription.
- You can’t cancel or update a mandate.
- UPI currently doesn’t support recurring transactions of greater than 15,000 INR in value.

## Upgrade guide 

### Handle inactive India recurring mandates

When applicable, Stripe now returns a Mandate for an India recurring card payment even if mandate setup fails. The Mandate has an `inactive` status and explains why it’s unusable. Previously, Stripe didn’t create a Mandate in these cases, making a failed setup indistinguishable from a case where no Mandate was expected, such as a non-India-issued card or a payment without off-session future usage.

If your integration uses India e-mandates, update it to check the mandate status before attempting an off-session payment.

### What’s changing 

| Change | Breaking change? |
| --- | --- |
| The [payment_method_details.card.mandate](https://docs.stripe.com/api/charges/object.md#charge_object-payment_method_details-card-mandate) field on a Charge, or the [mandate](https://docs.stripe.com/api/setup_intents/object.md#setup_intent_object-mandate) field on a SetupIntent, is now populated even when the mandate is `inactive`. Previously, it was `null` in this case. | Yes |
| The [payment_method_details.card.india.inactive_reason](https://docs.stripe.com/api/mandates/object.md#mandate_object-payment_method_details-card-india-inactive_reason) field on the mandate explains why an `inactive` card mandate failed. | No, additive |
| Duplicate `reference` validation now rejects references already used by a `pending` mandate, not only an `active` mandate. | Yes |

Two related changes affect how you handle mandate status:

- **Failed mandates no longer remain pending**: A mandate that fails to activate transitions from `pending` to `inactive` and sends a `mandate.updated` event. Your integration might receive more `mandate.updated` events than before.
- **Some failed mandates start as inactive**: If Stripe knows setup failed at creation time, the mandate doesn’t pass through `pending` and no `mandate.updated` event is sent. Check its status instead of waiting for a webhook event.

### Test mandate setup failures

Use the [test card and billing email patterns](https://docs.stripe.com/india-recurring-payments.md#simulate-mandate-setup-failures) to simulate mandate setup failures.

### Upgrade to the new behavior

To receive the new mandate setup failure behavior, use either of these options:

- **Upgrade your API version**: Upgrade to API version `2026-09-30.endive` or later. These versions always use the new behavior, regardless of account settings.
- **Disable the legacy setting**: If your account has the `Preserve legacy mandate registration failure behavior` setting, disable it to use the new behavior on earlier API versions. Disabling the setting applies all of the changes described in [What’s changing](https://docs.stripe.com/india-recurring-payments.md#whats-changing), including stricter duplicate `reference` validation.

You can disable the setting separately for `Live mode` and `Connect live mode` requests. If any of your connected accounts use legacy test mode, you can also disable it separately for `Connect test mode` requests.

To disable the setting:

1. Go to the [Account features](https://dashboard.stripe.com/settings/features) page in the Dashboard.
2. Select **Preserve legacy mandate registration failure behavior**.
3. For each context you want to update, select **Edit**, choose **Disabled**, and then select **Submit**.
4. Confirm that the setting shows `Disabled` for each updated context.
