Видео API Kling — не синхронный интерфейс, который за один запрос возвращает готовый ролик. Сначала создаётся задача, затем запрашивается статус и только потом скачивается результат. Если писать код как для Chat Completions, обычно всё ломается на первом шаге: запрос возвращает успех, но видео нет — есть только запись задачи.

Ниже разобран реальный порядок интеграции: поколения интерфейсов Kling API в 2026 году, аутентификация, создание задачи, опрос, callback, загрузка, идемпотентность и миграция. Пути и поля могут меняться от версии к версии; перед интеграцией сверяйтесь с официальной документацией.

Примечание: Kling и Kuaishou — товарные знаки их правообладателей. Статья носит технический характер; автор не связан с указанными компаниями и не выступает их агентом.

1. Сначала разделите два поколения интерфейса

Сейчас у Kling одновременно существуют две формы API, и их смешивание — частый источник ошибок.

Новый интерфейс помещает версию модели в путь, например POST /text-to-video/kling-3.0-turbo, POST /text-to-video/kling-2.6. В теле запроса больше не нужен model_name, авторизация — заголовок Bearer с API-ключом, ответ содержит поля data.id и data.status.

Старый интерфейс обычно расположен по пути /v1/videos/...: модель указывается в теле через model_name, для авторизации из AccessKey/SecretKey генерируется JWT, а ответ содержит task_id и task_status. Старый интерфейс ещё работает, но новым проектам не стоит начинать с него.

Примеры ниже в основном используют новый интерфейс; в конце дан чек-лист миграции между поколениями.

2. Base URL и авторизация

В документации Kling указаны адреса сервиса:

  • https://api-singapore.klingai.com — для серверов за пределами материкового Китая; по официальному описанию он заменяет старый api.klingai.com.
  • https://api-beijing.klingai.com — пекинский адрес из примеров документации, подходит для развёртывания внутри Китая.

Фактические доступные регионы, область действия аккаунта и доступность моделей определяются консолью. Не переключайтесь между регионами без необходимости: задача и результат обычно принадлежат региону, в котором задача была создана.

Заголовок авторизации — Authorization: Bearer <API_KEY>, между Bearer и ключом один пробел. Легко упустить деталь: запросы чтения в новом интерфейсе тоже требуют Content-Type: application/json, даже если это GET.

Ключ можно хранить только на сервере. Вызов из браузера, приложения или мини-программы раскрывает учётные данные, а также создаёт проблемы с CORS и недоступностью callback. Рекомендуется отправлять задачи через бэкенд, а фронтенду передавать только статус.

3. Отправка первой видеозадачи

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

export KLING_API_KEY="ваш-ключ"
export KLING_BASE_URL="https://api-singapore.klingai.com"

curl -sS -X POST "$KLING_BASE_URL/text-to-video/kling-3.0-turbo" \
  -H "Authorization: Bearer $KLING_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "Городская улица после дождя, камера медленно приближается, кинематографично, 16:9",
    "settings": {
      "resolution": "720p",
      "aspect_ratio": "16:9",
      "duration": 5
    },
    "options": {
      "external_task_id": "demo-20261019-001",
      "callback_url": "https://example.com/kling/callback"
    }
  }'

Успешный ответ имеет бизнес-код 0, идентификатор задачи находится в data.id, начальный статус обычно submitted:

{
  "code": 0,
  "message": "",
  "request_id": "…",
  "data": {
    "id": "…",
    "status": "submitted",
    "create_time": 0,
    "update_time": 0,
    "external_id": "demo-20261019-001"
  }
}

Есть несколько ограничений. У 3.0 Turbo duration поддерживает от 3 до 15 секунд, по умолчанию 5 секунд; у 2.6 обычно 5 или 10 секунд; prompt ограничен примерно 3072 символами, официально рекомендуется укладываться в 2500. Разрешение, пропорции и поддержка аудио зависят от модели — не переносите параметры одной модели на другую.

4. Опрос статуса задачи

Получив идентификатор, опрашивайте статус через интерфейс запроса:

