> ## 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.

# Génération vidéo Wan3.0

>  - Modèle vidéo de référence tout-en-un Alibaba Cloud Wanxiang 3.0
- Texte-vers-vidéo / première image / première+dernière image / référence multimodale / référence fichier ou lien
- Résolution 480P / 720P / 1080P, durée 2–30 secondes
- Prend en charge images, vidéo, audio, documents et pages web publiques comme références 

<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>

## Authentification

<ParamField header="Authorization" type="string" required>
  Tous les endpoints exigent une authentification Bearer Token

  Obtenez votre API Key depuis la [page de gestion des API Keys](https://apimart.ai/keys) :

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

## Modes de génération

Le nom du modèle est fixé à **`wan3.0-video`**. Les modes sont sélectionnés via les champs de la requête :

| Mode                                | Entrées typiques                                                                                        |
| ----------------------------------- | ------------------------------------------------------------------------------------------------------- |
| Texte-vers-vidéo                    | `prompt` uniquement                                                                                     |
| Vidéo à partir de la première image | un élément dans `image_urls` (famille frame)                                                            |
| Première + dernière image           | deux éléments dans `image_urls`, ou `image_with_roles` avec `first_frame` / `last_frame`                |
| Vidéo de référence                  | images / vidéos / audio de référence ; le prompt peut utiliser des libellés du style « 图1 / 视频1 / 音频1 » |
| Référence fichier / page            | `file_url` ou `link_url` (`prompt` optionnel)                                                           |

## Paramètres de la requête

### Bases

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

<ParamField body="prompt" type="string">
  Description textuelle. **Obligatoire sauf si** des champs média sont fournis (au moins un parmi prompt ou média).

  * Max **20 000** caractères ; le dépassement est tronqué automatiquement (sans erreur)
  * En mode référence, utilisez « 图N / 视频N / 音频N » pour désigner les assets ; les indices suivent l’ordre **au sein de chaque type de média**
</ParamField>

<ParamField body="resolution" type="string" default="1080P">
  Résolution de sortie (insensible à la casse)

  * `480P`
  * `720P`
  * `1080P` (**par défaut**, prix le plus élevé)

  <Warning>
    Omettre `resolution` facture au tarif **1080P**. Passez explicitement `480P` ou `720P` lorsque le coût compte.
  </Warning>
</ParamField>

<ParamField body="size" type="string" default="adaptive">
  Rapport d’aspect. `aspect_ratio` est également accepté.

  * `adaptive` (par défaut)
  * `16:9` / `4:3` / `1:1` / `3:4` / `9:16`
</ParamField>

<ParamField body="duration" type="integer" default="5">
  Durée en secondes :

  * `2`–`30` : durée de sortie fixée (défaut `5`)
  * `-1` : la durée est **choisie par le modèle**

  <Note>
    Avec des vidéos de référence : durée totale en entrée + sortie ≤ 30 s. Avec `duration: -1`, la durée choisie par le modèle doit aussi respecter cette contrainte.
  </Note>
</ParamField>

<ParamField body="audio" type="boolean" default="true">
  Indique si la sortie inclut une piste audio. Par défaut `true`. **Le prix est le même avec ou sans audio.**
</ParamField>

<ParamField body="seed" type="integer">
  Graine aléatoire dans `[0, 2147483647]`
</ParamField>

<ParamField body="watermark" type="boolean" default="false">
  Indique s’il faut ajouter un filigrane. Par défaut `false`
</ParamField>

<ParamField body="generation_type" type="string">
  Comment les `image_urls` brutes sont classées :

  * `frame` — famille première/dernière image
  * `reference` — famille de référence

  Si omis, la classification est automatique (voir les règles d’exclusion mutuelle).
</ParamField>

### Entrées média

<ParamField body="image_urls" type="string[]">
  Tableau d’URL d’images. L’attribution des rôles suit les règles d’exclusion mutuelle.

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

<ParamField body="image_with_roles" type="object[]">
  Images avec rôles explicites. Chaque élément :

  * `url` : adresse de l’image
  * `role` : `first_frame` / `last_frame` / `reference_image` (alias courants acceptés)
</ParamField>

<ParamField body="video_urls" type="string[]">
  Vidéos de référence, jusqu’à **5** clips ; chacun 1–15 s, **total ≤ 15 s**
</ParamField>

<ParamField body="audio_urls" type="string[]">
  Audio de référence, jusqu’à **5** clips ; chacun 1–15 s, **total ≤ 15 s**
</ParamField>

<ParamField body="audio_url" type="string">
  Audio de référence unique (forme monovaleur de `audio_urls`)
</ParamField>

<ParamField body="file_url" type="string">
  URL de document de référence, au plus **1**. **Ne peut pas être combiné avec `link_url`.**

  Formats : docx / doc / xlsx / xls / pptx / ppt / pdf / txt / key / pages / numbers / md, ≤100 Mo, ≤50 pages.
</ParamField>

<ParamField body="link_url" type="string">
  URL de page web publique, au plus **1**. Pages sans connexion uniquement. **Ne peut pas être combiné avec `file_url`.**
</ParamField>

## Exclusion mutuelle des familles de médias

Les médias appartiennent à l’une des deux familles et **ne doivent pas être mélangés** (validé avant soumission → 400, pas de tâche, pas de facturation) :

| Famille                  | Membres                                                                 | Signification                                 |
| ------------------------ | ----------------------------------------------------------------------- | --------------------------------------------- |
| **Famille frame**        | `first_frame`, `last_frame`                                             | Première / dernière image stricte de la vidéo |
| **Famille de référence** | `reference_image`, `reference_video`, `reference_audio`, `file`, `link` | Le modèle interprète le contenu librement     |

### Comment les `image_urls` brutes sont assignées

1. Si `generation_type` est défini → l’utiliser (`frame` / `reference`)
2. Sinon, si la requête contient déjà des entrées de la famille de référence (`video_urls` / `audio_urls` / `audio_url` / `file_url` / `link_url`) → traiter comme `reference_image`
3. Sinon → famille frame : premier élément `first_frame`, second `last_frame` (identique à `wan2.7`)

Utilisez `image_with_roles` lorsque vous avez besoin d’un contrôle explicite.

### Limites et formats des médias

| Type                      | Limites                                                                                 |
| ------------------------- | --------------------------------------------------------------------------------------- |
| Première / dernière image | ≤ 1 chacune                                                                             |
| Images de référence       | ≤ 10                                                                                    |
| Vidéo de référence        | ≤ 5 clips, 1–15 s chacun, total ≤15 s ; mp4/mov ; bord 240–4096 px, ratio ≤8:1, ≤100 Mo |
| Audio de référence        | ≤ 5 clips, 1–15 s chacun, total ≤15 s ; wav/mp3 ; ≤15 Mo                                |
| Images                    | JPEG/JPG/PNG (sans alpha) / BMP / WEBP ; bord 240–8000 px, ratio ≤8:1, ≤20 Mo           |
| Documents                 | ≤100 Mo, ≤50 pages                                                                      |
| Pages web                 | URL publiques, sans connexion                                                           |

## Exemples de requête

### Texte-vers-vidéo

```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
}
```

### Vidéo à partir de la première image

```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
}
```

### Première + dernière image

```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
}
```

Ou avec `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
}
```

### Référence multimodale

```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
}
```

> Avec `video_urls` présent, les `image_urls` brutes se classent automatiquement comme images de référence ; définir `generation_type: "reference"` est plus clair.

### Vidéo de référence par fichier

`prompt` peut être omis ; la génération est pilotée par le document :

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

### Vidéo de référence par page 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
}
```

## Facturation

**Par seconde × résolution** (aligné sur le tarif officiel). Audio activé/désactivé ne change pas le prix :

| Résolution | Prix unitaire | 5 s   | 30 s   |
| ---------- | ------------- | ----- | ------ |
| 480P       | **¥0.30** / s | ¥1.50 | ¥9.00  |
| 720P       | **¥0.60** / s | ¥3.00 | ¥18.00 |
| 1080P      | **¥1.20** / s | ¥6.00 | ¥36.00 |

* Par défaut **1080P** (le plus cher) ; passez `480P` / `720P` lorsque le coût est sensible
* Secondes facturables : pour `2`–`30`, la `duration` demandée ; pour `-1`, les secondes **réelles** de sortie
* `audio: true/false` **n’affecte pas** le prix

## Limites et notes

| Élément           | Notes                                                                   |
| ----------------- | ----------------------------------------------------------------------- |
| Durée             | Entier `2`–`30`, ou `-1` (le modèle choisit la durée)                   |
| Avec entrée vidéo | Durée totale des vidéos d’entrée + durée de sortie ≤ 30 s               |
| Latence           | Typiquement 1–5 minutes ; plus long pour les clips longs                |
| URL du résultat   | Miroirée sur le CDN de la plateforme après succès pour un accès durable |
| Prompt            | ≤20 000 caractères ; dépassement tronqué                                |

## Erreurs courantes

Toutes sont des **400 synchrones** (pas de tâche, pas de facturation) :

| Cas                                     | Que faire                                                                               |
| --------------------------------------- | --------------------------------------------------------------------------------------- |
| Mélange des familles frame et référence | Choisir une famille via `generation_type`, ou définir les rôles avec `image_with_roles` |
| `file_url` et `link_url` ensemble       | En choisir un seul                                                                      |
| `duration` invalide                     | Uniquement `2`–`30` ou `-1`                                                             |
| Résolution non prise en charge (ex. 4K) | Uniquement `480P` / `720P` / `1080P`                                                    |
| Plus de 10 images de référence          | Réduire à ≤10                                                                           |
| `prompt` vide et médias vides           | Fournir au moins l’un des deux                                                          |

## Réponse

<ResponseField name="code" type="integer">
  Code de statut ; 200 en cas de succès
</ResponseField>

<ResponseField name="data" type="array">
  Tableau de données de réponse

  <Expandable title="Éléments du tableau">
    <ResponseField name="status" type="string">
      Statut de la tâche ; `submitted` à la création
    </ResponseField>

    <ResponseField name="task_id" type="string">
      ID de tâche pour le polling
    </ResponseField>
  </Expandable>
</ResponseField>

<Note>
  **Consulter les résultats**

  La génération vidéo est asynchrone. Interrogez [Obtenir le statut de la tâche](/fr/api-reference/tasks/status) ou `GET /v1/videos/generations/{task_id}`.

  Intervalle recommandé 5–10 secondes ; la génération prend généralement 1–5 minutes. En cas de succès, utilisez les URL dans `result.videos`.
</Note>
