KovAPIKovAPI
POST https://kovapi.com/v1/videos/generations

Seedance 2.0 (ByteDance) — API генерации видео с посекундной оплатой. Работа через асинхронные задачи: после отправки сразу приходит id задачи, а MP4 вы получаете опросом или через вебхук. 5–15 секунд, 480P / 720P / 1080P, 5 пропорций кадра; референсные изображения, видео и аудио можно передать в одном запросе, и каждый ролик выходит со звуком. При ошибке ничего не списывается.

Попробовать в песочнице →

Быстрый старт

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

Шаг 1 · Отправка (сразу возвращает id задачи, HTTP 202)

curl
curl https://kovapi.com/v1/videos/generations \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "seedance-2.0", "prompt": "Дождливой ночью бумажный кораблик плывёт по воде вдоль неоновой улицы, камера низко следует за ним, чёткие брызги и отражения", "duration": 5, "resolution": "720P", "size": "16:9"}'

Ответ (HTTP 202)

JSON
{
  "id": "img_5c2e8f1a9b3d7e6f0a4c8b2d",
  "object": "video.generation.job",
  "status": "queued",
  "created": 1791281400,
  "model": "seedance-2.0"
}

Шаг 2 · Опрашивайте каждые 5–10 секунд, пока status не станет succeeded или failed

curl
curl https://kovapi.com/v1/videos/jobs/img_5c2e8f1a9b3d7e6f0a4c8b2d \
  -H "Authorization: Bearer YOUR_API_KEY"

Ответ при успехе

JSON
{
  "id": "img_5c2e8f1a9b3d7e6f0a4c8b2d",
  "object": "video.generation.job",
  "status": "succeeded",
  "created": 1791281400,
  "model": "seedance-2.0",
  "data": [
    {"url": "https://img.kovapi.com/i/8c1f0e5d2b7a49e3a6d0c4f1b9e2a7d5.mp4"}
  ],
  "usage": {"clips": 1, "model": "seedance-2.0"}
}

Шаг 3 · data[0].url — это ролик (MP4). Он хранится 15 дней; чтобы пользоваться им дольше, скачайте его в своё хранилище.

Полный пример (Python: отправить, дождаться, сохранить на диск)

Python
import time
import requests

BASE = "https://kovapi.com/v1"
HEADERS = {"Authorization": "Bearer YOUR_API_KEY"}

# 1. отправка
job = requests.post(f"{BASE}/videos/generations", headers=HEADERS, json={
    "model": "seedance-2.0",
    "prompt": "Дождливой ночью бумажный кораблик плывёт по воде вдоль неоновой улицы, камера низко следует за ним, чёткие брызги и отражения",
    "duration": 5,
    "resolution": "720P",
    "size": "16:9",
}).json()
if "error" in job:
    raise SystemExit(job["error"]["message"])

# 2. опрос каждые 10 секунд, не дольше часа
deadline = time.time() + 3600
while job["status"] not in ("succeeded", "failed") and time.time() < deadline:
    time.sleep(10)
    job = requests.get(f"{BASE}/videos/jobs/{job['id']}", headers=HEADERS).json()

# 3. скачивание видео
if job["status"] == "succeeded":
    url = job["data"][0]["url"]
    with open("seedance-2.0.mp4", "wb") as f:
        f.write(requests.get(url).content)
    print("saved", url)
elif job["status"] == "failed":
    print("failed:", job["error"]["code"], job["error"]["message"])
else:
    print("still", job["status"], job["id"])

Пока задача в очереди, опрос также возвращает queue_position (сколько задач впереди вашей) и eta_seconds (ожидаемое время ожидания). Если ваш лимит ожидания истёк, не отправляйте задачу заново: она никуда не делась, продолжайте опрашивать тот же id позже.

Аутентификация

Header
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json

Чтобы начать, создайте API-ключ в консоли.

Основные характеристики

Длительность5–15 с
Разрешение480P / 720P / 1080P
Пропорции16:9 / 9:16 / 1:1 / 4:3 / 3:4
Референсные изображениядо 9 · используются как референсы (персонажи, сцена, стиль), но не как кадр
Референсные видеодо 3, суммарно до 15 с
Референсное аудиодо 3, каждый не длиннее 15 с
Звуквсегда включён (диалоги, эффекты и музыку создаёт модель); отключить нельзя
Длина промптадо 5 000 байт (UTF-8; около 1 666 иероглифов)
Оплатапосекундно: цена за секунду × (секунды ролика + секунды референсных видео)

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

JSON-тело запроса POST /v1/videos/generations:

