Wan Spicy
The Wan Spicy models animate a single image into a video. wan2.7-i2v-spicy adds audio — generated,
or driven by a track you supply — and a negative prompt; wan2.2-i2v-spicy can pin the last frame
as well as the first.
For the rest of the Wan family (Wan 2.7 and Wan 3.0), see Wan.
https://llm.siraya.ai/v1/videos/generations
https://llm.siraya.ai/v1/videos/{video_id}
https://llm.siraya.ai/v1/videos/{video_id}
Send async: true and poll
Renders typically take one to three minutes. Send "async": true to get an id back
immediately, then poll GET /v1/videos/{video_id} until status is completed or failed —
or pass a callbackUrl to be notified instead. See
Asynchronous generation.
Supported Models
| Model ID | Inputs | Resolutions | seconds |
|---|---|---|---|
wan2.7-i2v-spicy |
image · negative prompt · audio | 720p, 1080p (default 1080p) |
2–15 (default 5) |
wan2.2-i2v-spicy |
image · optional last frame | 480p, 720p (default 480p) |
exactly 5 or 8 (default 5) |
Header
Bearer <API_KEY>).
Body
Every field is sent flat, at the top level of the request body.
wan2.7-i2v-spicy or wan2.2-i2v-spicy.
wan2.2-i2v-spicy only. The last frame, URL or base64.
wan2.7-i2v-spicy: 2–15. wan2.2-i2v-spicy: exactly 5 or 8 — anything else is a
400 before the job starts. The spelling duration is also accepted; if both arrive, seconds wins.
wan2.7-i2v-spicy: 720p or 1080p (default 1080p). wan2.2-i2v-spicy: 480p or
720p (default 480p).
wan2.7-i2v-spicy only. Content to steer away from.
wan2.7-i2v-spicy only. An https:// WAV or MP3 track, 2–30 s, ≤ 15 MB, that drives the content.
wan2.7-i2v-spicy only. Whether the video carries audio; false mutes it even when audio_url is
set. The spelling audio is also accepted; if both arrive, generate_audio wins.
0, for a random seed.
wan2.7-i2v-spicy; on wan2.2-i2v-spicy each rewritten
request is surcharged — turn it off if you don't need it.
true, the request returns immediately with a video id you poll for status. When false (the default), it waits for generation to finish and returns the completed video URL.
async is true. An https:// URL the router will POST the result to, so you don't have to poll.
curl https://llm.siraya.ai/v1/videos/generations \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <API_KEY>" \
-d '{
"model": "wan2.7-i2v-spicy",
"prompt": "She turns toward the camera and smiles",
"image": "https://your-domain.com/portrait.jpg",
"seconds": 5,
"resolution": "720p",
"async": true
}'
import requests
url = "https://llm.siraya.ai/v1/videos/generations"
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer <API_KEY>"
}
data = {
"model": "wan2.7-i2v-spicy",
"prompt": "She turns toward the camera and smiles",
"image": "https://your-domain.com/portrait.jpg",
"seconds": 5,
"resolution": "720p",
"async": True
}
response = requests.post(url, headers=headers, json=data)
print(response.json())
Example Response
Examples
First and last frame (wan2.2-i2v-spicy)
{
"model": "wan2.2-i2v-spicy",
"prompt": "The car drives from the city into the desert",
"image": "https://your-domain.com/city.jpg",
"last_image": "https://your-domain.com/desert.jpg",
"seconds": 8,
"resolution": "720p",
"prompt_extend": false,
"async": true
}
Audio-driven (wan2.7-i2v-spicy)
{
"model": "wan2.7-i2v-spicy",
"prompt": "The singer performs the song",
"image": "https://your-domain.com/singer.jpg",
"audio_url": "https://your-domain.com/song.mp3",
"negative_prompt": "blurry, distorted face",
"seconds": 10,
"resolution": "1080p",
"async": true
}
Poll for status
{
"id": "video_9M1Ll0p-27nCK2vX82bHn...",
"object": "video",
"status": "completed",
"seconds": 2,
"resolution": "720p",
"model": "wan2.7-i2v-spicy",
"output_url": "https://.../result_00.mp4",
"usage": { "completion_tokens": 0, "total_tokens": 0 }
}
| Field | Present | Meaning |
|---|---|---|
id |
always | Opaque — pass it as-is to the status and delete endpoints; don't parse it |
status |
always | processing · completed · failed |
seconds, resolution |
completed | Echoed from your request — not measured from the output |
output_url |
completed | Signed and expiring — download promptly rather than storing it as a stable link |
error |
failed | { "code": "...", "message": "..." } |
usage |
always | Always zero — no token concept |
Delete a task
Only completed tasks can be deleted. A task that is still processing answers 409; a failed
task is refused too, and the deletion is not retried for you. A successful delete returns
{ "id": "...", "object": "video", "deleted": true, "deleted_at": "...", "model": "..." }.
Behavior worth knowing
seconds and resolution are echoes. The finished task carries neither, so the status response
reports what you asked for at create time.
wan2.2-i2v-spicy validates duration hard. Exactly 5 or 8; anything else is a clean 400
naming the allowed values, before the job starts.
Image URLs must be public. The input is fetched by the model service itself; a URL behind authentication fails the task with a download error. For large images, prefer a URL over base64 — the request-body size limit applies to the whole payload.
Errors
A request-time refusal is final — retrying the same body won't help.
| Status | Meaning |
|---|---|
400 |
Parameter validation — a seconds outside the model's range, a resolution the model doesn't offer (e.g. Input should be '1080P' or '720P'), or a missing image |
401 |
Invalid API key |
404 |
Unrecognized model code |
409 |
DELETE on a task that is not completed |
200 with status: "processing" |
Accepted — keep polling. A task that fails after starting reports status: "failed" with an error object |