Dry-run 200 holiday renders free with the Sume Timeline plan call

POST /v1/timeline-1.0/plan is unbilled and returns billable_minutes and a cost estimate. A short Python loop totals the bill before you submit a batch.

3 min readSume
All posts

Call POST /v1/timeline-1.0/plan once per planned render and add up estimated_cost_usd_micros. The Sume docs say the plan runs the schema checks, the Sume-host URL checks and the compiler, returns duration_seconds, segment_count, billable_minutes, estimated_cost_usd_micros and a filtergraph_summary, and does not create a job, reserve credits or download media. It needs no Idempotency-Key. For 200 videos of 20 seconds, the docs' rate of $0.10 per ceil minute gives $20.00, and the plan call lets you confirm that on your real bodies.

What the free checks cover

Two dry-run routes exist for media preparation.

Unbilled checks on Sume, per the docs read 2026-10-08
RouteChecksNot covered
POST /v1/timeline-1.0/planSchema, Sume-host URLs, compile, cost estimateShort-source pad or loop warnings
POST /v1/video-filter/checkSchema, op list, filtergraph allowlist, source preflightFailures on the box such as memory or time

Steps

The script loops over comma-separated clip URLs in CLIP_URLS, plans a 20-second 1920x1080 render for each, and prints the total. Every URL must be an imported media.sume.com file in your workspace.

import json, os, urllib.request

KEY = os.environ["SUME_API_KEY"]
urls = os.environ["CLIP_URLS"].split(",")
total = 0
for u in urls:
    body = {"audio": {"mode": "silence", "duration_seconds": 20},
            "video": [{"source_url": u, "start": 0, "duration": 20}],
            "output": {"width": 1920, "height": 1080, "fps": 24}}
    req = urllib.request.Request(
        "https://api.sume.com/v1/timeline-1.0/plan",
        data=json.dumps(body).encode(),
        headers={"Authorization": "Bearer " + KEY,
                 "Content-Type": "application/json"})
    plan = json.load(urllib.request.urlopen(req))
    total += plan["estimated_cost_usd_micros"]
print(len(urls), "renders ->", total / 1_000_000, "USD")

If the total matches your budget, submit the real renders with unique Idempotency-Key values. If a body is bad, the plan returns an error before you spend anything. Re-run the plan whenever you change output or the slot durations, since the billable minutes follow the declared audio length.

Reading the plan result

The plan returns segment_count and a filtergraph_summary as well as the cost. A segment_count that is different from the number of slots you sent is worth a look. Long timelines are chunked automatically past 12 segments, which the docs call the auto render strategy, and you can read the render settings in the Timeline page.

Use the total as a gate in your script: if the sum is above the budget you set, stop. This costs nothing, so it is safe to run on every change. Keep the plan output with the batch record so you can compare it with the final charge later.

A plan that passes does not guarantee a render that passes. The check covers schema, URLs and the compiler. It does not download the media, so a corrupt file is caught only when the render runs.

Budget and detail

The loop above runs the plan one body at a time. For 200 bodies that is 200 sequential requests, which is fine for a nightly check but slow for an interactive one. If you need speed, group the calls in a thread pool of a small size and keep an eye on the rate limits your plan has. The docs for rate limits live separately, and I have not tested the plan endpoint under load.

What Sume does not do

The estimate is a plan, not a guarantee. The docs state the plan cannot predict warnings about padded or looped short sources, and the live price lives in GET /v1/catalog. The plan also does not generate footage, so any model cost is separate.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume