Генерация видео через API

Один POST-запрос тем же ключом, что и чат: описание сцены на вход, ссылка на mp4 на выход. Здесь собраны параметры, примеры на трёх языках и правила списания.

Эндпоинты и авторизация

Видео живёт на OpenAI-совместимом входе и работает тем же ключом, что и текстовые модели: меняется только путь. Anthropic-вход видео не генерирует.

МетодПутьНазначение
POSThttps://api.tokenator.top/v1/videosГенерация клипа по текстовому описанию. Тот же обработчик отвечает и на /v1/videos/generations — путь можно взять любой.
GET/v1/videos/{id}?model=…Статус асинхронной задачи апстрима, если вы получили её идентификатор.
GET/v1/videos/modelsКаталог видеомоделей, доступных этому ключу, вместе с их параметрами.

Ключ передаётся заголовком Authorization: Bearer sk-your-tokenator-key. Отдельного ключа для видео нет — генерации списываются с того же ключа, что и токены.

Первый запрос

Генерация клипа
curl https://api.tokenator.top/v1/videos \
  -H "Authorization: Bearer sk-your-tokenator-key" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "seedance-2.0-mini",
    "prompt": "неоновый город под дождём, медленный пролёт камеры",
    "duration": 6,
    "resolution": "720p",
    "aspect_ratio": "16:9"
  }'

Ответ приходит, когда клип готов, и выглядит как обычный ответ генерации: массив data со ссылками.

Ответ
{
  "created": 1755600000,
  "data": [
    { "url": "https://generated-video.tokenator.top/6f2c1a9b.mp4" }
  ]
}

В ответе ровно два поля: created — время в unix-секундах, и data — массив по числу заказанных клипов. У элемента либо url, либо b64_json — файл целиком в base64, если модель отдала видео инлайном. Ничего другого прокси в ответ не добавляет.

Ссылка ведёт на отдельный домен для файлов — generated-video.tokenator.top, прямо из корня хоста. Это не адрес API и не временная ссылка провайдера: файл скачан и перевыложен на нашей стороне, отдаётся с Cache-Control: immutable и живёт, пока лежит на диске сервиса.

Какие модели умеют видео

МодельAPI IDДлительностьРазрешениеЗвукКадр на входе
Seedance 2.0 Miniseedance-2.0-mini5, 10 секунд720pдада
Seedance 2.0seedance-2.04, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 секунд720pдада
HappyHorse 1.1happyhorse-1.13, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 секунд720p, 1080pдада
Omniomni10 секунд720pдада
H3hailuo-35, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 секунд768pдада
Seedance 2.0 Fastseedance-2.0-fast5, 10, 15 секунд720pдада
Seedance 2.5seedance-2.530 секунд720pдада
Grok Imagine Video 1.5grok-imagine-video-1.54, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 секунд480p, 720p, 1080pдада
Kling 3.0kling-3.03, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 секунд720p, 1080pданет
Kling 3.0 Prokling-3.0-pro4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 секунд720p, 1080pданет

Тот же список отдаёт API — вместе с длительностями, разрешениями, соотношениями сторон и значениями по умолчанию. Это надёжнее, чем зашивать параметры в код: список меняется вместе с каталогом.

Каталог видеомоделей
curl https://api.tokenator.top/v1/videos/models \
  -H "Authorization: Bearer sk-your-tokenator-key"
Ответ
{
  "object": "list",
  "data": [
    {
      "id": "seedance-2.0-mini",
      "object": "video_model",
      "durations": [4, 6, 8],
      "resolutions": ["480p", "720p", "1080p"],
      "aspect_ratios": ["16:9", "9:16", "1:1"],
      "audio": true,
      "image_input": true,
      "default_duration": 4,
      "default_resolution": "720p",
      "default_aspect_ratio": "16:9",
      "cost": {
        "480p|4": 1,
        "720p|4": 2,
        "720p|8": 4,
        "1080p|8": 8
      },
      "cost_default": 2
    }
  ]
}

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

