Metered Billing

    Learn how to record usage and bill for it at the end of a subscription period.

    Metered billing is useful in cases where you want to charge your customers a granular amount based on their consumption of your service during the billing cycle, instead of explicitly setting quantities. For example, if you are running an email SaaS business, you can track your customers’ API calls, then bill them for the total number used at the end of each month.

    Creating a metered billing plan

    To use metered billing, create a new plan, configure it with metered as the usage_type, and attach it to an existing product. Specify the desired amount, interval, and currency. With a metered plan, the amount is billed per unit of consumption. Note that we also support tiered pricing, which means we can dynamically adjust the price per unit depending on the total amount of units sold within a period.

    curl https://api.stripe.com/v1/plans \
       -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
       -d amount=3000 \
       -d interval=month \
       -d product=prod_BljM5US9aCw4AY \
       -d currency=usd \
       -d usage_type=metered
    
    # 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"
    
    plan = Stripe::Plan.create({
        currency: 'usd',
        interval: 'month',
        product: 'prod_CHxGUqw1dyKsDM',
        nickname: 'Pro Plan',
        amount: 3000,
        usage_type: 'metered',
    })
    
    # 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"
    
    plan = stripe.Plan.create(
      currency='usd',
      interval='month',
      product='prod_CHxGUqw1dyKsDM',
      nickname='Pro Plan',
      amount=3000,
      usage_type='metered',
    )
    
    // 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");
    
    $plan = \Stripe\Plan::create([
        'currency' => 'usd',
        'interval' => 'month',
        'product' => 'prod_CHxGUqw1dyKsDM',
        'nickname' => 'Pro Plan',
        'amount' => 3000,
        'usage_type' => 'metered',
    ]);
    
    // 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> params = new HashMap<>();
    params.put("currency", "usd");
    params.put("interval", "month");
    params.put("product", "prod_CHxGUqw1dyKsDM");
    params.put("nickname", "Pro Plan");
    params.put("amount", 3000);
    params.put("usage_type", "metered");
    Plan plan = Plan.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 plan = stripe.plans.create({
      currency: 'usd',
      interval: 'month',
      product: 'prod_CHxGUqw1dyKsDM',
      nickname: 'Pro Plan',
      amount: 3000,
      usage_type: 'metered',
    });
    
    // 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"
    
    params := &stripe.PlanParams{
        Currency: stripe.String(string(stripe.CurrencyUSD)),
        Interval: stripe.String(string(stripe.PlanIntervalMonth)),
        ProductID: stripe.String("prod_CHxGUqw1dyKsDM"),
        Nickname: stripe.String("Pro Plan"),
        Amount: stripe.Int64(3000),
        UsageType: stripe.String(string(stripe.PlanUsageTypeMetered)),
    }
    pro, _ := plan.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 options = new StripePlanCreateOptions {
        Currency = "usd",
        Interval = "month",
        Nickname = "Pro Plan",
        Amount = 3000,
        ProductId = "prod_CHxGUqw1dyKsDM",
        UsageType = "metered",
    };
    var service = new StripePlanService();
    StripePlan plan = service.Create(options);
    

    To subscribe a customer to the plan, create or update a subscription via the API endpoint, and do not specify a quantity—metered billing doesn’t use the subscription item quantity attribute. When you create the subscription, Stripe returns the subscription item record, which includes an ID. You should save this ID and associate it with the user, because it is used for usage reporting.

    By default, Stripe computes the total usage to be billed at invoice time by summing up all quantity values of subsequent usage records written with a billing period. When creating a plan, you can use the aggregate_usage parameter to configure alternative behaviors:

    • By setting the parameter to last_during_period, the latest usage record written during a period will determine the quantity for which to invoice. If no usage records are present during the given period, Stripe will invoice for the quantity of 0.
    • By setting the parameter to last_ever, the latest usage record ever written will determine the quantity for which to invoice. This means that even if no usage has been reported within a given period, Stripe will seek further back in time to find a usage record. If no usage records are present at all, Stripe will invoice for the quantity of 0.
    • By setting the parameter to max, the quantity for which to invoice is determined by looking through all usage records reported during a given period, and picking the maximum quantity. If no usage records are present during the given period, Stripe will invoice for the quantity of 0.

    Reporting usage

    In order for Stripe to compute the number of units at invoice time, you must report the customer’s usage by creating usage records on the subscription item, with the ID that you saved in the previous step.

    The Usage API call includes a timestamp, quantity, and action. The increment action adds the quantity to the usage total for the specified timestamp. The set action overwrites the usage for the specified timestamp.

    • If you preaggregate usage yourself, Stripe recommends periodically writing the current value, with the current timestamp and action=set, as the usage record. The underlying plan can be configured as aggregate_usage=last_during_period or aggregate_usage=last_ever.
    • If you do not aggregate usage on your end, you can write usage as it occurs, and use action=increment with the current timestamp. The underlying plan should be configured as aggregate_usage=sum. Reserve the set action for the unusual case where you need to make a usage adjustment.

    Note that reporting usage outside of the current billing interval results in an error. Stripe leaves a five-minute window in the default aggregation mode (aggregate_usage=sum) around the period end to allow for clock drift. For all other aggregation modes the timestamp must be within the current period.

    curl https://api.stripe.com/v1/subscription_items/{{SUBSCRIPTION_ITEM_ID}}/usage_records \
       -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
       -X POST \
       -d quantity=100 \
       -d timestamp=1522893428 \
       -d action=increment
    
    # 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"
    
    Stripe::UsageRecord.create(
      quantity: 100,
      timestamp: 1522893428,
      subscription_item: '{{SUBSCRIPTION_ITEM_ID}}',
      action: 'increment'
    )
    
    
    # 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"
    
    stripe.UsageRecord.create(
      quantity=100,
      timestamp=1522893428,
      subscription_item='{{SUBSCRIPTION_ITEM_ID}}',
      action='increment'
    )
    
    
    // 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");
    
    \Stripe\UsageRecord::create(array(
      "quantity" => 100,
      "timestamp" => 1522893428,
      "subscription_item" => "{{SUBSCRIPTION_ITEM_ID}}",
      "action" => "increment"
    ));>
    
    
    // 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> usageRecordParams = new HashMap<String, Object>();
    usageRecordParams.put("quantity", 100);
    usageRecordParams.put("timestamp", 1522893428);
    usageRecordParams.put("subscription_item", "{{SUBSCRIPTION_ITEM_ID}}");
    usageRecordParams.put("action", "increment");
    
    UsageRecord.create(usageRecordParams);
    
    
    // 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");
    
    stripe.usageRecords.create("{{SUBSCRIPTION_ITEM_ID}}", {
      quantity: 100,
      timestamp: 1522893428,
      action: "increment"
    });
    
    
    // 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"
    
    params := &stripe.UsageRecordParams{
      Quantity: stripe.Int64(100),
      Timestamp: stripe.Int64(1522893428),
      SubscriptionItem: stripe.String("{{SUBSCRIPTION_ITEM_ID}}"),
      Action: stripe.String(string(stripe.UsageRecordActionIncrement)),
    }
    ur, _ := usagerecord.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 usageRecordOptions = new StripeUsageRecordCreateOptions() {
      Quantity = 100,
      Timestamp = 1522893428,
      SubscriptionItem = "{{SUBSCRIPTION_ITEM_ID}}",
      Action = "increment"
    };
    var usageRecordService = new StripeUsageRecordService();
    StripeUsageRecord usageRecord = usageRecordService.Create(usageRecordOptions)
    
    

    Note: Using an idempotency key lets you safely re-report usage in the event of intermittent API errors.

    At the end of a subscription period, Stripe automatically totals and invoices for all usage during the billing period. Metered billing invoices respect trials. Note that once the invoice is submitted, it cannot be changed. The usage reporting endpoint is rate-limited, so you might need to exercise caution and avoid making too many separate usage records.

    When canceling a subscription at the end of the period, any usage reported before the subscription ends is billed in a final invoice at the end of the period. Canceling a subscription immediately does not bill for any usage accrued during the final billing cycle.

    Retrieving current usage

    To retrieve total usage for the current period, you can retrieve the upcoming invoice for the subscription. The usage is reflected as the quantity of the invoice item for a subscription_item.

    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.