Руководство
Как использовать gpt-image-2/text-to-image через API hiapi: параметры, код и рабочие примеры
Этот туториал показывает минимальный объём кода, необходимый для генерации изображения с помощью gpt-image-2/text-to-image через единый API задач hiapi, а затем по очереди объясняет каждый параметр и производственные подходы (обратные вызовы, идемпотентность, обработка ошибок), которые следует применять после того, как код заработает.
Предварительные условия
Вам нужен ключ API. Создайте его на странице ключей API в консоли hiapi — ключ начинается с sk-. На странице модели gpt-image-2/text-to-image указана текущая цена за одно изображение; полная детализация приведена на странице цен.
Все вызовы в этом руководстве направляются на единый асинхронный эндпоинт задач:
POST https://api.hiapi.ai/v1/tasks— создание задачи генерацииGET https://api.hiapi.ai/v1/tasks/{taskId}— опрос статуса задачи
Общая справочная документация платформы находится в документации API hiapi.
Минимальный рабочий пример (curl)
Одна генерация — это двухшаговое взаимодействие: сначала создайте задачу, затем дождитесь её завершения.
# 1. Create the task
curl -s -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer sk-YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2/text-to-image",
"input": {
"prompt": "a calico cat curled up on a sunlit windowsill, soft focus background",
"aspect_ratio": "1:1",
"resolution": "1K"
}
}'
# => {"code":200,"data":{"taskId":"tk-hiapi-01KVY...."},"message":"success"}
# 2. Poll until status == "success"
TASK_ID="tk-hiapi-01KVY...."
curl -s "https://api.hiapi.ai/v1/tasks/$TASK_ID" \
-H "Authorization: Bearer sk-YOUR_KEY"
# => {"code":200,"data":{"status":"success","output":[{"url":"https://..."}], ...}}
URL изображения находится в data.output[0].url. Скачайте его сразу — output[0].expireAt очень короткий, поэтому этот URL предназначен только для получения, а не для постоянного встраивания.
Python: создание + опрос + сохранение на диск
import os
import time
import urllib.request
import requests # pip install requests
API_BASE = "https://api.hiapi.ai/v1/tasks"
TOKEN = os.environ["HIAPI_API_KEY"] # sk-...
def create_task(prompt: str, aspect_ratio: str = "1:1", resolution: str = "1K") -> str:
payload = {
"model": "gpt-image-2/text-to-image",
"input": {
"prompt": prompt,
"aspect_ratio": aspect_ratio,
"resolution": resolution,
},
}
r = requests.post(API_BASE, json=payload,
headers={"Authorization": f"Bearer {TOKEN}"},
timeout=60)
r.raise_for_status()
body = r.json()
if body.get("error"):
raise RuntimeError(f"create failed: {body['error']}")
return body["data"]["taskId"]
def wait_task(task_id: str, timeout_s: int = 600, poll_s: int = 5) -> dict:
deadline = time.time() + timeout_s
while time.time() < deadline:
r = requests.get(f"{API_BASE}/{task_id}",
headers={"Authorization": f"Bearer {TOKEN}"},
timeout=30)
r.raise_for_status()
task = r.json().get("data") or {}
status = task.get("status")
if status == "success":
return task
if status == "fail":
raise RuntimeError(f"task failed: {task.get('error')}")
time.sleep(poll_s)
raise TimeoutError(f"task {task_id} did not finish in {timeout_s}s")
if __name__ == "__main__":
task_id = create_task(
"a calico cat curled up on a sunlit windowsill, soft focus background",
aspect_ratio="3:2",
resolution="1K",
)
task = wait_task(task_id)
url = task["output"][0]["url"]
urllib.request.urlretrieve(url, "cat.png")
print(f"saved cat.png from task {task_id}")
Node.js: тот же процесс с использованием fetch
// Node 18+ has global fetch
const API_BASE = "https://api.hiapi.ai/v1/tasks";
const TOKEN = process.env.HIAPI_API_KEY;
async function createTask(prompt, aspectRatio = "1:1", resolution = "1K") {
const res = await fetch(API_BASE, {
method: "POST",
headers: {
"Authorization": `Bearer ${TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "gpt-image-2/text-to-image",
input: { prompt, aspect_ratio: aspectRatio, resolution },
}),
});
const body = await res.json();
if (body.error) throw new Error(`create failed: ${body.error.code} ${body.error.message}`);
return body.data.taskId;
}
async function waitTask(taskId, { timeoutMs = 600_000, pollMs = 5_000 } = {}) {
const deadline = Date.now() + timeoutMs;
while (Date.now() < deadline) {
const res = await fetch(`${API_BASE}/${taskId}`, {
headers: { "Authorization": `Bearer ${TOKEN}` },
});
const task = (await res.json()).data || {};
if (task.status === "success") return task;
if (task.status === "fail") throw new Error(`task failed: ${JSON.stringify(task.error)}`);
await new Promise(r => setTimeout(r, pollMs));
}
throw new Error(`task ${taskId} timed out`);
}
(async () => {
const id = await createTask(
"a calico cat curled up on a sunlit windowsill, soft focus background",
"16:9",
"1K",
);
const task = await waitTask(id);
const url = task.output[0].url;
const img = await fetch(url).then(r => r.arrayBuffer());
const { writeFileSync } = await import("node:fs");
writeFileSync("cat.png", Buffer.from(img));
console.log(`saved cat.png from task ${id}`);
})();
Справочник по параметрам
Тело запроса всегда содержит два поля верхнего уровня: model (строка, голый идентификатор модели gpt-image-2/text-to-image) и input (объект с параметрами, специфичными для модели).
Поле input |
Обязательно | Тип | Описание |
|---|---|---|---|
prompt |
Да | string | Текстовое описание желаемого изображения. |
aspect_ratio |
Да | string | Одно из значений: 1:1, 3:2, 2:3, 4:3, 3:4, 5:4, 4:5, 16:9, 9:16, 21:9 или auto. |
resolution |
Нет | string | 1K (по умолчанию), 2K или 4K. Размеры в пикселях масштабируются в зависимости от выбранного соотношения сторон. |
callback |
Нет | object | { "url": "https://yours.example/hook", "when": "final" } — см. следующий раздел. |
Успешное создание возвращает {"code":200, "data":{"taskId":"tk-hiapi-..."}, "message":"success"}. GET /v1/tasks/{taskId} возвращает data.status со значением handling, success или fail; при успехе data.output — это массив, первый элемент которого содержит url изображения и временную метку expireAt.
Другие модели изображений hiapi (например,
z-image,qwen-image) используют несколько иные поляinput—aspect_ratio— это соглашение, принятое вgpt-image-2/text-to-image. При смене модели проверьте страницу модели, чтобы убедиться в точной структуреinput.
Производственные подходы
Используйте обратные вызовы вместо опроса
Опрос каждые 5 секунд подходит для прототипа, но для производственного трафика вы хотите, чтобы hiapi сам推送 (направлял) завершённые задачи вам, освобождая worker. Добавьте блок callback в input:
{
"model": "gpt-image-2/text-to-image",
"input": {
"prompt": "an astronaut sketching the moon",
"aspect_ratio": "3:2",
"resolution": "1K",
"callback": {
"url": "https://your-app.example.com/webhooks/hiapi",
"when": "final"
}
}
}
when: "final" срабатывает один раз, когда задача достигает конечного состояния (success или fail). Полезная нагрузка, которую получает ваш эндпоинт, имеет ту же структуру, что и GET /v1/tasks/{id}, поэтому обработчик может повторно использовать логику разбора при опросе. Сверьте taskId с taskId, сохранённым при создании задачи, чтобы понять, какому запросу принадлежит обратный вызов.
Сделайте операцию создания идемпотентной
Если worker упадёт после POST /v1/tasks, но до сохранения taskId, вы можете сгенерировать одно и то же изображение дважды. Недорогое решение: в момент получения ответа о создании сохранить (your_request_id → taskId) в базе данных в той же транзакции, что и отправка запроса. Если worker повторит попытку, он найдёт существующий taskId и возобновит опрос, а не создаст новую задачу.
Правильно обрабатывайте ошибки аутентификации
При ошибке аутентификации hiapi возвращает HTTP 200 со встроенной в тело ответа полезной нагрузкой ошибки:
{"error":{"code":"permission_denied","message":"This API key cannot use the selected model. ...","type":"hiapi_error"}}
Поэтому один лишь код состояния 200 не означает успех. Всегда сначала проверяйте body.error; если он есть, смотрите error.code (permission_denied, invalid_request и т. д.) и error.message. request_id в сообщении — это то, что вы вставляете в тикет поддержки, когда нужна помощь.
Скачивайте сразу и переразмещайте самостоятельно
data.output[0].url — это URL с коротким сроком действия — в ответе содержится expireAt. Не вставляйте URL hiapi напрямую в <img src> вашего продукта; как только задача завершится успешно, сразу скачайте байтовый поток, загрузите его в собственное хранилище (S3, R2, Supabase Storage и т. п.) и отдавайте оттуда.
Задавайте разумные тайм-ауты
Разумные значения по умолчанию: тайм-аут POST-запроса 60 секунд (создание задачи быстрое — вы фактически просто ждёте подтверждения получения API), общий бюджет цикла опроса 10 минут с интервалом опроса 5 секунд. Задачи, занимающие более 10 минут, почти всегда означают, что задача незаметно перешла в состояние fail, поэтому тайм-аут с записью последнего тела ответа задачи в лог полезнее бесконечного ожидания.
Частые вопросы
В чём разница между gpt-image-2 и gpt-image-2/text-to-image?
gpt-image-2 — это семейство моделей; gpt-image-2/text-to-image — это конкретный эндпоинт, который вы вызываете для преобразования текстового запроса в новое изображение. Другие варианты этого семейства предоставляют иную структуру input (например, редактирование изображений принимает референсное изображение). Если сомневаетесь, используйте голый идентификатор модели, который видите на странице модели.
Что делает aspect_ratio: auto?
auto позволяет модели самой определить соотношение сторон на основе запроса. Используйте это, когда у вас нет строгих требований к компоновке; в противном случае фиксируйте соотношение самостоятельно, чтобы последующая обрезка была предсказуемой.
Почему мой запрос возвращает HTTP 200 с permission_denied?
Либо ключ API неверен (опечатка, отозван, отсутствует префикс sk-), либо тарифный план этого ключа не включает gpt-image-2/text-to-image. Откройте консоль ключей API, проверьте строку ключа и посмотрите свой план на странице цен. Всегда проверяйте body.error.code — никогда не полагайтесь только на HTTP-код состояния.
Можно ли сгенерировать несколько изображений за один запрос?
gpt-image-2/text-to-image генерирует одно изображение за задачу — data.output является массивом, но для этой модели его длина всегда равна 1. Чтобы сгенерировать N вариантов, запускайте N задач параллельно и используйте шаблон callback, описанный выше, чтобы не держать N worker'ов занятыми в ожидании.
Как отменить выполняющуюся задачу?
Единый API задач в настоящее время не предоставляет эндпоинта отмены. Самое простое смягчение — позволить клиентскому worker'у отказаться от результата, когда он больше не нужен пользователю, — уже выполненная генерация всё равно будет списана, поэтому правильное место для принудительной отмены — перед вызовом POST /v1/tasks.
Как переключиться на другую модель изображений?
Измените model на новый голый ID (например, z-image/text-to-image) и скорректируйте input в соответствии со структурой этой модели. Структуры моделей не полностью одинаковы — некоторые принимают size, некоторые принимают aspect_ratio, а少数 (некоторые) не принимают resolution. Каталог моделей перечисляет все доступные модели, и на странице каждой модели документированы её поля input.
Похожие статьи
Все статьи →-
Руководство
Как вызвать hailuo-2.3-fast/image-to-video через HiAPI API: практика с curl и Python
Первый рабочий запрос к быстрому и недорогому уровню генерации видео по изображению — от ID модели до загрузки MP4
-
Руководство
Как вызывать hailuo-2.3/text-to-video через API HiAPI: curl, Python и рабочие примеры запросов
-
Руководство
Использование Kandinsky 6.0 Pro для преобразования текста в видео на HiAPI: руководство по curl и Python
Практическая демонстрация с упором на запросы: построение вызова от промпта до видеоклипа, отправка запроса, опрос статуса завершения и скачивание результата