Port an OpenRouter video client to Sume: base URL, key, model ids
Sume's /v1/videos follows the OpenRouter video wire. Three edits move a client: base URL, API key, bare model id. The six differences that still bite.

A client written for the OpenRouter video API moves to Sume with three edits: the base URL becomes https://api.sume.com/v1/videos, the key becomes SUME_API_KEY, and model ids lose their org/ prefix. Video generation says the surface matches the OpenRouter video API field for field, so submit, polling_url and unsigned_urls keep their shapes.
The part that needs care is the short list of places where Sume differs on purpose. Read it before you flip production traffic.
The port in Python
Submit returns id, polling_url, status and model. Poll the URL until the status is terminal. Sume spells the canceled state cancelled on this wire, so test for it.
import os, time, requests
BASE = "https://api.sume.com/v1/videos" # was https://openrouter.ai/api/v1/videos
H = {"Authorization": "Bearer " + os.environ["SUME_API_KEY"]}
r = requests.post(BASE, headers=H, timeout=30, json={
"model": "wan-3.0", # bare catalog id, no org/ prefix
"prompt": "Slow push-in on a ceramic mug, steam rising",
"duration": 5,
"resolution": "720p",
"aspect_ratio": "16:9",
})
r.raise_for_status()
job = r.json()
while job["status"] not in ("completed", "failed", "cancelled"):
time.sleep(10)
job = requests.get(job["polling_url"], headers=H, timeout=30).json()
print(job["status"], job.get("unsigned_urls"))What differs from OpenRouter
These rows come from the Sume differences table in the docs.
| Area | OpenRouter | Sume |
|---|---|---|
| Model ids | org/slug | Bare ids such as seedance-2 |
size | Accepted when the model lists sizes | 400 unsupported_parameter; use resolution + aspect_ratio |
provider.options | Forwarded upstream | Non-empty value returns 400 unsupported_parameter |
seed | Many models accept it | No v1 model accepts it |
| Webhook | video.generation.* events | Sume's job envelope, x-sume-webhook-signature |
| Retries | No idempotency on the route | Send Idempotency-Key; a replay returns the original job |
Cost of the check
A five-second Wan 3.0 clip at 720p is $0.625 on Sume, so a smoke test of the port costs well under a dollar. Run it with an Idempotency-Key and a second identical call should return the same job.
Fetch GET /v1/videos/models once and compare supported_durations with what your client sends. The catalog, not a cached list, decides what is valid.
A migration checklist
Treat the port as a short, testable change rather than a rewrite. The wire stays the same, so most of the risk sits in model ids and in the few parameters that Sume rejects on purpose.
- Replace the base URL and key, then list
GET /v1/videos/modelsand map every model id your client used to a bare Sume id. - Delete
seed,sizeand any non-emptyprovider.optionsfrom request builders; each returns a 400 rather than being ignored. - Add an
Idempotency-Keyto the submit call. OpenRouter has none on this route, so a ported client probably never sent one. - If you used webhooks, change the receiver: the signature header and the event names are Sume's, not OpenRouter's.
- Run one cheap job end to end and download the file from the content URL with the same Authorization header.
Why the order matters
Do the catalog check first. A model that exists under an org/slug name upstream may be a different bare id here, or may not be in the catalog at all, and a 404 at submit is cheaper to find in a test than in production. The /v1/videos/models response also tells you which resolutions, aspect ratios and durations each model accepts, so you can validate the request in your own code before it leaves.
Sources
Related posts
More in Developers
- PowerShell: Invoke-RestMethod for a 30-second Wan 3.0 clip
Windows PowerShell script that posts a 30-second wan-3.0 job, loops until it completes and saves the MP4 with Invoke-WebRequest. $3.75 at 720p.
- Pre-flight an Omni Flash request against the Sume model catalog
A short Python check that reads supported durations, resolutions and aspect ratios for gemini-omni-flash-1.1 via /v1/videos/models.
- Preflight a 3-minute Short with Timeline plan before you pay
POST /v1/timeline-1.0/plan compiles a Short without a job or a reserve and returns billable minutes and the estimate. A runnable Python check for six slots.
- Prompting Omni Flash with sound: write the audio as its own line
Gemini Omni Flash 1.1 always generates audio. A prompt layout that separates picture from sound, three example prompts, and the request on Sume.
Written by Sume