ПараметрТипОбязательныйОписание
modelstringДаID модели: seedance-2.0.
promptstringДаОписание того, что происходит в ролике: картинка, работа камеры и движение. До 5 000 байт (UTF-8; один иероглиф занимает 3 байта, то есть это около 1 666 иероглифов).
durationintegerНетДлительность в секундах: целое число от 5 до 15; по умолчанию 5. Можно также передавать как seconds.
resolutionstringНетРазрешение: 480P / 720P / 1080P; по умолчанию 720P. Указывайте вместе с буквой P (720 без неё отклоняется).
sizestringНетПропорция: 16:9 / 9:16 / 1:1 / 4:3 / 3:4; по умолчанию 16:9. Можно также передавать как aspect_ratio.
imagesarrayНетРеференсные изображения, не более 9. Они задают персонажей, сцену и стиль и никогда не используются как кадр. В промпте ссылайтесь на них как @Image1, @Image2 в порядке передачи. Одно изображение можно передать в image.
video_referencesarrayНетРеференсные видео, не более 3, суммарно до 15 с. Их можно передавать вместе с референсными изображениями (фото задают внешность, видео — движение и работу камеры); в промпте ссылайтесь на них как @Video1. Каждое видео — публичная ссылка или data:video/mp4;base64,... (mp4 / mov, не более 50 MB каждое и 100 MB на весь запрос). Ссылка должна вести прямо на файл: ссылки на веб-страницы (YouTube, Bilibili, TikTok, страницы облачных дисков) отклоняются при отправке с ошибкой 400.
audio_referencearrayНетРеференсные аудиофайлы, не более 3, каждый не длиннее 15 с (длительность считается точно: файл на 15,1 с отклоняется), — публичные ссылки http(s); передаются только вместе с референсным изображением или видео. В промпте ссылайтесь на них как @Audio1. Ссылка должна вести прямо на файл: ссылки на веб-страницы (YouTube, Bilibili, TikTok, страницы облачных дисков) отклоняются при отправке с ошибкой 400.
audiobooleanНетКаждый ролик выходит со звуком (диалоги, эффекты и музыка создаются по промпту); отключить его нельзя, false ни на что не влияет.
callback_urlstringНетКуда отправить результат, когда задача завершится; подробнее — в разделе о вебхуках ниже.
nintegerНетКаждая задача создаёт один ролик; передавать параметр не нужно. При значении больше 1 всё равно создаётся один ролик, но при отправке резервируется стоимость n роликов, а лишнее возвращается после завершения задачи.

Другие поля (seed, negative_prompt, fps, watermark и т. п.) дальше не передаются и не влияют на цену; результат всегда в MP4 и возвращается в виде url.

Цена

Оплата посекундно: стоимость = цена секунды для выбранного разрешения × (секунды ролика + секунды всех референсных видео). Референсные изображения и аудио бесплатны. Сумма резервируется при отправке и полностью возвращается при ошибке. 1 кредит = $0.005.

РазрешениеКредитов за секундуUSD за секундуРолик 5 с
480P Пока недоступно14$0.07$0.35
720P30$0.15$0.75
1080P60$0.30$1.50

Уровень 480P пока недоступен: при отправке вернётся ошибка 400; когда он откроется, таблица обновится автоматически.

Референсные материалы

  • Референсные изображения (не более 9) задают персонажей, сцену, продукт и стиль. Seedance никогда не использует изображение как кадр: чтобы люди или предметы с картинки появились в ролике, сошлитесь на неё в промпте (@Image1, @Image2 … в порядке передачи).
  • Референсные видео (не более 3, суммарно до 15 с) задают движение, работу камеры и темп; референсные аудиофайлы (не более 3, каждый не длиннее 15 с; файл на 15,1 с отклоняется) задают голос или музыку и передаются только вместе с изображением или видео. Все три вида материалов можно передать в одном запросе; ссылайтесь на них как @Image1 / @Video1 / @Audio1.
  • Реальные человеческие лица подходят в качестве референсных изображений, маскирование не требуется. Пожалуйста, убедитесь, что у вас есть право использовать внешность людей, изображённых на фото.
  • Каждое изображение — публичная ссылка на изображение, data: URI или base64, не более 16 MB; несколько изображений передавайте массивом в images. При отправке мы сначала сохраняем изображения у себя, и только потом задача встаёт в очередь; изображение, которое не удаётся прочитать, отклоняется с ошибкой 400, в message указано, какое именно, и ничего не списывается.
  • Референсные материалы мы размещаем у себя и храним 7 дней, готовые ролики — 15 дней.

Референсные изображения и референсное видео вместе

curl
curl https://kovapi.com/v1/videos/generations \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "seedance-2.0", "prompt": "Девушка из @Image1 на улице из @Image2 исполняет танец из @Video1", "images": ["https://example.com/character.png", "https://example.com/street.png"], "video_references": ["https://example.com/dance.mp4"], "duration": 5, "size": "16:9"}'

@Image1 — первое референсное изображение, @Video1 — первое референсное видео. Референсные видео не оплачиваются, оплачивается только длительность ролика.

