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

# Modelos oficiales de vídeo Grok

> Genera vídeo desde texto o imágenes de referencia con grok-imagine-video y grok-imagine-video-1.5, o edita un vídeo con el modelo base.

> [!NOTE]
>
> Esta página corresponde a los modelos oficiales `grok-imagine-video` y `grok-imagine-video-1.5`. Son distintos de `grok-imagine-1.5-video-ext`; no mezcles nombres ni parámetros.

> [!WARNING]
>
> Nunca expongas la API Key en el navegador, variables públicas, LocalStorage, URL o registros. Llama a GccAi desde tu backend o BFF.

```bash cURL theme={null}
curl --request POST \
  --url https://gccai.heqingsong.uk/v1/videos/generations \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --header 'Accept: application/json' \
  --header 'Idempotency-Key: 7d0141e4-a19a-4650-a717-dab777b3a330' \
  --data '{
    "model": "grok-imagine-video",
    "prompt": "A cinematic aerial shot of a coastal city at sunrise",
    "duration": 5,
    "resolution": "720p",
    "aspect_ratio": "16:9",
    "nsfw_check": true
  }'
```

```javascript JavaScript theme={null}
const response = await fetch("https://gccai.heqingsong.uk/v1/videos/generations", {
  method: "POST",
  headers: {
    Authorization: "Bearer <token>",
    "Content-Type": "application/json",
    Accept: "application/json",
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify({
    model: "grok-imagine-video",
    prompt: "Improve motion consistency and apply cinematic color grading",
    video: { url: "https://cdn.example.com/source-video.mp4" },
  }),
});

console.log(response.status, await response.json());
```

```json 200 theme={null}
{
  "code": 200,
  "data": [{
    "status": "submitted",
    "task_id": "task_01M09Y4Y101HTFFPV2QPW9DQ3W"
  }]
}
```

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

## Resumen de integración

Todos los modos usan el mismo endpoint asíncrono:

```http theme={null}
POST https://gccai.heqingsong.uk/v1/videos/generations
```

| Campos enviados | Modo | Modelos |
| - | - | - |
| Sin `image_urls` ni `video` | Texto a vídeo | Ambos modelos |
| `image_urls` | Imágenes de referencia a vídeo | Ambos modelos |
| `video` | Edición de vídeo | Solo `grok-imagine-video` |

Tras enviar, guarda `data[0].task_id` y consulta:

```http theme={null}
GET https://gccai.heqingsong.uk/v1/tasks/{task_id}
```

> [!WARNING]
>
> No envíes `X-GccAi-Response-Version`: cambia a una respuesta HTTP `202`. Esta página usa la respuesta asíncrona HTTP `200` anterior.

## Capacidades

| Capacidad | `grok-imagine-video` | `grok-imagine-video-1.5` |
| - | :-: | :-: |
| Texto a vídeo | ✅ | ✅ |
| Una o varias imágenes de referencia | ✅ | ✅ |
| Edición de vídeo | ✅ | ❌ |
| `480p` | ✅ | ✅ |
| `720p` | ✅ | ✅ |
| `1080p` | ❌ | ✅ |
| Duración: 1–15 segundos | 1–15 | 1–15 |
| Prompt | 1–8000 | 1–8000 |

```text theme={null}
duration     = 8
resolution   = 480p
aspect_ratio = auto
```

El contrato público no fija un máximo de imágenes. Conserva un array no vacío de URL válidas y su orden; no reutilices límites de modelos de imagen.

## Encabezados

**Authorization** `string` *required*

`Bearer <GCCAI_API_KEY>`

**Content-Type** `string` *required*

Usa siempre `application/json`.

**Accept** `string`

`application/json`

**Idempotency-Key** `string`

`Idempotency-Key` es opcional y muy recomendable para solicitudes de pago. Admite 1–191 caracteres ASCII visibles; se recomienda UUID. Un reintento de red reutiliza la clave y el cuerpo originales. No cambies la clave si el resultado es incierto.

Usa una clave nueva por operación lógica. Un reintento debe reutilizar la clave y el cuerpo originales.

## Parámetros

### Campos comunes

**model** `string` *required*

Nombre oficial; la edición solo admite el modelo base

* `grok-imagine-video`
* `grok-imagine-video-1.5`

**prompt** `string` *required*

Instrucción no vacía, máximo 8000 caracteres Unicode

`Array.from(prompt).length`

**nsfw\_check** `boolean` (default: false)

Indica si se modera el contenido antes de enviar la tarea de vídeo.

* `true`: Usa `omni-moderation-latest` para revisar el prompt y las imágenes de entrada
* `false` o se omite: No solicita moderación ni añade coste o latencia de revisión (predeterminado)

### Campos de generación

**duration** `integer` (default: 8)

Solo generación; entero 1–15, predeterminado 8

**resolution** `string` (default: 480p)

Base: `480p/720p`; 1.5: `480p/720p/1080p`; predeterminado `480p`

* `grok-imagine-video`: `480p`, `720p`
* `grok-imagine-video-1.5`: `480p`, `720p`, `1080p`

