CI test: assert Seedance 2.5 and Wan 3.0 still list 30 seconds
Fail a build when your 30-second video code outlives the catalog. A short Python test reads supported_durations from GET /v1/videos/models and checks 30.

Add one test that calls GET /v1/videos/models and checks that seedance-2.5 and wan-3.0 still list 30 in supported_durations, so a catalog change fails your build before it fails a customer's job. Your code that hard-codes duration: 30 is a contract with a provider, and the catalog is where Sume publishes that contract.
The docs state the limits today: seedance-2.5 accepts 4 to 30 seconds at 480p, 720p and 1080p, and wan-3.0 accepts 2 to 30 seconds.
What the endpoint returns
Each model entry has an id, supported_resolutions, supported_aspect_ratios, supported_durations, pricing_skus, and flags such as generate_audio and seed. The docs also say that other catalog models cap at 15 seconds, so a model-routing bug that sends 30 seconds to the wrong model fails in a different way from a retired duration.
| Model | Min | Max | Resolutions |
|---|---|---|---|
| seedance-2.5 | 4 s | 30 s | 480p, 720p, 1080p |
| wan-3.0 | 2 s | 30 s | listed per model in the catalog |
| seedance-2 | not stated here | 15 s | includes 1080p |
The test
This pytest file needs requests and SUME_API_KEY. The response shape is read defensively: it accepts a bare list or an object with a data list, because the docs show the fields per entry but not the wrapper.
import os
import pytest
import requests
def models():
r = requests.get("https://api.sume.com/v1/videos/models",
headers={"Authorization": "Bearer " + os.environ["SUME_API_KEY"]}, timeout=30)
r.raise_for_status()
body = r.json()
items = body["data"] if isinstance(body, dict) else body
return {m["id"]: m for m in items}
@pytest.mark.parametrize("model", ["seedance-2.5", "wan-3.0"])
def test_thirty_seconds_still_supported(model):
m = models().get(model)
assert m is not None, model + " is not in the catalog"
assert 30 in m["supported_durations"], m["supported_durations"]
def test_nothing_hardcoded_above_the_max():
for m in models().values():
assert max(m["supported_durations"]) >= 2Where it fits
A failing test is not an outage. It tells you the catalog moved, and whether to change your default length, your model choice, or your cost cap.
- Run it nightly rather than on every commit; it calls the network and needs a key.
- Use a read-only key if your plan allows scopes, because the test only reads the catalog.
- On failure, show the live list in the message so the fix is obvious.
- Pair it with a price check; the same endpoint returns
pricing_skusfor your estimate.
Why this beats a code comment
A comment that says # Seedance goes to 30 s is true on the day it is written. A test is true every night. The catalog is the one place Sume lists duration support, so asserting against it moves the risk from a customer to your CI.
Keep the assertions small. Check the model exists, check 30 is in the list, and stop. A test that tries to mirror every field will break on harmless additions and train people to ignore it.
If a test fails because the list changed, update the default in one place, in config, rather than patching call sites. Your code should read the duration from a single setting so the fix is one line.
Reading the result
A pass means only that the catalog still lists the length. It says nothing about queue depth or your balance, so keep the price guard and the admission checks in the code that submits. This test is a smoke alarm for one specific kind of drift, and that is enough to justify its few lines.
Sources
Related posts
More in Developers
- Retry, fix or stop: classify every Sume /v1/videos error in code
One Python function that maps each documented /v1/videos error code (400, 402, 404, 409, 429, 502) to retry, fix or stop, plus the two 409s that look alike.
- Claude Agent SDK init message: check the Sume server status first
Read the init message's mcp_servers statuses before a paid Sume call. failed and needs-auth mean the tools are not usable. pending is not a failure on its own.
- Claude Agent SDK allowedTools mcp__sume__* also allows paid Sume tools
A wildcard in allowedTools approves every tool the Sume server exposes. With an API key that includes paid ones. Name the read tools instead.
- claude -p total_cost_usd vs your Sume bill: which number to trust
claude -p prints total_cost_usd for the Claude side of a run. Sume's generation spend is billed on Sume and read from GET /v1/usage. Here is how to log both.
Written by Sume