---
title: "Crear una imagen o un vídeo con IA"
description: "Generar una imagen o un vídeo corto en los archivos multimedia del sitio, con un coste fijo en créditos."
canonical: "https://atelier201.com/docs/es/api/media/generate"
updated: "2026-11-06"
---

# Crear una imagen o un vídeo con IA

Requiere `media:generate`, un permiso independiente. Una credencial que permita editar sitios no puede gastar créditos salvo que también tenga este permiso. Se descuentan créditos del espacio de trabajo.

1. Haz la llamada con `estimate_only: true`. No cuesta nada y devuelve `estimated_credits` (el precio exacto) y `balance`.
2. Vuelve a hacer la llamada con `max_credits` establecido en ese precio. Sin `max_credits`, se rechaza la llamada. Si el precio supera ese límite, la llamada se rechaza sin cobrar nada: `invalid_parameter` en `max_credits`, con `details.reason` `price_above_max_credits`, `details.estimated_credits` y `details.max_credits`.

Los créditos se cobran cuando empieza la generación. Si falla, se devuelven. Normalmente, una imagen está lista en `wait_seconds` (50 de forma predeterminada) y la respuesta incluye `status: succeeded` y su `media`. Un vídeo tarda entre uno y cinco minutos: la respuesta es `status: running` con un `id`. Consulta [la generación](/docs/api/media/generation) hasta que termine.

El archivo se añade a los archivos multimedia del sitio como si se hubiera subido, con `credit` establecido en el modelo que lo ha creado. No presentes nunca una imagen generada como si fuera una fotografía del negocio, sus productos, su personal o sus instalaciones.

Se permiten como máximo 10 generaciones por minuto y espacio de trabajo. Si se supera el límite, se devuelve `429 rate_limited` con `details.retry_after_seconds`. Si no hay créditos suficientes, se devuelve `402 insufficient_credits` con `details.needed` y `details.balance`. Si el modelo está ocupado, la generación falla y se devuelven los créditos. Vuelve a intentarlo dentro de un minuto.

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

## Authorizations

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

## Path parameters

- `site_id` (`string`, required): El ID del sitio o su slug (la dirección antes de .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 muestra cada modelo, para qué es más adecuado y sus precios en créditos.
- `prompt` (`string`, required, length: `1–4000 chars`): Qué mostrar: tema, entorno, iluminación, encuadre y estilo.
- `aspect_ratio` (`enum<string>`, one of: `16:9, 1:1, 9:16, 4:3, 3:4, 3:2, 2:3`): Relación entre anchura y altura. Cada modelo admite las proporciones que devuelve list_media_models. Si no se indica ninguna, se usa la primera (16:9 en la mayoría de los casos).
- `quality` (`enum<string>`, one of: `draft, standard, high`): Imágenes: borrador, estándar (predeterminado) o alta.
- `duration` (`integer`, range: `1–10`): Vídeos: duración en segundos.
- `resolution` (`enum<string>`, one of: `480p, 720p, 768p, 1080p, 2k`): Vídeos: por defecto, la resolución del modelo (720p o 768p para minimax y p-video).
- `audio` (`boolean`): Vídeos: con sonido (solo seedance).
- `filename` (`string`, length: `1–100 chars`): Un nombre sin extensión.
- `alt` (`string`, length: `≤ 300 chars`)
- `estimate_only` (`boolean`): true: el precio exacto en créditos y el saldo. Es gratis y no se ejecuta nada.
- `max_credits` (`integer`, range: `≤ 9007199254740991`): Obligatorio para ejecutar: el máximo que aceptas gastar. Se rechaza la solicitud y no se cobra nada si el precio es superior. Obtén este valor con una llamada estimate_only.
- `wait_seconds` (`integer`, range: `0–55`): Cuánto tiempo esperar el resultado. El valor predeterminado es 50 para una imagen y 0 para un vídeo.

## Response

**202**: Crea una imagen o un vídeo con IA

- `data` (`Record<string, object>`, required)
- `data.id` (`string`): El id de la generación. Haz GET hasta que el estado sea succeeded o 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): Quién lo creó, cuando la licencia lo requiere: "Photo by Jane Doe on Pixabay", "Generated with Seedream 5 Lite (ByteDance)". Null si se ha subido el archivo.
- `data.media.keep_original` (`boolean`, required): Se almacena exactamente como se ha subido y nunca se vuelve a codificar durante una compilación. De lo contrario, las imágenes de más de 200 KB se comprimen al subirlas (máximo 2000 px, objetivo de 150 KB, calidad de 75 o superior y metadatos eliminados).
- `data.error` (`string,null`)
- `data.credits` (`integer | null`): Lo que ha costado.
- `data.credits_refunded` (`integer | null`): Se devuelve si se produce un error.
- `data.estimated_credits` (`integer`, range: `-9007199254740991–9007199254740991`): estimate_only: el precio exacto que tendría.
- `data.balance` (`number`): estimate_only: los créditos disponibles ahora en el espacio de trabajo.
- `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**: Códigos posibles: 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**: Códigos posibles: 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**: Códigos posibles: 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**: Códigos posibles: 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**: Códigos posibles: 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**: Códigos posibles: 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**: Códigos posibles: 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**: Códigos posibles: 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**: Códigos posibles: 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**: Códigos posibles: 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**: Códigos posibles: 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**: Códigos posibles: 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>"
}'
```