Требования к контенту

Каждая задача Seedance проходит проверку контента: промпт, файлы-референсы и готовый ролик — и изображение, и звук. Задача, не прошедшая проверку, завершается с content_policy, деньги не списываются.

Когда идёт проверка

При отправке проверяются промпт и референсы; после генерации ролика ещё раз проверяются изображение и звук. Поэтому отказ может прийти через несколько секунд после отправки или только после окончания рендера (это может занять больше получаса). Задача, завершившаяся со status failed и error.code content_policy, не прошла проверку; с вебхуком придёт событие video.failed.

Без оплаты

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

Звук

Звук (реплики, закадровый текст, пение и эффекты) модель генерирует по промпту, и он проверяется вместе с изображением: реплики, закадровый текст и тексты песен из промпта озвучиваются или поются. Если в ролике не нужны голоса, не пишите в промпте реплики и тексты песен. Эта модель всегда добавляет звук, отключить его нельзя: audio: false ни на что не влияет. Загруженное аудио-референс тоже проверяется; музыка, защищённая авторским правом, в качестве референса может быть отклонена. Если не прошёл звук, error.param равен audio, а в message сказано, был ли это сгенерированный звук или ваше аудио-референс.

Что чаще всего отклоняется

  • Сексуальный контент, обнажённость или сексуальные намёки, в том числе изображения, созданные или смонтированные с помощью ИИ
  • Кровь, жестокость, самоповреждение и насильственные травмы, например огнестрельные ранения и кровотечение
  • Огнестрельное оружие, взрывчатка и наркотики
  • Любой сексуализированный контент с несовершеннолетними; несовершеннолетние рядом с алкоголем, табаком, наркотиками или в опасных ситуациях тоже отклоняются
  • Политики, знаменитости, спортсмены, бизнесмены и другие публичные лица — внешность или голос, включая двойников
  • Персонажи и объекты, защищённые авторским правом, например персонажи Disney или Marvel
  • Контент с ненавистью или дискриминацией, фейковые новости

Длинные сценарии

Одна сцена с нарушением отклоняет весь ролик, и чаще всего это случается в длинных раскадровочных сценариях: перестрелка или крупный план крови в экшен-сцене, несовершеннолетние, которые пьют или курят, — и весь ролик не пройдёт. Перед отправкой прочитайте сценарий целиком и удалите или перепишите такие сцены.

Реальные люди

Чтобы использовать фото реального человека как референс, нужно право на использование его изображения; принимает ли модель такие референсы, указано выше на этой странице.

После отказа

Повторная отправка того же самого снова будет отклонена. Найдите часть, которая скорее всего нарушает правила, перепишите промпт или замените референс и отправьте заново.

Код ошибки: content_policy · status: failed

Статус задачи и поля ответа

GET /v1/videos/jobs/{id} возвращает эти статусы; все поля описаны в разделе Асинхронные задачи. Опрашивайте каждые 5–10 секунд или получайте результат вебхуком (см. ниже). Опрос бесплатный, и прочитать задачу может любой ключ того же аккаунта.

СтатусЧто значит
queuedВ очереди. В ответе есть queue_position (сколько задач впереди) и eta_seconds (ожидаемое время ожидания).
processingГенерируется.
succeededГотово. Результат в data[0].url, детали оплаты в usage.
failedОшибка. Причина в error; зарезервированные кредиты возвращаются полностью.
  • processing может снова смениться на queued: например, при высокой нагрузке, пока готовый ролик скачивается повторно или после перезапуска сервиса. Если задачу не удалось выполнить, шлюз может автоматически запустить рендер заново; сколько бы ни было повторов, задача оплачивается один раз.
  • Один аккаунт выполняет до 50 задач одновременно; остальные ждут в порядке отправки, а задача, не начавшаяся за 15 минут, завершается ошибкой с полным возвратом. Записи о задачах хранятся 3 дня, ссылки на видео — 15 дней.

Сколько ждать

Обычно 3–8 минут; отдельные задачи — 15 минут и больше.

Реальные вызовы за последние 30 дн.: медиана 4.8 мин, 90% завершаются за 7.2 мин.

Ошибки и возвраты

Ошибка при отправке сразу возвращается как HTTP 4xx / 5xx: задача не создаётся, ничего не списывается. О неудаче после того, как задача принята, сообщает эндпоинт задачи, а резерв возвращается полностью. Все коды перечислены в разделе Коды ошибок.

Ошибки при отправке

