Starting a subscription with Checkout

    Use Checkout to sell products or services requiring recurring payments.

    A Checkout Session represents the details of your customer’s intent to purchase. You create a Session when your customer wants to start a subscription. After redirecting your customer to a Checkout Session, Stripe presents a payment form where your customer can complete their purchase. Once your customer has completed a purchase, they will be redirected back to your site.

    Follow these steps to create a Checkout page for recurring payments:

    1. Create Products and Plans
    2. Create a Checkout Session on your server
    3. Redirect to Checkout

    Step 1: Create Products and Plans

    You first need to create a Product (an item that your customers can subscribe to) and a Plan that determines the pricing. You can either create a product and a plan through the API or through the Stripe Dashboard. If you have an existing Plan you’d like to use, skip this step.

    Creating products and plans through the Stripe Dashboard

    Before you start configuring products, make sure you are in test mode by toggling the View test data button at the bottom of the Stripe Dashboard. Next, define the goods and services you plan to sell. To create a new product:

    • Navigate to the Products section in the Dashboard
    • Click New
    • Click Recurring products
    • Add a pricing plan

    You can define multiple pricing plans with different parameters for each recurring product. Each plan has a generated ID that you can use as a reference during the checkout process.

    You can optionally define trial periods for each pricing plan. This automatically starts subscriptions with a free trial for the specified length of time.

    Step 2: Create a Checkout Session on your server

    Create a Session with subscription_data and the plan ID from the previous step or the ID of an existing Plan.

    When your customer successfully completes their payment, they are redirected to the success_url, a page on your website that informs the customer that their payment was successful.

    When your customer clicks on your logo in a Checkout Session without completing a payment, Checkout redirects them back to your website by navigating to the cancel_url. Typically, this is the page on your website that the customer viewed prior to redirecting to Checkout.

    curl https://api.stripe.com/v1/checkout/sessions \ -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \ -d "payment_method_types[]"=card \ -d "subscription_data[items][][plan]"=plan_123 \ -d success_url="https://example.com/success?session_id={CHECKOUT_SESSION_ID}" \ -d cancel_url="https://example.com/cancel"
    # 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' session = Stripe::Checkout::Session.create( payment_method_types: ['card'], subscription_data: { items: [{ plan: 'plan_123', }], }, success_url: 'https://example.com/success?session_id={CHECKOUT_SESSION_ID}', cancel_url: 'https://example.com/cancel', )
    # 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' session = stripe.checkout.Session.create( payment_method_types=['card'], subscription_data={ 'items': [{ 'plan': 'plan_123', }], }, success_url='https://example.com/success?session_id={CHECKOUT_SESSION_ID}', cancel_url='https://example.com/cancel', )
    // 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'); $session = \Stripe\Checkout\Session::create([ 'payment_method_types' => ['card'], 'subscription_data' => [ 'items' => [[ 'plan' => 'plan_123', ]], ], 'success_url' => 'https://example.com/success?session_id={CHECKOUT_SESSION_ID}', 'cancel_url' => 'https://example.com/cancel', ]);
    // 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"; Map<String, Object> params = new HashMap<String, Object>(); ArrayList<String> paymentMethodTypes = new ArrayList<>(); paymentMethodTypes.add("card"); params.put("payment_method_types", paymentMethodTypes); HashMap<String, Object> subscriptionData = new HashMap<String, Object>(); HashMap<String, Object> items = new HashMap<String, Object>(); HashMap<String, Object> item = new HashMap<String, Object>(); item.put("plan", "plan_123"); items.put("0", item); subscriptionData.put("items", items); params.put("subscription_data", subscriptionData); params.put("success_url", "https://example.com/success?session_id={CHECKOUT_SESSION_ID}"); params.put("cancel_url", "https://example.com/cancel"); Session session = Session.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'); (async () => { const session = await stripe.checkout.sessions.create({ payment_method_types: ['card'], subscription_data: { items: [{ plan: 'plan_123', }], }, success_url: 'https://example.com/success?session_id={CHECKOUT_SESSION_ID}', cancel_url: 'https://example.com/cancel', }); })();
    // 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.CheckoutSessionParams{ PaymentMethodTypes: stripe.StringSlice([]string{ "card", }), SubscriptionData: &stripe.CheckoutSessionSubscriptionDataParams{ Items: []*stripe.CheckoutSessionSubscriptionDataItemsParams{ &stripe.CheckoutSessionSubscriptionDataItemsParams{ Plan: stripe.String("plan_123"), }, }, }, SuccessURL: stripe.String("https://example.com/success?session_id={CHECKOUT_SESSION_ID}"), CancelURL: stripe.String("https://example.com/cancel"), } session, err := session.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"; var options = new SessionCreateOptions { PaymentMethodTypes = new List<string> { "card", }, SubscriptionData = new SessionSubscriptionDataOptions { Items = new List<SessionSubscriptionDataItemOptions> { new SessionSubscriptionDataItemOptions { Plan = "plan_123", }, }, }, SuccessUrl = "https://example.com/success?session_id={CHECKOUT_SESSION_ID}", CancelUrl = "https://example.com/cancel", }; var service = new SessionService(); Session session = service.Create(options);

    Creating a Checkout Session returns a Session id which is important for the following steps. Make the Session ID available on your success page by including the {CHECKOUT_SESSION_ID} template variable in the success_url as in the above example.

    Checkout Sessions expire 24 hours after creation.



    Handling trials optional

    Pass the trial_from_plan parameter when creating a Checkout session to specify that the trial period defined when you created the Plan should be applied.

    curl https://api.stripe.com/v1/checkout/sessions \ -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \ -d "payment_method_types[]"=card \ -d "subscription_data[items][][plan]"=plan_123 \ -d "subscription_data[trial_from_plan]"=true \ -d success_url="https://example.com/success?session_id={CHECKOUT_SESSION_ID}" \ -d cancel_url="https://example.com/cancel"
    # 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' session = Stripe::Checkout::Session.create( payment_method_types: ['card'], subscription_data: { items: [{ plan: 'plan_123', }], trial_from_plan: true }, success_url: 'https://example.com/success?session_id={CHECKOUT_SESSION_ID}', cancel_url: 'https://example.com/cancel', )
    # 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' session = stripe.checkout.Session.create( payment_method_types=['card'], subscription_data={ 'items': [{ 'plan': 'plan_123', }], 'trial_from_plan': True, }, success_url='https://example.com/success?session_id={CHECKOUT_SESSION_ID}', cancel_url='https://example.com/cancel', )
    // 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'); $session = \Stripe\Checkout\Session::create([ 'payment_method_types' => ['card'], 'subscription_data' => [ 'items' => [[ 'plan' => 'plan_123', ]], 'trial_from_plan' => true, ], 'success_url' => 'https://example.com/success?session_id={CHECKOUT_SESSION_ID}', 'cancel_url' => 'https://example.com/cancel', ]);
    // 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"; Map<String, Object> params = new HashMap<String, Object>(); ArrayList<String> paymentMethodTypes = new ArrayList<>(); paymentMethodTypes.add("card"); params.put("payment_method_types", paymentMethodTypes); HashMap<String, Object> subscriptionData = new HashMap<String, Object>(); HashMap<String, Object> items = new HashMap<String, Object>(); HashMap<String, Object> item = new HashMap<String, Object>(); item.put("plan", "plan_123"); items.put("0", item); subscriptionData.put("items", items); subscriptionData.put("trial_from_plan", true); params.put("subscription_data", subscriptionData); params.put("success_url", "https://example.com/success?session_id={CHECKOUT_SESSION_ID}"); params.put("cancel_url", "https://example.com/cancel"); Session session = Session.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'); (async () => { const session = await stripe.checkout.sessions.create({ payment_method_types: ['card'], subscription_data: { items: [{ plan: 'plan_123', }], trial_from_plan: true, }, success_url: 'https://example.com/success?session_id={CHECKOUT_SESSION_ID}', cancel_url: 'https://example.com/cancel', }); })();
    // 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.CheckoutSessionParams{ PaymentMethodTypes: stripe.StringSlice([]string{ "card", }), SubscriptionData: &stripe.CheckoutSessionSubscriptionDataParams{ Items: []*stripe.CheckoutSessionSubscriptionDataItemsParams{ &stripe.CheckoutSessionSubscriptionDataItemsParams{ Plan: stripe.String("plan_123"), }, }, TrialFromPlan: stripe.Bool(true), }, SuccessURL: stripe.String("https://example.com/success?session_id={CHECKOUT_SESSION_ID}"), CancelURL: stripe.String("https://example.com/cancel"), } s, _ := session.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"; var options = new SessionCreateOptions { PaymentMethodTypes = new List<string> { "card", }, SubscriptionData = new SessionSubscriptionDataOptions { Items = new List<SessionSubscriptionDataItemOptions> { new SessionSubscriptionDataItemOptions { Plan = "plan_123", }, }, TrialFromPlan = true, }, SuccessUrl = "https://example.com/success?session_id={CHECKOUT_SESSION_ID}", CancelUrl = "https://example.com/cancel", }; var service = new SessionService(); Session session = service.Create(options);
    ​​

    Prior to redirecting to Checkout with a trial period, you must obtain your customer’s explicit consent to the following:

    • Subscription terms
    • Terms of cancellation
    • Cancellation policy

    ​​Checkout displays the following information automatically when a subscription with a trial period ends:

    • Trial expiration date
    • Frequency and amount of charges after trial expiration

    Adding tax rates optional

    You may specify tax rates in Checkout Sessions to apply taxes to subscriptions. These parameters are similar to those when directly creating a subscription. Set subscription_data.default_tax_rates to apply a default tax rate to a subscription started with Checkout.

    curl https://api.stripe.com/v1/checkout/sessions \ -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \ -d "payment_method_types[]"=card \ -d "subscription_data[items][][plan]"=plan_123 \ -d "subscription_data[default_tax_rates][]"=txr_123 \ -d success_url="https://example.com/success" \ -d cancel_url="https://example.com/cancel"
    # 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' session = Stripe::Checkout::Session.create( payment_method_types: ['card'], subscription_data: { items: [{ plan: 'plan_123', }], default_tax_rates: ['txr_123'], }, success_url: 'https://example.com/success', cancel_url: 'https://example.com/cancel', )
    # 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' session = stripe.checkout.Session.create( payment_method_types=['card'], subscription_data={ 'items': [{ 'plan': 'plan_123', }], 'default_tax_rates': ['txr_123'], }, success_url='https://example.com/success', cancel_url='https://example.com/cancel', )
    // 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'); $session = \Stripe\Checkout\Session::create([ 'payment_method_types' => ['card'], 'subscription_data' => [ 'items' => [[ 'plan' => 'plan_123', ]], 'default_tax_rates' => ['txr_123'], ], 'success_url' => 'https://example.com/success', 'cancel_url' => 'https://example.com/cancel', ]);
    // 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"; Map<String, Object> params = new HashMap<String, Object>(); ArrayList<String> paymentMethodTypes = new ArrayList<>(); paymentMethodTypes.add("card"); params.put("payment_method_types", paymentMethodTypes); HashMap<String, Object> subscriptionData = new HashMap<String, Object>(); HashMap<String, Object> items = new HashMap<String, Object>(); HashMap<String, Object> item = new HashMap<String, Object>(); item.put("plan", "plan_123"); items.put("0", item); subscriptionData.put("items", items); ArrayList<String> defaultTaxRates = new ArrayList<>(); defaultTaxRates.add("txr_123"); subscriptionData.put("default_tax_rates", defaultTaxRates); params.put("subscription_data", subscriptionData); params.put("success_url", "https://example.com/success"); params.put("cancel_url", "https://example.com/cancel"); Session session = Session.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'); (async () => { const session = await stripe.checkout.sessions.create({ payment_method_types: ['card'], subscription_data: { items: [{ plan: 'plan_123', }], default_tax_rates: ['txr_123'], }, success_url: 'https://example.com/success', cancel_url: 'https://example.com/cancel', }); })();
    // 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.CheckoutSessionParams{ PaymentMethodTypes: stripe.StringSlice([]string{ "card", }), SubscriptionData: &stripe.CheckoutSessionSubscriptionDataParams{ Items: []*stripe.CheckoutSessionSubscriptionDataItemsParams{ &stripe.CheckoutSessionSubscriptionDataItemsParams{ Plan: stripe.String("plan_123"), }, }, DefaultTaxRates: stripe.StringSlice([]string{ "txr_123", }), }, SuccessURL: stripe.String("https://example.com/success"), CancelURL: stripe.String("https://example.com/cancel"), } session, err := session.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"; var options = new SessionCreateOptions { PaymentMethodTypes = new List<string> { "card", }, SubscriptionData = new SessionSubscriptionDataOptions { Items = new List<SessionSubscriptionDataItemOptions> { new SessionSubscriptionDataItemOptions { Plan = "plan_123", }, }, DefaultTaxRates = new List<string> { "txr_123", }, }, SuccessUrl = "https://example.com/success", CancelUrl = "https://example.com/cancel", }; var service = new SessionService(); Session session = service.Create(options);

    You may also specify subscription_data.items.tax_rates or line_items.tax_rates to apply tax rates to specific plans or invoice line items.

    Step 3: Redirect to Checkout

    Checkout relies on Stripe.js, Stripe’s foundational JavaScript library for building payment flows. Include the following script tag on your website—always load it directly from https://js.stripe.com:

    <script src="https://js.stripe.com/v3/"></script>
    npm install @stripe/stripe-js

    Next, create an instance of the Stripe object by providing your publishable API key as the first parameter:

    var stripe = Stripe('pk_test_TYooMQauvdEDq54NiTphI7jx');
    import {loadStripe} from '@stripe/stripe-js'; const stripe = await loadStripe('pk_test_TYooMQauvdEDq54NiTphI7jx');

    To use Checkout on your website, you must add a snippet of code that includes the Session id from step two. When your customer is ready to pay, call redirectToCheckout and provide the Session id as a parameter to begin the payment process.

    stripe.redirectToCheckout({ // Make the id field from the Checkout Session creation API response // available to this file, so you can provide it as parameter here // instead of the {{CHECKOUT_SESSION_ID}} placeholder. sessionId: '{{CHECKOUT_SESSION_ID}}' }).then(function (result) { // If `redirectToCheckout` fails due to a browser or network // error, display the localized error message to your customer // using `result.error.message`. });
    const {error} = await stripe.redirectToCheckout({ // Make the id field from the Checkout Session creation API response // available to this file, so you can provide it as parameter here // instead of the {{CHECKOUT_SESSION_ID}} placeholder. sessionId: '{{CHECKOUT_SESSION_ID}}' }) // If `redirectToCheckout` fails due to a browser or network // error, display the localized error message to your customer // using `error.message`.

    This code is typically invoked from an event handler that triggers in response to an action taken by your customer, such as clicking on a payment button.

    Once payment is successful, you should fulfill the customer’s purchase. You can use webhooks to fulfill the purchase when the checkout.session.completed event triggers. For more details about handling purchase fulfillment with Checkout, see after the payment.

    Next steps

    Now that you have a working integration, learn how to handle actions after the payment and the options available for customizing Checkout.

    Was this page helpful?

    Feedback about this page?

    Thank you for helping improve Stripe's documentation. If you need help or have any questions, please consider contacting support.

    On this page