# Проекты

> Эндпоинты проектов Slicer API — запуск монтажа с подтверждением цены, статус и этапы, версии ролика, пересборка, повтор, остановка, история и скачивание.

Источник: https://docs.slicer.media/api/reference/projects/

Проект — ролик и всё, что с ним происходило: материалы, запуски монтажа и экспорта, версии, история. Платные операции (создание с ИИ-монтажом, пересборка, повтор) сначала отвечают ценой и запускаются только с `confirmCost` — см. [Монтаж и цена](https://docs.slicer.media/api/montage/). Проект без ИИ-режиссёра (`mode: "manual"`) создаётся бесплатно и без подтверждения — см. [Проект без ИИ-режиссёра](https://docs.slicer.media/api/montage/#manual).

## Создать проект и запустить монтаж

`POST /v1/projects`

- **Области доступа:** `projects:write`
- **Лимит:** платные операции
- **Цена:** _тратит токены_

Без `confirmCost` возвращает `Quote` и ничего не создаёт. С `confirmCost`, равным текущей цене, создаёт проект и запускает монтаж: одна версия, которую режиссёр после рендера сам проверяет и поправляет. Первый ролик бесплатный (`cost: 0`). С `mode: "manual"` проект бесплатный: материалы ложатся на таймлайн по порядку, проект становится черновиком `draft` — `confirmCost` не нужен.

> **Важно.** Без `confirmCost` отвечает ценой (`Quote`) и ничего не запускает.

### Тело запроса `CreateProjectRequest`

| Поле | Тип | Описание |
| --- | --- | --- |
| `uploadIds` _(обязательное)_ | `string (uuid)[]` | Готовые загрузки `source` в порядке материалов — 1–20 |
| `mode` | `string` | `ai` (по умолчанию) — монтаж ИИ-режиссёром, платно; `manual` — материалы ложатся на таймлайн по порядку, проект — бесплатный черновик `draft`, его правят и экспортируют сами — `ai` · `manual` |
| `format` | `string` | Формат кадра проекта `manual` (по умолчанию 9:16) — `9:16` · `4:5` · `1:1` · `16:9` |
| `settings` | `MontageSettingsInput` |     |
| `title` | `string` | — ≤ 120 |
| `brief` | `string` | Пожелания режиссёру — ≤ 600 |
| `confirmCost` | `integer` | Цена, на которую вы согласны. Без неё ответ — `Quote`, ничего не запускается |

### Запрос

**curl**

```bash
curl -X POST "https://api.slicer.media/v1/projects" \
  -H "Authorization: Bearer $SLICER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"uploadIds":["6f1c2a4e-8b3d-4c1a-9e2f-3b5d7a9c1e20"]}'
```

**JavaScript**

```js
const response = await fetch('https://api.slicer.media/v1/projects', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.SLICER_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "uploadIds": [
      "6f1c2a4e-8b3d-4c1a-9e2f-3b5d7a9c1e20"
    ]
  }),
});
const { ok, data, error } = await response.json();
```

**Python**

```python
import os
import requests

response = requests.post(
    "https://api.slicer.media/v1/projects",
    headers={"Authorization": f"Bearer {os.environ['SLICER_TOKEN']}"},
    json={
        "uploadIds": ["6f1c2a4e-8b3d-4c1a-9e2f-3b5d7a9c1e20"],
    },
)
body = response.json()
```

### Ответ

Один из вариантов: Quote, ProjectDetails

**Поля ответа: `Quote` (8)**

| Поле | Тип | Описание |
| --- | --- | --- |
| `status` _(обязательное)_ | `"quote"` |     |
| `cost` _(обязательное)_ | `integer` | Цена в токенах; повторите запрос с `confirmCost`, равным ей. У операции по себестоимости (`atCost`) — предельная: спишется фактическая себестоимость, не больше |
| `free` _(обязательное)_ | `boolean` | Операция бесплатна (первый ролик, бесплатный повтор) |
| `estimate` | `number` | Операция по себестоимости: ожидаемая цена в токенах (дробно) |
| `atCost` | `boolean` | Цена — себестоимость ИИ-сервисов без наценки: списывается фактическая, не больше `cost` |
| `available` _(обязательное)_ | `integer` | Сколько токенов доступно сейчас |
| `enough` _(обязательное)_ | `boolean` | Токенов хватает |
| `spendLimitLeft` _(обязательное)_ | `integer \| null` | Остаток месячного лимита расходов токена; `null` — без лимита |

**Поля ответа: `ProjectDetails` (44)**

| Поле | Тип | Описание |
| --- | --- | --- |
| `id` _(обязательное)_ | `integer` |     |
| `title` _(обязательное)_ | `string` |     |
| `status` _(обязательное)_ | `string` | `draft` — проект «Сам в редакторе» до первого экспорта: правьте операциями и экспортируйте — `queued` · `processing` · `succeeded` · `failed` · `cancelled` · `draft` |
| `mode` _(обязательное)_ | `string` | `ai` — монтаж ИИ-режиссёром; `manual` — материалы на таймлайне как есть, бесплатно (платны только ИИ-операции) — `ai` · `manual` |
| `stage` _(обязательное)_ | `string \| null` |     |
| `progress` _(обязательное)_ | `integer` | Прогресс текущего запуска, % |
| `client` _(обязательное)_ | `string \| null` | Где создан: web, mobile, api, mcp |
| `settings` _(обязательное)_ | `object` | Настройки монтажа (см. MontageSettingsInput) |
| `brief` _(обязательное)_ | `string \| null` |     |
| `isFree` _(обязательное)_ | `boolean` |     |
| `watermark` _(обязательное)_ | `boolean` |     |
| `tokensCost` _(обязательное)_ | `integer` |     |
| `error` _(обязательное)_ | `object \| null` |     |
| `error.code` _(обязательное)_ | `string` |     |
| `error.message` _(обязательное)_ | `string` |     |
| `durationSec` _(обязательное)_ | `number \| null` |     |
| `versionChoice` _(обязательное)_ | `integer[] \| null` | Id версий, ждущих выбора; монтаж отдаёт одну версию, поэтому обычно `null` |
| `result` _(обязательное)_ | `object \| null` |     |
| `result.url` _(обязательное)_ | `string (uri)` | Скачать с токеном (поддерживается Range) |
| `result.posterUrl` _(обязательное)_ | `string (uri) \| null` |     |
| `result.container` _(обязательное)_ | `string` |     |
| `result.info` _(обязательное)_ | `object \| null` |     |
| `appUrl` _(обязательное)_ | `string (uri)` | Проект в веб-приложении Slicer |
| `sourcesAvailable` _(обязательное)_ | `boolean` | Исходники хранятся 7 дней после монтажа |
| `createdAt` _(обязательное)_ | `string` | Дата и время ISO 8601, UTC |
| `finishedAt` _(обязательное)_ | `string \| null` |     |
| `stages` _(обязательное)_ | `object[]` |     |
| `stages[].stage` _(обязательное)_ | `string` |     |
| `stages[].status` _(обязательное)_ | `string` | — `pending` · `running` · `succeeded` · `failed` · `skipped` |
| `stages[].inRun` _(обязательное)_ | `boolean` | Часть текущего запуска (не взят готовым) |
| `stages[].startedAt` _(обязательное)_ | `string \| null` |     |
| `stages[].finishedAt` _(обязательное)_ | `string \| null` |     |
| `stages[].durationSec` _(обязательное)_ | `number \| null` |     |
| `stages[].progress` _(обязательное)_ | `integer` |     |
| `stages[].tokens` _(обязательное)_ | `integer` | Доля цены запуска |
| `run` _(обязательное)_ | `object` |     |
| `run.kind` _(обязательное)_ | `string` |     |
| `run.status` _(обязательное)_ | `string` |     |
| `run.tokens` _(обязательное)_ | `integer` |     |
| `run.tokensState` _(обязательное)_ | `string` | — `free` · `reserved` · `charged` · `refunded` |
| `run.queuedAt` _(обязательное)_ | `string` | Дата и время ISO 8601, UTC |
| `run.startedAt` _(обязательное)_ | `string \| null` |     |
| `run.finishedAt` _(обязательное)_ | `string \| null` |     |
| `versions` _(обязательное)_ | `ProjectVersion[]` |     |

Пример ответа:

```json
{
  "ok": true,
  "data": {
    "status": "quote",
    "cost": 24,
    "free": true,
    "estimate": 1.5,
    "atCost": true,
    "available": 240,
    "enough": true,
    "spendLimitLeft": 200
  }
}
```

## Список проектов

`GET /v1/projects`

- **Области доступа:** `projects:read`
- **Лимит:** обычный

### Параметры запроса

| Поле | Тип | Описание |
| --- | --- | --- |
| `limit` | `integer` | — 1–100 |
| `cursor` | `string` | — ≤ 200 |
| `status` | `string` | — `all` · `ready` · `active` · `failed` · `draft` |
| `q` | `string` | — ≤ 100 |

### Запрос

**curl**

```bash
curl "https://api.slicer.media/v1/projects" \
  -H "Authorization: Bearer $SLICER_TOKEN"
```

**JavaScript**

```js
const response = await fetch('https://api.slicer.media/v1/projects', {
  headers: {
    Authorization: `Bearer ${process.env.SLICER_TOKEN}`,
  },
});
const { ok, data, error } = await response.json();
```

**Python**

```python
import os
import requests

response = requests.get(
    "https://api.slicer.media/v1/projects",
    headers={"Authorization": f"Bearer {os.environ['SLICER_TOKEN']}"},
)
body = response.json()
```

### Ответ

**Поля ответа: `object` (2)**

| Поле | Тип | Описание |
| --- | --- | --- |
| `items` _(обязательное)_ | `Project[]` |     |
| `nextCursor` _(обязательное)_ | `string \| null` |     |

Пример ответа:

```json
{
  "ok": true,
  "data": {
    "items": [
      {
        "id": 42,
        "title": "Монтаж за 3 минуты",
        "status": "queued",
        "mode": "ai",
        "stage": "string",
        "progress": 0.5,
        "client": "string",
        "settings": {},
        "brief": "Динамично, с акцентом на главные мысли",
        "isFree": true,
        "watermark": true,
        "tokensCost": 24,
        "error": {
          "code": null,
          "message": null
        },
        "durationSec": 42.5,
        "versionChoice": [
          null
        ],
        "result": {
          "url": null,
          "posterUrl": null,
          "container": null,
          "info": null
        },
        "appUrl": "https://api.slicer.media/v1/…",
        "sourcesAvailable": true,
        "createdAt": "2026-10-16T09:30:00Z",
        "finishedAt": "2026-10-16T09:30:00Z"
      }
    ],
    "nextCursor": "eyJpZCI6NDJ9"
  }
}
```

## Проект

`GET /v1/projects/{id}`

- **Области доступа:** `projects:read`
- **Лимит:** обычный

### Параметры пути

| Поле | Тип | Описание |
| --- | --- | --- |
| `id` _(обязательное)_ | `integer` | — ≥ 1 |

### Запрос

**curl**

```bash
curl "https://api.slicer.media/v1/projects/42" \
  -H "Authorization: Bearer $SLICER_TOKEN"
```

**JavaScript**

```js
const response = await fetch('https://api.slicer.media/v1/projects/42', {
  headers: {
    Authorization: `Bearer ${process.env.SLICER_TOKEN}`,
  },
});
const { ok, data, error } = await response.json();
```

**Python**

```python
import os
import requests

response = requests.get(
    "https://api.slicer.media/v1/projects/42",
    headers={"Authorization": f"Bearer {os.environ['SLICER_TOKEN']}"},
)
body = response.json()
```

### Ответ

**Поля ответа: `ProjectDetails` (44)**

| Поле | Тип | Описание |
| --- | --- | --- |
| `id` _(обязательное)_ | `integer` |     |
| `title` _(обязательное)_ | `string` |     |
| `status` _(обязательное)_ | `string` | `draft` — проект «Сам в редакторе» до первого экспорта: правьте операциями и экспортируйте — `queued` · `processing` · `succeeded` · `failed` · `cancelled` · `draft` |
| `mode` _(обязательное)_ | `string` | `ai` — монтаж ИИ-режиссёром; `manual` — материалы на таймлайне как есть, бесплатно (платны только ИИ-операции) — `ai` · `manual` |
| `stage` _(обязательное)_ | `string \| null` |     |
| `progress` _(обязательное)_ | `integer` | Прогресс текущего запуска, % |
| `client` _(обязательное)_ | `string \| null` | Где создан: web, mobile, api, mcp |
| `settings` _(обязательное)_ | `object` | Настройки монтажа (см. MontageSettingsInput) |
| `brief` _(обязательное)_ | `string \| null` |     |
| `isFree` _(обязательное)_ | `boolean` |     |
| `watermark` _(обязательное)_ | `boolean` |     |
| `tokensCost` _(обязательное)_ | `integer` |     |
| `error` _(обязательное)_ | `object \| null` |     |
| `error.code` _(обязательное)_ | `string` |     |
| `error.message` _(обязательное)_ | `string` |     |
| `durationSec` _(обязательное)_ | `number \| null` |     |
| `versionChoice` _(обязательное)_ | `integer[] \| null` | Id версий, ждущих выбора; монтаж отдаёт одну версию, поэтому обычно `null` |
| `result` _(обязательное)_ | `object \| null` |     |
| `result.url` _(обязательное)_ | `string (uri)` | Скачать с токеном (поддерживается Range) |
| `result.posterUrl` _(обязательное)_ | `string (uri) \| null` |     |
| `result.container` _(обязательное)_ | `string` |     |
| `result.info` _(обязательное)_ | `object \| null` |     |
| `appUrl` _(обязательное)_ | `string (uri)` | Проект в веб-приложении Slicer |
| `sourcesAvailable` _(обязательное)_ | `boolean` | Исходники хранятся 7 дней после монтажа |
| `createdAt` _(обязательное)_ | `string` | Дата и время ISO 8601, UTC |
| `finishedAt` _(обязательное)_ | `string \| null` |     |
| `stages` _(обязательное)_ | `object[]` |     |
| `stages[].stage` _(обязательное)_ | `string` |     |
| `stages[].status` _(обязательное)_ | `string` | — `pending` · `running` · `succeeded` · `failed` · `skipped` |
| `stages[].inRun` _(обязательное)_ | `boolean` | Часть текущего запуска (не взят готовым) |
| `stages[].startedAt` _(обязательное)_ | `string \| null` |     |
| `stages[].finishedAt` _(обязательное)_ | `string \| null` |     |
| `stages[].durationSec` _(обязательное)_ | `number \| null` |     |
| `stages[].progress` _(обязательное)_ | `integer` |     |
| `stages[].tokens` _(обязательное)_ | `integer` | Доля цены запуска |
| `run` _(обязательное)_ | `object` |     |
| `run.kind` _(обязательное)_ | `string` |     |
| `run.status` _(обязательное)_ | `string` |     |
| `run.tokens` _(обязательное)_ | `integer` |     |
| `run.tokensState` _(обязательное)_ | `string` | — `free` · `reserved` · `charged` · `refunded` |
| `run.queuedAt` _(обязательное)_ | `string` | Дата и время ISO 8601, UTC |
| `run.startedAt` _(обязательное)_ | `string \| null` |     |
| `run.finishedAt` _(обязательное)_ | `string \| null` |     |
| `versions` _(обязательное)_ | `ProjectVersion[]` |     |

Пример ответа:

```json
{
  "ok": true,
  "data": {
    "id": 42,
    "title": "Монтаж за 3 минуты",
    "status": "queued",
    "mode": "ai",
    "stage": "string",
    "progress": 0.5,
    "client": "string",
    "settings": {},
    "brief": "Динамично, с акцентом на главные мысли",
    "isFree": true,
    "watermark": true,
    "tokensCost": 24,
    "error": {
      "code": "string",
      "message": "string"
    },
    "durationSec": 42.5,
    "versionChoice": [
      1
    ],
    "result": {
      "url": "https://example.com/hook",
      "posterUrl": "https://api.slicer.media/v1/…",
      "container": "string",
      "info": {}
    },
    "appUrl": "https://api.slicer.media/v1/…",
    "sourcesAvailable": true,
    "createdAt": "2026-10-16T09:30:00Z",
    "finishedAt": "2026-10-16T09:30:00Z",
    "stages": [
      {
        "stage": "string",
        "status": "pending",
        "inRun": true,
        "startedAt": "2026-10-16T09:30:00Z",
        "finishedAt": "2026-10-16T09:30:00Z",
        "durationSec": 42.5,
        "progress": 0.5,
        "tokens": 24
      }
    ],
    "run": {
      "kind": "string",
      "status": "string",
      "tokens": 24,
      "tokensState": "free",
      "queuedAt": "2026-10-16T09:30:00Z",
      "startedAt": "2026-10-16T09:30:00Z",
      "finishedAt": "2026-10-16T09:30:00Z"
    },
    "versions": [
      {
        "id": 42,
        "version": null,
        "idea": "string",
        "durationSec": 42.5,
        "current": true,
        "awaitingChoice": true,
        "hasFile": true,
        "createdAt": "2026-10-16T09:30:00Z"
      }
    ]
  }
}
```

## Переименовать проект

`PATCH /v1/projects/{id}`

- **Области доступа:** `projects:write`
- **Лимит:** обычный

### Параметры пути

| Поле | Тип | Описание |
| --- | --- | --- |
| `id` _(обязательное)_ | `integer` | — ≥ 1 |

### Тело запроса `RenameRequest`

| Поле | Тип | Описание |
| --- | --- | --- |
| `title` _(обязательное)_ | `string` | — ≤ 120 |

### Запрос

**curl**

```bash
curl -X PATCH "https://api.slicer.media/v1/projects/42" \
  -H "Authorization: Bearer $SLICER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"Монтаж за 3 минуты"}'
```

**JavaScript**

```js
const response = await fetch('https://api.slicer.media/v1/projects/42', {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${process.env.SLICER_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "title": "Монтаж за 3 минуты"
  }),
});
const { ok, data, error } = await response.json();
```

**Python**

```python
import os
import requests

response = requests.patch(
    "https://api.slicer.media/v1/projects/42",
    headers={"Authorization": f"Bearer {os.environ['SLICER_TOKEN']}"},
    json={
        "title": "Монтаж за 3 минуты",
    },
)
body = response.json()
```

### Ответ

**Поля ответа: `Project` (26)**

| Поле | Тип | Описание |
| --- | --- | --- |
| `id` _(обязательное)_ | `integer` |     |
| `title` _(обязательное)_ | `string` |     |
| `status` _(обязательное)_ | `string` | `draft` — проект «Сам в редакторе» до первого экспорта: правьте операциями и экспортируйте — `queued` · `processing` · `succeeded` · `failed` · `cancelled` · `draft` |
| `mode` _(обязательное)_ | `string` | `ai` — монтаж ИИ-режиссёром; `manual` — материалы на таймлайне как есть, бесплатно (платны только ИИ-операции) — `ai` · `manual` |
| `stage` _(обязательное)_ | `string \| null` |     |
| `progress` _(обязательное)_ | `integer` | Прогресс текущего запуска, % |
| `client` _(обязательное)_ | `string \| null` | Где создан: web, mobile, api, mcp |
| `settings` _(обязательное)_ | `object` | Настройки монтажа (см. MontageSettingsInput) |
| `brief` _(обязательное)_ | `string \| null` |     |
| `isFree` _(обязательное)_ | `boolean` |     |
| `watermark` _(обязательное)_ | `boolean` |     |
| `tokensCost` _(обязательное)_ | `integer` |     |
| `error` _(обязательное)_ | `object \| null` |     |
| `error.code` _(обязательное)_ | `string` |     |
| `error.message` _(обязательное)_ | `string` |     |
| `durationSec` _(обязательное)_ | `number \| null` |     |
| `versionChoice` _(обязательное)_ | `integer[] \| null` | Id версий, ждущих выбора; монтаж отдаёт одну версию, поэтому обычно `null` |
| `result` _(обязательное)_ | `object \| null` |     |
| `result.url` _(обязательное)_ | `string (uri)` | Скачать с токеном (поддерживается Range) |
| `result.posterUrl` _(обязательное)_ | `string (uri) \| null` |     |
| `result.container` _(обязательное)_ | `string` |     |
| `result.info` _(обязательное)_ | `object \| null` |     |
| `appUrl` _(обязательное)_ | `string (uri)` | Проект в веб-приложении Slicer |
| `sourcesAvailable` _(обязательное)_ | `boolean` | Исходники хранятся 7 дней после монтажа |
| `createdAt` _(обязательное)_ | `string` | Дата и время ISO 8601, UTC |
| `finishedAt` _(обязательное)_ | `string \| null` |     |

Пример ответа:

```json
{
  "ok": true,
  "data": {
    "id": 42,
    "title": "Монтаж за 3 минуты",
    "status": "queued",
    "mode": "ai",
    "stage": "string",
    "progress": 0.5,
    "client": "string",
    "settings": {},
    "brief": "Динамично, с акцентом на главные мысли",
    "isFree": true,
    "watermark": true,
    "tokensCost": 24,
    "error": {
      "code": "string",
      "message": "string"
    },
    "durationSec": 42.5,
    "versionChoice": [
      1
    ],
    "result": {
      "url": "https://example.com/hook",
      "posterUrl": "https://api.slicer.media/v1/…",
      "container": "string",
      "info": {}
    },
    "appUrl": "https://api.slicer.media/v1/…",
    "sourcesAvailable": true,
    "createdAt": "2026-10-16T09:30:00Z",
    "finishedAt": "2026-10-16T09:30:00Z"
  }
}
```

## Удалить проект и файлы

`DELETE /v1/projects/{id}`

- **Области доступа:** `projects:write`
- **Лимит:** обычный

### Параметры пути

| Поле | Тип | Описание |
| --- | --- | --- |
| `id` _(обязательное)_ | `integer` | — ≥ 1 |

### Запрос

**curl**

```bash
curl -X DELETE "https://api.slicer.media/v1/projects/42" \
  -H "Authorization: Bearer $SLICER_TOKEN"
```

**JavaScript**

```js
const response = await fetch('https://api.slicer.media/v1/projects/42', {
  method: 'DELETE',
  headers: {
    Authorization: `Bearer ${process.env.SLICER_TOKEN}`,
  },
});
const { ok, data, error } = await response.json();
```

**Python**

```python
import os
import requests

response = requests.delete(
    "https://api.slicer.media/v1/projects/42",
    headers={"Authorization": f"Bearer {os.environ['SLICER_TOKEN']}"},
)
body = response.json()
```

### Ответ

**Поля ответа: `object` (2)**

| Поле | Тип | Описание |
| --- | --- | --- |
| `id` _(обязательное)_ | `integer` |     |
| `deleted` _(обязательное)_ | `boolean` |     |

Пример ответа:

```json
{
  "ok": true,
  "data": {
    "id": 42,
    "deleted": true
  }
}
```

## Запуски

### Пересобрать с новыми параметрами

`POST /v1/projects/{id}/remount`

- **Области доступа:** `montage:run`
- **Лимит:** платные операции
- **Цена:** _тратит токены_

> **Важно.** Без `confirmCost` отвечает ценой (`Quote`) и ничего не запускает.

#### Параметры пути

| Поле | Тип | Описание |
| --- | --- | --- |
| `id` _(обязательное)_ | `integer` | — ≥ 1 |

#### Тело запроса `RemountRequest`

| Поле | Тип | Описание |
| --- | --- | --- |
| `settings` _(обязательное)_ | `MontageSettingsInput` |     |
| `brief` | `string` | — ≤ 600 |
| `confirmCost` | `integer` | Цена, на которую вы согласны. Без неё ответ — `Quote`, ничего не запускается |

#### Запрос

**curl**

```bash
curl -X POST "https://api.slicer.media/v1/projects/42/remount" \
  -H "Authorization: Bearer $SLICER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"settings":{"templateId":"string","fontId":"string","colorId":"string","subtitles":{"enabled":true,"design":"dynamic","size":"small","position":"auto","speakerColors":true,"highlight":"auto","animation":"auto","words":"auto","letterCase":"auto"},"params":{"emoji":true,"soundEffects":true,"mediaCards":true,"plaques":true,"cameraMotion":true,"introZoom":true,"hook":true},"smartCut":true,"targetDurationSec":15,"language":"auto","direction":{"mode":"auto","pace":"calm","effects":"off","narration":true,"voice":"warm"}}}'
```

**JavaScript**

```js
const response = await fetch('https://api.slicer.media/v1/projects/42/remount', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.SLICER_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "settings": {
      "templateId": "string",
      "fontId": "string",
      "colorId": "string",
      "subtitles": {
        "enabled": true,
        "design": "dynamic",
        "size": "small",
        "position": "auto",
        "speakerColors": true,
        "highlight": "auto",
        "animation": "auto",
        "words": "auto",
        "letterCase": "auto"
      },
      "params": {
        "emoji": true,
        "soundEffects": true,
        "mediaCards": true,
        "plaques": true,
        "cameraMotion": true,
        "introZoom": true,
        "hook": true
      },
      "smartCut": true,
      "targetDurationSec": 15,
      "language": "auto",
      "direction": {
        "mode": "auto",
        "pace": "calm",
        "effects": "off",
        "narration": true,
        "voice": "warm"
      }
    }
  }),
});
const { ok, data, error } = await response.json();
```

**Python**

```python
import os
import requests

response = requests.post(
    "https://api.slicer.media/v1/projects/42/remount",
    headers={"Authorization": f"Bearer {os.environ['SLICER_TOKEN']}"},
    json={
        "settings": {
            "templateId": "string",
            "fontId": "string",
            "colorId": "string",
            "subtitles": {
                "enabled": True,
                "design": "dynamic",
                "size": "small",
                "position": "auto",
                "speakerColors": True,
                "highlight": "auto",
                "animation": "auto",
                "words": "auto",
                "letterCase": "auto",
            },
            "params": {
                "emoji": True,
                "soundEffects": True,
                "mediaCards": True,
                "plaques": True,
                "cameraMotion": True,
                "introZoom": True,
                "hook": True,
            },
            "smartCut": True,
            "targetDurationSec": 15,
            "language": "auto",
            "direction": {
                "mode": "auto",
                "pace": "calm",
                "effects": "off",
                "narration": True,
                "voice": "warm",
            },
        },
    },
)
body = response.json()
```

#### Ответ

Один из вариантов: Quote, ProjectDetails

**Поля ответа: `Quote` (8)**

| Поле | Тип | Описание |
| --- | --- | --- |
| `status` _(обязательное)_ | `"quote"` |     |
| `cost` _(обязательное)_ | `integer` | Цена в токенах; повторите запрос с `confirmCost`, равным ей. У операции по себестоимости (`atCost`) — предельная: спишется фактическая себестоимость, не больше |
| `free` _(обязательное)_ | `boolean` | Операция бесплатна (первый ролик, бесплатный повтор) |
| `estimate` | `number` | Операция по себестоимости: ожидаемая цена в токенах (дробно) |
| `atCost` | `boolean` | Цена — себестоимость ИИ-сервисов без наценки: списывается фактическая, не больше `cost` |
| `available` _(обязательное)_ | `integer` | Сколько токенов доступно сейчас |
| `enough` _(обязательное)_ | `boolean` | Токенов хватает |
| `spendLimitLeft` _(обязательное)_ | `integer \| null` | Остаток месячного лимита расходов токена; `null` — без лимита |

**Поля ответа: `ProjectDetails` (44)**

| Поле | Тип | Описание |
| --- | --- | --- |
| `id` _(обязательное)_ | `integer` |     |
| `title` _(обязательное)_ | `string` |     |
| `status` _(обязательное)_ | `string` | `draft` — проект «Сам в редакторе» до первого экспорта: правьте операциями и экспортируйте — `queued` · `processing` · `succeeded` · `failed` · `cancelled` · `draft` |
| `mode` _(обязательное)_ | `string` | `ai` — монтаж ИИ-режиссёром; `manual` — материалы на таймлайне как есть, бесплатно (платны только ИИ-операции) — `ai` · `manual` |
| `stage` _(обязательное)_ | `string \| null` |     |
| `progress` _(обязательное)_ | `integer` | Прогресс текущего запуска, % |
| `client` _(обязательное)_ | `string \| null` | Где создан: web, mobile, api, mcp |
| `settings` _(обязательное)_ | `object` | Настройки монтажа (см. MontageSettingsInput) |
| `brief` _(обязательное)_ | `string \| null` |     |
| `isFree` _(обязательное)_ | `boolean` |     |
| `watermark` _(обязательное)_ | `boolean` |     |
| `tokensCost` _(обязательное)_ | `integer` |     |
| `error` _(обязательное)_ | `object \| null` |     |
| `error.code` _(обязательное)_ | `string` |     |
| `error.message` _(обязательное)_ | `string` |     |
| `durationSec` _(обязательное)_ | `number \| null` |     |
| `versionChoice` _(обязательное)_ | `integer[] \| null` | Id версий, ждущих выбора; монтаж отдаёт одну версию, поэтому обычно `null` |
| `result` _(обязательное)_ | `object \| null` |     |
| `result.url` _(обязательное)_ | `string (uri)` | Скачать с токеном (поддерживается Range) |
| `result.posterUrl` _(обязательное)_ | `string (uri) \| null` |     |
| `result.container` _(обязательное)_ | `string` |     |
| `result.info` _(обязательное)_ | `object \| null` |     |
| `appUrl` _(обязательное)_ | `string (uri)` | Проект в веб-приложении Slicer |
| `sourcesAvailable` _(обязательное)_ | `boolean` | Исходники хранятся 7 дней после монтажа |
| `createdAt` _(обязательное)_ | `string` | Дата и время ISO 8601, UTC |
| `finishedAt` _(обязательное)_ | `string \| null` |     |
| `stages` _(обязательное)_ | `object[]` |     |
| `stages[].stage` _(обязательное)_ | `string` |     |
| `stages[].status` _(обязательное)_ | `string` | — `pending` · `running` · `succeeded` · `failed` · `skipped` |
| `stages[].inRun` _(обязательное)_ | `boolean` | Часть текущего запуска (не взят готовым) |
| `stages[].startedAt` _(обязательное)_ | `string \| null` |     |
| `stages[].finishedAt` _(обязательное)_ | `string \| null` |     |
| `stages[].durationSec` _(обязательное)_ | `number \| null` |     |
| `stages[].progress` _(обязательное)_ | `integer` |     |
| `stages[].tokens` _(обязательное)_ | `integer` | Доля цены запуска |
| `run` _(обязательное)_ | `object` |     |
| `run.kind` _(обязательное)_ | `string` |     |
| `run.status` _(обязательное)_ | `string` |     |
| `run.tokens` _(обязательное)_ | `integer` |     |
| `run.tokensState` _(обязательное)_ | `string` | — `free` · `reserved` · `charged` · `refunded` |
| `run.queuedAt` _(обязательное)_ | `string` | Дата и время ISO 8601, UTC |
| `run.startedAt` _(обязательное)_ | `string \| null` |     |
| `run.finishedAt` _(обязательное)_ | `string \| null` |     |
| `versions` _(обязательное)_ | `ProjectVersion[]` |     |

Пример ответа:

```json
{
  "ok": true,
  "data": {
    "status": "quote",
    "cost": 24,
    "free": true,
    "estimate": 1.5,
    "atCost": true,
    "available": 240,
    "enough": true,
    "spendLimitLeft": 200
  }
}
```

### Повторить неудачный запуск

`POST /v1/projects/{id}/retry`

- **Области доступа:** `montage:run`
- **Лимит:** платные операции
- **Цена:** _тратит токены_

> **Важно.** Без `confirmCost` отвечает ценой (`Quote`) и ничего не запускает.

#### Параметры пути

| Поле | Тип | Описание |
| --- | --- | --- |
| `id` _(обязательное)_ | `integer` | — ≥ 1 |

#### Тело запроса `RetryRequest`

| Поле | Тип | Описание |
| --- | --- | --- |
| `confirmCost` | `integer` | Цена, на которую вы согласны. Без неё ответ — `Quote`, ничего не запускается |

#### Запрос

**curl**

```bash
curl -X POST "https://api.slicer.media/v1/projects/42/retry" \
  -H "Authorization: Bearer $SLICER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{}'
```

**JavaScript**

```js
const response = await fetch('https://api.slicer.media/v1/projects/42/retry', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.SLICER_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({}),
});
const { ok, data, error } = await response.json();
```

**Python**

```python
import os
import requests

response = requests.post(
    "https://api.slicer.media/v1/projects/42/retry",
    headers={"Authorization": f"Bearer {os.environ['SLICER_TOKEN']}"},
    json={},
)
body = response.json()
```

#### Ответ

Один из вариантов: Quote, ProjectDetails

**Поля ответа: `Quote` (8)**

| Поле | Тип | Описание |
| --- | --- | --- |
| `status` _(обязательное)_ | `"quote"` |     |
| `cost` _(обязательное)_ | `integer` | Цена в токенах; повторите запрос с `confirmCost`, равным ей. У операции по себестоимости (`atCost`) — предельная: спишется фактическая себестоимость, не больше |
| `free` _(обязательное)_ | `boolean` | Операция бесплатна (первый ролик, бесплатный повтор) |
| `estimate` | `number` | Операция по себестоимости: ожидаемая цена в токенах (дробно) |
| `atCost` | `boolean` | Цена — себестоимость ИИ-сервисов без наценки: списывается фактическая, не больше `cost` |
| `available` _(обязательное)_ | `integer` | Сколько токенов доступно сейчас |
| `enough` _(обязательное)_ | `boolean` | Токенов хватает |
| `spendLimitLeft` _(обязательное)_ | `integer \| null` | Остаток месячного лимита расходов токена; `null` — без лимита |

**Поля ответа: `ProjectDetails` (44)**

| Поле | Тип | Описание |
| --- | --- | --- |
| `id` _(обязательное)_ | `integer` |     |
| `title` _(обязательное)_ | `string` |     |
| `status` _(обязательное)_ | `string` | `draft` — проект «Сам в редакторе» до первого экспорта: правьте операциями и экспортируйте — `queued` · `processing` · `succeeded` · `failed` · `cancelled` · `draft` |
| `mode` _(обязательное)_ | `string` | `ai` — монтаж ИИ-режиссёром; `manual` — материалы на таймлайне как есть, бесплатно (платны только ИИ-операции) — `ai` · `manual` |
| `stage` _(обязательное)_ | `string \| null` |     |
| `progress` _(обязательное)_ | `integer` | Прогресс текущего запуска, % |
| `client` _(обязательное)_ | `string \| null` | Где создан: web, mobile, api, mcp |
| `settings` _(обязательное)_ | `object` | Настройки монтажа (см. MontageSettingsInput) |
| `brief` _(обязательное)_ | `string \| null` |     |
| `isFree` _(обязательное)_ | `boolean` |     |
| `watermark` _(обязательное)_ | `boolean` |     |
| `tokensCost` _(обязательное)_ | `integer` |     |
| `error` _(обязательное)_ | `object \| null` |     |
| `error.code` _(обязательное)_ | `string` |     |
| `error.message` _(обязательное)_ | `string` |     |
| `durationSec` _(обязательное)_ | `number \| null` |     |
| `versionChoice` _(обязательное)_ | `integer[] \| null` | Id версий, ждущих выбора; монтаж отдаёт одну версию, поэтому обычно `null` |
| `result` _(обязательное)_ | `object \| null` |     |
| `result.url` _(обязательное)_ | `string (uri)` | Скачать с токеном (поддерживается Range) |
| `result.posterUrl` _(обязательное)_ | `string (uri) \| null` |     |
| `result.container` _(обязательное)_ | `string` |     |
| `result.info` _(обязательное)_ | `object \| null` |     |
| `appUrl` _(обязательное)_ | `string (uri)` | Проект в веб-приложении Slicer |
| `sourcesAvailable` _(обязательное)_ | `boolean` | Исходники хранятся 7 дней после монтажа |
| `createdAt` _(обязательное)_ | `string` | Дата и время ISO 8601, UTC |
| `finishedAt` _(обязательное)_ | `string \| null` |     |
| `stages` _(обязательное)_ | `object[]` |     |
| `stages[].stage` _(обязательное)_ | `string` |     |
| `stages[].status` _(обязательное)_ | `string` | — `pending` · `running` · `succeeded` · `failed` · `skipped` |
| `stages[].inRun` _(обязательное)_ | `boolean` | Часть текущего запуска (не взят готовым) |
| `stages[].startedAt` _(обязательное)_ | `string \| null` |     |
| `stages[].finishedAt` _(обязательное)_ | `string \| null` |     |
| `stages[].durationSec` _(обязательное)_ | `number \| null` |     |
| `stages[].progress` _(обязательное)_ | `integer` |     |
| `stages[].tokens` _(обязательное)_ | `integer` | Доля цены запуска |
| `run` _(обязательное)_ | `object` |     |
| `run.kind` _(обязательное)_ | `string` |     |
| `run.status` _(обязательное)_ | `string` |     |
| `run.tokens` _(обязательное)_ | `integer` |     |
| `run.tokensState` _(обязательное)_ | `string` | — `free` · `reserved` · `charged` · `refunded` |
| `run.queuedAt` _(обязательное)_ | `string` | Дата и время ISO 8601, UTC |
| `run.startedAt` _(обязательное)_ | `string \| null` |     |
| `run.finishedAt` _(обязательное)_ | `string \| null` |     |
| `versions` _(обязательное)_ | `ProjectVersion[]` |     |

Пример ответа:

```json
{
  "ok": true,
  "data": {
    "status": "quote",
    "cost": 24,
    "free": true,
    "estimate": 1.5,
    "atCost": true,
    "available": 240,
    "enough": true,
    "spendLimitLeft": 200
  }
}
```

### Остановить запуск

`POST /v1/projects/{id}/cancel`

- **Области доступа:** `projects:write`
- **Лимит:** обычный

#### Параметры пути

| Поле | Тип | Описание |
| --- | --- | --- |
| `id` _(обязательное)_ | `integer` | — ≥ 1 |

#### Запрос

**curl**

```bash
curl -X POST "https://api.slicer.media/v1/projects/42/cancel" \
  -H "Authorization: Bearer $SLICER_TOKEN"
```

**JavaScript**

```js
const response = await fetch('https://api.slicer.media/v1/projects/42/cancel', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.SLICER_TOKEN}`,
  },
});
const { ok, data, error } = await response.json();
```

**Python**

```python
import os
import requests

response = requests.post(
    "https://api.slicer.media/v1/projects/42/cancel",
    headers={"Authorization": f"Bearer {os.environ['SLICER_TOKEN']}"},
)
body = response.json()
```

#### Ответ

**Поля ответа: `ProjectDetails` (44)**

| Поле | Тип | Описание |
| --- | --- | --- |
| `id` _(обязательное)_ | `integer` |     |
| `title` _(обязательное)_ | `string` |     |
| `status` _(обязательное)_ | `string` | `draft` — проект «Сам в редакторе» до первого экспорта: правьте операциями и экспортируйте — `queued` · `processing` · `succeeded` · `failed` · `cancelled` · `draft` |
| `mode` _(обязательное)_ | `string` | `ai` — монтаж ИИ-режиссёром; `manual` — материалы на таймлайне как есть, бесплатно (платны только ИИ-операции) — `ai` · `manual` |
| `stage` _(обязательное)_ | `string \| null` |     |
| `progress` _(обязательное)_ | `integer` | Прогресс текущего запуска, % |
| `client` _(обязательное)_ | `string \| null` | Где создан: web, mobile, api, mcp |
| `settings` _(обязательное)_ | `object` | Настройки монтажа (см. MontageSettingsInput) |
| `brief` _(обязательное)_ | `string \| null` |     |
| `isFree` _(обязательное)_ | `boolean` |     |
| `watermark` _(обязательное)_ | `boolean` |     |
| `tokensCost` _(обязательное)_ | `integer` |     |
| `error` _(обязательное)_ | `object \| null` |     |
| `error.code` _(обязательное)_ | `string` |     |
| `error.message` _(обязательное)_ | `string` |     |
| `durationSec` _(обязательное)_ | `number \| null` |     |
| `versionChoice` _(обязательное)_ | `integer[] \| null` | Id версий, ждущих выбора; монтаж отдаёт одну версию, поэтому обычно `null` |
| `result` _(обязательное)_ | `object \| null` |     |
| `result.url` _(обязательное)_ | `string (uri)` | Скачать с токеном (поддерживается Range) |
| `result.posterUrl` _(обязательное)_ | `string (uri) \| null` |     |
| `result.container` _(обязательное)_ | `string` |     |
| `result.info` _(обязательное)_ | `object \| null` |     |
| `appUrl` _(обязательное)_ | `string (uri)` | Проект в веб-приложении Slicer |
| `sourcesAvailable` _(обязательное)_ | `boolean` | Исходники хранятся 7 дней после монтажа |
| `createdAt` _(обязательное)_ | `string` | Дата и время ISO 8601, UTC |
| `finishedAt` _(обязательное)_ | `string \| null` |     |
| `stages` _(обязательное)_ | `object[]` |     |
| `stages[].stage` _(обязательное)_ | `string` |     |
| `stages[].status` _(обязательное)_ | `string` | — `pending` · `running` · `succeeded` · `failed` · `skipped` |
| `stages[].inRun` _(обязательное)_ | `boolean` | Часть текущего запуска (не взят готовым) |
| `stages[].startedAt` _(обязательное)_ | `string \| null` |     |
| `stages[].finishedAt` _(обязательное)_ | `string \| null` |     |
| `stages[].durationSec` _(обязательное)_ | `number \| null` |     |
| `stages[].progress` _(обязательное)_ | `integer` |     |
| `stages[].tokens` _(обязательное)_ | `integer` | Доля цены запуска |
| `run` _(обязательное)_ | `object` |     |
| `run.kind` _(обязательное)_ | `string` |     |
| `run.status` _(обязательное)_ | `string` |     |
| `run.tokens` _(обязательное)_ | `integer` |     |
| `run.tokensState` _(обязательное)_ | `string` | — `free` · `reserved` · `charged` · `refunded` |
| `run.queuedAt` _(обязательное)_ | `string` | Дата и время ISO 8601, UTC |
| `run.startedAt` _(обязательное)_ | `string \| null` |     |
| `run.finishedAt` _(обязательное)_ | `string \| null` |     |
| `versions` _(обязательное)_ | `ProjectVersion[]` |     |

Пример ответа:

```json
{
  "ok": true,
  "data": {
    "id": 42,
    "title": "Монтаж за 3 минуты",
    "status": "queued",
    "mode": "ai",
    "stage": "string",
    "progress": 0.5,
    "client": "string",
    "settings": {},
    "brief": "Динамично, с акцентом на главные мысли",
    "isFree": true,
    "watermark": true,
    "tokensCost": 24,
    "error": {
      "code": "string",
      "message": "string"
    },
    "durationSec": 42.5,
    "versionChoice": [
      1
    ],
    "result": {
      "url": "https://example.com/hook",
      "posterUrl": "https://api.slicer.media/v1/…",
      "container": "string",
      "info": {}
    },
    "appUrl": "https://api.slicer.media/v1/…",
    "sourcesAvailable": true,
    "createdAt": "2026-10-16T09:30:00Z",
    "finishedAt": "2026-10-16T09:30:00Z",
    "stages": [
      {
        "stage": "string",
        "status": "pending",
        "inRun": true,
        "startedAt": "2026-10-16T09:30:00Z",
        "finishedAt": "2026-10-16T09:30:00Z",
        "durationSec": 42.5,
        "progress": 0.5,
        "tokens": 24
      }
    ],
    "run": {
      "kind": "string",
      "status": "string",
      "tokens": 24,
      "tokensState": "free",
      "queuedAt": "2026-10-16T09:30:00Z",
      "startedAt": "2026-10-16T09:30:00Z",
      "finishedAt": "2026-10-16T09:30:00Z"
    },
    "versions": [
      {
        "id": 42,
        "version": null,
        "idea": "string",
        "durationSec": 42.5,
        "current": true,
        "awaitingChoice": true,
        "hasFile": true,
        "createdAt": "2026-10-16T09:30:00Z"
      }
    ]
  }
}
```

## Версии и история

### Версии ролика

`GET /v1/projects/{id}/versions`

- **Области доступа:** `projects:read`
- **Лимит:** обычный

#### Параметры пути

| Поле | Тип | Описание |
| --- | --- | --- |
| `id` _(обязательное)_ | `integer` | — ≥ 1 |

#### Запрос

**curl**

```bash
curl "https://api.slicer.media/v1/projects/42/versions" \
  -H "Authorization: Bearer $SLICER_TOKEN"
