Working with Multiple Plans per Subscription

    Create subscriptions containing multiple plans or different variations of the same plan, all billed in a single invoice.

    Stripe offers the ability to simultaneously subscribe a customer to multiple plans on a single subscription. This provides another avenue for easily billing your customers in flexible ways. For example, if your business offers multiple products or services, each could be represented by its own plan and the same customer could be subscribed to more than one in a single subscription. You can also create subscriptions that combine metered billing plans with conventional fixed-fee plans. When you combine multiple plans in a single subscription, the plans do not have to be associated with the same product.

    Unlike our multiple subscriptions on a customer capability, which generates an invoice for each subscription, putting multiple plans into a single subscription results in a single invoice each billing period that combines every plan. Only a single payment for that invoice is required, reducing your costs and the number of charges your customer sees.

    Creating multiple-plan subscriptions

    Create multiple-plan subscriptions on a customer using the items parameter. Provide the plan and, optionally, a quantity (when using a value other than 1), for each plan:

    curl https://api.stripe.com/v1/subscriptions \
       -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
       -d customer=cus_4fdAW5ftNQow1a \
       -d items[0][plan]=plan_CBXbz9i7AIOTzr \
       -d items[1][plan]=plan_IFuCu48Snc02bc \
       -d items[1][quantity]=2
    
    # 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"
    
    subscription = Stripe::Subscription.create({
        customer: 'cus_4fdAW5ftNQow1a',
        items: [
            {
                plan: 'plan_CBXbz9i7AIOTzr',
            },
            {
                plan: 'plan_IFuCu48Snc02bc',
                quantity: 2,
            },
        ],
    })
    
    # 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"
    
    subscription = stripe.Subscription.create(
      customer='cus_4fdAW5ftNQow1a',
      items=[
        {
          'plan': 'plan_CBXbz9i7AIOTzr',
        },
        {
          'plan': 'plan_IFuCu48Snc02bc',
          'quantity': 2,
        },
      ],
    )
    
    // 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");
    
    $subscription = \Stripe\Subscription::create([
        'customer' => 'cus_4fdAW5ftNQow1a',
        'items' => [
            [
                'plan' => 'plan_CBXbz9i7AIOTzr',
            ],
            [
                'plan' => 'plan_IFuCu48Snc02bc',
                'quantity' => 2,
            ],
        ],
    ]);
    
    // 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> itemA = new HashMap<>();
    itemA.put("plan", "plan_CBXbz9i7AIOTzr");
    Map<String, Object> itemB = new HashMap<>();
    itemB.put("plan", "plan_IFuCu48Snc02bc");
    itemB.put("quantity", 2);
    Map<String, Object> items = new HashMap<>();
    items.put("0", itemA);
    items.put("1", itemB);
    Map<String, Object> params = new HashMap<>();
    params.put("customer", "cus_4fdAW5ftNQow1a");
    params.put("items", items);
    Subscription subscription = Subscription.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
    var stripe = require("stripe")("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    const subscription = stripe.subscriptions.create({
      customer: 'cus_4fdAW5ftNQow1a',
      items: [
        {
          plan: 'plan_CBXbz9i7AIOTzr',
        },
        {
          plan: 'plan_IFuCu48Snc02bc',
          quantity: 2,
        },
      ],
    });
    
    // 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"
    
    items := []*stripe.SubscriptionItemsParams{
      {
        Plan: stripe.String("plan_CBXbz9i7AIOTzr"),
      },
      {
        Plan: stripe.String("plan_IFuCu48Snc02bc"),
        Quantity: stripe.Int64(2),
      },
    }
    params := &stripe.SubscriptionParams{
      Customer: stripe.String("cus_4fdAW5ftNQow1a"),
      Items: items,
    }
    subscription, _ := sub.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.SetApiKey("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    var items = new List<StripeSubscriptionItemOption> {
        new StripeSubscriptionItemOption {
            PlanId = "plan_CBXbz9i7AIOTzr"
        },
        new StripeSubscriptionItemOption {
            PlanId = "plan_IFuCu48Snc02bc",
            Quantity = 2,
        },
    };
    var options = new StripeSubscriptionCreateOptions {
        Items = items,
    };
    var service = new StripeSubscriptionService();
    StripeSubscription subscription = service.Create("cus_4fdAW5ftNQow1a", options);
    

    When the subscription is created successfully, the response includes a list of all the plans:

    {
      "id": "sub_CZEpS1Zt9QLxdo",
      "object": "subscription",
      ...
      "items": {
        "object": "list",
        "data": [
          {
            "id": "si_CZEpxL7flyswvU",
            "object": "subscription_item",
            "created": 1522113139,
            "metadata": {},
            "plan": {
              "id": "plan_CZB2krKbBDOkTS",
              "object": "plan",
              "amount": 5000,
              "created": 1522098982,
              ...
            },
            "quantity": 1,
            "subscription": "sub_CZEpS1Zt9QLxdo"
          },
          {
            "id": "si_CZEpDeHTKq2iQm",
            "object": "subscription_item",
            "created": 1522113139,
            "metadata": {},
            "plan": {
              "id": "plan_CZB1AX3KOacNJw",
              "object": "plan",
              "amount": 5000,
              "created": 1522098979,
              ...
            },
            "quantity": 2,
            "subscription": "sub_CZEpS1Zt9QLxdo"
          }
        ],
        ...
      },
      ...
    }
    

    Billing periods with multiple plans

    Conventional plans that charge a fixed amount on an interval are billed at the start of each billing cycle. With each invoice, the customer effectively pays for the next interval of service. In a metered plan, the price paid by the customer varies based on consumption during the billing cycle, so the customer pays for their usage at the end.

    When a subscription combines a fixed rate plan and a metered billing plan, metered usage from the previous billing cycle is charged alongside the fixed rate for the new billing cycle at the start of each interval. The metered billing and fixed rate are combined in a single invoice.

    Restrictions

    Since putting multiple plans under a single subscription results in a single invoice and payment, all of the plans grouped together in a subscription must use the same currency and have the same billing interval. You are also limited to 20 plans in a single subscription.

    Discounts, taxes, and trial periods

    When using multiple plans on a single subscription, you can also create discounts, charge taxes, and use trial periods as you would with a single-plan subscription. Provide these as top-level arguments to the create or update subscription call, as they apply to the subscription at large:

    curl https://api.stripe.com/v1/subscriptions \
       -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
       -d customer=cus_4fdAW5ftNQow1a \
       -d coupon=free-period \
       -d tax_percent="6.34" \
       -d trial_end=1538443955 \
       -d items[0][plan]=plan_CBXbz9i7AIOTzr \
       -d items[1][plan]=plan_IFuCu48Snc02bc \
       -d items[1][quantity]=2
    
    # 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"
    
    subscription = Stripe::Subscription.create({
        customer: 'cus_4fdAW5ftNQow1a',
        coupon: 'free-period',
        tax_percent: 6.34,
        trial_end: 1538443955,
        items: [
            {
                plan: 'plan_CBXbz9i7AIOTzr',
            },
            {
                plan: 'plan_IFuCu48Snc02bc',
                quantity: 2,
            },
        ],
    })
    
    # 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"
    
    subscription = stripe.Subscription.create(
      customer='cus_4fdAW5ftNQow1a',
      coupon='free-period',
      tax_percent=6.34,
      trial_end=1538443955,
      items=[
        {
          'plan': 'plan_CBXbz9i7AIOTzr',
        },
        {
          'plan': 'plan_IFuCu48Snc02bc',
          'quantity': 2,
        },
      ],
    )
    
    // 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");
    
    $subscription = \Stripe\Subscription::create([
        'customer' => 'cus_4fdAW5ftNQow1a',
        'coupon' => 'free-period',
        'tax_percent' => 6.34,
        'trial_end' => 1538443955,
        'items' => [
            [
               'plan' => 'plan_CBXbz9i7AIOTzr',
            ],
            [
                'plan' => 'plan_IFuCu48Snc02bc',
                'quantity' => 2,
            ],
        ],
    ]);
    
    // 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> itemA = new HashMap<>();
    itemA.put("plan", "plan_CBXbz9i7AIOTzr");
    Map<String, Object> itemB = new HashMap<>();
    itemB.put("plan", "plan_IFuCu48Snc02bc");
    itemB.put("quantity", 2);
    Map<String, Object> items = new HashMap<>();
    items.put("0", itemA);
    items.put("1", itemB);
    Map<String, Object> params = new HashMap<>();
    params.put("customer", "cus_4fdAW5ftNQow1a");
    params.put("coupon", "free-period");
    params.put("tax_percent", 6.34);
    params.put("trial_end", 1538443955);
    params.put("items", items);
    Subscription subscription = Subscription.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
    var stripe = require("stripe")("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    const subscription = stripe.subscriptions.create({
      customer: 'cus_4fdAW5ftNQow1a',
      coupon: 'free-period',
      tax_percent: 6.34,
      trial_end: 1538443955,
      items: [
        {
          plan: 'plan_CBXbz9i7AIOTzr',
        },
        {
          plan: 'plan_IFuCu48Snc02bc',
          quantity: 2,
        },
      ],
    });
    
    // 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"
    
    items := []*stripe.SubscriptionItemsParams{
      {
        Plan: stripe.String("plan_CBXbz9i7AIOTzr"),
      },
      {
        Plan: stripe.String("plan_IFuCu48Snc02bc"),
        Quantity: stripe.Int64(2),
      },
    }
    params := &stripe.SubscriptionParams{
      Customer: stripe.String("cus_4fdAW5ftNQow1a"),
      Coupon: stripe.String("free-period"),
      TaxPercent: stripe.Float64(6.34),
      TrialEnd: stripe.Int64(1538443955),
      Items: items,
    }
    subscription, _ := sub.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.SetApiKey("sk_test_4eC39HqLyjWDarjtT1zdp7dc");
    
    var items = new List<StripeSubscriptionItemOption> {
        new StripeSubscriptionItemOption {
            PlanId = "plan_CBXbz9i7AIOTzr"
        },
        new StripeSubscriptionItemOption {
            PlanId = "plan_IFuCu48Snc02bc",
            Quantity = 2,
        },
    };
    var options = new StripeSubscriptionCreateOptions {
        CouponId = "free-period",
        TaxPercent = 6.34m,
        TrialEnd = DateTimeOffset.FromUnixTimeSeconds(1538443955).UtcDateTime,
        Items = items,
    };
    var service = new StripeSubscriptionService();
    StripeSubscription subscription = service.Create("cus_4fdAW5ftNQow1a", options);
    

    When you create a subscription by passing plans into the items attribute, it will ignore any trial period that is specified on the individual plans. The trial period is only respected if you create a subscription with a single plan via the plan attribute.

    Next steps

    Now that you understand how to use multiple plans on a single subscription, you may want to check out:

    Questions?

    We're always happy to help with code or other questions you might have! Search our documentation, contact support, or connect with our sales team. You can also chat live with other developers in #stripe on freenode.

    Was this page helpful? Yes No

    Send

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