> ## Documentation Index
> Fetch the complete documentation index at: https://docs.apimart.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Generasi Video Wan3.0

>  - Model video referensi all-in-one Alibaba Cloud Wanxiang 3.0
- Teks-ke-video / frame pertama / frame pertama+terakhir / referensi multimodal / referensi file atau tautan
- Resolusi 480P / 720P / 1080P, durasi 2–30 detik
- Mendukung gambar, video, audio, dokumen, dan halaman web publik sebagai referensi 

<RequestExample>
  ```bash cURL theme={null}
  curl --request POST \
    --url https://api.apimart.ai/v1/videos/generations \
    --header 'Authorization: Bearer <token>' \
    --header 'Content-Type: application/json' \
    --data '{
      "model": "wan3.0-video",
      "prompt": "A kitten runs across a moonlit rooftop, neon lights of the city flicker in the distance, cinematic quality, smooth camera move.",
      "resolution": "720P",
      "size": "16:9",
      "duration": 5
    }'
  ```

  ```python Python theme={null}
  import requests

  url = "https://api.apimart.ai/v1/videos/generations"

  payload = {
      "model": "wan3.0-video",
      "prompt": "A kitten runs across a moonlit rooftop, neon lights of the city flicker in the distance, cinematic quality, smooth camera move.",
      "resolution": "720P",
      "size": "16:9",
      "duration": 5,
  }

  headers = {
      "Authorization": "Bearer <token>",
      "Content-Type": "application/json",
  }

  response = requests.post(url, json=payload, headers=headers)

  print(response.json())
  ```

  ```javascript JavaScript theme={null}
  const url = "https://api.apimart.ai/v1/videos/generations";

  const payload = {
    model: "wan3.0-video",
    prompt: "A kitten runs across a moonlit rooftop, neon lights of the city flicker in the distance, cinematic quality, smooth camera move.",
    resolution: "720P",
    size: "16:9",
    duration: 5,
  };

  const headers = {
    Authorization: "Bearer <token>",
    "Content-Type": "application/json",
  };

  fetch(url, {
    method: "POST",
    headers: headers,
    body: JSON.stringify(payload),
  })
    .then((response) => response.json())
    .then((data) => console.log(data))
    .catch((error) => console.error("Error:", error));
  ```

  ```go Go theme={null}
  package main

  import (
      "bytes"
      "encoding/json"
      "fmt"
      "io/ioutil"
      "net/http"
  )

  func main() {
      url := "https://api.apimart.ai/v1/videos/generations"

      payload := map[string]interface{}{
          "model":      "wan3.0-video",
          "prompt":     "A kitten runs across a moonlit rooftop",
          "resolution": "720P",
          "size":       "16:9",
          "duration":   5,
      }

      jsonData, _ := json.Marshal(payload)
      req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
      req.Header.Set("Authorization", "Bearer <token>")
      req.Header.Set("Content-Type", "application/json")

      client := &http.Client{}
      resp, err := client.Do(req)
      if err != nil {
          panic(err)
      }
      defer resp.Body.Close()

      body, _ := ioutil.ReadAll(resp.Body)
      fmt.Println(string(body))
  }
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "code": 200,
    "data": [
      {
        "status": "submitted",
        "task_id": "task_01J9HA7JPQ9A0Z6JZ3V8M9W6PZ"
      }
    ]
  }
  ```

  ```json 400 theme={null}
  {
    "error": {
      "code": 400,
      "message": "Invalid request parameters",
      "type": "invalid_request_error"
    }
  }
  ```

  ```json 401 theme={null}
  {
    "error": {
      "code": 401,
      "message": "Authentication failed, please check your API key",
      "type": "authentication_error"
    }
  }
  ```

  ```json 402 theme={null}
  {
    "error": {
      "code": 402,
      "message": "Insufficient account balance, please top up and try again",
      "type": "payment_required"
    }
  }
  ```

  ```json 429 theme={null}
  {
    "error": {
      "code": 429,
      "message": "Too many requests, please try again later",
      "type": "rate_limit_error"
    }
  }
  ```
</ResponseExample>

## Autentikasi