GET /tasks?task_ids=<ID задачи>
GET /tasks?external_task_ids=<свой ID>

task_ids и external_task_ids взаимоисключающие; несколько идентификаторов разделяются запятыми. В ответе data — массив задач, каждая содержит id, status, message, create_time, update_time, external_id, outputs и billing.

Статусов четыре:

  • submitted — задача принята, но ещё не начата.
  • processing — идёт генерация.
  • succeeded — успех, можно читать outputs.
  • failed — ошибка, смотрите message и причину модерации.

Не опрашивайте с фиксированной высокой частотой. Начните с 5 секунд и постепенно увеличивайте интервал до 15–30 секунд, задав общий таймаут. Видеозадачи могут стоять в очереди: если ожидание превышает план, сначала проверьте параллельность и пакет ресурсов, а не отправляйте задачу повторно.

Для сверки или повторной выгрузки используйте курсорный запрос POST /tasks с фильтрами по start_time, end_time, status, product_type; максимум 500 записей на страницу.

5. Callback и проверка подписи

При создании задачи передайте callback_url — платформа отправит уведомление при изменении статуса. Callback экономит ресурсы по сравнению с опросом, но требует, чтобы ваш интерфейс был доступен из интернета, быстро возвращал 200 и складывал обработку в очередь.

В новом интерфейсе тело callback содержит id, status, message, outputs, external_id и billing; в старом — task_id, task_status, task_result, причём успешный статус записан как succeed. Не используйте один парсер для двух форматов.

Для безопасности можно создать в консоли Webhook Secret (начинается с whsec_). Callback содержит заголовки webhook-id, webhook-timestamp, webhook-signature; подписывается строка {webhook-id}.{webhook-timestamp}.{rawBody} алгоритмом HMAC-SHA256, результат кодируется в Base64. При проверке учтите три момента: метка времени должна быть в пределах ±5 минут, подпись считается по исходному телу запроса, сравнение выполняется функцией с постоянным временем. Официально поддерживается сосуществование старого и нового secret в течение 7 дней — удобно для плавной ротации.

Callback может приходить повторно или не по порядку. Обработка должна быть идемпотентной по ID задачи, а статус — двигаться только вперёд; не перезаписывайте processing обратно в submitted.

6. Скачивание и сохранение результата

Видео успешной задачи находится в массиве outputs; элемент с type = video содержит url, watermark_url, duration и id. Поле url — адрес загрузки с защитой от внешних ссылок: встраивание напрямую в сайт или стороннюю систему может быть отклонено.

Два жёстких ограничения:

  • Ссылки на результаты очищаются примерно через 30 дней после генерации; это не постоянный адрес CDN.
  • Из-за защиты от внешних ссылок скачивать нужно на сервере, а затем перекладывать в собственное объектное хранилище.

Рекомендуемый порядок сохранения: сразу после успеха скачать файл, проверить Content-Type и размер, вычислить контрольную сумму, записать в объектное хранилище и связать собственный адрес с ID задачи. Для внешней раздачи используйте собственные подписанные URL с ограниченным сроком действия.

7. Идемпотентность, повторы и параллельность

Самая дорогая ошибка в видеозадачах — повторная отправка после таймаута. Таймаут запроса не означает, что задача не создана: возможно, просто не пришёл ответ.

external_task_id — основной инструмент идемпотентности: сгенерируйте стабильный ID до отправки и сохраните его, а после таймаута проверьте через GET /tasks?external_task_ids=..., что задачи нет, и только затем повторяйте. В рамках одного аккаунта этот ID должен быть уникальным. Не используйте случайный UUID как ключ повтора: каждая попытка будет создавать новую задачу.

По параллельности официальная документация указывает, что в лимит входит только «создание задачи», запросы статуса не учитываются; платформа не ставит задачи в очередь за вас, а при превышении слотов пакета возвращает 1303. Все API-ключи используют общий пул параллельности аккаунта. Рекомендуемая стратегия — экспоненциальная задержка минимум от 1 секунды и очередь отправки на стороне приложения, которая пропускает задачи по мере освобождения слотов.

