Introduction
Wan 3.0 Image to video animates a still you supply. image_url is used exactly as the first frame, so wardrobe, body, set and light direction come from the picture and the prompt only has to describe motion. The prompt is optional; without it the model animates the frame on its own. An optional last_image_url fixes the exact final frame. Clips run 2 to 30 seconds at 480p, 720p or 1080p, with generated sound on by default. It is the most literal of the modes: when the output has to match your wording, put the look in the image and spend the prompt on movement.
Choose a Wan 3.0 mode by starting material
| What you have at the start | Mode |
|---|---|
| a written scene or script | Wan 3.0 Text to video |
| an approved opening image | Wan 3.0 Image to video |
| separate visual, motion, or sound references | Wan 3.0 Reference to video |
Key features & highlights
The opening frame sets the quality ceiling
Because the first frame is your image, its sharpness, lighting and composition are the upper limit of the clip. Sources can be JPEG, PNG without transparency, BMP or WEBP, 240 to 8000 pixels per side, no wider than 8:1 and at most 20 MB. Leave aspect_ratio out and the clip inherits the frame's shape; a conflicting ratio crops it.
A landing frame that is pinned, not suggested
last_image_url is not loose guidance: the clip ends exactly on that image, and it only works together with image_url. The bottle example passes the same packshot as both frames, so the bottle turns a quarter circle, lets a highlight travel across the glass and lands back on its starting angle with the label readable.
Long spans between two fixed moments
With both ends supplied, only the passage between them is generated. The rooftop example pins an open dance hold as the first frame and the bottom of a dip as the last, and the model fills the five seconds between them at 720p; the same two stills can bracket a much longer move, because duration_seconds reaches 30 on this endpoint.
Request parameters
| Parameter | Required | Description |
|---|---|---|
prompt | No | Optional: without it the model animates the opening frame on its own. When you write one, describe the shot: subject, one action, one camera move, then light and sound. at least 1 characters |
image_url | Yes | The opening frame, used exactly as the first frame, and the real quality ceiling of the shot. |
last_image_url | No | Optional, and only together with |
aspect_ratio | No | 16:9, 9:16, 1:1, 4:3, 3:4 or adaptive, which lets the model choose. Leave it out and the clip inherits the opening frame's shape; a conflicting value crops. |
enable_thinking | No | Has the model think through the brief and any reference material before generating. It helps with dense documents, web pages and complex reference images, and makes the run slower. Default: |
resolution | No | 480p, 720p or 1080p. Defaults to 720p. |
duration_seconds | No | Any whole number from 2 to 30, or -1 for smart duration, where the model picks the length: the 30-second maximum is held up front and the charge settles on the length actually d… |
generate_audio | No | On by default. The clip comes back with sound already locked to the picture. Default: |
enable_prompt_expansion | No | Off by default. When on, the prompt is rewritten before generation, which helps thin briefs and fights you on detailed ones. Default: |
seed | No | 0 to 2147483647. Hold it steady to compare one changed field at a time; drop it for variety. |
Pricing
| Specification | Price |
|---|---|
| $0.045 / second |
| $0.09 / second |
| $0.18 / second |
Use cases
Product turns that return to the hero angle
For packshots, supply the approved image as both first and last frame, lock the camera and describe a single movement. The bottle example uses one soft key from the left, no music (generate_audio set to false) and a fixed seed of 20260907, which makes it easy to rerun the same move after a small wording change and compare the two files.
Styled shots that follow the wording
When a garment, body or set has to appear exactly as approved, put it in the opening frame. The window-turn example starts from a still of a woman in a silk chemise; the prompt describes only her turn toward the lens, a sheer curtain drifting across the light and a slow push-in as dawn strengthens, and the clip runs 5 seconds at 1080p with audio.
Prompt guide & pro tips
Describe what changes, not what is visible
Everything already in the frame is inherited, so redescribing it spends words that the motion needs. Say who or what moves, in which direction and how fast, then what the camera does: "The bottle rotates a quarter turn so the highlight travels across the glass, then returns to its starting angle. Locked camera, single soft key from the left, no music."
Prepare both frames as a matched pair
When you add last_image_url, make both images at the same crop and from the same set, and let the prompt explain how one becomes the other. The rooftop example pairs an opening frame of a couple in an open dance hold with a closing frame of the same couple, on the same rooftop and from the same camera position, at the bottom of a dip, and the prompt describes only the movement between them: he draws her in by the hand and lowers her into the dip while the camera stays locked.
Check the middle of the clip, not only the ends
A matching final frame does not prove a believable transition. Review the opening, middle and final moments for identity and geometry; if they drift, reduce the number of simultaneous movements before extending the duration. Settle the motion at 5 seconds, then lengthen, and keep enable_prompt_expansion at its default false so a detailed motion brief runs as written.
API quick start
# Generate the idempotency key once; reuse it when retrying after a lost response.
export SPICY_IDEMPOTENCY_KEY="${SPICY_IDEMPOTENCY_KEY:-$(uuidgen)}"
curl -X POST https://api.spicyapi.ai/api/v1/jobs/createTask \
-H "Authorization: Bearer $SPICY_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $SPICY_IDEMPOTENCY_KEY" \
-d '{
"model": "alibaba/wan-3.0/image-to-video",
"input": {
"duration_seconds": 5,
"image_url": "https://example.com/reference.png",
"prompt": "A slow aerial shot drifting over a misty pine forest at sunrise",
"resolution": "720p"
}
}'
# Copy data.taskId from the response into TASK_ID, then poll the status.
TASK_ID="TASK_ID_FROM_RESPONSE"
curl "https://api.spicyapi.ai/api/v1/jobs/recordInfo?taskId=$TASK_ID" \
-H "Authorization: Bearer $SPICY_API_KEY"
See the API reference for authentication, the complete schema, polling, and error handling.



























