Stripe metered billing for AI video: bill each job's cost

Stripe metered billing sums meter events into each customer's invoice. Send one event per finished AI video job, valued at what the job cost.

6 min readSume
All posts

Stripe metered billing works in two parts: a meter defines how usage adds up over a billing period, and your code sends meter events, each naming the customer and a number. For AI video, send one meter event per finished generation job, valued at what that job actually cost you, with the job id in the event's identifier so Stripe can reject a retried duplicate.

The Stripe facts come from its usage-based billing docs and meter event API, read on 2026-09-28. The per-job cost comes from Sume's Usage API. Stripe calls this setup basic usage-based billing with Billing Meters, and now recommends Metronome for new integrations; the last section covers that.

How does a Stripe meter work?

You create the meter once, then send events that carry its event name. After configuration, only the meter's display name can change.

From Stripe's meter configuration, recording usage with the API and meter event pages, read 2026-09-28.
ItemWhat Stripe's docs say
AggregationSum, Count, or Last value over the billing period
Event payloadCustomer under stripe_customer_id and the number under value by default; decimals are accepted
identifierUnique per event; Stripe enforces uniqueness within a rolling period of at least 24 hours
timestampWithin the past 35 calendar days, or up to 5 minutes in the future
Rate limit1,000 meter event calls per second per account in live mode
ProcessingAsynchronous; invoices might not reflect recent events at once

What should each AI video job report?

The amount you were billed, not your own estimate. On Sume, a video job is reserved on submit at the provider's list price × 1.25 (Video generation), and the actual cost is captured on success (Core workflow). GET /v1/usage?job_id=… returns a summary whose debited_usd is "what the wallet deducted" and "the figure to quote"; final turns true once no hold is open (Usage). The API reference adds debited_usd_micros, an integer, and says it won't move after final.

With a Sum meter and the micros as the value, the meter holds each customer's cost for the period. What you charge per unit is set on the Stripe price attached to the meter, and that is your pricing decision. Store the job id and your Stripe customer id together when you submit, because the usage summary knows nothing about your customers.

import os
import requests

SUME = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"}

def report_job(job_id: str, stripe_customer_id: str) -> bool:
    summary = requests.get("https://api.sume.com/v1/usage", headers=SUME,
                           params={"job_id": job_id}, timeout=30).json()["data"]["summary"]
    if not summary["final"]:
        return False  # a hold is still open; try again later
    if summary["debited_usd_micros"] == 0:
        return True  # failed or canceled: nothing was debited
    requests.post(
        "https://api.stripe.com/v1/billing/meter_events",
        auth=(os.environ["STRIPE_SECRET_KEY"], ""),
        data={"event_name": "ai_video_cost_micros",
              "payload[stripe_customer_id]": stripe_customer_id,
              "payload[value]": summary["debited_usd_micros"],
              "identifier": f"sume-{job_id}"},
        timeout=30,
    ).raise_for_status()
    return True

How do I avoid billing a job twice?

  • Webhooks can arrive more than once. Sume retries a job webhook up to 10 attempts, a manual redeliver re-sends the same terminal event, and its docs say receivers must treat job_id as the idempotency key (Webhooks).
  • Use the job id as Stripe's identifier too. Stripe only guarantees uniqueness for at least 24 hours, so also keep your own record of which job ids you reported.
  • Never sum usage rows yourself: Sume's docs say a refunded row keeps its hold amount in billable_amount_usd_micros. Use the summary. What one Sume API run cost covers the other scopes, run_id and thread_id.
  • To fix a wrong event, Stripe lets you cancel it with a meter event adjustment, but only for events sent in the last 24 hours.

Should I use Stripe Billing Meters or Metronome?

Stripe's overview says to use Metronome "for most use cases including starting a new integration", unless you maintain an existing Billing Meters integration, and that current Billing Meters users don't need to migrate (Stripe). Whichever you choose, the job-level rule is the same: report the billed cost of each finished job, once.

Sources

Related posts

More in Pricing

All Pricing posts

Written by Sume