```

**JavaScript**

```js
const response = await fetch('https://api.slicer.media/v1/projects/42/versions', {
  headers: {
    Authorization: `Bearer ${process.env.SLICER_TOKEN}`,
  },
});
const { ok, data, error } = await response.json();
```

**Python**

```python
import os
import requests

response = requests.get(
    "https://api.slicer.media/v1/projects/42/versions",
    headers={"Authorization": f"Bearer {os.environ['SLICER_TOKEN']}"},
)
body = response.json()
```

#### Ответ

Пример ответа:

```json
{
  "ok": true,
  "data": [
    {
      "id": 42,
      "version": 1,
      "idea": "string",
      "durationSec": 42.5,
      "current": true,
      "awaitingChoice": true,
      "hasFile": true,
      "createdAt": "2026-10-16T09:30:00Z"
    }
  ]
}
```

### Выбрать версию

`POST /v1/projects/{id}/versions/{versionId}/choose`

- **Области доступа:** `projects:write`
- **Лимит:** обычный

Делает версию текущей: ждущую выбора (`versionChoice`) или любую версию из истории, файл которой хранится (`hasFile`), — как «Сделать текущей» в приложении. Прежний ролик остаётся в истории.

#### Параметры пути

| Поле | Тип | Описание |
| --- | --- | --- |
| `id` _(обязательное)_ | `integer` | — ≥ 1 |
| `versionId` _(обязательное)_ | `integer` | — ≥ 1 |

#### Запрос

**curl**

```bash
curl -X POST "https://api.slicer.media/v1/projects/42/versions/42/choose" \
  -H "Authorization: Bearer $SLICER_TOKEN"
