Upgrading and Downgrading Plans

    Learn how to change a customer's subscription by upgrading or downgrading their plan. If you need help after reading this, check out our answers to common questions or chat live with other developers in #stripe on freenode.

    One way existing subscriptions can be modified is by upgrading or downgrading the underlying plan. For example, a customer might want to switch from your basic plan to your pro plan, which is easily accomplished via an upgrade subscription call.

    Changing a subscription often results in a proration: a charge adjustment. So you can prepare your customer for any additional expense that comes with a plan change, we provide a method of previewing a proration. Alternatively, you can choose to disable proration.

    Switching plans

    Subscriptions can be changed by switching the plan to which a customer is subscribed or by changing the quantity of a plan. Normally the result qualifies as either upgrading or downgrading the subscription, depending upon the price difference between the two subscriptions.

    Assuming a customer is currently subscribed to the standard-monthly plan at $10 per month, the following code switches the customer to the pro-monthly plan at $30/month:

    curl https://api.stripe.com/v1/subscriptions/sub_49ty4767H20z6a \
       -u sk_test_BQokikJOvBiI2HlWgH4olfQ2: \
       -d plan=pro-monthly
    
    # 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_BQokikJOvBiI2HlWgH4olfQ2"
    
    subscription = Stripe::Subscription.retrieve("sub_49ty4767H20z6a")
    subscription.plan = "pro-monthly"
    subscription.save
    # 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_BQokikJOvBiI2HlWgH4olfQ2"
    
    subscription = stripe.Subscription.retrieve("sub_49ty4767H20z6a")
    subscription.plan = "pro-monthly"
    subscription.save()
    // 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_BQokikJOvBiI2HlWgH4olfQ2");
    
    $subscription = \Stripe\Subscription::retrieve("sub_49ty4767H20z6a");
    $subscription->plan = "pro-monthly";
    $subscription->save();
    // 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_BQokikJOvBiI2HlWgH4olfQ2";
    
    Subscription subscription = Subscription.retrieve("sub_49ty4767H20z6a");
    
    Map<String, Object> params = new HashMap<String, Object>();
    params.put("plan", "pro-monthly");
    subscription.update(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_BQokikJOvBiI2HlWgH4olfQ2");
    
    stripe.subscriptions.update("sub_49ty4767H20z6a", {
        plan: "pro-monthly",
      }, function(err, subscription) {
        // asynchronously called
      }
    );
    // 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_BQokikJOvBiI2HlWgH4olfQ2"
    
    params := &stripe.SubParams{
      Plan: "pro-monthly",
    }
    subscription, err := sub.Update("sub_49ty4767H20z6a", params)

    If both plans have the same billing periods—combination of interval and interval_count, the subscription retains the same billing dates. If the plans have different billing periods, the new plan is billed at the new interval, starting on the day of the change. For example, switching a customer from one monthly plan to another does not change the billing dates. However, switching a customer from a monthly plan to a yearly plan moves the billing date to the date of the switch. Switching a customer from a monthly plan to a monthly plan with a trial period also moves the billing date (to the conclusion of the trial).

    Stripe immediately attempts payment for these subscription changes:

    • From a subscription that doesn’t require payment (e.g., due to a trial, free plan, or coupon) to a paid subscription
    • When the billing period changes

    If the required payment fails, the subscription change request also fails, leaving the subscription unchanged.

    If you want the customer to immediately pay the price difference when switching to a more expensive plan on the same billing cycle, you need to generate an invoice after making the switch.

    Understanding proration

    The most confusing aspect to changing subscriptions is how existing payments are factored into the amount to be invoiced. By default, Stripe prorates subscription costs.

    For example, say the customer in the above code is billed on the 1st of each month and that code is executed exactly halfway through the plan’s billing cycle (i.e., on the 15th of April). In that case, the customer has already paid $10, and used half of the current billing cycle. When the customer switches to the new plan, with a cost of $30, the unused portion of the previous plan results in a credit of $5. The cost of the new plan for the rest of the billing cycle (i.e., the rest of April) is $15. Therefore, the total prorated cost of switching from the cheaper plan to the more expensive plan is $10. This amount is added to the next invoice.

    The next invoice, on May 1st, also reflects the payment required on the new plan for that upcoming month: $30. Thus, the May 1st invoice is for a total of $40.

    The customer is not billed the $40 at the time the plans are switched. The plan change impacts the next invoice, which remains on the same billing cycle (as both plans have the same billing interval).

    As another example, say a customer is halfway through a monthly plan that costs $30 per month and is switched to a yearly plan that costs $300 per year. The customer is credited $15 for the unused portion of the monthly plan and owes $300 for the first year of the new plan. The customer is invoiced—at the time of the switch—$285, and the annual billing cycle begins that day.

    When the new plan is less expensive than the current plan, the prorated credit is larger than the new amount due. For example, if the customer switches from the $30/month plan to the $10/month plan exactly halfway through the billing cycle, the customer receives a net credit of $10: a credit of $15 for the unused portion of the old plan less a charge of $5 for the remaining time on the new plan. The next invoice, at the start of the next billing period, reflects the $10 credit and the $10 due for a full, upcoming month on the new plan, resulting in a net amount due of $0.

    When credits are created, they’ll continue to apply to subsequent invoices until the credit is covered and payment is due again. For example, a move from a $50/month plan until a $10/month plan—exactly halfway through the billing period—results in a net credit of $20: a credit of $25 for the unused portion of the more expensive plan and a debit of $5 to pay for the remainder of the billing period on the new plan. The next two invoices would net to $0.

    The prorated amount is calculated down to the second by Stripe. We calculate the difference between the two plans based on the time the API call was made to change the customer’s subscription, using the current billing period’s start and end times.

    Previewing prorations

    To preview the cost of a proration before changing the customer’s subscription, make an upcoming invoice API call. This endpoint shows what the customer’s next invoice looks like after applying the provided parameters, such as a plan change.

    In the returned invoice, the invoice items reflect the prorations created by an update.

    # 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_BQokikJOvBiI2HlWgH4olfQ2"
    
    # Set proration date to this moment:
    proration_date = Time.now.to_i
    
    # See what the next invoice would look like with a plan switch
    # and proration set:
    invoice = Stripe::Invoice.upcoming(
      :customer => "cus_3R1W8PG2DmsmM9",
      :subscription => "sub_49ty4767H20z6a",
      :subscription_plan => "pro-monthly", # Switch to new plan
      :subscription_proration_date => proration_date)
    
    # Calculate the proration cost:
    current_prorations = invoice.lines.data.select { |ii| ii.period.start == proration_date }
    cost = 0
    current_prorations.each do |p|
      cost += p.amount
    end
    
    # 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_BQokikJOvBiI2HlWgH4olfQ2"
    
    # Set proration date to this moment:
    import time
    proration_date = int(time.time())
    
    # See what the next invoice would look like with a plan switch
    # and proration set:
    invoice = stripe.Invoice.upcoming(
      customer="cus_3R1W8PG2DmsmM9",
      subscription="sub_3R3PlB2YlJe84a",
      subscription_plan="pro-monthly", # Switch to new plan
      subscription_proration_date=proration_date)
    
    # Calculate the proration cost:
    current_prorations = [ii for ii in invoice.lines.data if ii.period.start == proration_date]
    cost = sum([p.amount for p in current_prorations])
    
    // 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_BQokikJOvBiI2HlWgH4olfQ2");
    
    // Set proration date to this moment:
    $proration_date = time();
    
    // See what the next invoice would look like with a plan switch
    // and proration set:
    $invoice = \Stripe\Invoice::upcoming(array(
      "customer" => "cus_3R1W8PG2DmsmM9",
      "subscription" => "sub_3R3PlB2YlJe84a",
      "subscription_plan" => "pro-monthly", # Switch to new plan
      "subscription_proration_date" => $proration_date
    ));
    
    // Calculate the proration cost:
    $cost = 0;
    $current_prorations = array();
    foreach ($invoice->lines->data as $line) {
      if ($line->period->start == $proration_date) {
        array_push($current_prorations, $line);
        $cost += $line->amount;
      }
    }
    
    // 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_BQokikJOvBiI2HlWgH4olfQ2";
    
    # Set proration date to this moment:
    long prorationDate = System.currentTimeMillis() / 1000L;
    
    # See what the next invoice would look like with a plan switch
    # and proration set:
    Map<String, Object> params = new HashMap<String, Object>();
    params.put("customer", "cus_3R1W8PG2DmsmM9");
    params.put("subscription", "sub_3R3PlB2YlJe84a");
    params.put("subscription_plan", "pro-monthly"); # Switch to new plan
    params.put("subscription_proration_date", prorationDate);
    
    Invoice invoice = Invoice.upcoming(params);
    
    # Calculate the proration cost:
    long cost = 0;
    List<InvoiceLineItem> currentProrations = new LinkedList<InvoiceLineItem>();
    for (InvoiceLineItem line: invoice.getLines().getData()) {
      if (line.getPeriod().getStart() == prorationDate) {
        currentProrations.add(line);
        cost += line.getAmount();
      }
    }
    
    // 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_BQokikJOvBiI2HlWgH4olfQ2");
    
    // Set proration date to this moment:
    var proration_date = Math.floor(Date.now() / 1000);
    
    // See what the next invoice would look like with a plan switch
    // and proration set:
    stripe.invoices.retrieveUpcoming(
      "cus_3R1W8PG2DmsmM9",
      "sub_3R3PlB2YlJe84a",
      {
        subscription_plan: 'pro-monthly', // Switch to new plan
        subscription_proration_date: proration_date
      },
      function(err, invoice) {
        // asynchronously called
        if (err === null) {
    
          // Calculate the proration cost:
          var current_prorations = [];
          var cost = 0;
          for (var i = 0; i < invoice.lines.data.length; i++) {
            var invoice_item = invoice.lines.data[i];
            if (invoice_item.period.start == proration_date) {
              current_prorations.push(invoice_item);
              cost += invoice_item.amount;
            }
          }
        } else {
          // handle error
        }
      }
    );
    
    // 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_BQokikJOvBiI2HlWgH4olfQ2"
    
    // Set the proration date to this moment:
    prorationDate := time.Now().Unix()
    
    // See what the next invoice would look like with a plan switch
    // and proration set:
    invoiceParams := &stripe.InvoiceParams{
      Customer: "cus_3R1W8PG2DmsmM9",
      Sub: "sub_3R3PlB2YlJe84a",
      SubPlan: "pro-monthly",
      SubProrationDate: prorationDate,
    }
    invoice, err := invoice.GetNext(invoiceParams)
    
    // Calculate the proration cost:
    var cost int64 = 0
    for _, invoiceItem := range invoice.Lines.Values {
      if (invoiceItem.Period.Start == prorationDate) {
        cost += invoiceItem.Amount
      }
    }
    

    After using the invoice items to calculate the cost of the proposed subscription change, you could confirm the amount with the customer before making the change. But because Stripe prorates to the second, the amount of the prorations can change slightly between the time they are previewed, and the time the update is actually performed. To avoid this problem, lock in the proration by passing a subscription_proration_date parameter (on an invoice, as in the above code) or proration_date parameter (on a subscription, in the following), which causes the proration to be calculated as though the change was made at that time.

    # 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_BQokikJOvBiI2HlWgH4olfQ2"
    
    # later...
    subscription = Stripe::Subscription.retrieve("sub_3R3PlB2YlJe84a")
    subscription.plan = "pro-monthly"
    subscription.proration_date = proration_date # Same value as before
    subscription.save
    
    # 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_BQokikJOvBiI2HlWgH4olfQ2"
    
    # later...
    subscription = stripe.Subscription.retrieve("sub_3R3PlB2YlJe84a")
    subscription.plan = "pro-monthly"
    subscription.proration_date = proration_date # Same value as before
    subscription.save()
    
    // 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_BQokikJOvBiI2HlWgH4olfQ2");
    
    // later...
    $subscription = \Stripe\Subscription::retrieve('sub_3R3PlB2YlJe84a');
    $subscription->plan = 'pro-monthly';
    $subscription->proration_date = $proration_date; // Same value as before
    $subscription->save();
    
    // 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_BQokikJOvBiI2HlWgH4olfQ2";
    
    // later...
    Subscription subscription = Subscription.retrieve("sub_3R3PlB2YlJe84a");
    
    Map<String, Object> params = new HashMap<String, Object>();
    params.put("plan", "pro-monthly");
    params.put("proration_date", prorationDate); # Same value as before
    
    subscription.update(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_BQokikJOvBiI2HlWgH4olfQ2");
    
    // later...
    stripe.subscriptions.update(
      "sub_3R3PlB2YlJe84a",
      {
        plan: "pro-monthly",
        proration_date: proration_date, // Same value as before
      },
      function(err, subscription) {
        // asynchronously called
      }
    );
    
    // 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_BQokikJOvBiI2HlWgH4olfQ2"
    
    // later...
    subscriptionParams := &stripe.SubParams{
      Plan: "pro-monthly",
      ProrationDate: prorationDate, // Same value as before
    }
    subscription, err := sub.Update("sub_3R3PlB2YlJe84a", subscriptionParams)
    

    Disabling prorations

    Prorating the costs of plans is the default behavior but you can disable proration by setting prorate to false when making a subscription change:

    curl https://api.stripe.com/v1/subscriptions/sub_49ty4767H20z6a \
       -u sk_test_BQokikJOvBiI2HlWgH4olfQ2: \
       -d plan=pro-monthly \
       -d prorate=false
    
    # 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_BQokikJOvBiI2HlWgH4olfQ2"
    
    subscription = Stripe::Subscription.retrieve("sub_49ty4767H20z6a")
    subscription.plan = "pro-monthly"
    subscription.prorate = false
    subscription.save
    # 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_BQokikJOvBiI2HlWgH4olfQ2"
    
    subscription = stripe.Subscription.retrieve("sub_49ty4767H20z6a")
    subscription.plan = "pro-monthly"
    subscription.prorate = False
    subscription.save()
    // 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_BQokikJOvBiI2HlWgH4olfQ2");
    
    $subscription = \Stripe\Subscription::retrieve("sub_49ty4767H20z6a");
    $subscription->plan = "pro-monthly";
    $subscription->prorate = false
    $subscription->save();
    // 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_BQokikJOvBiI2HlWgH4olfQ2";
    
    Subscription subscription = Subscription.retrieve("sub_49ty4767H20z6a");
    
    Map<String, Object> params = new HashMap<String, Object>();
    params.put("plan", "pro-monthly");
    params.put("prorate", false);
    subscription.update(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_BQokikJOvBiI2HlWgH4olfQ2");
    
    stripe.subscriptions.update("sub_49ty4767H20z6a", {
        plan: "pro-monthly",
        prorate: false,
      }, function(err, subscription) {
        // asynchronously called
      }
    );
    // 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_BQokikJOvBiI2HlWgH4olfQ2"
    
    params := &stripe.SubParams{
      Plan: "pro-monthly",
      Prorate: false,
    }
    subscription, err := sub.Update("sub_49ty4767H20z6a", params)

    With proration disabled, the customer is billed the full amount for the new plan when the next invoice is generated. You can choose to generate an invoice after making the switch to bill the customer sooner.

    Next steps

    Congrats! You know how to upgrade or downgrade a subscription. Some resources you might want to see next: