---
title: "Générer une image ou une vidéo avec l’IA"
description: "Générer une image ou une courte vidéo dans les fichiers multimédias du site, contre des crédits à prix fixe."
canonical: "https://atelier201.com/docs/fr/api/media/generate"
updated: "2026-11-06"
---

# Générer une image ou une vidéo avec l’IA

Nécessite `media:generate`, une autorisation distincte : un identifiant qui permet de modifier des sites ne peut pas dépenser de crédits à moins que cette autorisation lui ait aussi été accordée. Les crédits de l’espace de travail sont utilisés.

1. Appelez l’endpoint avec `estimate_only: true`. Cela ne coûte rien et renvoie `estimated_credits` (le prix exact) et `balance`.
2. Rappelez l’endpoint en définissant `max_credits` sur ce prix. Sans `max_credits`, l’appel est refusé. Si le prix dépasse cette limite, l’appel est refusé sans frais : `invalid_parameter` sur `max_credits`, avec `details.reason` défini sur `price_above_max_credits`, ainsi que `details.estimated_credits` et `details.max_credits`.

Les crédits sont débités au démarrage de la génération. En cas d’échec, ils sont restitués. Une image est généralement prête dans le délai indiqué par `wait_seconds` (50 par défaut) ; la réponse contient alors `status: succeeded` et son `media`. Une vidéo prend entre une et cinq minutes : la réponse indique `status: running` avec un `id` ; [récupérez la génération](/docs/api/media/generation) jusqu’à ce qu’elle soit terminée.

Le fichier est ajouté aux fichiers multimédias du site comme après un téléversement, avec `credit` défini sur le modèle qui l’a créé. Ne présentez jamais une image générée comme une photographie de l’entreprise, de ses produits, de ses employés ou de ses locaux.

La limite est de 10 générations par minute et par espace de travail (au-delà, `429 rate_limited` avec `details.retry_after_seconds`). Crédits insuffisants : `402 insufficient_credits` avec `details.needed` et `details.balance`. Si un modèle est occupé, la génération échoue et les crédits sont restitués : réessayez dans une minute.

```http
POST https://api.atelier201.com/v1/sites/{site_id}/media/generations
```

## Authorizations

- `Authorization` (bearer, in header, required)

## Path parameters

- `site_id` (`string`, required): L’identifiant du site ou son slug (l’adresse avant .atelier201.page).

## Body

`application/json`, required

- `model` (`enum<string>`, required, one of: `gpt-image, nano-banana, flux, p-image, wan, minimax, seedance, p-video`): GET /v1/media/models renvoie la liste des modèles, leurs points forts et leurs prix en crédits.
- `prompt` (`string`, required, length: `1–4000 chars`): À décrire : sujet, décor, lumière, cadrage, style.
- `aspect_ratio` (`enum<string>`, one of: `16:9, 1:1, 9:16, 4:3, 3:4, 3:2, 2:3`): Rapport largeur/hauteur. Chaque modèle accepte les ratios indiqués par list_media_models. Par défaut, le premier ratio est utilisé (16:9 pour la plupart des modèles).
- `quality` (`enum<string>`, one of: `draft, standard, high`): Images : draft, standard (par défaut) ou high.
- `duration` (`integer`, range: `1–10`): Vidéos : durée en secondes.
- `resolution` (`enum<string>`, one of: `480p, 720p, 768p, 1080p, 2k`): Vidéos : par défaut, la résolution du modèle (720p, ou 768p pour minimax et p-video).
- `audio` (`boolean`): Vidéos : avec son (seedance uniquement).
- `filename` (`string`, length: `1–100 chars`): Nom sans extension.
- `alt` (`string`, length: `≤ 300 chars`)
- `estimate_only` (`boolean`): true : prix exact en crédits et solde. Gratuit, aucune génération n’est lancée.
- `max_credits` (`integer`, range: `≤ 9007199254740991`): Obligatoire pour lancer la génération : montant maximal que vous acceptez de dépenser. Si le prix le dépasse, la demande est refusée et rien n’est débité. Reprenez le montant d’un appel avec estimate_only.
- `wait_seconds` (`integer`, range: `0–55`): Durée d’attente du résultat. Par défaut : 50 pour une image, 0 pour une vidéo.

## Response

**202**: Génère une image ou une vidéo avec l’IA

- `data` (`Record<string, object>`, required)
- `data.id` (`string`): Identifiant de la génération : récupère-la avec GET jusqu’à ce que son statut soit succeeded ou failed.
- `data.status` (`enum<string>`, one of: `running, succeeded, failed`)
- `data.media` (`object | null`)
- `data.media.path` (`string`, required)
- `data.media.url_path` (`string`, required)
- `data.media.mime` (`string`, required)
- `data.media.size` (`integer`, required, range: `-9007199254740991–9007199254740991`)
- `data.media.alt` (`string,null`, required)
- `data.media.credit` (`string,null`, required): Auteur, lorsque la licence l’exige : « Photo by Jane Doe on Pixabay », « Generated with Seedream 5 Lite (ByteDance) ». Null pour un fichier importé.
- `data.media.keep_original` (`boolean`, required): Stocké exactement comme lors de l’importation, sans jamais être réencodé lors d’une génération. Sinon, toute image de plus de 200 KB est compressée à l’importation (2000 px maximum, cible de 150 KB, qualité de 75 ou plus, métadonnées supprimées).
- `data.error` (`string,null`)
- `data.credits` (`integer | null`): Coût de la génération.
- `data.credits_refunded` (`integer | null`): Crédits recrédités en cas d’échec.
- `data.estimated_credits` (`integer`, range: `-9007199254740991–9007199254740991`): estimate_only : le prix exact de la génération.
- `data.balance` (`number`): estimate_only : solde actuel de l’espace de travail en crédits.
- `data.next_action` (`string,null`, required)
- `request_id` (`string`, required)

```json
{
  "data": {
    "id": "<string>",
    "status": "running",
    "media": {
      "path": "<string>",
      "url_path": "<string>",
      "mime": "<string>",
      "size": 123,
      "alt": null,
      "credit": null,
      "keep_original": true
    },
    "error": null,
    "credits": 123,
    "credits_refunded": 123,
    "estimated_credits": 123,
    "balance": 123.45,
    "next_action": null
  },
  "request_id": "<string>"
}
```

**400**: Codes possibles : invalid_request, unknown_field, invalid_parameter, invalid_cursor

- `error` (`object`, required)
- `error.type` (`string`, required)
- `error.code` (`string`, required)
- `error.message` (`string`, required)
- `error.param` (`string`)
- `error.docs_url` (`string`, required)
- `error.action_url` (`string<uri>`)
- `error.details` (`Record<string, object>`)
- `request_id` (`string`, required)

```json
{
  "error": {
    "type": "<string>",
    "code": "<string>",
    "message": "<string>",
    "param": "<string>",
    "docs_url": "<string>",
    "action_url": "<string>",
    "details": {}
  },
  "request_id": "<string>"
}
```

**401**: Codes possibles : authentication_required, invalid_api_key, api_key_expired, api_key_revoked

- `error` (`object`, required)
- `error.type` (`string`, required)
- `error.code` (`string`, required)
- `error.message` (`string`, required)
- `error.param` (`string`)
- `error.docs_url` (`string`, required)
- `error.action_url` (`string<uri>`)
- `error.details` (`Record<string, object>`)
- `request_id` (`string`, required)

```json
{
  "error": {
    "type": "<string>",
    "code": "<string>",
    "message": "<string>",
    "param": "<string>",
    "docs_url": "<string>",
    "action_url": "<string>",
    "details": {}
  },
  "request_id": "<string>"
}
```

**402**: Codes possibles : insufficient_credits

- `error` (`object`, required)
- `error.type` (`string`, required)
- `error.code` (`string`, required)
- `error.message` (`string`, required)
- `error.param` (`string`)
- `error.docs_url` (`string`, required)
- `error.action_url` (`string<uri>`)
- `error.details` (`Record<string, object>`)
- `request_id` (`string`, required)

```json
{
  "error": {
    "type": "<string>",
    "code": "<string>",
    "message": "<string>",
    "param": "<string>",
    "docs_url": "<string>",
    "action_url": "<string>",
    "details": {}
  },
  "request_id": "<string>"
}
```

**403**: Codes possibles : insufficient_scope, feature_not_available, admin_required

- `error` (`object`, required)
- `error.type` (`string`, required)
- `error.code` (`string`, required)
- `error.message` (`string`, required)
- `error.param` (`string`)
- `error.docs_url` (`string`, required)
- `error.action_url` (`string<uri>`)
- `error.details` (`Record<string, object>`)
- `request_id` (`string`, required)

```json
{
  "error": {
    "type": "<string>",
    "code": "<string>",
    "message": "<string>",
    "param": "<string>",
    "docs_url": "<string>",
    "action_url": "<string>",
    "details": {}
  },
  "request_id": "<string>"
}
```

**404**: Codes possibles : resource_not_found

- `error` (`object`, required)
- `error.type` (`string`, required)
- `error.code` (`string`, required)
- `error.message` (`string`, required)
- `error.param` (`string`)
- `error.docs_url` (`string`, required)
- `error.action_url` (`string<uri>`)
- `error.details` (`Record<string, object>`)
- `request_id` (`string`, required)

```json
{
  "error": {
    "type": "<string>",
    "code": "<string>",
    "message": "<string>",
    "param": "<string>",
    "docs_url": "<string>",
    "action_url": "<string>",
    "details": {}
  },
  "request_id": "<string>"
}
```

