Официальная документация Seedance 2.0 для международного маршрута опубликована BytePlus на английском, тогда как многие русскоязычные примеры в сети описывают сторонний gateway или ещё относятся к Seedance 1.x. Поэтому копировать только «похожий» ID модели недостаточно. Рабочий вызов состоит из четырёх совместимых частей: адрес API, область действия ключа, пространство имён модели и пути create/status. Все они должны принадлежать одному владельцу контракта.
После create API возвращает ID асинхронной задачи, а не готовое видео. Сохраните этот ID в локальном журнале; callback используйте для быстрой доставки событий, а polling — для восстановления пропущенных уведомлений. Это два канала обновления одной записи, а не две независимые генерации.
1. Сначала отличите текущий контракт от старого примера
Перед копированием кода проверьте пять признаков:
- Кто владеет ключом: BytePlus, Volcengine или конкретный gateway.
- Какой полный адрес указан рядом с примером.
- К какому пространству относится ID модели:
dreamina-*илиdoubao-*. - Возвращает ли create ID задачи и каким путём эта задача читается.
- Когда обновлялись первичный документ и список моделей.
Для международного прямого доступа владельцами текущих значений служат BytePlus create API, руководство по серии Seedance 2.0 и страница управления API-ключами. Китайский контракт проверяется по Volcengine Ark API, а relay — только по документации laozhang.ai.
Русский текст, удобный интерфейс или пример с названием Seedance сами по себе не делают страницу владельцем upstream-контракта. Если в примере фигурирует 1.x, собственный путь вроде /v1/media/create или произвольный alias модели, используйте его только с ключом того же поставщика. Не переносите такие значения в BytePlus или Volcengine.
2. Зафиксируйте один маршрутный контракт
| Маршрут | Адрес и область ключа | Текущие ID моделей | Создание и чтение задачи |
|---|---|---|---|
| BytePlus ModelArk, международный AP | https://ark.ap-southeast.bytepluses.com/api/v3; Bearer-ключ из resource project ModelArk | Standard dreamina-seedance-2-0-260128; Fast dreamina-seedance-2-0-fast-260128; Mini dreamina-seedance-2-0-mini-260615 | POST /contents/generations/tasks; GET /contents/generations/tasks/{id} |
| Volcengine Ark, Китай | https://ark.cn-beijing.volces.com/api/v3; Bearer-ключ проекта Ark в китайском регионе | Standard doubao-seedance-2-0-260128; Fast doubao-seedance-2-0-fast-260128 | те же относительные пути create/status на китайском адресе |
| laozhang.ai relay | https://api.laozhang.ai/seedance/api/v3; токен, назначенный группе SeeDance2 | doubao-seedance-2-0-260128 или doubao-seedance-2-0-fast-260128 | Ark-образные create/status; совместимое скачивание: GET https://api.laozhang.ai/v1/videos/{id}/content |
В BytePlus ключ создаётся внутри resource project. Его можно ограничить моделью или custom endpoint и списком разрешённых IP. Секрет хранится только на сервере: не помещайте его в браузерный JavaScript, мобильное приложение, URL или публичный репозиторий. Наличие ID в документации не доказывает, что модель активна для вашей учётной записи и региона; перед вызовом проверьте активацию и доступный пакет ресурсов.
Standard предназначен для приоритета качества, Fast — для баланса скорости и стоимости, Mini — для сценария с упором на экономичность. Это описание выбора внутри BytePlus, а не универсальные псевдонимы. Для китайского Mini нельзя выводить суффикс по аналогии: берите его только из текущего списка моделей своей учётной записи. Цена обновляется отдельно от API-контракта и разбирается в гайде по стоимости Seedance 2.
3. Отправьте минимальный вызов и ведите единый журнал
Ниже приведён вызов только для международного BytePlus AP. Если выбран другой маршрут, одновременно меняются адрес, ключ, ID модели и пути.
bashexport ARK_API_KEY="replace-with-server-side-secret" curl -X POST \ "https://ark.ap-southeast.bytepluses.com/api/v3/contents/generations/tasks" \ -H "Authorization: Bearer $ARK_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "dreamina-seedance-2-0-260128", "content": [{ "type": "text", "text": "Product on a clean studio table, one slow camera arc, neutral daylight" }], "ratio": "16:9", "duration": 5, "generate_audio": false, "priority": 3, "callback_url": "https://example.com/webhooks/seedance" }'
Для endpoint-based online inference Seedance 2.0 поле priority принимает целые числа от 0 до 9. Большее значение продвигает ожидающую задачу только внутри того же endpoint. Оно не прерывает уже выполняемую задачу, не сравнивает разные endpoints, не относится к offline flex inference и не гарантирует более быструю генерацию.
Create response означает только приём задачи. До отправки создайте локальную запись, а после ответа атомарно добавьте providerTaskId:
tstype LocalSeedanceJob = { localJobId: string; route: "byteplus-ap" | "volcengine-cn" | "laozhang-relay"; requestHash: string; providerTaskId?: string; state: "submitting" | "queued" | "running" | "succeeded" | "failed" | "expired"; lastEventId?: string; storedResult?: string; };
В requestHash включите маршрут, ID модели, нормализованный prompt, идентификаторы входных материалов и параметры результата. Это ваша защита от двойного create, а не гарантия дедупликации со стороны поставщика.
Текущий контракт BytePlus разрешает необязательный callback_url. Payload имеет форму retrieve-task response; состояния — queued, running, succeeded, failed, expired. Для неудачной доставки terminal-события succeeded или failed документация указывает три повторные попытки, если за пять секунд не получено успешное подтверждение. Публичный документ не даёт основания обещать определённую webhook signature.
tsconst order = { queued: 0, running: 1, succeeded: 2, failed: 2, expired: 2 } as const; const terminal = new Set(["succeeded", "failed", "expired"]); async function acceptSeedanceEvent(event: { id: string; status: keyof typeof order; }) { const job = await jobs.findByProviderTaskId(event.id); if (!job) return { status: 404 }; const eventId = `${event.id}:${event.status}`; if (job.lastEventId === eventId) return { status: 204 }; const currentOrder = job.state === "submitting" ? -1 : order[job.state]; if (terminal.has(job.state) || order[event.status] < currentOrder) { await events.recordIgnored(job.localJobId, event); return { status: 204 }; } await jobs.applyProviderState(job.localJobId, event.status, eventId, event); if (event.status === "succeeded") await queues.enqueueResultCopy(job.localJobId); return { status: 204 }; }
Обработчик должен проверять HTTPS, тип и размер тела, известный ID задачи и допустимый переход состояния, быстро отвечать 2xx и переносить скачивание в очередь. Отдельный процесс сверки читает незавершённые задачи по тому же маршруту:
bashcurl -X GET \ "https://ark.ap-southeast.bytepluses.com/api/v3/contents/generations/tasks/$TASK_ID" \ -H "Authorization: Bearer $ARK_API_KEY"
Если create завершился timeout до сохранения ID, найдите запись по requestHash, проверьте, не записал ли ID другой процесс, и используйте доступный у поставщика поиск или сверку. Пока отсутствие принятой задачи не доказано, помечайте результат как неопределённый и не отправляйте второй платный create.
4. Диагностируйте симптом на правильном слое
18 июля 2026 года без реальных ключей были отправлены POST-запросы с телом {}. BytePlus AP, Volcengine CN и правильный путь laozhang.ai ответили JSON 401. Путь laozhang.ai без /seedance ответил JSON 404, а устаревший /seedance/v3/... вернул HTML 200. Это проверка маршрута и границы аутентификации, не доказательство доступа к модели.
| Симптом | Слой проверки | Следующее действие | Что не делать |
|---|---|---|---|
JSON 401 | адрес, регион/проект, Bearer header, область ключа | для relay также проверить группу SeeDance2; отдельно проверить активацию и баланс | не менять prompt и не считать модель доступной |
JSON 404 | base URL и полный путь | сверить префикс с документацией владельца маршрута | не дописывать путь BytePlus к случайному gateway root |
HTML 200 | тип ответа | проверить Content-Type и наличие JSON body | не считать один status code успешным API-вызовом |
| model not found / not enabled | namespace и активация модели | сопоставить dreamina-* или doubao-* с тем же проектом | не придумывать Mini suffix |
| callback повторяется | доставка события | дедуплицировать по lastEventId, не откатывать конечное состояние | не создавать новую задачу |
| callback отсутствует | доставка или deploy | запустить polling по сохранённому task ID | не повторять create |
| generation failed | модель/входные данные | сохранить код и сообщение поставщика, классифицировать причину | не лечить auth/path ошибку повторной генерацией |
После succeeded проверьте status и media type скачивания, скопируйте результат в собственное object storage и запишите storedResult. В этом запуске срок жизни output URL не был подтверждён заново, поэтому статья не обещает конкретное время хранения. Реальные ключи не использовались; успешная генерация, latency, quota и доступность из России не проверялись.
5. Соблюдайте stop rules выбранного поставщика
- BytePlus direct выбирайте, если нужны официальное владение международной учётной записью, текущий каталог Standard/Fast/Mini или управление endpoint. Остановитесь, если модель не видна в вашей учётной записи или проект и регион ключа не совпадают.
- Volcengine direct подходит для китайской инфраструктуры и контракта
doubao-*. Не переносите туда международныйdreamina-*и не выводите Mini ID самостоятельно. - laozhang.ai relay полезен, когда единый gateway и документированный Seedance route упрощают эксплуатацию. Перейдите на официальный direct route, если relay не показывает нужный регион, вариант модели, контроль учётной записи или функцию. Текущая документация relay не поддерживает workflow с лицом реального человека; соответствующие границы описаны в гайде по реальным людям.
Выбор других поставщиков относится к сравнению Seedance 2 API, а проектирование prompt и references — к практическому prompt-гайду. На этой странице не фиксируются цена, бесплатные кредиты или универсально «лучший» маршрут.
Перед production проверьте одну строку контракта целиком: модель активна в нужном проекте, секрет остаётся на сервере, локальная запись существует до submit, task ID сохраняется один раз, lastEventId обновляется вместе с состоянием, callback и polling пишут в один reducer, timeout не запускает blind resubmit, а результат копируется в собственное хранилище. Если первые четыре условия не выполнены, платную задачу отправлять рано.
