# Vidéos

> Référence de POST /v1/videos et des routes GET /v1/videos : lancer une vidéo, suivre la tâche, la télécharger, lister vos vidéos, avec les délais et les coûts.

Une vidéo prend plusieurs minutes. Le lancement répond tout de suite avec une tâche ; vous suivez ensuite la tâche, puis téléchargez la vidéo une fois terminée. Les points d’accès suivent l’API vidéo d’OpenAI.

| Méthode | Chemin | Rôle |
| --- | --- | --- |
| `POST` | `/v1/videos` | [Lancer une vidéo](https://realmoon.ai/documentation/api/videos/#creer) |
| `GET` | `/v1/videos/{id}` | [Suivre une vidéo](https://realmoon.ai/documentation/api/videos/#suivre) |
| `GET` | `/v1/videos/{id}/content` | [Télécharger la vidéo](https://realmoon.ai/documentation/api/videos/#telecharger) |
| `GET` | `/v1/videos` | [Lister vos vidéos](https://realmoon.ai/documentation/api/videos/#lister) |

Une tâche passe par les statuts `queued` (en file), `in_progress` (en cours), puis `completed` (terminée) ou `failed` (en échec). Elle appartient au workspace de la clé qui l’a lancée : toute clé de ce workspace peut la suivre et la télécharger.

## Exemple complet

```bash title="cURL"
# 1. Lancer la vidéo
curl https://api.realmoon.ai/v1/videos \
  -H "Authorization: Bearer $MOONAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "alibaba/wan-2.6", "prompt": "Une vague au coucher du soleil", "seconds": "5"}'
# => {"id": "video_3c9e…", "status": "queued", …}

# 2. Suivre la tâche (toutes les 10 secondes environ)
curl https://api.realmoon.ai/v1/videos/video_3c9e... \
  -H "Authorization: Bearer $MOONAI_API_KEY"

# 3. Télécharger la vidéo une fois "completed"
curl https://api.realmoon.ai/v1/videos/video_3c9e.../content \
  -H "Authorization: Bearer $MOONAI_API_KEY" -o vague.mp4
```

```python title="Python"
import os
import time
from openai import OpenAI

client = OpenAI(base_url="https://api.realmoon.ai/v1", api_key=os.environ["MOONAI_API_KEY"])

job = client.videos.create(
    model="alibaba/wan-2.6",
    prompt="Une vague au coucher du soleil",
    seconds="5",
    extra_body={"resolution": "720p", "aspect_ratio": "16:9"},
)
while job.status in ("queued", "in_progress"):
    time.sleep(10)
    job = client.videos.retrieve(job.id)

if job.status == "completed":
    client.videos.download_content(job.id).write_to_file("vague.mp4")
else:
    print("Échec :", job.error)
```

```javascript title="JavaScript"
import fs from 'node:fs';
import OpenAI from 'openai';

const client = new OpenAI({ baseURL: 'https://api.realmoon.ai/v1', apiKey: process.env.MOONAI_API_KEY });

let job = await client.videos.create({
  model: 'alibaba/wan-2.6',
  prompt: 'Une vague au coucher du soleil',
  seconds: '5',
  resolution: '720p', // paramètre propre à Moon AI, envoyé tel quel
});
while (job.status === 'queued' || job.status === 'in_progress') {
  await new Promise((r) => setTimeout(r, 10_000));
  job = await client.videos.retrieve(job.id);
}

if (job.status === 'completed') {
  const content = await client.videos.downloadContent(job.id);
  fs.writeFileSync('vague.mp4', Buffer.from(await content.arrayBuffer()));
} else {
  console.error('Échec :', job.error);
}
```

## Lancer une vidéo

```http
POST https://api.realmoon.ai/v1/videos
```

- Authentification : clé `sk-moon-…` avec la portée `inference` (voir [Authentification](https://realmoon.ai/documentation/api/authentification/)).
- Corps : JSON, ou `multipart/form-data` (avec l’en-tête `Content-Length`) pour envoyer les images de départ et de fin comme fichiers. 60 Mo au plus.
- Réponse : l’[objet vidéo](https://realmoon.ai/documentation/api/videos/#objet) de la tâche, au statut `queued`, avec l’en-tête `X-Moon-Request-Id` qui sert à lire le coût sur [`/v1/generation`](https://realmoon.ai/documentation/api/solde/#generation).

### Paramètres

| Paramètre | Type | Obligatoire | Description |
| --- | --- | --- | --- |
| `model` | chaîne | oui | Un modèle de type `video` de `GET /v1/models?type=video`. |
| `prompt` | chaîne | oui | Description de la vidéo, 4 000 caractères au plus. |
| `seconds` (ou `duration`) | entier ou chaîne | non | Durée en secondes, parmi les `durations` du modèle. Par défaut : la première durée d’au moins 5 secondes, sinon la plus longue. |
| `resolution` | chaîne | non | Parmi les `resolutions` du modèle (`480p`, `720p`, `1080p`, `4K`…). Par défaut `720p` quand le modèle le propose, sinon sa première résolution. |
| `size` | chaîne | non | `LARGEURxHAUTEUR`, par exemple `1280x720` : la résolution et le format les plus proches en sont déduits, si vous ne les donnez pas. |
| `aspect_ratio` | chaîne | non | Parmi les `aspect_ratios` du modèle (`16:9`, `9:16`…). Par défaut, le premier de la liste. |
| `generate_audio` | booléen | non | Avec ou sans son, pour les modèles qui font du son (`audio: true`). Par défaut, avec son si le modèle en fait. `true` sur un modèle muet : `400 unsupported_value`. |
| `seed` | entier | non | Graine, de 0 à 2 147 483 647. |
| `input_reference`, `image` ou `first_frame` | image | non | Image de départ : adresse `https://`, adresse `data:` en base64, base64 seul, ou fichier en multipart. Pour les modèles où `first_frame` vaut `true`. |
| `last_frame` | image | non | Image de fin, avec une image de départ, pour les modèles où `last_frame` vaut `true`. |
| `user` | chaîne | non | Accepté, sans effet. |

Tout autre paramètre est refusé avec `400 unknown_parameter`. Une image fait 20 Mo au plus (PNG, JPEG, WebP ou GIF). Une image à une adresse `https://` est lue par le fournisseur du modèle, pas par Moon AI.

### Exemple

```bash title="cURL"
curl https://api.realmoon.ai/v1/videos \
  -H "Authorization: Bearer $MOONAI_API_KEY" \
  -F model=kwaivgi/kling-v3.0-std \
  -F prompt="La photo s’anime : les nuages défilent" \
  -F seconds=5 \
  -F generate_audio=false \
  -F first_frame=@paysage.png
```

```python title="Python"
job = client.videos.create(
    model="kwaivgi/kling-v3.0-std",
    prompt="La photo s’anime : les nuages défilent",
    seconds="5",
    input_reference=open("paysage.png", "rb"),
    extra_body={"generate_audio": False},
)
print(job.id, job.status)
```

```javascript title="JavaScript"
const job = await client.videos.create({
  model: 'kwaivgi/kling-v3.0-std',
  prompt: 'La photo s’anime : les nuages défilent',
  seconds: '5',
  input_reference: fs.createReadStream('paysage.png'),
  generate_audio: false, // paramètre propre à Moon AI, envoyé tel quel
});
console.log(job.id, job.status);
```

## L’objet vidéo

`POST /v1/videos`, `GET /v1/videos/{id}` et `GET /v1/videos` renvoient des objets vidéo.

```json title="Objet vidéo terminé"
{
  "id": "video_3c9e2f6a8b1d4e7f9a0b2c4d6e8f1a3b",
  "object": "video",
  "model": "alibaba/wan-2.6",
  "status": "completed",
  "progress": 100,
  "created_at": 1793577600,
  "completed_at": 1793577780,
  "seconds": "5",
  "size": "1280x720",
  "resolution": "720p",
  "aspect_ratio": "16:9",
  "generate_audio": true,
  "remixed_from_video_id": null,
  "error": null,
  "content_url": "/v1/videos/video_3c9e2f6a8b1d4e7f9a0b2c4d6e8f1a3b/content",
  "expires_at": 1793581380,
  "usage": { "seconds": 5, "credits": 2800 }
}
```

| Champ | Type | Description |
| --- | --- | --- |
| `id` | chaîne | Identifiant de la tâche : `video_` suivi de 32 caractères. |
| `object` | chaîne | Toujours `video`. |
| `model` | chaîne | Le modèle appelé. |
| `status` | chaîne | `queued`, `in_progress`, `completed` ou `failed`. |
| `progress` | entier | Avancement de 0 à 100, quand le fournisseur le donne ; 100 une fois terminée. |
| `created_at`, `completed_at` | entier | Dates en secondes Unix. `completed_at` vaut `null` avant la fin. |
| `seconds` | chaîne | Durée demandée au modèle. |
| `size` | chaîne | Dimensions qui correspondent à la résolution et au format, par exemple `1280x720`. |
| `resolution`, `aspect_ratio`, `generate_audio` | chaîne, chaîne, booléen | Ce qui a été demandé au modèle. |
| `remixed_from_video_id` | `null` | Toujours `null`, gardé pour la compatibilité. |
| `content_url` | chaîne | Une fois terminée : l’adresse de téléchargement. |
| `expires_at` | entier | Une fois terminée : la date jusqu’à laquelle la vidéo reste disponible (environ une heure après la fin). |
| `error` | objet ou `null` | En cas d’échec : `{"code", "message"}`. |
| `usage` | objet | Une fois la tâche réglée : `seconds` (durée) et `credits` (crédits facturés). |

Codes de `error.code` d’une tâche en échec, toujours sans frais :

| `code` | Cause |
| --- | --- |
| `generation_failed` | Le modèle n’a pas pu faire la vidéo. |
| `content_policy_violation` | Le système de sécurité du modèle a refusé la demande. |
| `timeout` | La vidéo n’était pas finie au bout de 6 heures et a été abandonnée. |
| `not_found` | Le fournisseur ne connaît plus la tâche. |

## Suivre une vidéo

```http
GET https://api.realmoon.ai/v1/videos/{id}
```

Renvoie l’[objet vidéo](https://realmoon.ai/documentation/api/videos/#objet) à jour.

- Authentification : clé `sk-moon-…` du workspace qui a lancé la vidéo, avec la portée `inference`.
- Paramètre de chemin : `id`, l’identifiant `video_…` de la tâche.
- Interrogez la tâche toutes les 10 secondes environ : Moon AI ne demande pas l’état au fournisseur plus d’une fois toutes les 5 secondes.
- La lecture n’est pas facturée.

```bash title="cURL"
curl https://api.realmoon.ai/v1/videos/video_3c9e2f6a8b1d4e7f9a0b2c4d6e8f1a3b \
  -H "Authorization: Bearer $MOONAI_API_KEY"
```

```python title="Python"
job = client.videos.retrieve("video_3c9e2f6a8b1d4e7f9a0b2c4d6e8f1a3b")
print(job.status, job.progress)
```

```javascript title="JavaScript"
const job = await client.videos.retrieve('video_3c9e2f6a8b1d4e7f9a0b2c4d6e8f1a3b');
console.log(job.status, job.progress);
```

## Télécharger la vidéo

```http
GET https://api.realmoon.ai/v1/videos/{id}/content
```

Envoie le fichier vidéo, en général `video/mp4`, avec l’en-tête `Content-Disposition` qui propose le nom `<id>.mp4`.

- Authentification : clé `sk-moon-…` du workspace qui a lancé la vidéo, avec la portée `inference`.
- Avant la fin : `409 video_not_ready`.
- Moon AI ne garde pas la vidéo : elle est lue chez le fournisseur au moment du téléchargement. Téléchargez-la dans l’heure qui suit la fin et gardez votre copie. Quand le fournisseur ne l’a plus : `410 video_expired`.
- Au plus 4 téléchargements à la fois par workspace (au-delà : `429 too_many_concurrent`).
- Le téléchargement n’est pas facturé.

```bash title="cURL"
curl https://api.realmoon.ai/v1/videos/video_3c9e2f6a8b1d4e7f9a0b2c4d6e8f1a3b/content \
  -H "Authorization: Bearer $MOONAI_API_KEY" -o vague.mp4
```

```python title="Python"
client.videos.download_content("video_3c9e2f6a8b1d4e7f9a0b2c4d6e8f1a3b").write_to_file("vague.mp4")
```

```javascript title="JavaScript"
const content = await client.videos.downloadContent('video_3c9e2f6a8b1d4e7f9a0b2c4d6e8f1a3b');
fs.writeFileSync('vague.mp4', Buffer.from(await content.arrayBuffer()));
```

## Lister vos vidéos

```http
GET https://api.realmoon.ai/v1/videos
```

Liste les vidéos du workspace, les plus récentes d’abord.

| Paramètre | Type | Obligatoire | Description |
| --- | --- | --- | --- |
| `limit` | entier | non | Nombre de vidéos par page, ramené entre 1 et 100. 20 par défaut. |
| `after` | chaîne | non | Identifiant d’une vidéo du workspace : la page commence après elle. |

```bash title="cURL"
curl "https://api.realmoon.ai/v1/videos?limit=10" \
  -H "Authorization: Bearer $MOONAI_API_KEY"
```

```python title="Python"
# Le SDK charge les pages suivantes au fil de l'itération.
for video in client.videos.list(limit=10):
    print(video.id, video.status)
```

```javascript title="JavaScript"
// Le SDK charge les pages suivantes au fil de l'itération.
for await (const video of client.videos.list({ limit: 10 })) {
  console.log(video.id, video.status);
}
```

```json title="Réponse"
{
  "object": "list",
  "data": [{ "id": "video_3c9e2f6a8b1d4e7f9a0b2c4d6e8f1a3b", "object": "video", "status": "completed" }],
  "first_id": "video_3c9e2f6a8b1d4e7f9a0b2c4d6e8f1a3b",
  "last_id": "video_3c9e2f6a8b1d4e7f9a0b2c4d6e8f1a3b",
  "has_more": false
}
```

| Champ | Type | Description |
| --- | --- | --- |
| `object` | chaîne | Toujours `list`. |
| `data` | tableau | Les [objets vidéo](https://realmoon.ai/documentation/api/videos/#objet) de la page (raccourcis dans l’exemple). |
| `first_id`, `last_id` | chaîne ou `null` | Premier et dernier identifiant de la page. |
| `has_more` | booléen | `true` s’il reste des vidéos : passez `last_id` dans `after` pour la page suivante. |

## Modèles

Liste au 5 novembre 2026 ; la liste à jour, avec les prix par seconde, vient de `GET /v1/models?type=video`.

| Modèle | Durées (s) | Résolutions | Formats | Son | Image de départ / de fin |
| --- | --- | --- | --- | --- | --- |
| `alibaba/wan-2.6` | 5, 10 | 480p, 720p, 1080p | 16:9, 9:16 | oui | oui / non |
| `alibaba/wan-2.7` | 2 à 10 | 720p, 1080p | 16:9, 9:16, 1:1, 4:3, 3:4 | oui | oui / oui |
| `alibaba/wan-3.0` | 2 à 15 | 480p, 720p, 1080p | 16:9, 9:16, 1:1, 4:3, 3:4 | oui | oui / oui |
| `kwaivgi/kling-v3.0-std`, `kling-v3.0-pro` | 3 à 15 | 720p, 1080p | 16:9, 9:16, 1:1 | oui, ou sans (moins cher) | oui / oui |
| `google/veo-3.1-lite` | 4, 6, 8 | 720p, 1080p | 16:9, 9:16 | oui, ou sans (moins cher) | oui / oui |
| `google/veo-3.1-fast`, `google/veo-3.1` | 4, 6, 8 | 720p, 1080p, 4K | 16:9, 9:16 | oui, ou sans (moins cher) | oui / oui |
| `minimax/hailuo-2.3` | 6, 10 | 1080p | 16:9 | non | oui / non |
| `x-ai/grok-imagine-video` | 1 à 15 | 480p, 720p | 16:9, 9:16, 1:1, 4:3, 3:4, 3:2, 2:3 | non | oui / non |
| `runway/gen-4.5` | 2 à 10 | 720p | 16:9, 9:16 | non | oui / non |

## Coûts

- Au lancement, la tâche retient le prix de la durée demandée, avec une petite marge, plus les images de départ et de fin pour les modèles qui les facturent.
- Une vidéo terminée est facturée au coût réel annoncé par le fournisseur (à défaut, au prix de la liste), et le reste de la retenue est rendu.
- Une vidéo en échec, refusée, abandonnée après 6 heures, ou dont le lancement a été coupé par notre délai, ne coûte rien.
- La retenue d’une tâche en cours compte dans le solde et les plafonds de dépense jusqu’à sa fin.

Voir [Coûts et porte-monnaie](https://realmoon.ai/documentation/api/couts/).

## Limites

- Au plus 20 vidéos en cours à la fois par workspace (au-delà : `429 too_many_concurrent`, `Retry-After: 30`).
- Le lancement répond en une minute environ au plus.
- Moon AI garde l’état de la tâche (statut, durée, résolution, format, coût), pas votre description ni la vidéo.

## Erreurs

| HTTP | `code` | Point d’accès | Signification |
| --- | --- | --- | --- |
| 400 | `missing_required_parameter` | lancement | `model` ou `prompt` absent. |
| 400 | `unknown_parameter` | lancement | Paramètre inconnu. |
| 400 | `unsupported_value` | lancement | Durée, résolution, format, `size` ou `generate_audio` hors de ce que le modèle accepte. |
| 400 | `unsupported_parameter` | lancement | Image de départ ou de fin sur un modèle qui ne l’accepte pas, ou paramètre refusé par le modèle (avec une indication). |
| 400 | `string_above_max_length` | lancement | Description de plus de 4 000 caractères. |
| 400 | `invalid_image` | lancement | Image illisible, d’un autre type ou trop grande. |
| 400 | `content_policy_violation` | lancement | Le système de sécurité du modèle a refusé la demande. |
| 400 | `null` | lancement, liste | `seed` ou `generate_audio` invalide, image de fin sans image de départ, base64 invalide, `after` inconnu. |
| 403 | `org_policy` | lancement | Les règles de votre organisation refusent ce modèle. |
| 404 | `model_not_found` | lancement | Modèle inconnu ou qui ne sert pas ce point d’accès. |
| 404 | `video_not_found` | suivi, téléchargement | Aucune vidéo de ce workspace ne porte cet identifiant. |
| 409 | `video_not_ready` | téléchargement | La vidéo n’est pas encore terminée. |
| 410 | `video_expired` | téléchargement | La vidéo n’est plus disponible chez le fournisseur. |
| 411 | `length_required` | lancement | Envoi multipart sans en-tête `Content-Length`. |
| 413 | `request_too_large`, `file_too_large` | lancement | Corps ou image trop volumineux. |
| 429 | `too_many_concurrent` | lancement, téléchargement | Trop de vidéos en cours, ou de téléchargements, dans le workspace. |
| 429 | `upstream_rate_limited` | lancement | Le modèle est surchargé : réessayez après `Retry-After` (10 secondes). |
| 502 | `upstream_error` | lancement, téléchargement | Le modèle a échoué, ou la vidéo n’a pas pu être lue : réessayez dans un instant. |
| 503 | `job_not_recorded` | lancement | La vidéo a été lancée mais n’a pas pu être enregistrée : contactez le support. |
| 504 | `upstream_timeout` | lancement | Le modèle n’a pas répondu à temps au lancement. Rien n’est facturé. |

Les erreurs de clé, de solde et de plafonds sont dans [Erreurs](https://realmoon.ai/documentation/api/erreurs/).

## Voir aussi

- [Modèles](https://realmoon.ai/documentation/api/modeles/#medias) : les champs `durations`, `resolutions`, `audio`, `first_frame` et `last_frame`.
- [Limites](https://realmoon.ai/documentation/api/limites/#nouvelles-tentatives) : réessayer sans lancer deux vidéos.

---

Documentation Moon AI › API développeur › Vidéos. Page : https://realmoon.ai/documentation/api/videos/. Modifiée le 5 novembre 2026.

© 2026 Stellarr Studio SAS. Tous droits réservés. Moon AI, Moon Blur et Stellarr Studio sont des marques déposées à l’INPI.
