India e-Mandates allow you to collect a one-time payment authorization from Indian customers, enabling recurring or sporadic charges without requiring the customer to be present for each transaction. This is a requirement from the Reserve Bank of India (RBI) for recurring card payments, and Stripe supports this through their SetupIntent API with India-specific mandate options (docs).
When an e-Mandate is properly configured in Stripe and linked to an Orb customer, Orb can automatically charge the customer’s default payment method when issuing invoices — just like any other Stripe payment method.
Why e-Mandates require extra setup
Unlike standard card payments, India e-Mandates require the merchant to explicitly create a mandate with specific parameters (amount cap, interval, start date) as part of the payment method setup. This means you cannot simply attach a card to a Stripe customer — you must go through the SetupIntent flow with mandate_options configured for India.
This additional step is often a source of confusion during testing, since there is no way to create an India e-Mandate directly from the Stripe dashboard. You must use the Stripe API (or a frontend integration with Stripe Elements) to collect the mandate.
Prerequisites
All testing should be done in Stripe test mode and Orb test mode. Using live mode keys during testing can result in real charges to customers. In Orb, ensure you are operating in your test environment before connecting Stripe or creating customers.
Before setting up an India e-Mandate, ensure the following:
How it works
The e-Mandate collection flow involves three steps:
- Create a SetupIntent with India-specific mandate options via the Stripe API
- Collect the card details from the customer using Stripe Elements on the frontend
- Set the payment method as default on the Stripe customer so Orb can use it for auto-collection
SetupIntent mandate options
When creating a SetupIntent for an India e-Mandate, you must include mandate_options under payment_method_options.card. The key parameters are:
| Parameter | Description |
|---|
reference | A unique identifier for the mandate (e.g., combining the customer ID and a timestamp) |
amount | The maximum amount that can be charged per interval, in the smallest currency unit |
amount_type | Set to "maximum" to define a cap on the charge amount |
currency | The currency for the mandate (e.g., "inr") |
interval | How often charges can occur — "sporadic" for on-demand or "monthly" for regular billing |
start_date | Unix timestamp for when the mandate becomes active |
supported_types | Must include "india" to indicate this is an India-specific mandate |
The SetupIntent should also specify usage: "off_session" to indicate that the payment method will be used for charges when the customer is not present.
The amount field represents the maximum amount that can be charged per transaction, not a fixed charge amount. Set this to a value that accommodates your highest expected invoice amount for the customer.
Confirming the SetupIntent
On the frontend, use Stripe Elements to render a payment form and collect the customer’s card details. When the customer submits the form, confirm the SetupIntent using stripe.confirmSetup(). Stripe handles the mandate authorization as part of this confirmation step.
Setting the default payment method
After the SetupIntent is confirmed, the resulting payment method must be set as the customer’s default in Stripe:
await stripe.customers.update(customerId, {
invoice_settings: { default_payment_method: paymentMethodId },
});
This ensures that Orb will use this payment method when auto-collecting invoices.
Testing with the example application
We provide a reference implementation that demonstrates the full e-Mandate collection flow using a Node.js/Express backend and a Stripe Elements frontend.
Setup
Please follow the instructions in the reference implementation to set up the example application.
Test card details
Use the following Stripe test card to simulate an India e-Mandate:
| Field | Value |
|---|
| Card number | 4000003560000123 |
| Expiry | Any future date |
| CVC | Any 3 digits |
| Postal code | Any 5 digits |
What to expect
After submitting the form with the test card:
- The SetupIntent is confirmed and the mandate is created in Stripe
- The payment method is set as the customer’s default
- Approximately one minute later, a
mandate.updated webhook event fires (visible in the Stripe developers tab)
- The payment method appears under “Payment methods” in the customer’s Stripe dashboard page
The example application uses a simple implementation that generates a unique mandate reference on server startup. You will need to restart the server (Ctrl+C then node server.js) between mandate setups.
Connecting to Orb
Once the e-Mandate is set up and the payment method is the customer’s default in Stripe, connect it to Orb:
- Ensure the Stripe customer is mapped to an Orb customer with
payment_provider set to stripe_charge or stripe_invoice.
- Verify that auto-collection is enabled for the customer.
- Orb will automatically sync the default payment method from Stripe and use it when issuing invoices.
When Orb issues an invoice for this customer, it will charge the e-Mandate payment method through Stripe. The mandate’s amount cap must be sufficient to cover the invoice amount, or the charge will be declined by Stripe.
If the invoice amount exceeds the mandate’s configured amount cap, Stripe will decline the charge. Ensure the mandate amount is set high enough to accommodate your expected invoice amounts. There is a maximum amount cap of 15,000 INR for India e-Mandates. Anything above this amount will be rounded down to 15,000 INR.
Troubleshooting
Mandate not appearing on the customer
Ensure the SetupIntent was confirmed successfully and the payment method was explicitly set as the customer’s default via invoice_settings.default_payment_method. Simply attaching a payment method is not sufficient — it must be set as the default.
Charges failing after mandate setup
- Verify the mandate’s
amount cap is higher than the invoice amount
- Check that the mandate’s
start_date is in the past (the mandate must be active)
- Confirm the
mandate.updated webhook event has fired in Stripe (this indicates the mandate is fully active)
Webhook events to monitor
The following Stripe webhook events are relevant to the e-Mandate lifecycle:
| Event | Description |
|---|
setup_intent.succeeded | The SetupIntent was confirmed and the mandate was created |
mandate.updated | The mandate status has changed (fires ~1 minute after creation when it becomes active) |
payment_intent.succeeded | A charge against the mandate was successful |
payment_intent.payment_failed | A charge against the mandate failed |