```

**JavaScript**

```js
const response = await fetch('https://api.slicer.media/v1/projects/42/versions/42/choose', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.SLICER_TOKEN}`,
  },
});
const { ok, data, error } = await response.json();
```

**Python**

```python
import os
import requests

response = requests.post(
    "https://api.slicer.media/v1/projects/42/versions/42/choose",
    headers={"Authorization": f"Bearer {os.environ['SLICER_TOKEN']}"},
)
body = response.json()
```

#### Ответ

**Поля ответа: `ProjectDetails` (44)**

| Поле | Тип | Описание |
| --- | --- | --- |
| `id` _(обязательное)_ | `integer` |     |
| `title` _(обязательное)_ | `string` |     |
| `status` _(обязательное)_ | `string` | `draft` — проект «Сам в редакторе» до первого экспорта: правьте операциями и экспортируйте — `queued` · `processing` · `succeeded` · `failed` · `cancelled` · `draft` |
| `mode` _(обязательное)_ | `string` | `ai` — монтаж ИИ-режиссёром; `manual` — материалы на таймлайне как есть, бесплатно (платны только ИИ-операции) — `ai` · `manual` |
| `stage` _(обязательное)_ | `string \| null` |     |
| `progress` _(обязательное)_ | `integer` | Прогресс текущего запуска, % |
| `client` _(обязательное)_ | `string \| null` | Где создан: web, mobile, api, mcp |
| `settings` _(обязательное)_ | `object` | Настройки монтажа (см. MontageSettingsInput) |
| `brief` _(обязательное)_ | `string \| null` |     |
| `isFree` _(обязательное)_ | `boolean` |     |
| `watermark` _(обязательное)_ | `boolean` |     |
| `tokensCost` _(обязательное)_ | `integer` |     |
| `error` _(обязательное)_ | `object \| null` |     |
| `error.code` _(обязательное)_ | `string` |     |
| `error.message` _(обязательное)_ | `string` |     |
| `durationSec` _(обязательное)_ | `number \| null` |     |
| `versionChoice` _(обязательное)_ | `integer[] \| null` | Id версий, ждущих выбора; монтаж отдаёт одну версию, поэтому обычно `null` |
| `result` _(обязательное)_ | `object \| null` |     |
| `result.url` _(обязательное)_ | `string (uri)` | Скачать с токеном (поддерживается Range) |
| `result.posterUrl` _(обязательное)_ | `string (uri) \| null` |     |
| `result.container` _(обязательное)_ | `string` |     |
| `result.info` _(обязательное)_ | `object \| null` |     |
| `appUrl` _(обязательное)_ | `string (uri)` | Проект в веб-приложении Slicer |
| `sourcesAvailable` _(обязательное)_ | `boolean` | Исходники хранятся 7 дней после монтажа |
| `createdAt` _(обязательное)_ | `string` | Дата и время ISO 8601, UTC |
| `finishedAt` _(обязательное)_ | `string \| null` |     |
| `stages` _(обязательное)_ | `object[]` |     |
| `stages[].stage` _(обязательное)_ | `string` |     |
| `stages[].status` _(обязательное)_ | `string` | — `pending` · `running` · `succeeded` · `failed` · `skipped` |
| `stages[].inRun` _(обязательное)_ | `boolean` | Часть текущего запуска (не взят готовым) |
| `stages[].startedAt` _(обязательное)_ | `string \| null` |     |
| `stages[].finishedAt` _(обязательное)_ | `string \| null` |     |
| `stages[].durationSec` _(обязательное)_ | `number \| null` |     |
| `stages[].progress` _(обязательное)_ | `integer` |     |
| `stages[].tokens` _(обязательное)_ | `integer` | Доля цены запуска |
| `run` _(обязательное)_ | `object` |     |
| `run.kind` _(обязательное)_ | `string` |     |
| `run.status` _(обязательное)_ | `string` |     |
| `run.tokens` _(обязательное)_ | `integer` |     |
| `run.tokensState` _(обязательное)_ | `string` | — `free` · `reserved` · `charged` · `refunded` |
| `run.queuedAt` _(обязательное)_ | `string` | Дата и время ISO 8601, UTC |
| `run.startedAt` _(обязательное)_ | `string \| null` |     |
| `run.finishedAt` _(обязательное)_ | `string \| null` |     |
| `versions` _(обязательное)_ | `ProjectVersion[]` |     |

