User Guide
Video Model

Wan 2.7 Video Generation

Call Wan 2.7 text-to-video, image-to-video, reference-to-video, and video editing models through the unified video task API.

  • Submission route: POST /v1/videos
  • Task query: GET /v1/videos/{task_id}
  • Content download: GET /v1/videos/{task_id}/content

Video generation is asynchronous. Submit a task first, then poll with the returned task_id. After the task succeeds, download the generated video promptly. Wan 2.7 upstream result URLs are usually valid for 24 hours.

Supported Models

ModelUse caseMain input
wan2.7-t2vText to videoprompt
wan2.7-i2vImage to video, first/last frame, video continuationprompt, media, or image/images
wan2.7-r2vReference to video, multi-subject reference, reference voicesprompt, media
wan2.7-videoeditVideo editingprompt, video item in media

Common Request Fields

FieldTypeDescription
modelstringRequired. Use wan2.7-r2v for reference-to-video generation.
promptstringRequired for wan2.7-r2v, up to 5000 characters. Refer to assets by order, such as Image 1 and Video 1; image and video references are numbered separately.
mediaarrayRequired for wan2.7-r2v. Must contain at least one reference_image or reference_video.
negative_promptstringNegative prompt, up to 500 characters.
resolutionstringResolution tier. 720P or 1080P; default is 1080P. Cost changes with resolution.
ratiostringOutput aspect ratio. Supports 16:9, 9:16, 1:1, 4:3, 3:4; default is 16:9. For wan2.7-r2v, this is ignored when first_frame is provided.
durationnumberDuration in seconds; default is 5. For wan2.7-r2v, range is 2 to 10 when reference video is included, and 2 to 15 without reference video.
secondsstringString form of duration; prefer duration for new integrations.
metadataobjectExtra parameters. Common wan2.7-r2v keys: prompt_extend, watermark, seed.

wan2.7-r2v media

Each media item must include at least type and url. Array order defines the prompt references: the first reference_image is Image 1, and the first reference_video is Video 1. Images and videos are counted independently.

typeAvailabilityDescription
reference_imageOne of the required reference typesReference image for a person, animal, object, or scene. Supports public URLs, OSS temporary URLs, and Base64 Data URLs.
reference_videoOne of the required reference typesReference video. Use content that contains the subject; it can also provide a voice reference when it has audio. Supports public URLs and OSS temporary URLs.
first_frameOptionalFirst-frame image, maximum 1. When provided, ratio is ignored and the output follows the first-frame aspect ratio.

reference_image plus reference_video supports up to 5 items total. If a reference asset represents a subject, the official recommendation is to keep one role per asset. reference_image and reference_video may include reference_voice to set that subject's voice.

Media Limits

AssetFormatsLimits
reference_image / first_frameJPEG, JPG, PNG, BMP, WEBPWidth and height [240, 8000], aspect ratio 1:8 to 8:1, file size up to 20MB. PNG transparency is not supported.
reference_videoMP4, MOVDuration 1 to 30 seconds, width and height [240, 4096], aspect ratio 1:8 to 8:1, file size up to 100MB.
reference_voiceWAV, MP3Duration 1 to 10 seconds, file size up to 15MB. It only controls voice timbre, not spoken content.

Reference to Video

Multi-subject example with reference images, a reference video, and reference voices:

curl --request POST \
  --url https://api.magickapi.com/v1/videos \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "model": "wan2.7-r2v",
    "prompt": "Video 1 is holding Image 3 while playing a gentle country song on the chair from Image 4, and says: The sunshine is lovely today. Image 1 walks past Video 1 holding Image 2, puts Image 2 on the nearby table, and says: That sounds great, can you sing it again?",
    "media": [
      {
        "type": "reference_image",
        "url": "https://example.com/girl.jpg",
        "reference_voice": "https://example.com/girl-voice.mp3"
      },
      {
        "type": "reference_video",
        "url": "https://example.com/boy-role.mp4",
        "reference_voice": "https://example.com/boy-voice.mp3"
      },
      {
        "type": "reference_image",
        "url": "https://example.com/prop.png"
      },
      {
        "type": "reference_image",
        "url": "https://example.com/chair.png"
      }
    ],
    "resolution": "720P",
    "ratio": "16:9",
    "duration": 10,
    "metadata": {
      "prompt_extend": false,
      "watermark": false,
      "seed": 7
    }
  }'

For a single storyboard image, still use reference_image:

