Посібники
Генерування зображень
Асинхронно надсилайте завдання генерування й редагування зображень, опитуйте статус і завантажуйте підписані посилання на зображення.
Image API Felo генерує та редагує зображення за допомогою моделей із каталогу моделей Felo. Він асинхронний: запит на надсилання одразу повертає ID завдання, а ви опитуєте завдання, доки воно не досягне термінального стану.
Ця сторінка описує контракт, специфічний для зображень. Про спільний життєвий цикл завдань див. Асинхронні завдання.
Перш ніж почати
- API-ключ. Див. Автентифікація.
- Модель, у якої
model_kindдорівнюєimage_generation. Див. Як знайти модель зображень. - Базова URL-адреса
https://openapi.felo.ai.
Чим це відрізняється від OpenAI Images API
Шлях схожий на OpenAI Images API. Відповідь — ні:
| OpenAI Images API | Felo Image API | |
|---|---|---|
| Відповідь на надсилання | 200 з даними зображення | 202 з task_id, status: "queued" |
| Коли зображення існує | У відповіді на надсилання | Після того як опитування досягне succeeded |
| Корисне навантаження зображення | b64_json або url | Обмежена в часі підписана url |
| Помилки запиту | Помилка HTTP під час надсилання | Зазвичай status: "failed" у завданні |
Не надсилайте openai.images.generate() на цей endpoint. SDK очікує синхронний масив data і не може опитувати завдання. Викликайте endpoint через HTTP та опитуйте завдання або напишіть невелику обгортку для обох кроків.
Надсилання завдання
curl -X POST "https://openapi.felo.ai/api/v1/images/generations" \
-H "Authorization: Bearer ${FELO_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-3-pro-image",
"prompt": "A studio product photo of a ceramic coffee cup on warm linen, soft morning light",
"resolution": "2K",
"aspect_ratio": "4:3"
}'Успішне надсилання повертає HTTP 202:
{
"task_id": "6d1f0c9a-...",
"status": "queued",
"kind": "image",
"outputs": []
}202 означає, що платформа прийняла завдання. Це не означає, що підказка, параметри або референсні зображення дійсні. Виклик вищого постачальника виконується після відповіді, тому більшість проблем із запитом з'являються пізніше як завдання зі збоєм. Виняток — маршрутизація моделей: модель чату або відео відхиляється під час надсилання.
Опитування до термінального статусу
curl "https://openapi.felo.ai/api/v1/images/generations/${TASK_ID}" \
-H "Authorization: Bearer ${FELO_API_KEY}"| Статус | Значення | Що робити |
|---|---|---|
queued | Прийнято; очікує запуску | Продовжуйте опитування |
running | Модель генерує | Продовжуйте опитування |
succeeded | Термінальний; outputs заповнено | Завантажте результати |
failed | Термінальний; прочитайте error.message | Виправте запит; не повторюйте без змін |
interrupted | Термінальний; результат не вдалося відновити | Надішліть завдання повторно |
Збої завдання залишають код стану HTTP 200. Перевіряйте status у тілі, а не лише код стану HTTP.
Почніть з інтервалу 2–5 секунд і збільшуйте його. Більшість зображень завершуються протягом хвилини; вивід 4K і редагування з багатьма референсними зображеннями тривають довше. Завжди задавайте власний дедлайн.
import os
import time
import requests
BASE = "https://openapi.felo.ai"
HEADERS = {"Authorization": f"Bearer {os.environ['FELO_API_KEY']}"}
def generate_image(prompt: str, **params) -> list[dict]:
response = requests.post(
f"{BASE}/api/v1/images/generations",
headers=HEADERS,
json={"model": "gemini-3-pro-image", "prompt": prompt, **params},
timeout=30,
)
response.raise_for_status()
task = response.json()
deadline = time.monotonic() + 300
delay = 2.0
while time.monotonic() < deadline:
time.sleep(delay)
delay = min(delay * 1.5, 10.0)
poll = requests.get(
f"{BASE}/api/v1/images/generations/{task['task_id']}",
headers=HEADERS,
timeout=30,
)
poll.raise_for_status()
task = poll.json()
if task["status"] == "succeeded":
return task["outputs"]
if task["status"] in {"failed", "interrupted"}:
message = task.get("error", {}).get("message", task["status"])
raise RuntimeError(message)
raise TimeoutError(f"image task {task['task_id']} did not finish")Читання та збереження результатів
Коли завдання успішне, outputs містить один запис на кожне згенероване зображення:
{
"task_id": "6d1f0c9a-...",
"status": "succeeded",
"kind": "image",
"outputs": [
{
"media_type": "image/png",
"url": "https://openapi.felo.ai/api/v1/media/...?exp=...&sig=..."
}
]
}outputsпорожній, доки завдання не завершиться успішно.url— це підписана URL-адреса. Вона завантажується без API-ключа, тому поводьтеся з нею як із посиланням-носієм.- URL-адреса обмежена в часі. Параметр запиту
exp— це час її завершення. Завантажте файл і збережіть його у власному сховищі або файловій системі; завдання не є постійним сховищем. - Повторне опитування після завершення строку дії URL-адреси повертає ту саму прострочену URL-адресу. Воно не видає свіжу.
- Відповідь не містить даних зображення в base64.
for index, output in enumerate(outputs):
image = requests.get(output["url"], timeout=60)
image.raise_for_status()
with open(f"image-{index}.png", "wb") as file:
file.write(image.content)Редагування зображення
Передавайте референсні зображення в input_references. Модель використовує їх як контекст; підказка все одно описує зміну.
curl -X POST "https://openapi.felo.ai/api/v1/images/generations" \
-H "Authorization: Bearer ${FELO_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-3-pro-image",
"prompt": "Keep the product and framing. Replace the background with a sunlit marble countertop.",
"resolution": "2K",
"aspect_ratio": "4:3",
"input_references": [
{
"type": "image_url",
"image_url": {"url": "https://example.com/product.png"}
}
]
}'Кожен референс — це URL-адреса HTTP(S) або URL-адреса даних base64. Порядок референсів зберігається; коли це важливо, посилайтеся на зображення за позицією в підказці. Поточні моделі приймають до 14 референсів.
Поля запиту
| Поле | Обов'язкове | Опис |
|---|---|---|
model | Так | ID моделі з каталогу, наприклад gemini-3-pro-image. Не використовуйте ID google/... вищого постачальника |
prompt | Так | Текстова інструкція. Для редагування опишіть зміну та те, що має залишитися незмінним |
resolution | Ні | Рівень виводу. Поточні моделі приймають 1K, 2K або 4K |
aspect_ratio | Ні | Співвідношення сторін виводу. Прийнятні значення залежать від моделі |
n | Ні | Кількість зображень. Поточні моделі приймають 1 |
input_references | Ні | Референсні зображення для редагування або компонування |
Поточні моделі зображень:
| ID моделі | Роздільні здатності | Співвідношення сторін | Зображень на завдання | Референси |
|---|---|---|---|---|
gemini-3-pro-image | 1K, 2K, 4K | 1:1, 2:3, 3:2, 3:4, 4:3, 4:5, 5:4, 9:16, 16:9, 21:9 | 1 | До 14 |
gemini-nano-banana-2.1 | 1K, 2K, 4K | 1:1, 1:4, 1:8, 2:3, 3:2, 3:4, 4:1, 4:3, 4:5, 5:4, 8:1, 9:16, 16:9, 21:9 | 1 | До 14 |
Щоб прив'язати постачальника, надішліть заголовок X-Felo-Channel із кодом каналу зі списку channels моделі. Див. Канали та маршрутизація постачальників.
Як знайти модель зображень
Окремого endpoint для списку моделей зображень немає. Запитайте загальний каталог і відфільтруйте за model_kind:
curl "https://openapi.felo.ai/api/v1/models" \
-H "Authorization: Bearer ${FELO_API_KEY}" \
| jq '.data[] | select(.model_kind == "image_generation") | {id, name}'GET /api/v1/models/{model_id} повертає канали моделі та опубліковані тарифи.
supported_parameters у загальному каталозі — це список рівня протоколу. Для моделей зображень він не перелічує надійно поля зображень, наведені вище, тому не будуйте свій запит на його основі. Використовуйте таблицю полів у цьому посібнику та підтвердьте ID моделі за каталогом.
Ціни
Генерація зображень оплачується за опублікованими тарифами моделі. Каталог надає input_image і output_image поряд із текстовими тарифами prompt і completion. Тарифи зображень — це тарифи на токени: resolution змінює кількість вихідних токенів зображення, які споживає одне зображення, тому зображення 4K коштує більше за зображення 1K. Референсні зображення додають вхідні токени зображень.
Відповідь завдання не містить об'єкта usage. Перевірте плату в Console Billing.
Завдання, яке завершується failed або interrupted, не дає результату й не оплачується. Надсилання, відхилене з 402, не створило завдання.
Помилки
Помилки рівня endpoint від маршруту зображень використовують структуру помилок OpenAI:
{
"error": {
"message": "Model kind does not match this generation endpoint",
"type": "invalid_request_error",
"param": null,
"code": "model_kind_mismatch"
}
}ID запиту міститься в заголовку відповіді X-Request-Id. Записуйте його в журнал разом з ID завдання.
| HTTP | error.code | Значення |
|---|---|---|
| 400 | invalid_request_error | model відсутній або тіло не є об'єктом JSON |
| 400 | model_not_configured | ID моделі відсутній у ввімкненому каталозі |
| 400 | chat_model_not_allowed | На endpoint зображень надіслано модель чату |
| 400 | model_kind_mismatch | Надіслано відеомодель або іншу модель, що не є моделлю зображень |
| 402 | insufficient_balance | Недостатньо кредитів; завдання не створено |
| 404 | generation_task_not_found | ID завдання невідомий або належить іншому обліковому запису |
| 429 | daily_spend_limit_exceeded | Досягнуто денного ліміту витрат облікового запису |
| 503 | generation_unavailable | Генерація тимчасово недоступна; повторіть пізніше |
Помилки автентифікації описано в Помилки, обмеження та повторні спроби.