Пример ответа:

```json
{
  "ok": true,
  "data": {
    "id": 42,
    "title": "Монтаж за 3 минуты",
    "status": "queued",
    "mode": "ai",
    "stage": "string",
    "progress": 0.5,
    "client": "string",
    "settings": {},
    "brief": "Динамично, с акцентом на главные мысли",
    "isFree": true,
    "watermark": true,
    "tokensCost": 24,
    "error": {
      "code": "string",
      "message": "string"
    },
    "durationSec": 42.5,
    "versionChoice": [
      1
    ],
    "result": {
      "url": "https://example.com/hook",
      "posterUrl": "https://api.slicer.media/v1/…",
      "container": "string",
      "info": {}
    },
    "appUrl": "https://api.slicer.media/v1/…",
    "sourcesAvailable": true,
    "createdAt": "2026-10-16T09:30:00Z",
    "finishedAt": "2026-10-16T09:30:00Z",
    "stages": [
      {
        "stage": "string",
        "status": "pending",
        "inRun": true,
        "startedAt": "2026-10-16T09:30:00Z",
        "finishedAt": "2026-10-16T09:30:00Z",
        "durationSec": 42.5,
        "progress": 0.5,
        "tokens": 24
      }
    ],
    "run": {
      "kind": "string",
      "status": "string",
      "tokens": 24,
      "tokensState": "free",
      "queuedAt": "2026-10-16T09:30:00Z",
      "startedAt": "2026-10-16T09:30:00Z",
      "finishedAt": "2026-10-16T09:30:00Z"
    },
    "versions": [
      {
        "id": 42,
        "version": null,
        "idea": "string",
        "durationSec": 42.5,
        "current": true,
        "awaitingChoice": true,
        "hasFile": true,
        "createdAt": "2026-10-16T09:30:00Z"
      }
    ]
  }
}
```

