Prorations

    Learn how prorations work and how to use them.

    Proration comes into play when a customer receives service for only part of the billing cycle. There are several cases where this can occur, notably when upgrading or downgrading a subscription during the billing cycle. Proration is only applicable to licensed (per-seat) subscriptions, because they are charged in advance–at the start of each billing cycle.

    When a customer’s plan changes during a billing cycle, a proration line item is applied on their next invoice. If a customer whose subscription is billed on the first of the month changes to a more expensive plan, they receive a credit for the unused portion of the old plan and are billed for only the remainder of the month for the new plan.

    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). When credits are created, they’ll continue to apply to subsequent invoices until the credit is covered and payment is due again.

    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 proration

    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
    
    subscription = Stripe::Subscription.retrieve('sub_49ty4767H20z6a')
    
    # See what the next invoice would look like with a plan switch
    # and proration set:
    items = [{
        id: subscription.items.data[0].id,
        plan: 'plan_CBb6IXqvTLXp3f', # Switch to new plan
    }]
    
    invoice = Stripe::Invoice.upcoming({
        customer: 'cus_4fdAW5ftNQow1a',
        subscription: 'sub_49ty4767H20z6a',
        subscription_items: items,
        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())
    
    subscription = stripe.Subscription.retrieve('sub_49ty4767H20z6a')
    
    # See what the next invoice would look like with a plan switch
    # and proration set:
    items=[{
      'id': subscription['items']['data'][0].id,
      'plan': 'plan_CBb6IXqvTLXp3f', # Switch to new plan
    }]
    
    invoice = stripe.Invoice.upcoming(
      customer='cus_4fdAW5ftNQow1a',
      subscription='sub_49ty4767H20z6a',
      subscription_items=items,
      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();
    
    $subscription = \Stripe\Subscription::retrieve('sub_49ty4767H20z6a');
    
    // See what the next invoice would look like with a plan switch
    // and proration set:
    $items = [
        [
            'id' => $subscription->items->data[0]->id,
            'plan' => 'plan_CBb6IXqvTLXp3f', # Switch to new plan
        ],
    ];
    
    $invoice = \Stripe\Invoice::upcoming([
        'customer' => 'cus_4fdAW5ftNQow1a',
        'subscription' => 'sub_49ty4767H20z6a',
        'subscription_items' => $items,
        'subscription_proration_date' => $proration_date,
    ]);
    
    // Calculate the proration cost:
    $cost = 0;
    $current_prorations = [];
    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;
    
    Subscription subscription = Subscription.retrieve("sub_49ty4767H20z6a");
    
    // See what the next invoice would look like with a plan switch
    // and proration set:
    Map<String, Object> item = new HashMap<>();
    item.put("id", subscription.getSubscriptionItems().getData().get(0).getId());
    item.put("plan", "plan_CBb6IXqvTLXp3f"); // Switch to new plan
    Map<String, Object> items = new HashMap<>();
    items.put("0", item);
    
    Map<String, Object> params = new HashMap<>();
    params.put("customer", "cus_4fdAW5ftNQow1a");
    params.put("subscription", "sub_49ty4767H20z6a");
    params.put("subscription_items", items);
    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:
    const proration_date = Math.floor(Date.now() / 1000);
    
    const subscription = await stripe.subscriptions.retrieve('sub_49ty4767H20z6a');
    
    // See what the next invoice would look like with a plan switch
    // and proration set:
    const items = [{
      id: subscription.items.data[0].id,
      plan: 'plan_CBb6IXqvTLXp3f', // Switch to new plan
    }];
    
    const invoice = await stripe.invoices.retrieveUpcoming('cus_4fdAW5ftNQow1a', 'sub_49ty4767H20z6a', {
      subscription_items: items,
      subscription_proration_date: proration_date,
    });
    
    // Calculate the proration cost:
    const current_prorations = [];
    var cost = 0;
    for (var i = 0; i < invoice.lines.data.length; i++) {
      const invoice_item = invoice.lines.data[i];
      if (invoice_item.period.start == proration_date) {
        current_prorations.push(invoice_item);
        cost += invoice_item.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.Key = "sk_test_BQokikJOvBiI2HlWgH4olfQ2"
    
    // Set the proration date to this moment:
    prorationDate := time.Now().Unix()
    
    susbscription, err := sub.Get("sub_49ty4767H20z6a", nil)
    
    // See what the next invoice would look like with a plan switch
    // and proration set:
    items := []*stripe.SubItemsParams{
      {
        ID: subscription.Items.Values[0].ID,
        Plan: "plan_CBb6IXqvTLXp3f", // Switch to new plan
      },
    }
    
    params := &stripe.InvoiceParams{
      Customer: "cus_4fdAW5ftNQow1a",
      Sub: "sub_49ty4767H20z6a",
      SubItems: items,
      SubProrationDate: prorationDate,
    }
    inv, err := invoice.GetNext(params)
    
    // Calculate the proration cost:
    var cost int64 = 0
    for _, invoiceItem := range invoice.Lines.Values {
      if (invoiceItem.Period.Start == prorationDate) {
        cost += invoiceItem.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
    StripeConfiguration.SetApiKey("sk_test_BQokikJOvBiI2HlWgH4olfQ2");
    
    // Set the proration date to this moment:
    long timeStamp = DateTimeOffset.Now.ToUnixTimeSeconds();
    
    var subService = new StripeSubscriptionService();
    StripeSubscription subscription = subService.Get("sub_49ty4767H20z6a");
    
    // See what the next invoice would look like with a plan switch
    // and proration set:
    var items = new List<StripeSubscriptionItemOption> {
        new StripeSubscriptionItemOption {
            Id: subscription.Items.Data[0].Id,
            PlanId = "plan_CBb6IXqvTLXp3f", // Switch to new plan
        },
    };
    
    var options = new StripeSubscriptionUpdateOptions{
        SubscriptionItems = items,
        SubscriptionProrationDate = timeStamp,
    };
    
    var invService = new StripeInvoiceService();
    StripeInvoice invoice = invService.Upcoming("cus_4fdAW5ftNQow1a", options)
    
    // Calculate the proration cost:
    int cost = 0;
    foreach (var invoiceItem in invoice) {
      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"
    
    subscription = Stripe::Subscription.retrieve('sub_49ty4767H20z6a')
    subscription.items = [
        {
            id: subscription.items.data[0].id,
            plan: 'plan_CBb6IXqvTLXp3f',
        },
    ]
    subscription.proration_date = proration_date
    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')
    stripe.Subscription.modify('sub_49ty4767H20z6a',
      items=[{
        'id': subscription['items']['data'][0].id,
        'plan': 'plan_CBb6IXqvTLXp3f',
      }],
      proration_date=proration_date,
    )
    
    // 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');
    \Stripe\Subscription::update('sub_49ty4767H20z6a', [
        'items' => [
            [
                'id' => $subscription->items->data[0]->id,
                'plan' => 'plan_CBb6IXqvTLXp3f',
            ],
        ],
        'proration_date' => $proration_date,
    ]);
    
    // 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> item = new HashMap<>();
    item.put("id", subscription.getSubscriptionItems().getData().get(0).getId());
    item.put("plan", "plan_CBb6IXqvTLXp3f");
    
    Map<String, Object> items = new HashMap<>();
    items.put("0", item);
    
    Map<String, Object> items = new HashMap<>();
    params.put("items", items);
    params.put("proration_date", prorationDate);
    
    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");
    
    const subscription = await stripe.subscriptions.retrieve('sub_49ty4767H20z6a');
    stripe.subscriptions.update('sub_49ty4767H20z6a', {
      items: [{
        id: subscription.items.data[0].id,
        plan: 'plan_CBb6IXqvTLXp3f',
      }]
      proration_date: proration_date,
    });
    
    // 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"
    
    subscription, err := sub.Get("sub_49ty4767H20z6a", nil)
    params := &stripe.SubParams{
      Items: []*stripe.SubItemsParams{
        {
          ID: subscription.Items.Values[0].ID,
          Plan: "plan_CBb6IXqvTLXp3f",
        },
      },
      ProrationDate: proration_date,
    }
    subscription, err = sub.Update("sub_49ty4767H20z6a", 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_BQokikJOvBiI2HlWgH4olfQ2");
    
    var service = new StripeSubscriptionService();
    StripeSubscription subscription = service.Get("sub_49ty4767H20z6a");
    
    var items = new List<StripeSubscriptionItemOption> {
        new StripeSubscriptionItemOption {
            Id: subscription.Items.Data[0].Id,
            PlanId = "plan_CBb6IXqvTLXp3f",
        },
    };
    var options = new StripeSubscriptionUpdateOptions {
        Items = items,
        ProrationDate = prorationDate,
    };
    StripeSubscription subscription = service.Update("sub_49ty4767H20z6a", options);
    

    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 items[0][id]=si_1AkFf6LlRB0eXbMtRFjYiJ0J \
       -d items[0][plan]=plan_CBb6IXqvTLXp3f \
       -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.items = [
        {
            id: subscription.items.data[0].id,
            plan: 'plan_CBb6IXqvTLXp3f',
        },
    ]
    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')
    stripe.Subscription.modify('sub_49ty4767H20z6a',
      items=[{
        'id': subscription['items']['data'][0].id,
        'plan': 'plan_CBb6IXqvTLXp3f',
      }],
      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\Stripe::setApiKey("sk_test_BQokikJOvBiI2HlWgH4olfQ2");
    
    $subscription = \Stripe\Subscription::retrieve('sub_49ty4767H20z6a');
    \Stripe\Subscription::update('sub_49ty4767H20z6a', [
        'items' => [
            [
                'id' => $subscription->items->data[0]->id,
                'plan' => 'plan_CBb6IXqvTLXp3f',
            ],
        ],
        '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.apiKey = "sk_test_BQokikJOvBiI2HlWgH4olfQ2";
    
    Subscription subscription = Subscription.retrieve("sub_49ty4767H20z6a");
    
    Map<String, Object> item = new HashMap<>();
    item.put("id", subscription.getSubscriptionItems().getData().get(0).getId());
    item.put("plan", "plan_CBb6IXqvTLXp3f");
    
    Map<String, Object> items = new HashMap<>();
    items.put("0", item);
    
    Map<String, Object> params = new HashMap<>();
    params.put("items", items);
    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");
    
    const subscription = await stripe.subscriptions.retrieve('sub_49ty4767H20z6a');
    stripe.subscriptions.update('sub_49ty4767H20z6a', {
      items: [{
        id: subscription.items.data[0].id,
        plan: 'plan_CBb6IXqvTLXp3f',
      }]
      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.Key = "sk_test_BQokikJOvBiI2HlWgH4olfQ2"
    
    subscription, err := sub.Get("sub_49ty4767H20z6a", nil)
    params := &stripe.SubParams{
      Items: []*stripe.SubItemsParams{
        {
          ID: subscription.Items.Values[0].ID,
          Plan: "plan_CBb6IXqvTLXp3f",
        },
      },
      NoProrate: true,
    }
    subscription, err = sub.Update("sub_49ty4767H20z6a", 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_BQokikJOvBiI2HlWgH4olfQ2");
    
    var service = new StripeSubscriptionService();
    StripeSubscription subscription = service.Get("sub_49ty4767H20z6a");
    
    var items = new List<StripeSubscriptionItemOption> {
        new StripeSubscriptionItemOption {
            Id: subscription.Items.Data[0].Id,
            PlanId = "plan_CBb6IXqvTLXp3f",
        },
    };
    var options = new StripeSubscriptionUpdateOptions {
        Items = items,
        Prorate = false,
    };
    StripeSubscription subscription = service.Update("sub_49ty4767H20z6a", options);
    

    With proration disabled, the customer is billed the full amount for the new plan when the next invoice is generated. The customer is still moved to the new plan immediately, however, even though they don’t pay for the new plan until the next billing cycle.

    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.