ПолеТипЧто делает
modelstringAPI ID видеомодели из каталога. Если поле не задано, берётся первая включённая видеомодель — лучше указывать явно.
promptstring, обязательноеОписание сцены. Пустая строка отклоняется с кодом 400.
nintegerОдин запрос — один клип. Поле принимается для совместимости, но значение больше 1 обрезается до 1: чтобы получить несколько клипов, отправьте несколько запросов.
durationinteger, секундыДлительность клипа. Принимаются также seconds и duration_seconds — их провайдеры ждут строкой ("5"), и если вы пришлёте число, сервис перепишет его сам. Максимум — 60 секунд, а конкретный список значений задаёт модель.
resolutionstringНапример 720p. Синонимы приводятся к каноническому виду: sd → 480p, hd → 720p, 1k и fhd → 1080p.
aspect_ratiostringСоотношение сторон, например 16:9. Запись через x (16x9) тоже понимается.
sizestringРазмер кадра вида 1280x720. Если aspect_ratio не задан, соотношение сторон выводится из него.
generate_audiobooleanПросить модель нарисовать звук. Работает только у моделей, которые заявили звук.
seedintegerЗерно генерации — с одним и тем же значением результат воспроизводим настолько, насколько это позволяет модель.
frame_imagesмассивСтартовые кадры для оживления готового изображения.
first_image_urlстрокаСсылка на первый кадр — клип начинается с него. Годится любая публичная ссылка http(s) или data:, необязательно наша. Нужна модель, которая заявила первый кадр: в каталоге у неё стоит «Первый кадр: принимается», иначе 400 до списания генераций.
last_image_urlстрокаСсылка на последний кадр — клип приходит к нему. Те же правила, что и у первого кадра.
input_referencesмассивРеференсы стиля или персонажа. Вместе с frame_images — не больше четырёх изображений на запрос.
reference_image_urlsмассивСсылки на изображения-референсы, до пяти. Несколько ссылок — мультиреференс; в промпте на них можно ссылаться как @Image1, если модель это умеет. Нужна модель со входом изображением.
reference_videosмассивСсылки на видео-референсы, до трёх — движение или монтаж, за которым модель следует.
reference_audiosмассивСсылки на аудио-референсы, до трёх — голос или музыка, под которую модель попадает.

Незаполненные поля подставляются из значений модели по умолчанию, а значения вне заявленного списка отклоняются до обращения к провайдеру — неудачная попытка не тратит генерации. Поля callback_url, webhook_url и provider вырезаются из запроса и апстриму не уходят: обратные вызовы шли бы мимо вашего ключа.

Сколько ждать и что происходит внутри

Рендер видео занимает от десятков секунд до нескольких минут. Запрос синхронный: соединение держится, пока клип не готов, а чтобы промежуточные прокси не закрыли его по тишине, сервис досылает keep-alive прямо в тело ответа. Итоговый JSON приходит последним куском — обычный парсер прочитает его как есть.

Если провайдер отвечает асинхронной задачей, прокси сам опрашивает её статус и отдаёт готовый клип — писать свой цикл опроса не нужно. Общее ожидание ограничено 15 мин; по истечении приходит 504, списанные генерации возвращаются на ключ, а в ответе лежит job_id задачи у провайдера — рендер продолжается, и GET /v1/videos/{id}?model=… заберёт результат, когда он будет готов.

Практический вывод: поднимите таймаут HTTP-клиента до 15 мин и не ставьте ретрай по таймауту — повторный запрос запустит второй рендер.

Статус задачи, если идентификатор уже есть
curl "https://api.tokenator.top/v1/videos/vid_123?model=seedance-2.0-mini" \
  -H "Authorization: Bearer sk-your-tokenator-key"

Параметр model здесь обязателен по смыслу: по нему выбирается провайдер, у которого нужно спрашивать статус. Без него запрос уйдёт к первой включённой видеомодели.

Стартовый кадр и референсы

