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

# Официальные видеомодели Grok

> Создавайте видео из текста или изображений с grok-imagine-video и grok-imagine-video-1.5 либо редактируйте исходное видео базовой моделью.

<Info>
  Страница относится к официальным моделям `grok-imagine-video` и `grok-imagine-video-1.5`. Они отличаются от `grok-imagine-1.5-video-ext`; не смешивайте имена и параметры.
</Info>

<Warning>
  Не размещайте API Key в браузере, публичных переменных, LocalStorage, URL или логах. Вызывайте APIMart через backend или BFF.
</Warning>

<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' \
    --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://api.apimart.ai/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());
  ```
</RequestExample>

<ResponseExample>
  ```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"
    }
  }
  ```
</ResponseExample>

## Обзор интеграции

Все режимы используют один асинхронный endpoint:

```http theme={null}
POST https://api.apimart.ai/v1/videos/generations
```

| Поля запроса               | Режим                | Модели                      |
| -------------------------- | -------------------- | --------------------------- |
| Без `image_urls` и `video` | Текст в видео        | Обе модели                  |
| `image_urls`               | Изображения в видео  | Обе модели                  |
| `video`                    | Редактирование видео | Только `grok-imagine-video` |

После отправки сохраните `data[0].task_id`, затем опрашивайте:

```http theme={null}
GET https://api.apimart.ai/v1/tasks/{task_id}
```

<Warning>
  Не отправляйте `X-APIMart-Response-Version`: он включает ответ HTTP `202`. Здесь используется прежний асинхронный формат HTTP `200`.
</Warning>

## Возможности

| Возможность                    | `grok-imagine-video` | `grok-imagine-video-1.5` |
| ------------------------------ | :------------------: | :----------------------: |
| Текст в видео                  |           ✅          |             ✅            |
| Одно или несколько изображений |           ✅          |             ✅            |
| Редактирование видео           |           ✅          |             ❌            |
| `480p`                         |           ✅          |             ✅            |
| `720p`                         |           ✅          |             ✅            |
| `1080p`                        |           ❌          |             ✅            |
| Длительность: 1–15 секунд      |         1–15         |           1–15           |
| Промпт                         |        1–8000        |          1–8000          |

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

Публичный контракт не задаёт лимит числа изображений. Сохраняйте непустой массив допустимых URL и их порядок; не используйте лимиты моделей изображений.

## Заголовки

<ParamField header="Authorization" type="string" required>
  `Bearer <APIMART_API_KEY>`
</ParamField>

<ParamField header="Content-Type" type="string" required>
  Всегда используйте `application/json`.
</ParamField>

<ParamField header="Accept" type="string">
  `application/json`
</ParamField>

<ParamField header="Idempotency-Key" type="string">
  `Idempotency-Key` необязателен, но настоятельно рекомендуется для платных запросов. Допустимы 1–191 видимый символ ASCII; рекомендуется UUID. Сетевой повтор использует исходный ключ и body. Не меняйте ключ при неопределённом результате.

  Для новой логической операции используйте новый ключ. Повтор должен использовать исходный ключ и тот же body.
</ParamField>

## Параметры

### Общие поля

<ParamField body="model" type="string" required>
  Официальная модель; редактирование только базовой

  * `grok-imagine-video`
  * `grok-imagine-video-1.5`
</ParamField>

<ParamField body="prompt" type="string" required>
  Непустая инструкция, максимум 8000 Unicode

  `Array.from(prompt).length`
</ParamField>

<ParamField body="nsfw_check" type="boolean" default={false}>
  Определяет, выполнять ли модерацию контента перед отправкой видеозадачи.

  * `true`: Проверять промпт и входные изображения с помощью `omni-moderation-latest`
  * `false` или поле отсутствует: Не запускать модерацию и не добавлять её стоимость или задержку (по умолчанию)
</ParamField>

### Поля генерации

<ParamField body="duration" type="integer" default={8}>
  Только генерация; целое 1–15, по умолчанию 8
</ParamField>

<ParamField body="resolution" type="string" default="480p">
  Base: `480p/720p`; 1.5: `480p/720p/1080p`; по умолчанию `480p`

  * `grok-imagine-video`: `480p`, `720p`
  * `grok-imagine-video-1.5`: `480p`, `720p`, `1080p`
</ParamField>

<ParamField body="aspect_ratio" type="string" default="auto">
  Только генерация; `auto`, `1:1`, `16:9`, `9:16`, `4:3`, `3:4`, `3:2` или `2:3`

  * `auto`
  * `1:1`, `16:9`, `9:16`
  * `4:3`, `3:4`, `3:2`, `2:3`
</ParamField>

<ParamField body="image_urls" type="string[]">
  Необязательный массив; каждый элемент — публичный HTTPS URL; пустой массив не отправлять

  * Каждый элемент должен быть публичным HTTPS URL; относительные URL, Data URL и сырой Base64 не поддерживаются.
  * Не отправляйте псевдонимы `image`, `images` или `input_reference`.
  * Порядок сохраняется; дубли URL занимают несколько слотов и могут оплачиваться повторно.
</ParamField>

### Поля редактирования видео

<ParamField body="video" type="object">
  Исходное видео `{url}` по публичному HTTPS; только Base

  <Expandable title="URL">
    <ParamField body="url" type="string" required>
      HTTPS
    </ParamField>
  </Expandable>
</ParamField>

Для редактирования обязательны `model`, `prompt` и `video`; `nsfw_check` можно передать дополнительно. Не отправляйте `duration`, `resolution`, `aspect_ratio` или `image_urls`; платформа определяет длительность источника.

## Типы запроса TypeScript

Используйте дискриминированное объединение, чтобы поля генерации не попали в редактирование.

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

## Примеры

<Tabs>
  <Tab title="Текст в видео">
    ```json theme={null}
    {"model":"grok-imagine-video","prompt":"A cinematic aerial shot at sunrise","duration":5,"resolution":"720p","aspect_ratio":"16:9"}
    ```
  </Tab>

  <Tab title="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"}
    ```
  </Tab>

  <Tab title="Одно или несколько изображений">
    ```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"
      ]
    }
    ```
  </Tab>

  <Tab title="Редактирование">
    ```json theme={null}
    {
      "model":"grok-imagine-video",
      "prompt":"Improve motion consistency and apply cinematic color grading",
      "video":{"url":"https://cdn.example.com/source.mp4"}
    }
    ```
  </Tab>
