Задачи в API, создание, опрос и результат

Как запустить картинку, видео, музыку, озвучку или документ запросом POST /v1/tasks, дождаться готовности опросом и забрать файлы.

Обновлено: 6 мин чтения

Создайте задачу

curl https://epicai.ru/v1/tasks \
  -H "Authorization: Bearer $EPICAI_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: video-001" \
  -d '{
    "model": "kling",
    "prompt": "Кошка идёт по подоконнику, за окном дождь",
    "parameters": {"scenario": "t2v", "engine": "v3", "quality": "std", "duration": 5, "aspect_ratio": "16:9"}
  }'

Так запускаются картинки, видео, музыка, озвучка, расшифровка речи и документы. Для текстовых моделей остаётся чат. В теле запроса всего восемь полей, лишние epicai отклоняет ответом 400 unknown_parameter.

ПолеЧто передать
modelИмя модели из GET /v1/models. Обязательное
promptОписание или текст задачи. Предельную длину и обязательность называют поля prompt_max и prompt_required модели
parametersОбъект с настройками модели. Допустимые имена и значения лежат в parameters ответа GET /v1/models/{id}. Незаданные берутся по умолчанию, как на сайте
images, videos, audiosСписки входных файлов, см. ниже
sourceГотовая задача и номер её результата для операций вроде увеличения картинки или продления трека, см. операции над результатом
webhook_urlАдрес для уведомления о завершении, см. вебхуки

Незнакомое имя в parameters и значение вне списка дают 400 invalid_parameter, а в param стоит parameters.имя. Молча подставлять умолчание epicai не станет: опечатка превратилась бы в платный запуск с другими настройками.

В ответ приходит задача. Код 201, у части моделей 202 с тем же телом. Заголовок Location ведёт на адрес задачи.

{
  "id": "task_7fa4be5e14351e3dff994aa3",
  "object": "task",
  "type": "video",
  "model": "kling",
  "status": "in_progress",
  "created_at": 1793114499,
  "started_at": 1793114499,
  "finished_at": null,
  "price": {"tokens": 75000, "charged": 0},
  "parameters": {"scenario": "t2v", "engine": "v3", "quality": "std", "duration": 5, "aspect_ratio": "16:9", "sound": false, "shots_mode": "off"}
}

В parameters вернулись все настройки, с которыми работает задача, включая подставленные по умолчанию. Цена в price.tokens зафиксирована. Заранее её можно узнать запросом POST /v1/quote (подробнее о цене задачи).

Дождитесь результата

curl https://epicai.ru/v1/tasks/task_7fa4be5e14351e3dff994aa3 \
  -H "Authorization: Bearer $EPICAI_API_KEY"

Запрос сам проверяет, что с задачей у вендора, поэтому ждать фонового обхода не нужно. Пока задача в работе, ответ содержит заголовок Retry-After: 3. Чаще раза в 3 секунды спрашивать нет смысла. Срок зависит от модели и нагрузки у вендора.

statusЗначение
queuedЗадача принята, вендору ещё не передана
in_progressВендор работает. Цена зарезервирована, price.charged равно 0
succeededГотово. Файлы в output, цена списана и записана в price.charged
failedНе получилось. Причина в error, токены не списаны

Первые два статуса промежуточные, последние два окончательные. Тот же цикл на Python:

import os
import time

import requests

API = "https://epicai.ru/v1"
headers = {"Authorization": "Bearer " + os.environ["EPICAI_API_KEY"]}

reply = requests.post(API + "/tasks", headers=headers, json={
    "model": "kling",
    "prompt": "Кошка идёт по подоконнику, за окном дождь",
    "parameters": {"scenario": "t2v", "engine": "v3", "quality": "std", "duration": 5},
})
reply.raise_for_status()
task = reply.json()

while task["status"] in ("queued", "in_progress"):
    time.sleep(5)
    reply = requests.get(API + "/tasks/" + task["id"], headers=headers)
    reply.raise_for_status()
    task = reply.json()

if task["status"] == "succeeded":
    for item in task["output"]:
        print(item["type"], item["url"])
else:
    print(task["error"]["code"], task["error"]["message"])

Не полагайтесь на то, что свежая задача придёт в работе. Если вендор ответил сразу, она может прийти уже со статусом succeeded. Чужая или несуществующая задача даёт 404 task_not_found.

Заберите файлы

"status": "succeeded",
"price": {"tokens": 75000, "charged": 75000},
"output": [
  {"type": "video", "url": "https://epicai.ru/storage/api/7fa4be5e14351e3dff994aa3/1.mp4", "mime": "video/mp4", "bytes": 5236392}
],
"expires_at": 1793719429

В output лежат ссылки на готовые файлы с типом (image, video, audio, text или document), mime и размером в байтах. У картинок есть ещё width и height. Ссылка открывается без ключа, поэтому её можно отдать браузеру или плееру. Вместе с главным файлом бывает вспомогательный .json или .txt, например описание треков у музыки и текст расшифровки. У каждого вида свой состав результата, смотрите статьи про картинки, видео, музыку, озвучку и расшифровку и документы.

