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 also define trial periods for each pricing plan.

    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 change this 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 change this 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 change this 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 change this 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 change this 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 change this 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 change this 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 existing customers optional

    If you have previously created a Customer object to represent a customer, use the customer argument to pass their Customer ID when creating a Checkout Session. This ensures that all objects created during the Session are associated with the correct Customer object.

    When you pass a Customer ID, Stripe also uses the email stored on the Customer object to prefill the email field on the Checkout page. If the customer changes their email on the Checkout page, it will be updated on the Customer object after a successful payment.

    curl https://api.stripe.com/v1/checkout/sessions \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
      -d customer=cus_123 \
      -d "payment_method_types[]"=card \
      -d "line_items[][name]"=T-shirt \
      -d "line_items[][description]"="Comfortable cotton t-shirt" \
      -d "line_items[][images][]"="https://example.com/t-shirt.png" \
      -d "line_items[][amount]"=500 \
      -d "line_items[][currency]"=usd \
      -d "line_items[][quantity]"=1 \
      -d success_url="https://example.com/success" \
      -d cancel_url="https://example.com/cancel"
    
    # Set your secret key: remember to change this 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(
      customer: 'cus_123',
      payment_method_types: ['card'],
      line_items: [{
        name: 'T-shirt',
        description: 'Comfortable cotton t-shirt',
        images: ['https://example.com/t-shirt.png'],
        amount: 500,
        currency: 'usd',
        quantity: 1,
      }],
      success_url: 'https://example.com/success',
      cancel_url: 'https://example.com/cancel',
    )
    
    # Set your secret key: remember to change this 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(
      customer='cus_123',
      payment_method_types=['card'],
      line_items=[{
        'name': 'T-shirt',
        'description': 'Comfortable cotton t-shirt',
        'images': ['https://example.com/t-shirt.png'],
        'amount': 500,
        'currency': 'usd',
        'quantity': 1,
      }],
      success_url='https://example.com/success',
      cancel_url='https://example.com/cancel',
    )
    
    // Set your secret key: remember to change this 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([
      'customer' => 'cus_123',
      'payment_method_types' => ['card'],
      'line_items' => [[
        'name' => 'T-shirt',
        'description' => 'Comfortable cotton t-shirt',
        'images' => ['https://example.com/t-shirt.png'],
        'amount' => 500,
        'currency' => 'usd',
        'quantity' => 1,
      ]],
      'success_url' => 'https://example.com/success',
      'cancel_url' => 'https://example.com/cancel',
    ]);
    
    // Set your secret key: remember to change this 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>();
    
    params.put("customer", "cus_123");
    
    ArrayList<String> paymentMethodTypes = new ArrayList<>();
    paymentMethodTypes.add("card");
    params.put("payment_method_types", paymentMethodTypes);
    
    ArrayList<HashMap<String, Object>> lineItems = new ArrayList<>();
    HashMap<String, Object> lineItem = new HashMap<String, Object>();
    lineItem.put("name", "T-shirt");
    lineItem.put("description", "Comfortable cotton t-shirt");
    lineItem.put("amount", 500);
    lineItem.put("currency", "usd");
    lineItem.put("quantity", 1);
    lineItems.add(lineItem);
    params.put("line_items", lineItems);
    
    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 change this 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({
        customer: 'cus_123',
        payment_method_types: ['card'],
        line_items: [{
          name: 'T-shirt',
          description: 'Comfortable cotton t-shirt',
          images: ['https://example.com/t-shirt.png'],
          amount: 500,
          currency: 'usd',
          quantity: 1,
        }],
        success_url: 'https://example.com/success',
        cancel_url: 'https://example.com/cancel',
      });
    })();
    
    // Set your secret key: remember to change this 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{
        Customer: stripe.String("cus_123"),
        PaymentMethodTypes: stripe.StringSlice([]string{
            "card",
        }),
        LineItems: []*stripe.CheckoutSessionLineItemParams{
            &stripe.CheckoutSessionLineItemParams{
                Name: stripe.String("T-shirt"),
                Description: stripe.String("Comfortable cotton t-shirt"),
                Amount: stripe.Int64(500),
                Currency: stripe.String(string(stripe.CurrencyUSD)),
                Quantity: stripe.Int64(1),
            },
        },
        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 change this 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 {
        Customer = "cus_123",
        PaymentMethodTypes = new List<string> {
            "card",
        },
        LineItems = new List<SessionLineItemOptions> {
            new SessionLineItemOptions {
                Name = "T-shirt",
                Description = "Comfortable cotton t-shirt",
                Amount = 500,
                Currency = "usd",
                Quantity = 1,
            },
        },
        SuccessUrl = "https://example.com/success",
        CancelUrl = "https://example.com/cancel",
    };
    
    var service = new SessionService();
    Session session = service.Create(options);
    

    Prefilling customer data optional

    You may have already collected information about your customer that you want to prefill in the Checkout Session to avoid your customers needing to enter information twice. Currently, you can prefill the customer email on the Checkout page by passing customer_email when creating a Checkout Session. We plan to expand this feature to allow you to prefill more fields in the future.

    curl https://api.stripe.com/v1/checkout/sessions \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
      -d customer_email="customer@example.com" \
      -d "payment_method_types[]"=card \
      -d "line_items[][name]"=T-shirt \
      -d "line_items[][description]"="Comfortable cotton t-shirt" \
      -d "line_items[][images][]"="https://example.com/t-shirt.png" \
      -d "line_items[][amount]"=500 \
      -d "line_items[][currency]"=usd \
      -d "line_items[][quantity]"=1 \
      -d success_url="https://example.com/success" \
      -d cancel_url="https://example.com/cancel"
    
    # Set your secret key: remember to change this 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(
      customer_email: 'customer@example.com',
      payment_method_types: ['card'],
      line_items: [{
        name: 'T-shirt',
        description: 'Comfortable cotton t-shirt',
        images: ['https://example.com/t-shirt.png'],
        amount: 500,
        currency: 'usd',
        quantity: 1,
      }],
      success_url: 'https://example.com/success',
      cancel_url: 'https://example.com/cancel',
    )
    
    # Set your secret key: remember to change this 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(
      customer_email='customer@example.com',
      payment_method_types=['card'],
      line_items=[{
        'name': 'T-shirt',
        'description': 'Comfortable cotton t-shirt',
        'images': ['https://example.com/t-shirt.png'],
        'amount': 500,
        'currency': 'usd',
        'quantity': 1,
      }],
      success_url='https://example.com/success',
      cancel_url='https://example.com/cancel',
    )
    
    // Set your secret key: remember to change this 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([
      'customer_email' => 'customer@example.com',
      'payment_method_types' => ['card'],
      'line_items' => [[
        'name' => 'T-shirt',
        'description' => 'Comfortable cotton t-shirt',
        'images' => ['https://example.com/t-shirt.png'],
        'amount' => 500,
        'currency' => 'usd',
        'quantity' => 1,
      ]],
      'success_url' => 'https://example.com/success',
      'cancel_url' => 'https://example.com/cancel',
    ]);
    
    // Set your secret key: remember to change this 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>();
    
    params.put("customer_email", "customer@example.com");
    
    ArrayList<String> paymentMethodTypes = new ArrayList<>();
    paymentMethodTypes.add("card");
    params.put("payment_method_types", paymentMethodTypes);
    
    ArrayList<HashMap<String, Object>> lineItems = new ArrayList<>();
    HashMap<String, Object> lineItem = new HashMap<String, Object>();
    lineItem.put("name", "T-shirt");
    lineItem.put("description", "Comfortable cotton t-shirt");
    lineItem.put("amount", 500);
    lineItem.put("currency", "usd");
    lineItem.put("quantity", 1);
    lineItems.add(lineItem);
    params.put("line_items", lineItems);
    
    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 change this 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({
        customer_email: 'customer@example.com',
        payment_method_types: ['card'],
        line_items: [{
          name: 'T-shirt',
          description: 'Comfortable cotton t-shirt',
          images: ['https://example.com/t-shirt.png'],
          amount: 500,
          currency: 'usd',
          quantity: 1,
        }],
        success_url: 'https://example.com/success',
        cancel_url: 'https://example.com/cancel',
      });
    })();
    
    // Set your secret key: remember to change this 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{
        CustomerEmail: stripe.String("customer@example.com"),
        PaymentMethodTypes: stripe.StringSlice([]string{
            "card",
        }),
        LineItems: []*stripe.CheckoutSessionLineItemParams{
            &stripe.CheckoutSessionLineItemParams{
                Name: stripe.String("T-shirt"),
                Description: stripe.String("Comfortable cotton t-shirt"),
                Amount: stripe.Int64(500),
                Currency: stripe.String(string(stripe.CurrencyUSD)),
                Quantity: stripe.Int64(1),
            },
        },
        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 change this 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 {
        CustomerEmail = "customer@example.com",
        PaymentMethodTypes = new List<string> {
            "card",
        },
        LineItems = new List<SessionLineItemOptions> {
            new SessionLineItemOptions {
                Name = "T-shirt",
                Description = "Comfortable cotton t-shirt",
                Amount = 500,
                Currency = "usd",
                Quantity = 1,
            },
        },
        SuccessUrl = "https://example.com/success",
        CancelUrl = "https://example.com/cancel",
    };
    
    var service = new SessionService();
    Session session = service.Create(options);
    

    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>
    

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

    var stripe = Stripe('pk_test_TYooMQauvdEDq54NiTphI7jx');
    
    const stripe = Stripe('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?

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

    On this page