Image-to-video API: set the first and last frame with frame_images
Send frame_images to POST /v1/videos with a first_frame and an optional last_frame. Which Sume models take each frame, what wins, and what gets refused.

To turn a still image into a video with the Sume API, send POST /v1/videos with a frame_images array: an entry with frame_type: "first_frame" sets the clip's first frame, and an optional "last_frame" entry sets its last. Every video model in the catalog accepts a first frame, and all but grok-imagine-video-1.5 also accept a last frame.
Field rules below come from the Video generation docs. Per-model support comes from the catalog that GET /v1/videos/models returns, read on 2026-09-26.
How do I send a first and last frame?
Each frame_images entry has type: "image_url", an image_url object holding the url, and a frame_type of first_frame or last_frame. The request below adapts the docs' image-to-video example to pin both ends of a Seedance 2.0 clip at 1080p.
- Image URLs must be fetchable public HTTPS URLs. Localhost, private-network, non-HTTPS, and signed or private URLs are rejected before the job is submitted.
- Send
Idempotency-Keyto make retries safe: a replay returns the original job. - The call returns
202with a jobidand apolling_url. Poll untilstatusiscompleted, then download fromunsigned_urls[0].
curl -X POST https://api.sume.com/v1/videos \
-H "Authorization: Bearer $SUME_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: i2v-first-last-001" \
-d '{
"model": "seedance-2",
"prompt": "A character walking through a forest",
"frame_images": [
{
"type": "image_url",
"image_url": { "url": "https://example.com/first-frame.png" },
"frame_type": "first_frame"
},
{
"type": "image_url",
"image_url": { "url": "https://example.com/last-frame.png" },
"frame_type": "last_frame"
}
],
"resolution": "1080p"
}'Which models accept a first frame, a last frame, or both?
Each model lists the frame_type values it accepts in supported_frame_images. A model that also does text-to-video runs from the prompt alone when you send no frame. grok-imagine-video-1.5 is image-to-video only: it requires a first frame and takes no end frame.
| Model id | `first_frame` | `last_frame` | Prompt only |
|---|---|---|---|
seedance-2.5, seedance-2, seedance-2-fast, seedance-2-mini | Yes | Yes | Yes |
kling-3 | Yes | Yes | Yes |
wan-3.0 | Yes | Yes | Yes |
minimax-h3, minimax-h3-max | Yes | Yes | Yes |
gemini-omni-flash-1.1 | Yes | Yes | Yes |
grok-imagine-video-1.5 | Required | No | No |
What happens if I send frames and references together?
frame_images takes precedence. When a request carries both frame_images and input_references, Sume treats it as image-to-video and does not pass the references to the model. A frame image sets the clip's first or last frame; references are visual guidance rather than exact frames, covered in Reference-to-video API.
Why was my image-to-video request refused?
POST /v1/videos checks your frames against the model's catalog entry and refuses a mismatch with a 400 and the error code unsupported_capability:
- A
last_framewith nofirst_frame: “frame_images with a last_frame also requires a first_frame.” - A
frame_typethe model does not list, such aslast_frameongrok-imagine-video-1.5: “grok-imagine-video-1.5 does not support frame_type last_frame.” The errordetailscarry the model'ssupportedvalues. resolution,aspect_ratio, anddurationare checked against the model's lists the same way. See AI video length limits by model for durations.
What if my code still sends image_url and end_image_url?
Those are the flat fields of the older routes: Video 1.0, which is retiring soon, and the Video Router, which still works unchanged, take image_url for the first frame and end_image_url for the end frame. The field-by-field move is in Video 1.0 and Image 1.0 are retiring soon.
Two frame rules differ by route when model is a catalog id. POST /v1/videos refuses the flat fields with 400 invalid_request, so send frame_images there. POST /v1/video-router/generate refuses a first frame and reference_*_urls in the same request, where /v1/videos lets the frames take precedence.
How is an image-to-video clip billed?
Like any video job: the cost is reserved from the workspace USD balance on submit at the provider's list price × 1.25, plus a 5.5% agent fee by default, using the rates each model lists in pricing_skus on GET /v1/videos/models; see API pricing.
Sources
Related posts
Written by Sume