HiAPI
Блог

Руководство

Создавайте мультимодельные AI-приложения на hiapi через единый унифицированный API

Oct 8, 2026
Создавайте мультимодельные AI-приложения на hiapi через единый унифицированный API
Модель
seedance-2.5

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

Большинство команд в итоге обращаются к трём-четырём разным AI-провайдерам для одного продукта: модель текст-в-изображение для миниатюр, модель текст-в-видео для коротких роликов для соцсетей, а может быть и TTS-модель для озвучки. У каждого провайдера свой SDK, своя схема аутентификации, своя логика опроса. hiapi сводит всё это к одной схеме эндпоинтов: POST /v1/tasks создаёт задачу, GET /v1/tasks/:id опрашивает задачу, и это применимо к каждой модели генерации на платформе.

В этом руководстве показана эта схема интеграции на трёх реальных, работающих сейчас моделях — z-image (текст-в-изображение), qwen-image-2.0 (текст-в-изображение, другая схема) и seedance-2.5 (текст-в-видео) — чтобы вы ясно увидели, где API полностью совпадает, а где отличается только объект input каждой модели.

Предварительные требования

  • API-ключ hiapi, полученный в консоли
  • curl или любой HTTP-клиент, умеющий отправлять JSON
  • SDK не нужен — каждый пример ниже это чистый HTTP-вызов

Каждому запросу нужен один заголовок:

Authorization: Bearer <your-api-key>

При недействительном или отсутствующем ключе возвращается ошибка класса 401 ещё до обращения к какой-либо модели:

{
  "error": {
    "code": "permission_denied",
    "message": "invalid api key",
    "request_id": "req_...",
    "type": "hiapi_error"
  }
}

Бесключевого или анонимного режима нет — каждый вызов /v1/tasks должен нести действующий bearer-токен. О ротации ключей и областях действия см. Аутентификация.

Минимальный рабочий пример

1. Создание задачи

Структура вызова создания всегда одинакова: идентификатор model и объект input, специфичный для модели. Вот создание задачи изображения через z-image:

curl -s -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "z-image",
    "input": {
      "prompt": "a minimalist workspace, soft morning light, isometric illustration",
      "aspect_ratio": "16:9"
    }
  }'

Ответ возвращается сразу — генерация идёт асинхронно:

{
  "code": 200,
  "message": "ok",
  "data": {
    "taskId": "tk-hiapi-xxxxxxxxxxxx",
    "status": "queued"
  }
}

Теперь та же схема с qwen-image-2.0. Тот же эндпоинт, та же внешняя структура — отличается только input (эта модель принимает строку size, а не aspect_ratio):

curl -s -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen-image-2.0",
    "input": {
      "prompt": "a minimalist workspace, soft morning light, isometric illustration",
      "size": "2048*2048"
    }
  }'

И создание видеозадачи через seedance-2.5/text-to-video — всё та же внешняя структура, но теперь с duration и более широким перечислением aspect_ratio:

curl -s -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "seedance-2.5/text-to-video",
    "input": {
      "prompt": "a paper airplane gliding through a sunlit office, slow motion",
      "duration": 5,
      "aspect_ratio": "16:9"
    }
  }'

В этом и суть: внешняя структура задачи никогда не меняется, меняется только input. Каждая модель на hiapi документирует свою схему input на странице модели — обязательно проверяйте схему конкретной модели перед построением новой интеграции, потому что поля вроде aspect_ratio, size и duration не взаимозаменяемы между моделями.

2. Опрос результата

curl -s https://api.hiapi.ai/v1/tasks/tk-hiapi-xxxxxxxxxxxx \
  -H "Authorization: Bearer $HIAPI_API_KEY"

status последовательно проходит queued → handling → archiving, а затем переходит в терминальное состояние success или fail. При успехе data.output — это массив: большинство моделей изображений/видео возвращают одну запись, но одна задача может вернуть несколько типов вывода (например, видеомодель возвращает и video, и thumbnail):

{
  "code": 200,
  "message": "ok",
  "data": {
    "taskId": "tk-hiapi-xxxxxxxxxxxx",
    "status": "success",
    "output": [
      { "type": "image", "url": "https://...", "expireAt": "2026-10-09T00:00:00Z" }
    ]
  }
}

expireAt важен — URL вывода по умолчанию временные. Скачивайте байты сразу после завершения задачи (или перезагружайте в собственное хранилище). Если нужно более долгое хранение файлов платформой, задайте при создании storage: "persistent" или повысьте уровень позже — см. Хранилище.

При неудаче вы получите объект error вместо output:

{
  "code": 200,
  "message": "ok",
  "data": {
    "taskId": "tk-hiapi-xxxxxxxxxxxx",
    "status": "fail",
    "error": { "code": "...", "message": "..." }
  }
}

Этот минимальный цикл опроса на Python одинаково работает для всех моделей выше:

import time
import requests

