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.Documentation Index
Fetch the complete documentation index at: https://docs.withorb.com/llms.txt
Use this file to discover all available pages before exploring further.
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 withmandate_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
Before setting up an India e-Mandate, ensure the following:- Your Stripe test mode account is connected to Orb in test mode (see Connecting Stripe with Orb)
- You have access to your Stripe test mode API keys (
sk_test_andpk_test_prefixed keys from the Stripe API keys page) - You have a test customer created in the Stripe test dashboard
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 includemandate_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 |
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 usingstripe.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: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.updatedwebhook 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_providerset tostripe_chargeorstripe_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.
amount cap must be sufficient to cover the invoice amount, or the charge will be declined by Stripe.
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 viainvoice_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
amountcap is higher than the invoice amount - Check that the mandate’s
start_dateis in the past (the mandate must be active) - Confirm the
mandate.updatedwebhook 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 |