Luma Ray 2 API parameters: keyframes, loop and callback_url
Luma's video docs list ray-2 and ray-flash-2 with keyframes, loop, concepts and callback_url. Here is each field mapped to the Sume /v1/videos request.

Luma's video generation docs, read 2026-10-03, list two models, ray-2 and ray-flash-2, with resolutions from 540p to 4k and request fields for keyframes, loop, concepts and a callback_url. On Sume the same jobs map to POST /v1/videos with frame_images, a callback_url and a catalog model id, and you read the supported ranges from GET /v1/videos/models instead of from a doc page.
One caveat from the research: Luma's docs page lists Ray 2 only and may lag newer Ray releases, so treat the table below as the state of that page on the read date.
What the Luma page says
The facts below are taken from the Luma docs page and nothing else.
| Item | What the page lists |
|---|---|
| Models | ray-2 and ray-flash-2 |
| Resolutions | 540p, 720p, 1080, 4k |
| Request features | keyframes, loop, concepts, callback_url |
| Extend | Only for videos Luma generated |
| Image inputs | Must be CDN URLs |
Mapping each field to Sume
Sume follows the OpenRouter video wire on /v1/videos, so a few Luma ideas have a direct counterpart and a few do not.
- Keyframes: send
frame_imageswithframe_typeset tofirst_frameorlast_frame. Each model lists which values it accepts insupported_frame_images. - Callback: pass
callback_url. It must be HTTPS, and Sume posts its standard job webhook envelope when the job reaches a terminal state. - Image inputs: Sume wants public HTTPS URLs, and a URL Sume cannot fetch returns an error such as
image_not_fetchablerather than a silent skip. - Loop and concepts: the Sume docs list no
looporconceptsfield on/v1/videos, so describe a seamless loop or a camera move in the prompt instead. - Extend: the docs describe no extend endpoint on this route. Chain a new job from a chosen frame if you need a longer shot.
Webhook or polling
Luma exposes a callback_url; Sume does too, and the webhooks guide says to keep polling as a fallback because delivery is an optimization. Sume retries a failed delivery up to 10 times, 30 seconds apart by default, with a 10 second timeout per attempt. Use the job_id as your idempotency key, since a redelivery repeats the same event.
A submit that uses both mechanisms looks like this:
curl -X POST https://api.sume.com/v1/videos \
-H "Authorization: Bearer $SUME_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: ray2-port-001" \
-d '{
"model": "sume/auto",
"prompt": "Slow push-in on a ceramic mug, steam rising, soft window light",
"duration": 5,
"resolution": "720p",
"aspect_ratio": "16:9",
"callback_url": "https://example.com/hooks/sume"
}'Verify the callback
Sume signs the raw body with HMAC SHA 256 over <timestamp>.<raw_body> and sends x-sume-webhook-timestamp and x-sume-webhook-signature: sume-v1=<hex>. This verifier refuses an empty secret and a stale timestamp.
import hashlib, hmac, time
def verify(raw_body: bytes, timestamp: str, header: str, secret: str, tolerance=300) -> bool:
if not secret:
raise ValueError("empty webhook secret")
try:
ts = int(timestamp)
except ValueError:
return False
if abs(int(time.time()) - ts) > tolerance:
return False
signed = f"{ts}.".encode() + raw_body
digest = hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
expected = "sume-v1=" + digest
ok = False
for entry in header.split(","):
if hmac.compare_digest(entry.strip(), expected):
ok = True
return okPorting checklist
Work through the list in order before you switch traffic.
- Replace every CDN image URL with a public HTTPS URL that Sume can fetch without cookies.
- Move keyframes to
frame_imagesand confirm the model lists them insupported_frame_images. - Add an
Idempotency-Keyto every paid submit so a network retry cannot create a second job. - Store the Sume
job_idbeside your own record, and use it as the idempotency key for webhook handling. - Keep a polling fallback running, because a callback can be refused ten times and the job still finishes.
- Test one failure on purpose, for example an unreachable image URL, and confirm your handler reads the public error.
What to check before porting
Read supported_resolutions, supported_durations and supported_frame_images for the model you pin, because limits are not uniform across the catalog. If you do not want to pin one, model: "sume/auto" lets Sume pick the family, and the job echoes sume/auto. Sume bills workspace USD balance reserved at submit, at provider list times 1.25, and usage.cost on the poll response is the billable amount.
Sources
Related posts
More in Comparisons
- Luma Ray3.2 video-to-video vs Sume Omni edit: cost per clip
Editing a 5-second clip costs $1.44 on Luma Ray3.2 at 720p and $0.625 with Gemini Omni Flash edit on Sume. 10 seconds is $2.16 versus $1.25. Math inside.
- Magic Hour API on every plan vs Sume concurrency by plan
Magic Hour lists the full API on all plans and 3 to unlimited concurrent jobs. Sume runs 1, 4, 8 or 20 jobs at once by plan, with queues of 5 to 100.
- MAI-Transcribe-1 deprecated Aug 20: what to switch to, and Sume STT
Microsoft's page says MAI-Transcribe-1 was deprecated on August 20, 2026. What replaces it, what is still preview, and what a Sume STT job needs instead.
- MAI-Transcribe-2 timestamps option vs Sume STT: words[] are always on
On Microsoft's MAI-Transcribe you ask for word timestamps in modelOptions. Sume STT returns words[] with start and end on every job: what that changes for you.
Written by Sume