Billing
Additional features
Prorations

Prorations

Learn how prorations work and how to use them.

Prorations come 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, as they are billed in advance–at the start of each cycle.

When a customer’s subscription 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 option, they receive a credit for the unused portion of the subscription at the old price and are billed for only the remainder of the month for the new price.

The prorated amount is calculated down to the second by Stripe. We calculate the difference between the two subscriptions 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 price change.

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

# 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' # 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 price switch # and proration set: items = [{ id: subscription.items.data[0].id, price: 'price_CBb6IXqvTLXp3f', # Switch to new price }] 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 <= 1 } cost = 0 current_prorations.each do |p| cost += p.amount end
# 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' # 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 price switch # and proration set: items=[{ 'id': subscription['items']['data'][0].id, 'price': 'price_CBb6IXqvTLXp3f', # Switch to new price }] 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 <= 1] cost = sum([p.amount for p in current_prorations])
// 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'); // 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 price switch // and proration set: $items = [ [ 'id' => $subscription->items->data[0]->id, 'price' => 'price_CBb6IXqvTLXp3f', # Switch to new price ], ]; $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 <= 1) { array_push($current_prorations, $line); $cost += $line->amount; } }
// 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"; // 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 price switch // and proration set: InvoiceUpcomingParams params = InvoiceUpcomingParams.builder() .setCustomer("cus_4fdAW5ftNQow1a") .setSubscription("sub_49ty4767H20z6a") .addSubscriptionItem( InvoiceUpcomingParams.SubscriptionItem.builder() .setId(subscription.getItems().getData().get(0).getId()) .setPrice("price_CBb6IXqvTLXp3f") // Switch to new price .build()) .setSubscriptionProrationDate(prorationDate) .build(); Invoice invoice = Invoice.upcoming(params); // Calculate the proration cost: long cost = 0; List<InvoiceLineItem> currentProrations = new ArrayList<>(); for (InvoiceLineItem line: invoice.getLines().getData()) { if (line.getPeriod().getStart() - prorationDate <= 1) { currentProrations.add(line); cost += line.getAmount(); } }
// 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'); // 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 price switch // and proration set: const items = [{ id: subscription.items.data[0].id, price: 'price_CBb6IXqvTLXp3f', // Switch to new price }]; const invoice = await stripe.invoices.retrieveUpcoming({ customer: 'cus_4fdAW5ftNQow1a', subscription: '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 <= 1) { current_prorations.push(invoice_item); cost += invoice_item.amount; } }
// 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" // Set the proration date to this moment: prorationDate := time.Now().Unix() subscription, err := sub.Get("sub_49ty4767H20z6a", nil) // See what the next invoice would look like with a price switch // and proration set: items := []*stripe.SubscriptionItemsParams{ { ID: stripe.String(subscription.Items.Data[0].ID), Price: stripe.String("price_CBb6IXqvTLXp3f"), // Switch to new price }, } params := &stripe.InvoiceParams{ Customer: stripe.String("cus_4fdAW5ftNQow1a"), Subscription: stripe.String("sub_49ty4767H20z6a"), SubscriptionItems: items, SubscriptionProrationDate: stripe.Int64(prorationDate), } inv, err := invoice.GetNext(params) // Calculate the proration cost: var cost int64 = 0 for _, invoiceItem := range inv.Lines.Data { if (invoiceItem.Period.Start - prorationDate <= 1) { cost += invoiceItem.Amount } }
// 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"; // Set the proration date to this moment: DateTimeOffset prorationDate = DateTimeOffset.UtcNow; var subService = new SubscriptionService(); Subscription subscription = subService.Get("sub_49ty4767H20z6a"); // See what the next invoice would look like with a price switch // and proration set: var items = new List<InvoiceSubscriptionItemOptions> { new InvoiceSubscriptionItemOptions { Id = subscription.Items.Data[0].Id, Price = "price_CBb6IXqvTLXp3f", // Switch to new price }, }; var options = new UpcomingInvoiceOptions{ Customer = "cus_4fdAW5ftNQow1a", Subscription = "sub_49ty4767H20z6a", SubscriptionItems = items, SubscriptionProrationDate = prorationDate.UtcDateTime, }; var invService = new InvoiceService(); Invoice invoice = invService.Upcoming(options); // Calculate the proration cost: long cost = 0; foreach (var invoiceLineItem in invoice.Lines) { DateTimeOffset periodStart = new DateTimeOffset(invoiceLineItem.Period.Start.Value); if (periodStart.ToUnixTimeSeconds() - prorationDate.ToUnixTimeSeconds() <= 1) { cost += invoiceLineItem.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 switch 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.update( 'sub_49ty4767H20z6a', { items: [ { id: subscription.items.data[0].id, price: 'price_CBb6IXqvTLXp3f', }, ], proration_date: proration_date, } )
# 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' subscription = stripe.Subscription.modify( 'sub_49ty4767H20z6a', items=[{ 'id': subscription['items']['data'][0].id, 'price': 'price_CBb6IXqvTLXp3f', }], proration_date=proration_date, )
// 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'); $subscription = \Stripe\Subscription::retrieve('sub_49ty4767H20z6a'); \Stripe\Subscription::update('sub_49ty4767H20z6a', [ 'items' => [ [ 'id' => $subscription->items->data[0]->id, 'price' => 'price_CBb6IXqvTLXp3f', ], ], 'proration_date' => $proration_date, ]);
// 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"; Subscription subscription = Subscription.retrieve("sub_49ty4767H20z6a"); SubscriptionUpdateParams params = SubscriptionUpdateParams.builder() .addItem( SubscriptionUpdateParams.Item.builder() .setId(subscription.getItems().getData().get(0).getId()) .setPrice("price_CBb6IXqvTLXp3f") .build()) .setProrationDate(prorationDate) .build(); subscription.update(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'); const subscription = await stripe.subscriptions.retrieve('sub_49ty4767H20z6a'); stripe.subscriptions.update( 'sub_49ty4767H20z6a', { items: [{ id: subscription.items.data[0].id, price: 'price_CBb6IXqvTLXp3f', }], proration_date: proration_date, } );
// 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" subscription, err := sub.Get("sub_49ty4767H20z6a", nil) params := &stripe.SubscriptionParams{ Items: []*stripe.SubscriptionItemsParams{ { ID: stripe.String(subscription.Items.Data[0].ID), Price: stripe.String("price_CBb6IXqvTLXp3f"), }, }, ProrationDate: stripe.Int64(proration_date), } subscription, err = sub.Update("sub_49ty4767H20z6a", 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 service = new SubscriptionService(); Subscription subscription = service.Get("sub_49ty4767H20z6a"); var items = new List<SubscriptionItemOptions> { new SubscriptionItemOptions { Id = subscription.Items.Data[0].Id, Price = "price_CBb6IXqvTLXp3f", }, }; var prorationDate = DateTime.Now; var options = new SubscriptionUpdateOptions { Items = items, ProrationDate = prorationDate, }; subscription = service.Update("sub_49ty4767H20z6a", options);

