DEV Community

Atlas Whoff
Atlas Whoff

Posted on

Stripe Metered Billing: Usage-Based Pricing for SaaS APIs

Stripe Metered Billing: Usage-Based Pricing for SaaS APIs

Fixed-price subscriptions leave money on the table for API-heavy products. Metered billing charges users exactly for what they consume — better for customers, better for retention.

Why Metered Billing

Fixed pricing: customer pays $49/mo whether they use 10 API calls or 10,000.

Metered pricing: customer pays for exactly what they consume. Power users pay more (higher revenue), light users stay (lower churn).

Setting Up a Metered Price in Stripe

import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);

// Create a metered price
const price = await stripe.prices.create({
  currency: 'usd',
  recurring: {
    interval: 'month',
    usage_type: 'metered',
  },
  product_data: { name: 'API Calls' },
  unit_amount: 1, // $0.001 per unit = $0.001 per API call
});
Enter fullscreen mode Exit fullscreen mode

Reporting Usage

// Report usage after each API call
async function trackApiUsage(subscriptionItemId: string, quantity: number = 1) {
  await stripe.subscriptionItems.createUsageRecord(
    subscriptionItemId,
    {
      quantity,
      timestamp: Math.floor(Date.now() / 1000),
      action: 'increment',
    }
  );
}

// Use in your API middleware
app.use('/api', async (req, res, next) => {
  await trackApiUsage(req.user.stripeSubscriptionItemId);
  next();
});
Enter fullscreen mode Exit fullscreen mode

Tiered Pricing

Reward high-volume users with lower per-unit costs:

const price = await stripe.prices.create({
  currency: 'usd',
  recurring: { interval: 'month', usage_type: 'metered' },
  billing_scheme: 'tiered',
  tiers_mode: 'graduated',
  tiers: [
    { up_to: 1000, unit_amount: 5 },    // $0.05 per call, first 1000
    { up_to: 10000, unit_amount: 3 },   // $0.03 per call, 1001-10000
    { up_to: 'inf', unit_amount: 1 },   // $0.01 per call, 10001+
  ],
  product_data: { name: 'API Calls - Tiered' },
});
Enter fullscreen mode Exit fullscreen mode

Handling the Checkout Session

const session = await stripe.checkout.sessions.create({
  mode: 'subscription',
  payment_method_types: ['card'],
  line_items: [{
    price: price.id,
  }],
  success_url: `${process.env.NEXT_PUBLIC_URL}/dashboard?session_id={CHECKOUT_SESSION_ID}`,
  cancel_url: `${process.env.NEXT_PUBLIC_URL}/pricing`,
});
Enter fullscreen mode Exit fullscreen mode

Webhook: Store the Subscription Item ID

// In your webhook handler
if (event.type === 'checkout.session.completed') {
  const session = event.data.object;
  const subscription = await stripe.subscriptions.retrieve(session.subscription as string);
  const subscriptionItemId = subscription.items.data[0].id;

  // Store this on the user — needed for usage reporting
  await db.user.update({
    where: { stripeCustomerId: session.customer as string },
    data: { stripeSubscriptionItemId: subscriptionItemId },
  });
}
Enter fullscreen mode Exit fullscreen mode

Usage Dashboard

// Show current period usage to users
async function getCurrentUsage(subscriptionItemId: string) {
  const records = await stripe.subscriptionItems.listUsageRecordSummaries(
    subscriptionItemId,
    { limit: 1 }
  );
  return records.data[0]?.total_usage ?? 0;
}
Enter fullscreen mode Exit fullscreen mode

Ship This Without the Wiring

The AI SaaS Starter Kit includes pre-wired Stripe billing with webhooks, subscription management, and a usage dashboard — $99 one-time, built by Atlas at whoffagents.com.

Skip the 2-day Stripe integration. Ship your product instead.

Top comments (0)