Metered Billing

Metered billing lets you charge customers based on how much they use your product during a billing cycle, rather than a fixed price. For example, you might charge per API call, per email sent, or per GB of storage used.

Setting up a metered subscription

First, create a product with a metered price in your Stripe dashboard. The price must be linked to a Billing Meter that tracks the usage events.

Then, create a subscription using meteredPrice:

start/routes.ts
router.get('/subscribe', async ({ auth, request }) => {
  const user = auth.getUserOrFail()
  const paymentMethodId = request.input('paymentMethodId')

  await user.newSubscription('default').meteredPrice('price_metered').create(paymentMethodId)
})

You can also start a metered subscription via Stripe Checkout:

const checkout = await user
  .newSubscription('default')
  .meteredPrice('price_metered')
  .checkout({
    success_url: urlFor('checkout.success'),
    cancel_url: urlFor('checkout.cancel'),
  })

Reporting usage

As your customers use your product, report their usage to Stripe. You can use the reportUsage method on a subscription:

const subscription = await user.subscription('default')

// Report a single unit of usage
await subscription.reportUsage('api_calls')

// Report a larger quantity
await subscription.reportUsage('api_calls', '150')

If the subscription has multiple metered prices, specify which one:

await subscription.reportUsageFor('price_metered', 'api_calls', '150')

You can also use the Stripe SDK directly for more control:

import shopkeeper from '@foadonis/shopkeeper/services/shopkeeper'

const stripe = shopkeeper.stripe

await stripe.billing.meterEvents.create({
  event_name: 'api_calls',
  payload: {
    stripe_customer_id: user.stripeId,
    value: '150',
  },
})

The event_name must match the Billing Meter you created in the Stripe dashboard. The value is always a string.

Retrieving usage records

To view a customer's past usage for a subscription:

const subscription = await user.subscription('default')
const usageRecords = await subscription.usageRecords(meterId, {
  start_time: startTimestamp,
  end_time: endTimestamp,
})

If the subscription has multiple metered prices, specify which one:

const usageRecords = await subscription.usageRecordsFor('price_metered', meterId, {
  start_time: startTimestamp,
  end_time: endTimestamp,
})

You can display usage records in a template:

@each(record in usageRecords)
  <p>
    Period: {{ record.period.start }} - {{ record.period.end }}
    Usage: {{ record.total_usage }}
  </p>
@end

For pagination and the full usage record API, see the Stripe usage records documentation.

Going further

On this page