Keep your Sora-style create_video() call: map it onto Sume
Sora's seconds, size and input_reference become duration, resolution plus aspect_ratio, and a first frame. Here is that map as a Python wrapper over Sume.

You can keep a Sora-shaped create_video(prompt, seconds, size, input_reference) function and change only its body. Higgsfield's migration guide maps seconds to duration, size to resolution plus aspect_ratio, and input_reference to an image URL. On Sume, the same three changes apply, with the reference sent as a first frame.
| Sora-style field | Sume field | Note |
|---|---|---|
| seconds | duration | Integer seconds; limits differ per model |
| size | resolution + aspect_ratio | A size field returns 400 unsupported_parameter on Sume |
| input_reference | frame_images[0] with frame_type first_frame | Public HTTPS image URL |
| Bearer token | Authorization: Bearer $SUME_API_KEY | Same header shape |
The wrapper
The wrapper translates four common size strings and derives an idempotency key from the arguments, so repeating a call replays the same job rather than paying twice. It returns the submit response, which carries id and polling_url.
import hashlib
import os
import requests
SIZES = {"1280x720": ("720p", "16:9"), "720x1280": ("720p", "9:16"),
"1920x1080": ("1080p", "16:9"), "1080x1920": ("1080p", "9:16")}
def create_video(prompt, seconds=8, size="1280x720", input_reference=None,
model="seedance-2.5"):
resolution, aspect = SIZES[size]
body = {"model": model, "prompt": prompt, "duration": int(seconds),
"resolution": resolution, "aspect_ratio": aspect}
if input_reference:
body["frame_images"] = [{"type": "image_url", "frame_type": "first_frame",
"image_url": {"url": input_reference}}]
raw = f"{model}|{prompt}|{seconds}|{size}|{input_reference}"
key = hashlib.sha256(raw.encode()).hexdigest()[:32]
headers = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}",
"Idempotency-Key": key}
r = requests.post("https://api.sume.com/v1/videos", json=body, headers=headers)
r.raise_for_status()
return r.json()What stays the same
The guide says the submit, poll and download steps are unchanged in shape, and that holds on Sume: poll the returned polling_url until the status is completed, then fetch the file from unsigned_urls[0] or from GET /v1/videos/{jobId}/content with your key. A failed status carries an error field. Statuses on this route are pending, in_progress, completed, failed and cancelled.
What does not carry over
Three differences need a decision rather than a mapping:
- Durations: Sora-era code may request lengths the new model does not list. Seedance 2.5 accepts 4 to 30 seconds on Sume, so a 2-second request fails validation.
- Seeds and passthrough: Sume models report
seed: falseand reject aseedfield, and a non-emptyprovider.optionsreturns 400. - Output retention and URLs: treat artifact URLs as opaque and download on completion.
Testing the wrapper
Call it once with a 6-second 1280x720 text prompt and once with an input_reference. Confirm the poll response reports the model you passed and a usage.cost that matches the reservation. The field-by-field request reference is in Video generation.
Sources
Related posts
More in Developers
- Luma callback_url or polling: which Sume job mode matches
Luma's API docs list keyframes, loop and callback_url for ray-2. On Sume the equivalent choice is job mode: async, sync up to 30 s, subscribe or webhook.
- Luma API callback_url vs Sume callback_url: signing and retries
Luma's video API takes a callback_url, and so does Sume's /v1/videos. What Sume's callback is signed with, how often it retries, and a Python verifier.
- MCP 2026-07-28 deprecations: SSE, sampling, roots, logging checklist
MCP 2026-07-28 deprecates Roots, Sampling and Logging and reclassifies HTTP+SSE as Deprecated, with 12 months of notice. A checklist for media servers.
- MCP OAuth without DCR: client ID metadata documents and issuer checks
MCP 2026-07-28 deprecates dynamic client registration for Client ID Metadata Documents and requires clients to validate iss. What it means for Sume.
Written by Sume