Payments
Setup Intents

The Setup Intents API

Learn more about the Setup Intents API for saving payment methods.

Use the Setup Intents API to set up a payment method for future payments. It’s similar to a payment, but no charge is created. Set up a payment method for future payments now.

The goal is to have payment credentials saved and optimized for future payments, meaning the payment method is configured correctly for any scenario. When setting up a card, for example, it may be necessary to authenticate the customer or check the card’s validity with the customer’s bank. Stripe updates the SetupIntent object throughout that process.


UI that collects card details but does not charge the card

Saving and reusing payment methods

The Setup Intents API is useful for businesses that onboard customers but don’t charge them right away:

  • A car rental company that collects payment method details before the customer rents the car and charges the card after the rental period ends
  • A crowdfunding website that collects card details to be charged later, only if the campaign reaches a certain amount
  • A utility company that charges a different amount each month based on usage but collects SEPA payment details before the first month’s payment

Get started

Getting permission to save a payment method

If you set up a payment method for future off-session payments, you need permission. Creating an agreement (sometimes called a mandate) up front allows you to charge the customer when they’re not actively using your website or app.

Add terms to your website or app that state how you plan to process payments, and let customers opt in. At a minimum, ensure that your terms cover the following:

  • The customer’s permission to your initiating a payment or a series of payments on their behalf
  • The anticipated frequency of payments (i.e., one-time or recurring)
  • How the payment amount will be determined

See recommended mandate text for saving cards or saving SEPA bank details.

For users impacted by SCA, this agreement helps payments succeed without interruption. When you set up your integration to properly save a card, Stripe marks any subsequent off-session payment as a merchant-initiated transaction (MIT) so that your customers don’t have to come back online and authenticate. Merchant-initiated transactions require an agreement between you and your customer.

Increasing success rate by specifying usage

The usage parameter tells Stripe how you plan to use payment method details later. For some payment methods, Stripe can use your usage setting to pick the most frictionless flow for the customer. This optimization is designed to increase the number of successful payments.

For example, credit and debit cards under European SCA regulation may require the customer to authenticate the card during the saving process. Setting usage to off_session properly authenticates a credit or debit card for off-session payments so that your customer doesn’t have to come back online and re-authenticate. So although it creates initial friction in the setup flow, setting usage to off_session can reduce customer intervention in later off-session payments.

However, if you only plan to use the card when the customer is checking out, set usage to on_session. This lets the bank know you plan to use the card when the customer is available to authenticate, so you can postpone authenticating the card details until then and avoid upfront friction.

How you intend to use the card usage enum value to use
On-session payments only on_session
Off-session payments only off_session (default)
Both on and off-session payments off_session (default)

Note that usage is an optimization. A card set up for on-session payments can still be used to make off-session payments, but the bank is more likely to reject the off-session payment and require authentication from the customer. In either case, later authentication may still be required, so build a recovery process in your app. When an off-session card payment requires authentication, bring your customer back online to complete the payment.

If not specified, usage defaults to off_session. See how to create a SetupIntent on your server and specify the usage:

curl https://api.stripe.com/v1/setup_intents \ -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \ -d usage=on_session
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' setup_intent = Stripe::SetupIntent.create({ usage: 'on_session', # The default usage is off_session })
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' setup_intent = stripe.SetupIntent.create( usage='on_session', # The default usage is off_session )
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); $setup_intent = \Stripe\SetupIntent::create([ 'usage' => 'on_session', // The default usage is off_session ]);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; // The default usage is off_session SetupIntentCreateParams params = SetupIntentCreateParams.builder() .setUsage(SetupIntentCreateParams.Usage.ON_SESSION) .build(); SetupIntent setupIntent = SetupIntent.create(params);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); const setupIntent = await stripe.setupIntents.create({ usage: 'on_session', // The default usage is off_session });
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc" params := &stripe.SetupIntentParams{ // The default usage is off_session Usage: stripe.String(string(stripe.SetupIntentUsageOnSession)), } si, _ := setupintent.New(params)
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys StripeConfiguration.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; // The default usage is off_session var options = new SetupIntentCreateOptions { Usage = "on_session", }; var service = new SetupIntentService(); var setupIntent = service.Create(options);
Was this page helpful?
Questions? Contact us.
Developer tutorials on YouTube.