### История проекта

`GET /v1/projects/{id}/history`

- **Области доступа:** `projects:read`
- **Лимит:** обычный

#### Параметры пути

| Поле | Тип | Описание |
| --- | --- | --- |
| `id` _(обязательное)_ | `integer` | — ≥ 1 |

#### Запрос

**curl**

```bash
curl "https://api.slicer.media/v1/projects/42/history" \
  -H "Authorization: Bearer $SLICER_TOKEN"
```

**JavaScript**

```js
const response = await fetch('https://api.slicer.media/v1/projects/42/history', {
  headers: {
    Authorization: `Bearer ${process.env.SLICER_TOKEN}`,
  },
});
const { ok, data, error } = await response.json();
```

**Python**

```python
import os
import requests

response = requests.get(
    "https://api.slicer.media/v1/projects/42/history",
    headers={"Authorization": f"Bearer {os.environ['SLICER_TOKEN']}"},
)
body = response.json()
```

#### Ответ

Пример ответа:

```json
{
  "ok": true,
  "data": [
    {
      "id": 42,
      "kind": "string",
      "status": "string",
      "title": "Монтаж за 3 минуты",
      "version": 1,
      "createdAt": "2026-10-16T09:30:00Z"
    }
  ]
}
```

## Файлы

### Скачать ролик

