Move an OpenRouter video client to Sume: base URL, key, model ids
Sume POST /v1/videos matches the OpenRouter video API. Change the base URL, key and model id, then check size, seed, provider.options and webhooks.

A client written against the OpenRouter video generation API works on Sume after you change the base URL to https://api.sume.com/v1/videos and the API key. Then fix four things: model ids, size, seed and provider.options, and the webhook envelope.
The docs say Sume agrees with that surface field for field, and list the differences, so this is a short checklist and not a rewrite.
The differences that bite
Model ids are bare catalog ids such as seedance-2.5, not org/slug. size returns 400 unsupported_parameter because each v1 model reports supported_sizes: null; use resolution plus aspect_ratio. No v1 model accepts seed, and a non-empty provider.options is rejected rather than ignored.
Webhooks carry Sume's job envelope with x-sume-webhook-signature, not the OpenRouter video.generation.* events. Verify with the Sume scheme before you trust the payload.
| Area | OpenRouter | Sume |
|---|---|---|
| Base path | openrouter.ai/api/v1/videos | api.sume.com/v1/videos |
| Model ids | org/slug | Bare catalog id |
| size | If model lists sizes | 400 unsupported_parameter |
| seed | Many models | Not accepted |
| Idempotency | None on this route | Idempotency-Key header |
| Billing | Credits | Workspace USD balance |
The same code, two lines changed
The snippet below posts to Sume with the fields you already had, and adds an idempotency key. Keep callback_url HTTPS and public.
import os, requests
r = requests.post(
"https://api.sume.com/v1/videos",
headers={"Authorization": f"Bearer {os.environ['SUME_API_KEY']}",
"Idempotency-Key": "migrate-demo-001"},
json={"model": "wan-3.0", "prompt": "A kite over a beach at sunset",
"duration": 10, "resolution": "720p", "aspect_ratio": "16:9"},
timeout=30)
r.raise_for_status()
print(r.json()["id"], r.json()["polling_url"])What you gain
The same job is also readable at GET /v1/jobs/{id}/status and /result. model: "sume/auto" is a Sume addition if you do not want to pin a family.
Sources
Related posts
More in Developers
- Move captions on an avatar video: design.placement and anchor_ratio
Inline avatar captions take no design overrides. To lift the caption line off the platform buttons, re-burn with the standalone job. Fields, price, example.
- mulmo images and mulmo movie break on gpt-image-1: set a model now
mulmocast-cli issue 1605: the gpt-image-1 default breaks mulmo images and movie after Oct 23, 2026. Which files to change, and a Python call to Sume instead.
- Music 1.0 is retiring: keep old calls, move new code to the router
Sume Music 1.0 routes still work and keep job.model sume/music-1.0, but every request now resolves through the Music Router. What to change and when.
- Music job metadata: stored on the Sume job, not sent to Lyria
The metadata object on a Sume music request is stored on the job and never sent to the provider. Tag takes by scene and brief with it.
Written by Sume