<ParamField header="Authorization" type="string" required>
  Semua endpoint memerlukan autentikasi Bearer Token

  Dapatkan API Key Anda dari [Halaman Manajemen API Key](https://apimart.ai/keys):

  ```
  Authorization: Bearer YOUR_API_KEY
  ```
</ParamField>

## Mode Generasi

Nama model ditetapkan ke **`wan3.0-video`**. Mode dipilih melalui field permintaan:

| Mode                     | Input tipikal                                                                         |
| ------------------------ | ------------------------------------------------------------------------------------- |
| Teks-ke-video            | hanya `prompt`                                                                        |
| Video frame pertama      | satu item di `image_urls` (keluarga frame)                                            |
| Frame pertama + terakhir | dua item di `image_urls`, atau `image_with_roles` dengan `first_frame` / `last_frame` |
| Video referensi          | gambar / video / audio referensi; prompt dapat memakai label gaya “图1 / 视频1 / 音频1”    |
| Referensi file / halaman | `file_url` atau `link_url` (`prompt` opsional)                                        |

## Parameter Permintaan

### Dasar

<ParamField body="model" type="string" required>
  Nilai tetap: `wan3.0-video`
</ParamField>

<ParamField body="prompt" type="string">
  Deskripsi teks. **Wajib kecuali** field media disediakan (setidaknya salah satu dari prompt atau media).

  * Maks **20.000** karakter; kelebihan dipotong otomatis (tanpa error)
  * Dalam mode referensi, gunakan “图N / 视频N / 音频N” untuk merujuk aset; indeks mengikuti urutan **dalam setiap jenis media**
</ParamField>

<ParamField body="resolution" type="string" default="1080P">
  Resolusi keluaran (tidak peka huruf besar/kecil)

  * `480P`
  * `720P`
  * `1080P` (**default**, harga tertinggi)

  <Warning>
    Menghilangkan `resolution` akan ditagih pada **1080P**. Kirim `480P` atau `720P` secara eksplisit bila biaya penting.
  </Warning>
</ParamField>

<ParamField body="size" type="string" default="adaptive">
  Rasio aspek. `aspect_ratio` juga diterima.

  * `adaptive` (default)
  * `16:9` / `4:3` / `1:1` / `3:4` / `9:16`
</ParamField>

<ParamField body="duration" type="integer" default="5">
  Durasi dalam detik:

  * `2`–`30`: durasi keluaran tetap (default `5`)
  * `-1`: durasi **ditentukan model**

  <Note>
    Jika ada video referensi: total durasi input + output ≤ 30 detik. Dengan `duration: -1`, durasi yang dipilih model tetap harus memenuhi batasan ini.
  </Note>
</ParamField>

<ParamField body="audio" type="boolean" default="true">
  Apakah keluaran menyertakan trek audio. Default `true`. **Harga sama dengan atau tanpa audio.**
</ParamField>

<ParamField body="seed" type="integer">
  Seed acak di `[0, 2147483647]`
</ParamField>

<ParamField body="watermark" type="boolean" default="false">
  Apakah menambahkan watermark. Default `false`
</ParamField>

<ParamField body="generation_type" type="string">
  Cara `image_urls` tanpa peran eksplisit diklasifikasikan:

  * `frame` — keluarga frame pertama/terakhir
  * `reference` — keluarga referensi

  Jika dihilangkan, klasifikasi otomatis (lihat aturan saling eksklusif).
</ParamField>

### Input media

<ParamField body="image_urls" type="string[]">
  Array URL gambar. Penugasan peran mengikuti aturan saling eksklusif.

  URL publik atau Base64 (`data:image/png;base64,...`).
</ParamField>

<ParamField body="image_with_roles" type="object[]">
  Gambar dengan peran eksplisit. Setiap item:

  * `url`: alamat gambar
  * `role`: `first_frame` / `last_frame` / `reference_image` (alias umum diterima)
</ParamField>

<ParamField body="video_urls" type="string[]">
  Video referensi, hingga **5** klip; masing-masing 1–15 d, **total ≤ 15 d**
</ParamField>

<ParamField body="audio_urls" type="string[]">
  Audio referensi, hingga **5** klip; masing-masing 1–15 d, **total ≤ 15 d**
</ParamField>

<ParamField body="audio_url" type="string">
  Audio referensi tunggal (bentuk nilai tunggal dari `audio_urls`)
</ParamField>

<ParamField body="file_url" type="string">
  URL dokumen referensi, paling banyak **1**. **Tidak dapat digabungkan dengan `link_url`.**

  Format meliputi docx / doc / xlsx / xls / pptx / ppt / pdf / txt / key / pages / numbers / md, ≤100MB, ≤50 halaman.
</ParamField>

<ParamField body="link_url" type="string">
  URL halaman web publik, paling banyak **1**. Hanya halaman tanpa login. **Tidak dapat digabungkan dengan `file_url`.**
</ParamField>

## Saling Eksklusif Keluarga Media

Media termasuk salah satu dari dua keluarga dan **tidak boleh digabung** (divalidasi sebelum submit → 400, tanpa tugas, tanpa biaya):

| Keluarga               | Anggota                                                                 | Arti                                      |
| ---------------------- | ----------------------------------------------------------------------- | ----------------------------------------- |
| **Keluarga frame**     | `first_frame`, `last_frame`                                             | Frame pertama / terakhir ketat dari video |
| **Keluarga referensi** | `reference_image`, `reference_video`, `reference_audio`, `file`, `link` | Model menafsirkan konten secara bebas     |

### Cara `image_urls` tanpa peran ditetapkan

1. Jika `generation_type` disetel → gunakan itu (`frame` / `reference`)
2. Jika tidak, dan permintaan sudah memiliki input keluarga referensi (`video_urls` / `audio_urls` / `audio_url` / `file_url` / `link_url`) → perlakukan sebagai `reference_image`
3. Jika tidak → keluarga frame: item pertama `first_frame`, kedua `last_frame` (sama seperti `wan2.7`)

Gunakan `image_with_roles` bila Anda membutuhkan kontrol eksplisit.

### Batas dan format media

| Jenis                    | Batas                                                                                      |
| ------------------------ | ------------------------------------------------------------------------------------------ |
| Frame pertama / terakhir | ≤ 1 masing-masing                                                                          |
| Gambar referensi         | ≤ 10                                                                                       |
| Video referensi          | ≤ 5 klip, 1–15 d masing-masing, total ≤15 d; mp4/mov; tepi 240–4096 px, rasio ≤8:1, ≤100MB |
| Audio referensi          | ≤ 5 klip, 1–15 d masing-masing, total ≤15 d; wav/mp3; ≤15MB                                |
| Gambar                   | JPEG/JPG/PNG (tanpa alpha) / BMP / WEBP; tepi 240–8000 px, rasio ≤8:1, ≤20MB               |
| Dokumen                  | ≤100MB, ≤50 halaman                                                                        |
| Halaman web              | URL publik, tanpa login                                                                    |

## Contoh Permintaan

### Teks-ke-video

```json theme={null}
{
  "model": "wan3.0-video",
  "prompt": "A kitten runs across a moonlit rooftop, neon lights of the city flicker in the distance, cinematic quality, smooth camera move.",
  "resolution": "720P",
  "size": "16:9",
  "duration": 5
}
```

### Video frame pertama

```json theme={null}
{
  "model": "wan3.0-video",
  "prompt": "The person in the frame starts freestyle rapping, camera slowly pushes in",
  "image_urls": ["https://example.com/first.png"],
  "resolution": "720P",
  "duration": 5
}
```

### Frame pertama + terakhir

```json theme={null}
{
  "model": "wan3.0-video",
  "prompt": "Smile gradually becomes laughter, background light shifts from cool to warm",
  "image_urls": [
    "https://example.com/first.png",
    "https://example.com/last.jpg"
  ],
  "duration": 5
}
```

Atau dengan `image_with_roles`:

```json theme={null}
{
  "model": "wan3.0-video",
  "prompt": "Smile gradually becomes laughter",
  "image_with_roles": [
    {"url": "https://example.com/first.png", "role": "first_frame"},
    {"url": "https://example.com/last.jpg", "role": "last_frame"}
  ],
  "duration": 5
}
```

### Referensi multimodal

```json theme={null}
{
  "model": "wan3.0-video",
  "prompt": "视频1抱着图1，在图3的椅子上弹奏一支舒缓的乡村民谣，并说道：\"今天的阳光真好。\"",
  "generation_type": "reference",
  "image_urls": [
    "https://example.com/object1.jpg",
    "https://example.com/object2.png",
    "https://example.com/chair.png"
  ],
  "video_urls": ["https://example.com/role.mp4"],
  "resolution": "480P",
  "duration": 5
}
```

> Dengan `video_urls` hadir, `image_urls` tanpa peran otomatis diklasifikasikan sebagai gambar referensi; mengatur `generation_type: "reference"` lebih jelas.

### Video referensi file

`prompt` boleh dihilangkan; generasi didorong oleh dokumen:

```json theme={null}
{
  "model": "wan3.0-video",
  "file_url": "https://example.com/glass.pptx",
  "resolution": "480P",
  "duration": 10
}
```

### Video referensi halaman web

```json theme={null}
{
  "model": "wan3.0-video",
  "prompt": "Turn this article into a short educational video",
  "link_url": "https://example.com/article/123",
  "duration": 15
}
```

## Penagihan

**Per detik × resolusi** (selaras dengan harga resmi). Audio on/off tidak mengubah harga:

| Resolusi | Harga satuan  | 5 d   | 30 d   |
| -------- | ------------- | ----- | ------ |
| 480P     | **¥0.30** / d | ¥1.50 | ¥9.00  |
| 720P     | **¥0.60** / d | ¥3.00 | ¥18.00 |
| 1080P    | **¥1.20** / d | ¥6.00 | ¥36.00 |

* Default adalah **1080P** (paling mahal); kirim `480P` / `720P` bila sensitif biaya
* Detik yang ditagih: untuk `2`–`30`, `duration` yang diminta; untuk `-1`, detik keluaran **aktual**
* `audio: true/false` **tidak** memengaruhi harga

## Batasan dan Catatan

| Item               | Catatan                                                               |
| ------------------ | --------------------------------------------------------------------- |
| Durasi             | Bilangan bulat `2`–`30`, atau `-1` (model menentukan durasi)          |
| Dengan input video | Total durasi video input + durasi keluaran ≤ 30 d                     |
| Latensi            | Biasanya 1–5 menit; lebih lama untuk klip panjang                     |
| URL hasil          | Dicerminkan ke CDN platform setelah sukses untuk akses jangka panjang |
| Prompt             | ≤20.000 karakter; kelebihan dipotong                                  |

## Error Umum

Semua adalah **400 sinkron** (tanpa tugas, tanpa biaya):

| Kasus                                  | Yang harus dilakukan                                                                    |
| -------------------------------------- | --------------------------------------------------------------------------------------- |
| Mencampur keluarga frame dan referensi | Pilih satu keluarga lewat `generation_type`, atau setel peran dengan `image_with_roles` |
| `file_url` dan `link_url` bersamaan    | Pilih salah satu                                                                        |
| `duration` tidak valid                 | Hanya `2`–`30` atau `-1`                                                                |
| Resolusi tidak didukung (mis. 4K)      | Hanya `480P` / `720P` / `1080P`                                                         |
| Lebih dari 10 gambar referensi         | Kurangi menjadi ≤10                                                                     |
| `prompt` kosong dan media kosong       | Sediakan setidaknya salah satu                                                          |

## Respons

<ResponseField name="code" type="integer">
  Kode status; 200 jika sukses
</ResponseField>

<ResponseField name="data" type="array">
  Array data respons

  <Expandable title="Elemen array">
    <ResponseField name="status" type="string">
      Status tugas; `submitted` saat dibuat
    </ResponseField>

    <ResponseField name="task_id" type="string">
      ID tugas untuk polling
    </ResponseField>
  </Expandable>
</ResponseField>

<Note>
  **Kueri hasil**

  Generasi video bersifat asinkron. Poll [Dapatkan Status Tugas](/id/api-reference/tasks/status) atau `GET /v1/videos/generations/{task_id}`.

  Interval yang direkomendasikan 5–10 detik; generasi biasanya memakan waktu 1–5 menit. Saat sukses, gunakan URL di `result.videos`.
</Note>