**aspect\_ratio** `string` (default: auto)

Solo generación; `auto`, `1:1`, `16:9`, `9:16`, `4:3`, `3:4`, `3:2` o `2:3`

* `auto`
* `1:1`, `16:9`, `9:16`
* `4:3`, `3:4`, `3:2`, `2:3`

**image\_urls** `string[]`

Array opcional; cada elemento debe ser una URL HTTPS pública; omitir si está vacío

* Cada elemento debe ser una URL HTTPS pública; no se admiten URL relativas, Data URL ni Base64 sin formato.
* No envíes alias como `image`, `images` o `input_reference`.
* Se conserva el orden; las URL repetidas ocupan varias entradas y pueden cobrarse varias veces.

### Campos de edición de vídeo

**video** `object`

Vídeo fuente `{url}` mediante HTTPS público; solo modelo base

**URL**

**url** `string` *required*

HTTPS

La edición requiere `model`, `prompt` y `video`, y admite `nsfw_check` opcional. No envíes `duration`, `resolution`, `aspect_ratio` ni `image_urls`; la plataforma detecta la duración.

## Tipos de solicitud TypeScript

Usa una unión discriminada para impedir que los campos de generación lleguen a la edición.

```ts theme={null}
type GrokVideoModel =
  | "grok-imagine-video"
  | "grok-imagine-video-1.5";

type GrokVideoResolution = "480p" | "720p" | "1080p";

type GrokVideoAspectRatio =
  | "auto"
  | "1:1"
  | "16:9"
  | "9:16"
  | "4:3"
  | "3:4"
  | "3:2"
  | "2:3";

interface GrokVideoGenerateRequest {
  model: GrokVideoModel;
  prompt: string;
  nsfw_check?: boolean;
  duration?: number;
  resolution?: GrokVideoResolution;
  aspect_ratio?: GrokVideoAspectRatio;
  image_urls?: string[];
}

interface GrokVideoEditRequest {
  model: "grok-imagine-video";
  prompt: string;
  nsfw_check?: boolean;
  video: { url: string };
}

type GrokVideoRequest =
  | GrokVideoGenerateRequest
  | GrokVideoEditRequest;
```

## Ejemplos

**Texto a vídeo**

```json theme={null}
{"model":"grok-imagine-video","prompt":"A cinematic aerial shot at sunrise","duration":5,"resolution":"720p","aspect_ratio":"16:9"}
```

**1.5 · 1080p**

```json theme={null}
{"model":"grok-imagine-video-1.5","prompt":"A smooth studio product commercial","duration":5,"resolution":"1080p","aspect_ratio":"16:9"}
```

**Una o varias imágenes de referencia**

```json theme={null}
{
  "model":"grok-imagine-video-1.5",
  "prompt":"Use the first image as subject and the second as style",
  "duration":5,
  "resolution":"720p",
  "aspect_ratio":"16:9",
  "image_urls":[
    "https://cdn.example.com/subject.jpg",
    "https://cdn.example.com/style.jpg"
  ]
}
```

**Edición de vídeo**

```json theme={null}
{
  "model":"grok-imagine-video",
  "prompt":"Improve motion consistency and apply cinematic color grading",
  "video":{"url":"https://cdn.example.com/source.mp4"}
}
```

## Tareas asíncronas

### Creación correcta

La creación correcta devuelve HTTP `200`. Guarda `data[0].task_id`; el envío no significa que el vídeo esté listo. Un ID de tarea significa enviado, no completado.

```json theme={null}
{
  "code":200,
  "data":[{"status":"submitted","task_id":"task_01M09Y4Y101HTFFPV2QPW9DQ3W"}]
}
```

### Consultar tarea

```http theme={null}
GET https://gccai.heqingsong.uk/v1/tasks/{task_id}
Authorization: Bearer <GCCAI_API_KEY>
Accept: application/json
```

Consulta `GET /v1/tasks/{task_id}` cada 3–5 segundos. Tras recargar, reanuda con el ID guardado.

| `data.status` | Significado | Acción |
| - | - | - |
| `pending` | En cola | Seguir consultando |
| `processing` | Generando | Mostrar progreso y continuar |
| `completed` | Completada | Leer resultado y detener |
| `failed` | Fallida y reembolsada | Mostrar error y detener |
| `unknown` | Temporalmente desconocida | Reducir frecuencia y reintentar después |

### Respuesta completada

```json theme={null}
{
  "code":200,
  "data":{
    "id":"task_xxx",
    "status":"completed",
    "progress":100,
    "created":1787040038,
    "completed":1787040081,
    "actual_time":43,
    "estimated_time":100,
    "cost":0.072,
    "credits_cost":0.72,
    "result":{"videos":[{"url":["https://cdn.example.com/result.mp4"],"expires_at":1787126481}]}
  }
}
```

`result.videos[0].url` es un array de cadenas, no una cadena. Valida cada valor como URL HTTPS. Se recomienda validar en tiempo de ejecución:

```ts theme={null}
function extractVideoURLs(payload: unknown): string[] {
  const groups = (payload as any)?.data?.result?.videos;
  if (!Array.isArray(groups)) return [];

  return groups.flatMap((group: any) =>
    Array.isArray(group?.url)
      ? group.url.filter(
          (url: unknown): url is string =>
            typeof url === "string" && /^https:///i.test(url),
        )
      : [],
  );
}
```

Usa `expires_at` para la caducidad. No fijes un plazo; pide descargar o guardar el resultado.

### Respuesta fallida

```json theme={null}
{
  "code":200,
  "data":{
    "id":"task_xxx",
    "status":"failed",
    "progress":100,
    "cost":0,
    "credits_cost":0,
    "error":{"message":"Task failed.","type":"task_failed","param":"","code":"task_failed"}
  }
}
```

> [!WARNING]
>
> La consulta puede devolver HTTP `200` con `data.status=failed`. Decide por `data.status`; una tarea fallida tiene `cost=0`.

## Catálogo de precios

```http theme={null}
GET https://gccai.heqingsong.uk/api/pricing/models/all
```

Lee `GET /api/pricing/models/all` y busca el `id` en `data.models.video`. Los precios son estimaciones; el importe final es `data.cost` de la tarea.

### Precio del vídeo de salida

```json theme={null}
{
  "fixed_prices":{
    "unit":"usd_per_second",
    "dimension":"resolution",
    "items":[
      {"key":"480P","original_price":0.05,"after_discount":0.04},
      {"key":"720P","original_price":0.07,"after_discount":0.056}
    ]
  }
}
```

* Las claves de precio son `480P/720P/1080P` y los valores de solicitud usan minúsculas; normaliza al buscar.
* `default` es un dato de compatibilidad, no una resolución seleccionable.
* Usa `after_discount` directamente; no apliques otro descuento.

### Precio del material de entrada

```json theme={null}
{"unit":"usd_per_image","original_price":0.002,"after_discount":0.0016}
```

```json theme={null}
{"unit":"usd_per_second","original_price":0.01,"after_discount":0.008}
```

El precio de vídeo es un objeto escalar. No exijas `items`, `billing_mode` ni `max_billable_seconds`. 1.5 no tiene precio de vídeo de entrada.

### Fórmulas de estimación

```text theme={null}
Generación = precio de salida/segundo × duración + precio por imagen × cantidad
Edición = precio 720P/segundo × segundos fuente + precio de entrada de vídeo × segundos fuente
```

El precio específico y el redondeo pueden variar. El importe final siempre es `data.cost`.

## Reglas del frontend

### Cambio de modelo

* Base muestra `480p/720p`; 1.5 añade `1080p`.
* Al pasar de 1.5 `1080p` a Base, volver a `480p`.
* La edición fija `grok-imagine-video`.

### Cambio de modo

| Modo | Controles visibles | Campos enviados | Debe limpiarse |
| - | - | - | - |
| Generación | `prompt/duration/resolution/aspect_ratio/nsfw_check` | Campos de generación | `image_urls/video` |
| Imágenes de referencia | Campos de generación + `image_urls` | Campos de generación + `image_urls` | `video` |
| Edición de vídeo | `prompt/video/nsfw_check` | `model/prompt/video/nsfw_check` | `duration/resolution/aspect_ratio/image_urls` |

`nsfw_check` es opcional en todos los modos. Envía `true` al activar la moderación; omítelo o envía `false` al desactivarla.

Desactiva el botón si se cumple alguna condición:

* Texto omite `image_urls` y `video`.
* Referencia envía `image_urls` y omite `video`.
* La edición limpia campos de generación.
* Desactivar con prompt o duración inválidos, resolución o URL no admitida, carga activa o envío duplicado.
* Prompt ≤8000 Unicode y duración entera 1–15.
* Solo URL HTTPS públicas; omitir `image_urls` vacío.

## Errores comunes

| HTTP / Estado | Causa | Tratamiento |
| - | - | - |
| `400` | Parámetros, prompt o enum inválido | Mostrar mensaje y campo |
| `401` | API Key ausente o inválida | No reintentar; revisar servidor |
| `402` | Saldo insuficiente | Solicitar recarga |
| `403` | Sin permiso del modelo | No reintentar automáticamente |
| `409` | Conflicto idempotente o solicitud en curso | Conservar clave y reintentar después |
| `429` | Límite de solicitudes | Respetar `Retry-After` |
| `500/502/503` | Fallo temporal | Reintentos limitados con la clave original |
| `failed` | Tarea asíncrona fallida | Detener consulta; coste cero |

## Comprobación del frontend

* Guardar la API Key solo en backend o BFF.
* No mezclar modelos oficiales con `grok-imagine-1.5-video-ext`.
* Prompt ≤8000 Unicode y duración entera 1–15.
* Solo URL HTTPS públicas; omitir `image_urls` vacío.
* En edición, envía solo `model/prompt/video` más `nsfw_check` opcional y usa el modelo base.
* Leer `data[0].task_id` y el final desde `data.status`.
* Leer `result.videos[].url[]` y respetar `expires_at`.
* Mostrar catálogo y usar `data.cost` final.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.