</Tabs>

## Асинхронные задачи

### Создание успешно

Успешное создание возвращает HTTP `200`. Сохраните `data[0].task_id`; отправка не означает завершение. ID задачи означает отправку, а не завершение.

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

### Запрос задачи

```http theme={null}
GET https://api.apimart.ai/v1/tasks/{task_id}
Authorization: Bearer <APIMART_API_KEY>
Accept: application/json
```

Опрашивайте `GET /v1/tasks/{task_id}` каждые 3–5 секунд. После перезагрузки продолжите с сохранённым ID.

| `data.status` | Значение            | Действие                          |
| ------------- | ------------------- | --------------------------------- |
| `pending`     | В очереди           | Продолжать опрос                  |
| `processing`  | Генерация           | Показывать прогресс               |
| `completed`   | Завершена           | Прочитать результат и остановить  |
| `failed`      | Ошибка и возврат    | Показать ошибку и остановить      |
| `unknown`     | Временно неизвестно | Снизить частоту и повторить позже |

### Завершённый ответ

```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` — массив строк, а не одна строка. Проверяйте каждый элемент как HTTPS URL. Рекомендуется проверка во время выполнения:

```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),
        )
      : [],
  );
}
```

Срок определяет `expires_at`. Не фиксируйте время; предложите скачать или сохранить результат.

### Ответ с ошибкой