Важно

Файлы хранятся 7 суток после завершения, срок назван в expires_at. Потом epicai стирает их, а задача остаётся с пустым output и признаком expired: true. Сохраните результат у себя раньше.

У задачи со статусом failed вместо файлов приходит объект error.

"status": "failed",
"price": {"tokens": 75000, "charged": 0},
"error": {"code": "task_timeout", "message": "Нейросеть не завершила задачу вовремя. Токены не списаны. Повторите запрос"}

Опирайтесь на code. Он стабилен, а текст написан для человека. Среди кодов встречаются content_filter (описание или файл отклонил фильтр безопасности нейросети), input_unavailable (нейросеть не смогла скачать входной файл), empty_result (вендор завершил работу без файла) и task_timeout. Полный перечень общих ошибок ищите в Ошибках API.

Посмотрите список задач

curl "https://epicai.ru/v1/tasks?status=succeeded&model=kling&limit=20" \
  -H "Authorization: Bearer $EPICAI_API_KEY"

Ответ — объект list с массивом data, где каждая задача выглядит как в GET /v1/tasks/{id}. Свежие идут первыми. В список попадают задачи всех ключей владельца в том же пространстве, личном или организации.

ПараметрЗначение
limitОт 1 до 100, по умолчанию 20
afterНомер задачи, после которой продолжить. Берите его из next_after прошлого ответа, он есть, когда has_more равно true
statusqueued, in_progress, succeeded или failed
modelИмя модели

Передайте входные файлы

Картинки-референсы, видео для перерисовки и записи идут в полях images, videos и audios. Каждое поле — массив строк. Строка может быть ссылкой http(s) или данными data:…;base64,….

{
  "model": "kling",
  "prompt": "Камера медленно приближается",
  "parameters": {"scenario": "i2v", "engine": "v3", "quality": "std", "duration": 5},
  "images": ["https://example.com/photo.jpg"]
}
  • Картинка — PNG, JPEG или WebP до 10 МБ. Присланные данные проверяются по содержимому, а не по расширению. В виде данных строка выглядит как data:image/png;base64,….
  • Видео — MP4, MOV или WebM, звук — MP3, WAV, M4A, OGG, FLAC, AAC или WebM, данные записываются как data:video/…;base64,… и data:audio/…;base64,…. Список форматов и предельный размер у каждой модели свои, их называет поле input_files в GET /v1/models/{id}. Если модель предел не задаёт, он равен 100 МБ.
  • Видео и звук epicai скачивает и сохраняет всегда, затем сам измеряет длительность. От неё зависит цена, и верить числу со слов клиента нельзя.
  • Ссылка должна вести на публичный сервер по порту 80 или 443, без логина и пароля, длиной до 2000 знаков. До трёх перенаправлений epicai пройдёт, адреса во внутренних сетях отклонит.

Сколько файлов принимает модель, написано в полях inputs и inputs_by её описания. У моделей с режимами, как у Kling, число файлов зависит от значения параметра, и inputs_by показывает его по каждому значению. Лишние файлы дают 400 invalid_image (картинки) или 400 invalid_input (видео и звук), нехватка обязательных картинок — 400 missing_required_parameter. Весь запрос не больше 12 МБ (иначе 413 request_too_large), поэтому крупные видео передавайте ссылкой. Присланные файлы epicai стирает, когда задача завершилась.

Защититесь от двойного запуска

Если связь оборвалась после отправки запроса, неизвестно, создалась ли задача. Повтор без защиты запустит вторую платную. Заголовок Idempotency-Key (до 64 знаков, латиница, цифры и символы . _ : -) связывает повтор с первым запросом. Тот же ключ с тем же телом вернёт уже созданную задачу с кодом 200 и заголовком Idempotent-Replayed: true, и ничего не спишется второй раз. Тот же ключ с другой моделью, текстом, параметрами, файлами или вебхуком даст 409 idempotency_conflict. Для каждой новой задачи берите новое значение.

Учтите пределы

  • У одного ключа по умолчанию не больше 20 задач в работе. Двадцать первая получает 429 too_many_active_tasks и Retry-After: 10.
  • Задача, которая не завершилась за 100 минут, переходит в failed с кодом task_timeout, резерв возвращается.
  • Суточный и месячный потолки ключа проверяются по цене задачи в момент создания. Остальные пределы перечислены в Лимитах API.

Не нашли ответ?

Посмотрите частые вопросы или напишите в поддержку.

Войти или создать аккаунт

20 000 токенов в подарок новым пользователям. Без карты и без VPN.

или через сервис

Продолжая, вы получаете сервисные письма.

Для защиты от роботов используется Yandex SmartCaptcha. Условия обработки данных.