`GET /v1/projects/{id}/result`

- **Области доступа:** `projects:read`
- **Лимит:** обычный

Поддерживаются Range-запросы. `?version={versionId}` — файл версии.

#### Параметры пути

| Поле | Тип | Описание |
| --- | --- | --- |
| `id` _(обязательное)_ | `integer` | — ≥ 1 |

#### Параметры запроса

| Поле | Тип | Описание |
| --- | --- | --- |
| `version` | `integer` | — ≥ 1 |

#### Запрос

**curl**

```bash
curl "https://api.slicer.media/v1/projects/42/result" \
  -H "Authorization: Bearer $SLICER_TOKEN" \
  -o video.mp4
```

**JavaScript**

```js
import { writeFile } from 'node:fs/promises';

const response = await fetch('https://api.slicer.media/v1/projects/42/result', {
  headers: {
    Authorization: `Bearer ${process.env.SLICER_TOKEN}`,
  },
});
await writeFile('video.mp4', Buffer.from(await response.arrayBuffer()));
```

**Python**

```python
import os
import requests

response = requests.get(
    "https://api.slicer.media/v1/projects/42/result",
    headers={"Authorization": f"Bearer {os.environ['SLICER_TOKEN']}"},
    stream=True,
)
with open("video.mp4", "wb") as out:
    for chunk in response.iter_content(chunk_size=1 << 20):
        out.write(chunk)
```

#### Ответ

Файл (`application/octet-stream`), поддерживаются Range-запросы.

### Скачать обложку (JPEG)

`GET /v1/projects/{id}/poster`

- **Области доступа:** `projects:read`
- **Лимит:** обычный

#### Параметры пути

| Поле | Тип | Описание |
| --- | --- | --- |
| `id` _(обязательное)_ | `integer` | — ≥ 1 |

#### Запрос

**curl**

```bash
curl "https://api.slicer.media/v1/projects/42/poster" \
  -H "Authorization: Bearer $SLICER_TOKEN" \
  -o poster.jpg
```

**JavaScript**

```js
import { writeFile } from 'node:fs/promises';

const response = await fetch('https://api.slicer.media/v1/projects/42/poster', {
  headers: {
    Authorization: `Bearer ${process.env.SLICER_TOKEN}`,
  },
});
await writeFile('poster.jpg', Buffer.from(await response.arrayBuffer()));
```

**Python**

```python
import os
import requests

response = requests.get(
    "https://api.slicer.media/v1/projects/42/poster",
    headers={"Authorization": f"Bearer {os.environ['SLICER_TOKEN']}"},
    stream=True,
)
with open("poster.jpg", "wb") as out:
    for chunk in response.iter_content(chunk_size=1 << 20):
        out.write(chunk)
```

#### Ответ

Файл (`application/octet-stream`), поддерживаются Range-запросы.

## Схемы

`Project`