```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>
  Опрос может вернуть HTTP `200` при `data.status=failed`. Определяйте результат по `data.status`; у ошибки `cost=0`.
</Warning>

## Каталог цен

```http theme={null}
GET https://api.apimart.ai/api/pricing/models/all
```

Читайте `GET /api/pricing/models/all` и ищите `id` в `data.models.video`. Показанная цена предварительная; итог — `data.cost` задачи.

### Цена выходного видео

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

* Ключи цен — `480P/720P/1080P`, значения запроса — в нижнем регистре; нормализуйте при поиске.
* `default` — метаданные совместимости, а не доступное разрешение.
* Используйте `after_discount` напрямую, не применяйте скидку повторно.

### Цена входного материала

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

Цена входного видео — скалярный объект. Не требуйте `items`, `billing_mode` или `max_billable_seconds`. У 1.5 нет цены входного видео.

### Формулы оценки

```text theme={null}
Генерация = цена вывода/сек × duration + цена изображения × количество
Редактирование = цена 720P/сек × секунды источника + цена входного видео × секунды
```

Персональные цены и округление могут изменить оценку. Итог всегда берите из `data.cost`.

## Правила frontend

### Смена модели

* Base показывает `480p/720p`; 1.5 также `1080p`.
* При переходе с 1.5 `1080p` на Base выбрать `480p`.
* Редактирование фиксирует `grok-imagine-video`.

### Смена режима

| Режим                | Показываемые элементы                                | Отправляемые поля               | Нужно очистить                                |
| -------------------- | ---------------------------------------------------- | ------------------------------- | --------------------------------------------- |
| Генерация            | `prompt/duration/resolution/aspect_ratio/nsfw_check` | Поля генерации                  | `image_urls/video`                            |
| Изображения          | Поля генерации + `image_urls`                        | Поля генерации + `image_urls`   | `video`                                       |
| Редактирование видео | `prompt/video/nsfw_check`                            | `model/prompt/video/nsfw_check` | `duration/resolution/aspect_ratio/image_urls` |

`nsfw_check` необязателен во всех режимах. При включённой модерации отправляйте `true`; иначе опустите поле или отправьте `false`.

Отключите кнопку, если выполняется любое условие:

* Текстовый режим не отправляет `image_urls` и `video`.
* Режим изображений отправляет `image_urls` без `video`.
* Редактирование очищает поля генерации.
* Отключать при неверном промпте, длительности, разрешении, URL, загрузке или дубле.
* Промпт ≤8000 Unicode, длительность — целое 1–15.
* Только публичные HTTPS URL; пустой `image_urls` не отправлять.

## Частые ошибки

| HTTP / Статус | Причина                               | Действие                              |
| ------------- | ------------------------------------- | ------------------------------------- |
| `400`         | Неверный параметр, промпт или enum    | Показать сообщение и поле             |
| `401`         | Нет или неверен API Key               | Не повторять; проверить сервер        |
| `402`         | Недостаточно средств                  | Предложить пополнение                 |
| `403`         | Нет доступа к модели                  | Не повторять автоматически            |
| `409`         | Конфликт ключа или запрос выполняется | Сохранить ключ и повторить позже      |
| `429`         | Лимит запросов                        | Соблюдать `Retry-After`               |
| `500/502/503` | Временный сбой                        | Ограниченный повтор с исходным ключом |
| `failed`      | Ошибка асинхронной задачи             | Остановить опрос; стоимость ноль      |

## Проверка frontend

* API Key только на backend или BFF.
* Не смешивать официальные модели с `grok-imagine-1.5-video-ext`.
* Промпт ≤8000 Unicode, длительность — целое 1–15.
* Только публичные HTTPS URL; пустой `image_urls` не отправлять.
* Для редактирования используйте Base и отправляйте только `model/prompt/video` плюс необязательный `nsfw_check`.
* Читать `data[0].task_id`, финал определять по `data.status`.
* Читать `result.videos[].url[]` и учитывать `expires_at`.
* Показывать каталог, итог брать из `data.cost`.
