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.

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.
| Item | What Stripe's docs say |
|---|---|
| Aggregation | Sum, Count, or Last value over the billing period |
| Event payload | Customer under stripe_customer_id and the number under value by default; decimals are accepted |
identifier | Unique per event; Stripe enforces uniqueness within a rolling period of at least 24 hours |
timestamp | Within the past 35 calendar days, or up to 5 minutes in the future |
| Rate limit | 1,000 meter event calls per second per account in live mode |
| Processing | Asynchronous; 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 TrueHow 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_idas the idempotency key (Webhooks). - Use the job id as Stripe's
identifiertoo. 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_idandthread_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
- Stripe: Basic usage-based billing (read 2026-09-28)
- Stripe: Record usage for billing (read 2026-09-28)
- Stripe: Record usage with the API (read 2026-09-28)
- Stripe: Create and configure a meter (read 2026-09-28)
- Stripe API: Create a billing meter event (read 2026-09-28)
- Usage
- Webhooks
- Video generation
- Core workflow
- Sume API reference
- API reference
Related posts
More in Pricing
- Synthesia API pricing: which plan, and how credits work
Synthesia's API comes with a subscription on the Creator plan and up. API video is paid in plan credits: 75 credits per minute of API usage.
- How Sume pricing works: plans, one wallet, published model rates
Sume plans set access and concurrency. Usage draws from one prepaid wallet at each model's published USD rate, for generation, the Agent, Formats, and the API.
- AI avatar video API pricing: cost per second and per minute
Sume bills AI avatar video per second by quality tier, with separate rates when you send a product image. Per-minute costs for standard, plus, and max.
- Estimate AI video generation cost before running a Sume job
See what an AI video will cost on Sume before paying: published rates, GET /v1/catalog estimates, unbilled plan checks, MCP dry runs, and spend caps.
Written by Sume