**409**: Codes possibles : conflict, result_not_ready, idempotency_key_reused

- `error` (`object`, required)
- `error.type` (`string`, required)
- `error.code` (`string`, required)
- `error.message` (`string`, required)
- `error.param` (`string`)
- `error.docs_url` (`string`, required)
- `error.action_url` (`string<uri>`)
- `error.details` (`Record<string, object>`)
- `request_id` (`string`, required)

```json
{
  "error": {
    "type": "<string>",
    "code": "<string>",
    "message": "<string>",
    "param": "<string>",
    "docs_url": "<string>",
    "action_url": "<string>",
    "details": {}
  },
  "request_id": "<string>"
}
```

**410**: Codes possibles : result_expired

- `error` (`object`, required)
- `error.type` (`string`, required)
- `error.code` (`string`, required)
- `error.message` (`string`, required)
- `error.param` (`string`)
- `error.docs_url` (`string`, required)
- `error.action_url` (`string<uri>`)
- `error.details` (`Record<string, object>`)
- `request_id` (`string`, required)

```json
{
  "error": {
    "type": "<string>",
    "code": "<string>",
    "message": "<string>",
    "param": "<string>",
    "docs_url": "<string>",
    "action_url": "<string>",
    "details": {}
  },
  "request_id": "<string>"
}
```

**413**: Codes possibles : request_too_large

- `error` (`object`, required)
- `error.type` (`string`, required)
- `error.code` (`string`, required)
- `error.message` (`string`, required)
- `error.param` (`string`)
- `error.docs_url` (`string`, required)
- `error.action_url` (`string<uri>`)
- `error.details` (`Record<string, object>`)
- `request_id` (`string`, required)

```json
{
  "error": {
    "type": "<string>",
    "code": "<string>",
    "message": "<string>",
    "param": "<string>",
    "docs_url": "<string>",
    "action_url": "<string>",
    "details": {}
  },
  "request_id": "<string>"
}
```

**422**: Codes possibles : request_too_large_for_plan

- `error` (`object`, required)
- `error.type` (`string`, required)
- `error.code` (`string`, required)
- `error.message` (`string`, required)
- `error.param` (`string`)
- `error.docs_url` (`string`, required)
- `error.action_url` (`string<uri>`)
- `error.details` (`Record<string, object>`)
- `request_id` (`string`, required)

```json
{
  "error": {
    "type": "<string>",
    "code": "<string>",
    "message": "<string>",
    "param": "<string>",
    "docs_url": "<string>",
    "action_url": "<string>",
    "details": {}
  },
  "request_id": "<string>"
}
```

**429**: Codes possibles : rate_limited

- `error` (`object`, required)
- `error.type` (`string`, required)
- `error.code` (`string`, required)
- `error.message` (`string`, required)
- `error.param` (`string`)
- `error.docs_url` (`string`, required)
- `error.action_url` (`string<uri>`)
- `error.details` (`Record<string, object>`)
- `request_id` (`string`, required)

```json
{
  "error": {
    "type": "<string>",
    "code": "<string>",
    "message": "<string>",
    "param": "<string>",
    "docs_url": "<string>",
    "action_url": "<string>",
    "details": {}
  },
  "request_id": "<string>"
}
```

**500**: Codes possibles : internal_error

- `error` (`object`, required)
- `error.type` (`string`, required)
- `error.code` (`string`, required)
- `error.message` (`string`, required)
- `error.param` (`string`)
- `error.docs_url` (`string`, required)
- `error.action_url` (`string<uri>`)
- `error.details` (`Record<string, object>`)
- `request_id` (`string`, required)

```json
{
  "error": {
    "type": "<string>",
    "code": "<string>",
    "message": "<string>",
    "param": "<string>",
    "docs_url": "<string>",
    "action_url": "<string>",
    "details": {}
  },
  "request_id": "<string>"
}
```

**503**: Codes possibles : service_unavailable

- `error` (`object`, required)
- `error.type` (`string`, required)
- `error.code` (`string`, required)
- `error.message` (`string`, required)
- `error.param` (`string`)
- `error.docs_url` (`string`, required)
- `error.action_url` (`string<uri>`)
- `error.details` (`Record<string, object>`)
- `request_id` (`string`, required)

```json
{
  "error": {
    "type": "<string>",
    "code": "<string>",
    "message": "<string>",
    "param": "<string>",
    "docs_url": "<string>",
    "action_url": "<string>",
    "details": {}
  },
  "request_id": "<string>"
}
```

**Example request**

```bash
curl --request POST \
  --url 'https://api.atelier201.com/v1/sites/<site_id>/media/generations' \
  --header 'Authorization: <api-key>' \
  --header 'Content-Type: application/json' \
  --data '{
  "model": "gpt-image",
  "prompt": "<string>"
}'
```