8. Справочник типичных ошибок

Код HTTP Значение Что делать
1002 401 Неверные учётные данные Проверьте ключ, регион и заголовки
1103 403 Нет доступа к интерфейсу или модели Убедитесь, что аккаунт и пакет включают модель
1101 429 Задолженность по постоплате Пополните баланс и повторите
1102 429 Пакет исчерпан или просрочен Купите пакет или смените способ расчёта
1201 400 Недопустимое значение параметра Прочитайте message, проверьте длительность, пропорции, разрешение
1301 400 Не пройдена модерация контента Измените промпт или материал, не повторяйте как есть
1302 429 Слишком высокая частота запросов Снизьте частоту, используйте экспоненциальную задержку
1303 429 Превышен лимит параллельности Отправляйте через очередь, дождитесь освобождения слота
1203 404 Ресурс или модель не найдены Сверьте путь и версию модели
5002 500 Внутренний таймаут сервиса Сохраните ID задачи и запросите статус позже, не отправляйте заново

При разборе сначала смотрите HTTP-статус, затем бизнес-код, затем request_id. Записывайте все три в лог — это заметно ускоряет диагностику при обращении в поддержку.

9. Чек-лист миграции со старого интерфейса

  1. Переведите авторизацию с JWT на AccessKey/SecretKey на Bearer с API-ключом; старый интерфейс сохраняет совместимость с JWT.
  2. Замените путь /v1/videos/... на путь с моделью, например /text-to-video/kling-3.0-turbo.
  3. Уберите model_name из тела: модель определяется путём.
  4. Замените поля ответа task_id, task_status на id, status.
  5. Замените успешный статус succeed на succeeded.
  6. Перейдите от GET-пути по задаче к GET /tasks?task_ids=....
  7. Берите результат не из task_result.videos, а из элемента outputs с type=video.
  8. Разделите парсеры callback для старого и нового форматов, чтобы избежать несовпадения полей.
  9. Добавьте очистку результатов через 30 дней и логику перекладывания из-за защиты от внешних ссылок.
  10. Дополните идемпотентность через external_task_id и проведите учения: таймаут, повторный callback, отказ модерации.

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

10. Контрольные точки при подключении через шлюз

Если вы подключаетесь через ZSQH AI Gateway, помимо ключа и Base URL уточните, открыт ли видеоканал, передаются ли асинхронные задачи без изменений, сохраняются ли external_task_id и callback, как выдаются ссылки на результаты. OpenAI-совместимый интерфейс текстовых моделей нельзя напрямую использовать для видеозадач.

Начните со страницы моделей и тарифов, затем зарегистрируйтесь и создайте тестовый ключ. Проверьте полную цепочку на одной 5-секундной задаче — отправка, запрос статуса, скачивание — и только потом решайте, как переводить production-трафик.

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

Kling API синхронный или асинхронный?

Асинхронный. Отправка возвращает только ID задачи; далее нужно опрашивать GET /tasks или принимать callback, а после успеха скачивать видео из outputs.

Какой Base URL использовать: сингапурский или пекинский?

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

Задача долго висит в processing. Что делать?

Проверьте слоты параллельности и остаток пакета, затем убедитесь, не стоит ли задача в очереди. Если ожидание превышает план, запросите статус по ID и не отправляйте повторно; при необходимости обратитесь в поддержку и приложите request_id.

Можно ли вставлять ссылку на результат прямо на сайт или в мини-программу?

Не рекомендуется. Ссылка имеет защиту от внешних ссылок и очищается примерно через 30 дней. Скачивайте на сервере, перекладывайте в объектное хранилище и раздавайте через собственный подписанный URL.

Повтор после сбоя приведёт к двойному списанию?

Зависит от причины сбоя и правил биллинга платформы. После отказа модерации обычно не стоит повторять тот же запрос; при сетевом таймауте сначала проверьте задачу по external_task_id и отправляйте новую только при её отсутствии. До запуска прочитайте правила биллинга и проверьте их на небольших задачах.

Читайте также: