Billing
Additional features
Prorations

Prorations

Learn about prorations.

Changes to a subscription such as upgrading or downgrading can result in prorated charges. For example, if a customer upgrades from a 10 USD per month subscription to a 20 USD option, they’re charged prorated amounts for the time spent on each option. Assuming the change occurred halfway through the billing period, the customer is billed an additional 5 USD: -5 USD for unused time on the initial price, and 10 USD for the remaining time on the new price.

The prorated amount is calculated as soon as the API updates the subscription. The current billing period’s start and end times are used to calculate the cost of the subscription before and after the change.

Preview a proration

You can retrieve an upcoming invoice to preview changes to a subscription. This API call doesn’t modify the subscription, it returns the upcoming invoice based only on the parameters that you pass. Changing the price or quantity both result in a proration. This example changes the price and sets a date for the proration.

# 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, })
# 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, )
// 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, ]);
// 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);
// 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, });
// 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)
// 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);

You can expand the example response below to see:

  • The credit for unused time at the previous price on lines 36-38.
  • The cost for time spent at the new price on lines 107-109.
  • The new subtotal and total for the invoice on lines 276-279.
{ "account_country": "US", "account_name": "Test account", "amount_due": 3627, "amount_paid": 0, "amount_remaining": 3627, "application_fee_amount": null, "attempt_count": 0, "attempted": false, "billing_reason": "upcoming",
See all 284 lines "charge": null, "collection_method": "charge_automatically", "created": 1599427688, "currency": "usd", "custom_fields": null, "customer": "cus_DGEhAXrZWrzdYs", "customer_address": null, "customer_email": "jenny.rosen@example.com", "customer_name": null, "customer_phone": null, "customer_shipping": null, "customer_tax_exempt": "none", "customer_tax_ids": [], "default_payment_method": null, "default_source": null, "default_tax_rates": [], "description": null, "discount": null, "discounts": [], "due_date": null, "ending_balance": 0, "footer": null, "lines": { "data": [ { "amount": -166, "currency": "usd", "description": "Unused time on Silver plan after 01 Sep 2020", "discount_amounts": [], "discountable": false, "discounts": [], "id": "il_tmp1HMdV2AJVYItwOKqQi4H", "invoice_item": "ii_1HMdV2AJVYItwUH1Qi4H", "livemode": false, "metadata": {}, "object": "line_item", "period": { "end": 1599427688, "start": 1598982148 }, "plan": { "active": true, "aggregate_usage": null, "amount": 1000, "amount_decimal": "1000", "billing_scheme": "per_unit", "created": 1585856460, "currency": "usd", "id": "price_H1c8v1lifcd", "interval": "month", "interval_count": 1, "livemode": false, "metadata": {}, "nickname": null, "object": "plan", "product": "prod_c7exjJHbC4", "tiers": null, "tiers_mode": null, "transform_usage": null, "trial_period_days": null, "usage_type": "licensed" }, "price": { "active": true, "billing_scheme": "per_unit", "created": 1585856460, "currency": "usd", "id": "price_c8v1liEvrf", "livemode": false, "lookup_key": null, "metadata": {}, "nickname": null, "object": "price", "product": "prod_c7exjJHbC4", "recurring": { "aggregate_usage": null, "interval": "month", "interval_count": 1, "trial_period_days": null, "usage_type": "licensed" }, "tiers_mode": null, "transform_quantity": null, "type": "recurring", "unit_amount": 1000, "unit_amount_decimal": "1000" }, "proration": true, "quantity": 1, "subscription": "sub_H38lqYjDO0DSzl", "subscription_item": "si_H38lIMagWoFx0W", "tax_amounts": [], "tax_rates": [], "type": "invoiceitem" }, { "amount": 541, "currency": "usd", "description": "Remaining time on Gold plan after 01 Sep 2020", "discount_amounts": [], "discountable": false, "discounts": [], "id": "il_tmp1HMdV2AJVYItwOKqDcgkmpzz", "invoice_item": "ii_1HMdV2AJVYItwOKqDcgkmpzz", "livemode": false, "metadata": {}, "object": "line_item", "period": { "end": 1599427688, "start": 1598982148 }, "plan": { "active": true, "aggregate_usage": null, "amount": 3252, "amount_decimal": "3252", "billing_scheme": "per_unit", "created": 1598473039, "currency": "usd", "id": "price_KV3bAJVYItwOKq16frkr", "interval": "month", "interval_count": 1, "livemode": false, "metadata": {}, "nickname": null, "object": "plan", "product": "prod_JfJiw2l6ke", "tiers": null, "tiers_mode": null, "transform_usage": null, "trial_period_days": null, "usage_type": "licensed" }, "price": { "active": true, "billing_scheme": "per_unit", "created": 1598473039, "currency": "usd", "id": "price_KV3bAJVYItwOKq16frkr", "livemode": false, "lookup_key": null, "metadata": {}, "nickname": null, "object": "price", "product": "prod_JfJiw2l6ke", "recurring": { "aggregate_usage": null, "interval": "month", "interval_count": 1, "trial_period_days": null, "usage_type": "licensed" }, "tiers_mode": null, "transform_quantity": null, "type": "recurring", "unit_amount": 3252, "unit_amount_decimal": "3252" }, "proration": true, "quantity": 1, "subscription": "sub_H38lqYjDO0DSzl", "subscription_item": "si_H38lIMagWoFx0W", "tax_amounts": [], "tax_rates": [], "type": "invoiceitem" }, { "amount": 3252, "currency": "usd", "description": "1 \u00d7 Gold product (at $32.52 / month)", "discount_amounts": [], "discountable": true, "discounts": [], "id": "il_tmp_7fc9ba9b6aa9aa", "livemode": false, "metadata": {}, "object": "line_item", "period": { "end": 1602019688, "start": 1599427688 }, "plan": { "active": true, "aggregate_usage": null, "amount": 3252, "amount_decimal": "3252", "billing_scheme": "per_unit", "created": 1598473039, "currency": "usd", "id": "price_KV3bAJVYItwOKq16frkr", "interval": "month", "interval_count": 1, "livemode": false, "metadata": {}, "nickname": null, "object": "plan", "product": "prod_JfJiw2l6ke", "tiers": null, "tiers_mode": null, "transform_usage": null, "trial_period_days": null, "usage_type": "licensed" }, "price": { "active": true, "billing_scheme": "per_unit", "created": 1598473039, "currency": "usd", "id": "price_KV3bAJVYItwOKq16frkr", "livemode": false, "lookup_key": null, "metadata": {}, "nickname": null, "object": "price", "product": "prod_JfJiw2l6ke", "recurring": { "aggregate_usage": null, "interval": "month", "interval_count": 1, "trial_period_days": null, "usage_type": "licensed" }, "tiers_mode": null, "transform_quantity": null, "type": "recurring", "unit_amount": 3252, "unit_amount_decimal": "3252" }, "proration": false, "quantity": 1, "subscription": "sub_H38lqYjDO0DSzl", "subscription_item": "si_H38lIMagWoFx0W", "tax_amounts": [], "tax_rates": [], "type": "subscription" } ], "has_more": false, "object": "list", "total_count": 3, "url": "/v1/invoices/upcoming/lines?customer=cus_EhAXrZWrzd&subscription=sub_8lqYjDO0DS" }, "livemode": false, "metadata": {}, "next_payment_attempt": 1599431288, "number": null, "object": "invoice", "paid": false, "payment_intent": null, "period_end": 1599427688, "period_start": 1596749288, "post_payment_credit_notes_amount": 0, "pre_payment_credit_notes_amount": 0, "receipt_number": null, "starting_balance": 0, "statement_descriptor": null, "status": "draft", "status_transitions": { "finalized_at": null, "marked_uncollectible_at": null, "paid_at": null, "voided_at": null }, "subscription": "sub_8lqYjDO0DS", "subscription_proration_date": 1598982148, "subtotal": 3627, "tax": null, "tax_percent": null, "total": 3627, "total_discount_amounts": [], "total_tax_amounts": [], "transfer_data": null, "webhooks_delivered_at": null }

You can use this information to confirm the changes with the customer before modifying the subscription. Because Stripe prorates to the second, prorated amounts can change between the time they’re previewed and the time the update is made. To avoid this, pass in a subscription_proration_date to the invoice when you preview a change. When you update the subscription, you can pass the same date using the proration_date parameter on a subscription so that the proration is calculated at the same 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);

Disable prorations

Prorating is the default behavior, but you can disable it by setting proration_behavior to none:

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);

When prorations are disabled, customers are billed the full amount at the new price when the next invoice is generated.