Disabling prorations

Prorating is the default behavior but you can disable proration by setting proration_behavior to none when making a subscription change:

curl https://api.stripe.com/v1/subscriptions/sub_49ty4767H20z6a \ -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \ -d "items[0][id]"=si_1AkFf6LlRB0eXbMtRFjYiJ0J \ -d "items[0][price]"=price_CBb6IXqvTLXp3f \ -d proration_behavior=none
# 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' subscription = Stripe::Subscription.update( 'sub_49ty4767H20z6a', { items: [ { id: subscription.items.data[0].id, price: 'price_CBb6IXqvTLXp3f', }, ], proration_behavior: 'none', } )
# 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' subscription = stripe.Subscription.modify( 'sub_49ty4767H20z6a', items=[{ 'id': subscription['items']['data'][0].id, 'price': 'price_CBb6IXqvTLXp3f', }], proration_behavior='none', )
// 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'); $subscription = \Stripe\Subscription::retrieve('sub_49ty4767H20z6a'); \Stripe\Subscription::update('sub_49ty4767H20z6a', [ 'items' => [ [ 'id' => $subscription->items->data[0]->id, 'price' => 'price_CBb6IXqvTLXp3f', ], ], 'proration_behavior' => 'none', ]);
// 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"; Subscription subscription = Subscription.retrieve("sub_49ty4767H20z6a"); SubscriptionUpdateParams params = SubscriptionUpdateParams.builder() .addItem( SubscriptionUpdateParams.Item.builder() .setId(subscription.getItems().getData().get(0).getId()) .setPrice("price_CBb6IXqvTLXp3f") .build()) .setProrationBehavior(SubscriptionUpdateParams.ProrationBehavior.NONE) .build(); subscription.update(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'); const subscription = await stripe.subscriptions.retrieve('sub_49ty4767H20z6a'); stripe.subscriptions.update('sub_49ty4767H20z6a', { items: [{ id: subscription.items.data[0].id, price: 'price_CBb6IXqvTLXp3f', }], proration_behavior: 'none', });
// 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" subscription, err := sub.Get("sub_49ty4767H20z6a", nil) params := &stripe.SubscriptionParams{ Items: []*stripe.SubscriptionItemsParams{ { ID: stripe.String(subscription.Items.Data[0].ID), Price: stripe.String("price_CBb6IXqvTLXp3f"), }, }, ProrationBehavior: stripe.String(string(stripe.SubscriptionProrationBehaviorNone)), } subscription, err = sub.Update("sub_49ty4767H20z6a", 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 service = new SubscriptionService(); Subscription subscription = service.Get("sub_49ty4767H20z6a"); var items = new List<SubscriptionItemOptions> { new SubscriptionItemOptions { Id = subscription.Items.Data[0].Id, Price = "price_CBb6IXqvTLXp3f", }, }; var options = new SubscriptionUpdateOptions { Items = items, ProrationBehavior = "none", }; subscription = service.Update("sub_49ty4767H20z6a", options);

With proration disabled, the customer is billed the full amount at the new price when the next invoice is generated.

Was this page helpful?
Questions? Contact us.
Developer tutorials on YouTube.
You can unsubscribe at any time. Read our privacy policy.