{
  "model": "wan2.7-r2v",
  "prompt": "Reference image, 3D cartoon adventure film style, keep the characters and forest scene consistent. Story beats: wide shot of the forest, the boy opens vines, the robot scans ahead, and they finally find a treasure chest.",
  "media": [
    {
      "type": "reference_image",
      "url": "https://example.com/storyboard.png"
    }
  ],
  "resolution": "720P",
  "duration": 10,
  "metadata": {
    "prompt_extend": false,
    "watermark": false
  }
}

To constrain the first frame, add first_frame:

{
  "model": "wan2.7-r2v",
  "prompt": "Video 1 enters from the doorway of the room in Image 1 and talks with the character in Image 2.",
  "media": [
    {
      "type": "first_frame",
      "url": "https://example.com/first-frame.png"
    },
    {
      "type": "reference_video",
      "url": "https://example.com/role.mp4"
    },
    {
      "type": "reference_image",
      "url": "https://example.com/second-role.png"
    }
  ],
  "resolution": "720P",
  "duration": 8
}

Other Wan 2.7 Modes

Text to video:

curl --request POST \
  --url https://api.magickapi.com/v1/videos \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "model": "wan2.7-t2v",
    "prompt": "A paper airplane slowly glides over a desk in sunlight, steady camera, clean composition.",
    "resolution": "720P",
    "ratio": "16:9",
    "duration": 5
  }'

Image to video:

{
  "model": "wan2.7-i2v",
  "prompt": "Make the cat in the image look up at the camera, with a slight camera push-in.",
  "image": "https://example.com/first-frame.png",
  "resolution": "720P",
  "duration": 5
}

Video editing:

{
  "model": "wan2.7-videoedit",
  "prompt": "Keep the subject motion, replace the background with a cyberpunk street at night.",
  "media": [
    {
      "type": "video",
      "url": "https://example.com/source.mp4"
    },
    {
      "type": "reference_image",
      "url": "https://example.com/style-reference.png"
    }
  ],
  "resolution": "720P",
  "duration": 5,
  "metadata": {
    "audio_setting": "origin",
    "watermark": false
  }
}

Response, Query, and Download

Successful submission returns a task object:

{
  "id": "task_01KXYZ1234567890ABCDE",
  "task_id": "task_01KXYZ1234567890ABCDE",
  "object": "video",
  "model": "wan2.7-r2v",
  "status": "queued",
  "progress": 0,
  "created_at": 1712345678
}

Query task status:

curl https://api.magickapi.com/v1/videos/task_01KXYZ1234567890ABCDE \
  -H 'Authorization: Bearer YOUR_API_KEY'

Status can be queued, in_progress, completed, or failed. When the task succeeds, metadata.url contains the upstream temporary video URL. Prefer the content download route to save the file:

curl -L https://api.magickapi.com/v1/videos/task_01KXYZ1234567890ABCDE/content \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  --output wan2-7-r2v-output.mp4

Polling Example

import { writeFile } from "node:fs/promises";

const baseUrl = "https://api.magickapi.com";
const apiKey = "YOUR_API_KEY";

const submitResp = await fetch(`${baseUrl}/v1/videos`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${apiKey}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "wan2.7-r2v",
    prompt: "Image 1 sits by the cafe window playing guitar. Video 1 walks into the frame and talks with Image 1.",
    media: [
      {
        type: "reference_image",
        url: "https://example.com/character.png",
        reference_voice: "https://example.com/voice.mp3",
      },
      {
        type: "reference_video",
        url: "https://example.com/action.mp4",
      },
    ],
    resolution: "720P",
    ratio: "16:9",
    duration: 10,
    metadata: {
      prompt_extend: false,
      watermark: false,
    },
  }),
});

if (!submitResp.ok) {
  throw new Error(await submitResp.text());
}

const task = await submitResp.json();
const taskId = task.id || task.task_id;

while (true) {
  const queryResp = await fetch(`${baseUrl}/v1/videos/${taskId}`, {
    headers: { Authorization: `Bearer ${apiKey}` },
  });
  const status = await queryResp.json();

  if (status.status === "completed") {
    const downloadResp = await fetch(`${baseUrl}/v1/videos/${taskId}/content`, {
      headers: { Authorization: `Bearer ${apiKey}` },
    });
    const buffer = Buffer.from(await downloadResp.arrayBuffer());
    await writeFile("wan2-7-r2v-output.mp4", buffer);
    break;
  }

  if (status.status === "failed") {
    throw new Error(status.error?.message || "video generation failed");
  }

  await new Promise((resolve) => setTimeout(resolve, 15000));
}

Last updated on

On this page