| Поле | Тип | Описание |
| --- | --- | --- |
| `id` _(обязательное)_ | `integer` |     |
| `title` _(обязательное)_ | `string` |     |
| `status` _(обязательное)_ | `string` | `draft` — проект «Сам в редакторе» до первого экспорта: правьте операциями и экспортируйте — `queued` · `processing` · `succeeded` · `failed` · `cancelled` · `draft` |
| `mode` _(обязательное)_ | `string` | `ai` — монтаж ИИ-режиссёром; `manual` — материалы на таймлайне как есть, бесплатно (платны только ИИ-операции) — `ai` · `manual` |
| `stage` _(обязательное)_ | `string \| null` |     |
| `progress` _(обязательное)_ | `integer` | Прогресс текущего запуска, % |
| `client` _(обязательное)_ | `string \| null` | Где создан: web, mobile, api, mcp |
| `settings` _(обязательное)_ | `object` | Настройки монтажа (см. MontageSettingsInput) |
| `brief` _(обязательное)_ | `string \| null` |     |
| `isFree` _(обязательное)_ | `boolean` |     |
| `watermark` _(обязательное)_ | `boolean` |     |
| `tokensCost` _(обязательное)_ | `integer` |     |
| `error` _(обязательное)_ | `object \| null` |     |
| `error.code` _(обязательное)_ | `string` |     |
| `error.message` _(обязательное)_ | `string` |     |
| `durationSec` _(обязательное)_ | `number \| null` |     |
| `versionChoice` _(обязательное)_ | `integer[] \| null` | Id версий, ждущих выбора; монтаж отдаёт одну версию, поэтому обычно `null` |
| `result` _(обязательное)_ | `object \| null` |     |
| `result.url` _(обязательное)_ | `string (uri)` | Скачать с токеном (поддерживается Range) |
| `result.posterUrl` _(обязательное)_ | `string (uri) \| null` |     |
| `result.container` _(обязательное)_ | `string` |     |
| `result.info` _(обязательное)_ | `object \| null` |     |
| `appUrl` _(обязательное)_ | `string (uri)` | Проект в веб-приложении Slicer |
| `sourcesAvailable` _(обязательное)_ | `boolean` | Исходники хранятся 7 дней после монтажа |
| `createdAt` _(обязательное)_ | `string` | Дата и время ISO 8601, UTC |
| `finishedAt` _(обязательное)_ | `string \| null` |     |

`ProjectDetails`

| Поле | Тип | Описание |
| --- | --- | --- |
| `id` _(обязательное)_ | `integer` |     |
| `title` _(обязательное)_ | `string` |     |
| `status` _(обязательное)_ | `string` | `draft` — проект «Сам в редакторе» до первого экспорта: правьте операциями и экспортируйте — `queued` · `processing` · `succeeded` · `failed` · `cancelled` · `draft` |
| `mode` _(обязательное)_ | `string` | `ai` — монтаж ИИ-режиссёром; `manual` — материалы на таймлайне как есть, бесплатно (платны только ИИ-операции) — `ai` · `manual` |
| `stage` _(обязательное)_ | `string \| null` |     |
| `progress` _(обязательное)_ | `integer` | Прогресс текущего запуска, % |
| `client` _(обязательное)_ | `string \| null` | Где создан: web, mobile, api, mcp |
| `settings` _(обязательное)_ | `object` | Настройки монтажа (см. MontageSettingsInput) |
| `brief` _(обязательное)_ | `string \| null` |     |
| `isFree` _(обязательное)_ | `boolean` |     |
| `watermark` _(обязательное)_ | `boolean` |     |
| `tokensCost` _(обязательное)_ | `integer` |     |
| `error` _(обязательное)_ | `object \| null` |     |
| `error.code` _(обязательное)_ | `string` |     |
| `error.message` _(обязательное)_ | `string` |     |
| `durationSec` _(обязательное)_ | `number \| null` |     |
| `versionChoice` _(обязательное)_ | `integer[] \| null` | Id версий, ждущих выбора; монтаж отдаёт одну версию, поэтому обычно `null` |
| `result` _(обязательное)_ | `object \| null` |     |
| `result.url` _(обязательное)_ | `string (uri)` | Скачать с токеном (поддерживается Range) |
| `result.posterUrl` _(обязательное)_ | `string (uri) \| null` |     |
| `result.container` _(обязательное)_ | `string` |     |
| `result.info` _(обязательное)_ | `object \| null` |     |
| `appUrl` _(обязательное)_ | `string (uri)` | Проект в веб-приложении Slicer |
| `sourcesAvailable` _(обязательное)_ | `boolean` | Исходники хранятся 7 дней после монтажа |
| `createdAt` _(обязательное)_ | `string` | Дата и время ISO 8601, UTC |
| `finishedAt` _(обязательное)_ | `string \| null` |     |
| `stages` _(обязательное)_ | `object[]` |     |
| `stages[].stage` _(обязательное)_ | `string` |     |
| `stages[].status` _(обязательное)_ | `string` | — `pending` · `running` · `succeeded` · `failed` · `skipped` |
| `stages[].inRun` _(обязательное)_ | `boolean` | Часть текущего запуска (не взят готовым) |
| `stages[].startedAt` _(обязательное)_ | `string \| null` |     |
| `stages[].finishedAt` _(обязательное)_ | `string \| null` |     |
| `stages[].durationSec` _(обязательное)_ | `number \| null` |     |
| `stages[].progress` _(обязательное)_ | `integer` |     |
| `stages[].tokens` _(обязательное)_ | `integer` | Доля цены запуска |
| `run` _(обязательное)_ | `object` |     |
| `run.kind` _(обязательное)_ | `string` |     |
| `run.status` _(обязательное)_ | `string` |     |
| `run.tokens` _(обязательное)_ | `integer` |     |
| `run.tokensState` _(обязательное)_ | `string` | — `free` · `reserved` · `charged` · `refunded` |
| `run.queuedAt` _(обязательное)_ | `string` | Дата и время ISO 8601, UTC |
| `run.startedAt` _(обязательное)_ | `string \| null` |     |
| `run.finishedAt` _(обязательное)_ | `string \| null` |     |
| `versions` _(обязательное)_ | `ProjectVersion[]` |     |

`ProjectVersion`

| Поле | Тип | Описание |
| --- | --- | --- |
| `id` _(обязательное)_ | `integer` | Id версии (записи истории) |
| `version` _(обязательное)_ | `integer \| null` |     |
| `idea` _(обязательное)_ | `string \| null` | Чем версия отличается |
| `durationSec` _(обязательное)_ | `number \| null` |     |
| `current` _(обязательное)_ | `boolean` |     |
| `awaitingChoice` _(обязательное)_ | `boolean` | Предложена на выбор после последнего монтажа |
| `hasFile` _(обязательное)_ | `boolean` | Файл хранится (последние 10 версий) |
| `createdAt` _(обязательное)_ | `string` | Дата и время ISO 8601, UTC |

`CreateProjectRequest`

| Поле | Тип | Описание |
| --- | --- | --- |
| `uploadIds` _(обязательное)_ | `string (uuid)[]` | Готовые загрузки `source` в порядке материалов — 1–20 |
| `mode` | `string` | `ai` (по умолчанию) — монтаж ИИ-режиссёром, платно; `manual` — материалы ложатся на таймлайн по порядку, проект — бесплатный черновик `draft`, его правят и экспортируют сами — `ai` · `manual` |
| `format` | `string` | Формат кадра проекта `manual` (по умолчанию 9:16) — `9:16` · `4:5` · `1:1` · `16:9` |
| `settings` | `MontageSettingsInput` |     |
| `title` | `string` | — ≤ 120 |
| `brief` | `string` | Пожелания режиссёру — ≤ 600 |
| `confirmCost` | `integer` | Цена, на которую вы согласны. Без неё ответ — `Quote`, ничего не запускается |

`HistoryEvent`

| Поле | Тип | Описание |
| --- | --- | --- |
| `id` _(обязательное)_ | `integer` |     |
| `kind` _(обязательное)_ | `string` |     |
| `status` _(обязательное)_ | `string` |     |
| `title` _(обязательное)_ | `string \| null` |     |
| `version` _(обязательное)_ | `integer \| null` |     |
| `createdAt` _(обязательное)_ | `string` | Дата и время ISO 8601, UTC |