def run_task(model: str, input_payload: dict, api_key: str) -> list[dict]:
    headers = {"Authorization": f"Bearer {api_key}"}
    create = requests.post(
        "https://api.hiapi.ai/v1/tasks",
        headers=headers,
        json={"model": model, "input": input_payload},
    ).json()
    task_id = create["data"]["taskId"]

    time.sleep(3)  # initial wait before first poll
    while True:
        poll = requests.get(
            f"https://api.hiapi.ai/v1/tasks/{task_id}", headers=headers
        ).json()
        status = poll["data"]["status"]
        if status == "success":
            return poll["data"]["output"]
        if status == "fail":
            raise RuntimeError(poll["data"]["error"])
        time.sleep(4)  # 3-5s between polls; use 5-10s for video models

Паттерны для продакшена

Используйте callback вместо опроса в продакшене

Опрос подходит для скриптов или CLI-инструментов, но при любом реальном объёме трафика предпочтительнее callback: передайте объект callback при создании задачи, и hiapi отправит POST с терминальным результатом на ваш эндпоинт, вместо того чтобы вы в цикле повторно запрашивали GET /v1/tasks/:id.

{
  "model": "z-image",
  "input": { "prompt": "...", "aspect_ratio": "1:1" },
  "callback": { "url": "https://yourapp.com/webhooks/hiapi", "when": "final" }
}

when: "final" означает, что вы получите ровно один POST, срабатывающий в терминальном состоянии (success или fail), — без шума от промежуточных состояний handling/archiving. Если вы настроили callback, но ничего не получили, проверьте, доступен ли ваш эндпоинт публично и быстро ли он возвращает 2xx; о самой частой причине тихой потери callback см. эту статью.

Идемпотентные повторы

Сетевые сбои неизбежны. Если повторять вызов POST /v1/tasks после таймаута без защиты, можно создать (и оплатить) дублирующиеся задачи. Отправьте заголовок Idempotency-Key (любая строка не длиннее 255 байт, обычно UUID, генерируемый для каждого логического запроса), и повторы с тем же ключом вернут исходную задачу, а не создадут новую:

curl -s -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Idempotency-Key: 8f14e45f-ceea-467e-bd5f-...-9a2c" \
  -H "Content-Type: application/json" \
  -d '{"model": "z-image", "input": {"prompt": "...", "aspect_ratio": "1:1"}}'

Обработка ошибок валидации по моделям

Поскольку у каждой модели своя схема input, самый частый вид сбоя — 400 по полю, которое допустимо для одной модели, но недопустимо для другой, например отправка aspect_ratio модели, ожидающей size:

{
  "code": 400,
  "data": null,
  "error_code": "INVALID_REQUEST",
  "message": "invalid input: aspect_ratio: value must be one of '1:1', '4:3', '3:4', '16:9', '9:16'"
}

Если вы строите мультимодельный роутер (позволяющий пользователю или вашей собственной логике выбирать модель во время выполнения), ведите небольшой реестр построителей input по моделям, а не одну общую структуру payload:

MODEL_INPUT_BUILDERS = {
    "z-image": lambda prompt, **kw: {
        "prompt": prompt, "aspect_ratio": kw.get("aspect_ratio", "1:1")
    },
    "qwen-image-2.0": lambda prompt, **kw: {
        "prompt": prompt, "size": kw.get("size", "2048*2048")
    },
    "seedance-2.5/text-to-video": lambda prompt, **kw: {
        "prompt": prompt,
        "duration": kw.get("duration", 5),
        "aspect_ratio": kw.get("aspect_ratio", "16:9"),
    },
}

def build_task_payload(model: str, prompt: str, **kw) -> dict:
    return {"model": model, "input": MODEL_INPUT_BUILDERS[model](prompt, **kw)}

Так особенности каждой модели собраны в одном месте, а не разбросаны по каждой точке вызова. Несуществующий или принадлежащий другому аккаунту taskId возвращает обычный 404:

{ "code": 404, "message": "task not found", "data": null }

А временные 503 следует повторять с экспоненциальной задержкой, а не показывать пользователю напрямую — ограничения по скорости и ёмкости описаны в Ограничения скорости.

См. также

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

Нужны ли для каждой модели отдельный SDK или API-ключ? Нет. Один API-ключ, одна схема эндпоинтов (/v1/tasks) — для каждой модели на платформе. Меняется только объект input в теле запроса.

Почему сразу после создания задачи в ответе ещё нет output? Генерация асинхронна. Вызов создания возвращает только taskId и status: "queued" — вы должны опрашивать GET /v1/tasks/:id (или использовать callback), пока status не достигнет success или fail.

Можно ли вызывать API без аутентификации для быстрого теста? Нет — каждый вызов /v1/tasks требует действующего ключа Authorization: Bearer. В продакшене нет бесключевого или демо-режима; сначала сгенерируйте ключ в консоли.

Что будет, если опрашивать после истечения URL вывода? Сама запись задачи сохраняется, но output[].url непостоянных задач перестанет разрешаться после expireAt. Скачивайте файлы сразу при успехе или, если нужно долгое хранение, задайте при создании storage: "persistent".

Как узнать, какие поля принимает модель? Смотрите страницу этой модели в разделе Модели — каждая документирует свою точную схему input. Не предполагайте, что aspect_ratio, size или duration переносимы между моделями; как показано выше, z-image и qwen-image-2.0 уже расходятся в том, как задаётся форма изображения.

Похожие статьи

Все статьи →

Начните работать с постоянными артефактами ИИ

Получите API-ключ и вызывайте модели изображений, видео и аудио через один API на основе tasks.

Читать документацию API