HTTPcodeПричинаЧто делать
400invalid_requestНедопустимый параметр: длительность, разрешение, пропорция или число референсов выходят за пределы, допустимые для этой модели; промпт слишком длинный; не удаётся прочитать референсное изображение или видео; передан audio: false модели, ролики которой всегда со звуком, и т. п. Что именно не так, указано в message.Исправьте то, что указано в message, и отправьте снова.
400invalid_callback_urlcallback_url — не публичный адрес http(s) или длиннее 2000 символов.Укажите адрес, доступный из интернета.
400model_not_foundID модели написан с ошибкой, model не передан или модель нельзя использовать на этом эндпоинте (например, чат-модель на эндпоинте изображений).Берите ID модели из GET /v1/models или из справочника API.
401invalid_api_keyКлюч не существует, удалён или отключён, либо отключён аккаунт.Проверьте ключ на странице API Keys в консоли.
402insufficient_quotaБаланса не хватает, чтобы зарезервировать стоимость этого запроса. Шлюз сначала резервирует максимально возможную стоимость запроса, поэтому ошибка может возникнуть и при всплеске одновременных вызовов.Если был всплеск запросов, подождите несколько секунд и повторите; в остальных случаях пополните баланс.
429rate_limit_exceededПревышен лимит запросов в минуту, заданный для этого ключа (считается за последние 60 секунд). Заголовка Retry-After нет.Подождите несколько секунд и повторите или увеличьте лимит ключа в консоли.
503model_maintenanceМодель на обслуживании и не принимает запросы; пока идёт обслуживание, другая модель вместо неё не ответит.Повторите, когда обслуживание закончится; ход работ — на странице статуса.
503service_unavailableВременный сбой на нашей стороне, например при сохранении референсного файла. Задача не создана, ничего не списано.Повторите чуть позже.

Неудачные задачи (status — failed)

codeКогда возникаетЧто делать
content_policyВидео: промпт, референс или сгенерированный видеоряд либо звук не прошли проверку контента (если отклонён звук, param равен audio). Wan Standard и Prime: исходные материалы не прошли проверку. error.reason — FaceDetectionSuspect (предположительно лицо реального человека) или DataInspectionFailed (отклонён входной контент). В error.message указаны причина и рекомендуемые изменения. Неудачные задания не оплачиваются.Перепишите промпт или замените референс и только потом отправляйте снова: те же входные данные будут отклонены повторно.
render_failedВидео: на этот раз ролик не получился; обычно это разовый сбой.Повторная отправка того же запроса обычно проходит успешно.
invalid_materialВидео: поставщик обнаружил проблему во входных данных. Это общая ошибка, и часто она разовая.Сначала отправьте задачу ещё раз без изменений; если ошибка повторяется, проверьте референсы и длину промпта.
duration_rejectedВидео: длительность не принята. Чаще всего референсное аудио или видео длиннее допустимого, пусть даже на долю секунды.Обрежьте референсное аудио или видео до допустимой длины и отправьте снова: те же входные данные снова не пройдут.
reference_unreadableВидео: модели не удалось скачать референсное изображение, видео или аудио; чаще всего ссылка ведёт на веб-страницу (YouTube, страница облачного диска).Укажите ссылку, которая ведёт прямо на файл, или загрузите файл в Playground: те же входные данные снова не пройдут.
render_timeoutВидео: очередь или рендер заняли слишком много времени, и поставщик отказался от задачи.Отправьте задачу заново.
wait_timeoutВидео: за 120 минут результата не было, задача завершилась по таймауту, кредиты возвращены полностью; если ролик будет готов позже, он выдаётся бесплатно.Отправьте задачу заново.
upstream_unstableВидео: во время рендера оборвалось соединение.Отправьте задачу заново.
result_fetch_failedВидео создано, но на нашей стороне его так и не удалось скачать или сохранить, несмотря на повторные попытки.Отправьте задачу заново.
upstream_errorЛюбая другая ошибка: автоматические повторы не помогли, задача ждала 15 минут и так и не запустилась, поставщик отказал без объяснения причины и т. п.; что именно произошло, указано в message.Обычно повторная отправка проходит успешно.

Ориентируйтесь на code, а не на текст message. Любой незнакомый code (или его отсутствие) обрабатывайте как upstream_error: повторная отправка обычно проходит успешно. За каждую неудачную задачу деньги возвращаются полностью.

Вебхуки вместо опроса

Добавьте при отправке callback_url — как только задача завершится, успешно или с ошибкой, шлюз отправит на этот URL ровно то же, что возвращает эндпоинт опроса; запрос подписан, а при неудачной доставке повторяется. Общий адрес для всего аккаунта можно также задать в консоли, в разделе «Настройки → Вебхуки». Документация по вебхукам →

curl · callback_url
curl https://kovapi.com/v1/videos/generations \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "seedance-2.0", "prompt": "Дождливой ночью бумажный кораблик плывёт по воде вдоль неоновой улицы, камера низко следует за ним, чёткие брызги и отражения", "duration": 5, "resolution": "720P", "size": "16:9", "callback_url": "https://your-domain.com/webhook"}'