Felo API PlatformFelo API Platform

Посібники

Генерування зображень

Асинхронно надсилайте завдання генерування й редагування зображень, опитуйте статус і завантажуйте підписані посилання на зображення.

Image API Felo генерує та редагує зображення за допомогою моделей із каталогу моделей Felo. Він асинхронний: запит на надсилання одразу повертає ID завдання, а ви опитуєте завдання, доки воно не досягне термінального стану.

Ця сторінка описує контракт, специфічний для зображень. Про спільний життєвий цикл завдань див. Асинхронні завдання.

Перш ніж почати

Чим це відрізняється від OpenAI Images API

Шлях схожий на OpenAI Images API. Відповідь — ні:

OpenAI Images APIFelo 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-image1K, 2K, 4K1:1, 2:3, 3:2, 3:4, 4:3, 4:5, 5:4, 9:16, 16:9, 21:91До 14
gemini-nano-banana-2.11K, 2K, 4K1: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:91До 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 завдання.

HTTPerror.codeЗначення
400invalid_request_errormodel відсутній або тіло не є об'єктом JSON
400model_not_configuredID моделі відсутній у ввімкненому каталозі
400chat_model_not_allowedНа endpoint зображень надіслано модель чату
400model_kind_mismatchНадіслано відеомодель або іншу модель, що не є моделлю зображень
402insufficient_balanceНедостатньо кредитів; завдання не створено
404generation_task_not_foundID завдання невідомий або належить іншому обліковому запису
429daily_spend_limit_exceededДосягнуто денного ліміту витрат облікового запису
503generation_unavailableГенерація тимчасово недоступна; повторіть пізніше

Помилки автентифікації описано в Помилки, обмеження та повторні спроби.

Пов'язані розділи