Модели, которые заявили вход изображением, умеют оживлять готовый кадр. Картинки передаются в frame_images, а референсы стиля или персонажа — в input_references; суммарно не больше четырёх на запрос. Часть моделей вместо этого принимает ссылки в reference_image_urls (до пяти), reference_videos и reference_audios (по три) — эти поля уходят на апстрим как есть, лимиты и тип ссылки проверяются на нашей стороне. Если модель вход изображением не заявляла, запрос отклоняется с 400 — до списания генераций.

Первый и последний кадр — отдельная пара полей: first_image_url и last_image_url, по одной ссылке в каждом. Клип начинается с первого кадра и приходит к последнему; можно передать только один из двух. Ссылка нужна публичная — http(s) или data:, — и она может вести куда угодно, файл необязательно загружать к нам. Модель должна заявить кадр: в каталоге у неё написано «Первый кадр: принимается», иначе 400. Разные провайдеры ждут разную форму записи — перекладывание на ту, которую понимает конкретный апстрим, делает прокси, вам достаточно этих двух полей.

Оживление кадра
{
  "model": "seedance-2.0-mini",
  "prompt": "камера медленно наезжает, ветер шевелит листву",
  "duration": 4,
  "frame_images": ["https://example.com/frame.jpg"]
}
Переход от первого кадра к последнему
{
  "model": "seedance-2.0-mini",
  "prompt": "плавный переход, камера не двигается",
  "duration": 5,
  "first_image_url": "https://example.com/first.jpg",
  "last_image_url": "https://example.com/last.jpg"
}

SDK и готовые примеры

Видео-эндпоинт не входит в типизированную часть OpenAI SDK, поэтому вызывать его удобнее «сырым» запросом. Ключ и базовый адрес при этом остаются теми же, что и для чата — отдельный клиент заводить не нужно.

Python — openai
from openai import OpenAI

client = OpenAI(
    api_key="sk-your-tokenator-key",
    base_url="https://api.tokenator.top/v1",
    timeout=900,
)

result = client.post(
    "/videos",
    body={
        "model": "seedance-2.0-mini",
        "prompt": "неоновый город под дождём",
        "duration": 6,
        "resolution": "720p",
    },
    cast_to=dict,
)

print(result["data"][0]["url"])
Python — requests
import requests

response = requests.post(
    "https://api.tokenator.top/v1/videos",
    headers={"Authorization": "Bearer sk-your-tokenator-key"},
    json={
        "model": "seedance-2.0-mini",
        "prompt": "неоновый город под дождём",
        "duration": 6,
        "resolution": "720p",
    },
    timeout=900,
)
response.raise_for_status()
print(response.json()["data"][0]["url"])
Node.js — fetch
const response = await fetch("https://api.tokenator.top/v1/videos", {
  method: "POST",
  headers: {
    Authorization: "Bearer sk-your-tokenator-key",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "seedance-2.0-mini",
    prompt: "неоновый город под дождём",
    duration: 6,
    resolution: "720p",
  }),
  signal: AbortSignal.timeout(900_000),
})

const result = await response.json()
console.log(result.data[0].url)

Готовые фрагменты под ваш ключ и адрес есть в дашборде ключа — там же, где сниппеты для чата.

Как списывается видео

Видео не тратит токены. У ключа есть отдельный счётчик генераций видео, и одна генерация — это один клип базового разрешения и базовой длительности. Более тяжёлые параметры стоят кратно дороже: множитель по разрешению задаёт оператор (например 480p — 1×, 720p — 2×, 1080p — 4×), а длительность масштабируется относительно базовой. Итоговое списание — число клипов × множитель модели × множитель разрешения × множитель длительности, округлённое вверх.

Считать цену руками не нужно: /v1/videos/models отдаёт по каждой модели поле cost — список объектов {"resolution", "seconds", "price"}, по одному на каждое сочетание параметров (и с aspect_ratio, если соотношение сторон меняет цену), плюс cost_default для параметров по умолчанию. Если разрешение задано через size, цена считается по короткой стороне: 1920x1080 — это 1080p.

Генерации резервируются до обращения к провайдеру и возвращаются, если клип не приехал: неудачный рендер ничего не стоит. Пакеты видео продаются отдельно от токенов; ключ с token_limit: -1 — это ключ только под генерацию, текстовые модели ему недоступны.

Остаток генераций
curl https://api.tokenator.top/v1/tokens \
  -H "Authorization: Bearer sk-your-tokenator-key"
Ответ
{
  "name": "my-key",
  "limit": 1000000,
  "used": 240000,
  "remaining": 760000,
  "image_limit": 0,
  "image_used": 0,
  "image_remaining": 0,
  "video_limit": 20,
  "video_used": 3,
  "video_remaining": 17
}

Ограничения

  • Один клип за запрос: n больше 1 обрезается до 1.
  • Длительность клипа — не больше 60 секунд, и не больше того, что заявила модель.
  • Не больше четырёх входных изображений на запрос (frame_images и input_references вместе).
  • Референсов — до пяти изображений (reference_image_urls), до трёх видео и до трёх аудио. Ссылки должны быть http(s) или data:; всё остальное отклоняется с 400 до списания генераций.
  • Часть моделей вообще не рисует по одному описанию: у них в каталоге стоит «Референс: обязателен», и запрос без reference_image_urls / reference_videos / frame_images отклоняется с 400 сразу, без обращения к провайдеру.
  • Одновременных генераций на ключ: 1. Пятый запрос не встаёт в очередь, а сразу получает 429 с полем busy_for_seconds.
  • Общее ожидание одного запроса ограничено 15 мин.

Ошибки

СимптомПричинаЧто сделать
400 prompt requiredВ теле нет описания сцены или тело вообще не JSON.Проверьте Content-Type: application/json и непустой prompt.
400 о длительности, разрешении или соотношении сторонЗначение не входит в список, который заявила модель.Сообщение об ошибке перечисляет допустимые значения; их же возвращает /v1/videos/models.
400 does not generate videoУказана обычная текстовая или картиночная модель.Возьмите ID видеомодели из каталога.
429 с полем video_gen_limitГенерации видео на ключе закончились.Пополните видео-пакет в личном кабинете; остаток виден в /v1/tokens.
429 с полем video_concurrent_limitНа ключе уже идёт генерация: параллельные рендеры ограничены.Поле busy_for_seconds показывает, сколько идёт текущая генерация. Ставьте запросы в очередь, а не в параллель.
504Модель не закончила рендер за отведённое время.Попробуйте более короткий клип или меньшее разрешение. Списанные генерации возвращаются.
502 Request errorОшибка на стороне провайдера. Её текст клиенту не пересылается.Повторите запрос — Tokenator сам переключается на следующего провайдера модели. Если ошибка стабильна, напишите в поддержку.

Попробовать без кода

В дашборде ключа есть «Студия» с переключателем «Картинки / Видео»: длительность, разрешение и соотношение сторон выбираются кнопками, готовые клипы складываются в галерею. Это тот же эндпоинт и тот же счётчик генераций — удобно, чтобы проверить модель до того, как писать интеграцию.

Частые вопросы

Нужен ли отдельный ключ для генерации видео?

Нет. Работает тот же ключ, что и для чата: меняется только путь запроса. Отдельно покупается лишь пакет генераций.

Можно ли сгенерировать видео через Anthropic-формат?

Нет. Видео есть только на OpenAI-совместимом входе — /v1/videos. Для чата оба формата по-прежнему взаимозаменяемы.

Как узнать, какие длительности и разрешения поддерживает модель?

Запросом /v1/videos/models: он возвращает списки durations, resolutions, aspect_ratios и значения по умолчанию. То же самое написано на странице модели в каталоге.

Списываются ли генерации, если рендер не удался?

Нет. Генерации резервируются до запроса и возвращаются на ключ, если клип не приехал — ошибка провайдера или таймаут ничего не стоят.

Сколько живёт ссылка на готовое видео?

Файл перевыкладывается на стороне сервиса и отдаётся с нашего адреса, а не по временной ссылке провайдера. Скачайте его сразу, если клип нужен надолго.

Можно ли запускать несколько генераций параллельно?

На один ключ — 1 одновременно; остальные запросы получают 429. Один запрос отдаёт один клип, поэтому несколько клипов — это несколько запросов, по очереди.