Dry-run a Sume timeline and video filter in Python before paying
POST /v1/timeline-1.0/plan and POST /v1/video-filter/check are free. This Python script calls both and prints the estimate.

Before you pay for a render, call the two free preflight routes: POST /v1/timeline-1.0/plan for a timeline and POST /v1/video-filter/check for a filter program. Plan returns the duration, segment count, billable minutes and an estimated cost; check returns valid, diagnostics, an estimate and a next_action.
The script below uses only the Python standard library and reads the key from SUME_API_KEY, refusing to run without it. Both route descriptions come from the Sume Timeline and Video filter pages, read on 2026-10-03.
The script
Fill in your own body files. The timeline body is the same JSON you would send to the render route, and the filter body is the same JSON you would send to the encode route. Neither creates a job nor reserves credit.
import json, os, sys, urllib.request
KEY = os.environ.get("SUME_API_KEY", "")
if not KEY:
sys.exit("set SUME_API_KEY")
def post(path, body):
req = urllib.request.Request(
"https://api.sume.com" + path,
data=json.dumps(body).encode(),
headers={"Authorization": "Bearer " + KEY,
"Content-Type": "application/json"},
)
with urllib.request.urlopen(req) as r:
return json.load(r)
plan = post("/v1/timeline-1.0/plan", json.load(open("timeline.json")))
print("billable minutes:", plan.get("billable_minutes"))
print("estimate micros:", plan.get("estimated_cost_usd_micros"))
chk = post("/v1/video-filter/check", json.load(open("filter.json")))
print("valid:", chk.get("valid"), chk.get("next_action"))
for d in chk.get("diagnostics", []):
print(" -", d)
What each response tells you
Read the fields you act on, not the whole body. A timeline plan with billable_minutes of 2 for a video you meant to be 60 seconds means the output ran over a minute, and each output minute bills $0.10 rounded up. A filter check with valid: false lists diagnostics you can fix and re-check at no cost; the same mistake sent to the encode route would be a 400.
A passing check is not a guarantee. The filter page says a program can still fail on the worker for resource reasons, which returns a structured job error, so keep your own retry path.
| Route | Billed | Key fields | Paid sibling |
|---|---|---|---|
| POST /v1/timeline-1.0/plan | No | duration_seconds, segment_count, billable_minutes, estimated_cost_usd_micros | Render at $0.10 per output minute, rounded up |
| POST /v1/video-filter/check | No | valid, diagnostics, estimate, next_action | Encode at $0.02 |
Wire it into a build
Run the script in CI whenever a template changes, and fail the build when valid is false or the estimate exceeds your own ceiling. Because both routes are free, they can run on every pull request. The estimate is still an estimate; the ledger from GET /v1/usage is the record of what a real job cost.
Sources
Related posts
More in Media tools
- Gemini SynthID audio check: detach the track from a Sume video
Gemini's SynthID checker takes audio under 1 hour. Detach a Sume video's audio as wav or mp3 and see which format stays under 100 MB.
- Gemini SynthID: 10 video checks a day, which clips to submit
Google's Gemini app allows about 10 video checks per 24 hours, up to 5 minutes in total. Work out how many clips fit and which ones are worth checking.
- Gemini SynthID video check: 100 MB, under 90 seconds, trim first
Google's Gemini app checks videos for its SynthID watermark up to 100 MB and under 90 seconds. Trim a longer Sume video to fit, and know what a miss means.
- Gmail's 25 MB attachment limit and the Drive link fallback for video
Gmail personal accounts stop at 25 MB per message and turn bigger attachments into Drive links. Trim and downscale a clip with Sume to keep it attached.
Written by Sume