Charging users for AI video: price each one from usage.cost

After Sora, your app pays Sume's usage.cost per video. Add a margin, round up to the cent, charge only completed jobs. A JavaScript helper and rules.

4 min readSume
All posts

If your product sold Sora clips to your own users, price each Sume clip from the usage.cost on the completed job, multiply by one plus your margin, and round up to the cent. Charge your customer only when the status is completed. Failed jobs release or refund the reservation on Sume's side, so you should not bill the customer for them either.

Where the cost comes from

The poll response for a finished job includes a usage object whose cost is the billed amount. That is the number to build on, not a figure you multiplied yourself, because edit jobs treat duration only as a reserve hint.

Decide whether you quote before or after the render. A quote before needs a model's per-second rate and your clip length; a charge after uses usage.cost. Many products show an estimate up front and settle on the real number, which handles edits where the duration is only a hint.

Examples

From billed cost to customer price (read 2026-10-07)
ClipSume billed costPrice at +40%Price at +100%
10 s, gemini-omni-flash-1.1, 720p$1.25$1.75$2.50
10 s, wan-3.0, 1080p$2.50$3.50$5.00
10 s, grok-imagine-video-1.5$0.13$0.19$0.26

A note on the examples

The margins in the table are illustrations, not recommendations. The Sume column is the billed price: list per second times 1.25, with the reservation rounded up to the cent.

The helper

This helper rounds up, so a tiny floating-point wobble never costs you a cent. Run it with node and compare the two logged prices to the table.

const price = (cost, margin) => Math.ceil(cost * (1 + margin) * 100 - 1e-9) / 100;

const job = { status: "completed", usage: { cost: 1.25 } }; // from GET /v1/videos/{id}
if (job.status === "completed") {
  console.log(price(job.usage.cost, 0.4)); // 1.75
  console.log(price(job.usage.cost, 1.0)); // 2.5
}

Rules that keep the books straight

Take payment after completion, or hold funds and capture on completion. Either way, tie the customer charge to your own record of the job id, and send an Idempotency-Key with the submit, so that a retried request cannot create two jobs for one payment.

Keep margin in one place in your code, and store it with each order. When you change it, old orders keep the margin they were sold at, and your reports still add up.

  • Charge on status completed only.
  • Release or refund for failed jobs, and read usage.cost on a cancelled one before billing.
  • Store job id, model, resolution and usage.cost with the order.
  • Handle 402 insufficient_credits by pausing new orders and alerting yourself.

Quote before you render

Keep a small buffer in your own balance, since each submit reserves the full amount before a clip exists. See the admission docs for the reservation rules and the per-second table for quoting a price before the job runs.

Sources

Related posts

More in Use cases

All Use cases posts

Written by Sume