> ## Documentation Index
> Fetch the complete documentation index at: https://docs.apiyi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Основы API изображений и лучшие практики

> Все API изображений APIYI являются синхронными: нет асинхронного task ID, и при обрыве соединения результат теряется, хотя запрос все равно тарифицируется. Включает рекомендации по тайм-ауту для каждой модели, а также справочную таблицу вывода base64/URL.

<Info>
  **Краткий ответ**: все image-модели в APIYI работают **синхронно** — вы отправляете запрос, держите соединение открытым, и сгенерированное изображение возвращается в том же ответе. Здесь нет async ID задачи и нет эндпоинта опроса; если ваш клиент отключится раньше, результат будет потерян, но запрос всё равно будет учтён в тарификации. **Достаточный timeout — правило номер один при разработке API для изображений.**
</Info>

## Три факта, которые нужно знать перед началом

<CardGroup cols={3}>
  <Card title="Все выполняется синхронно" icon="arrow-right-left">
    Один HTTP-запрос блокируется до завершения, что соответствует форме официального upstream API — режима «отправить и затем опрашивать» нет. Даже у upstream-провайдеров с асинхронной моделью (например, FLUX) шлюз оборачивает вызовы в синхронные, так что вам никогда не придется писать цикл опроса.
  </Card>

  <Card title="Нет task_id" icon="search-x">
    Эндпоинта для поиска по task\_id нет, и вы не можете позже восстановить изображение по request\_id. APIYI прозрачно проксирует запросы и не хранит сгенерированные результаты — как только соединение разрывается, результат восстановить нельзя.
  </Card>

  <Card title="Отключения по-прежнему тарифицируются" icon="unplug">
    Если ваш клиент истекает по тайм-ауту и отключается, сервер и upstream все равно завершают генерацию, и запрос **тарифицируется как обычно**. Слишком маленький тайм-аут означает, что вы платите за изображения, которые так и не получаете.
  </Card>
</CardGroup>

## Краткая справка по сериям моделей

Рекомендуемые тайм-ауты, форматы вывода и поддержка URL для каждой серии моделей изображений:

| Серия модели                                                               | Эндпоинт                                                                     | Рекомендуемый тайм-аут                                 | Формат вывода                                                                                                                  | Вывод URL и срок действия                                                                                        |
| -------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------- |
| [GPT-Image-2 (Official)](/ru/api-capabilities/gpt-image-2/overview)        | `/v1/images/generations`, `/v1/images/edits`                                 | **360s** (high + 2K/4K — 3-5 минут по замерам)         | Raw b64\_json (**без `data:` префикса**)                                                                                       | ❌ Не поддерживается (`response_format` возвращает 400; группа `image2_OSS` пока не охватывает официальный канал) |
| [GPT-Image-2-All (Reverse)](/ru/api-capabilities/gpt-image-2-all/overview) | То же, что и выше                                                            | **300s**                                               | По умолчанию `b64_json` (**без `data:` префикса**, подтверждено в 2026-07); переключается через явный `response_format: "url"` | ✅ Явный `url`: R2 CDN, около 24 часов; используйте группу `image2_OSS`, если вам нужны URL                       |
| [GPT-Image-2-VIP](/ru/api-capabilities/gpt-image-2-vip/overview)           | То же, что и выше                                                            | **300s**                                               | То же, что и у All (по умолчанию `b64_json`, без префикса, подтверждено в 2026-07)                                             | ✅ То же, что и у All (явный `url` или группа `image2_OSS`)                                                       |
| [Nano Banana Pro](/ru/api-capabilities/nano-banana-image/overview)         | Нативный Gemini `:generateContent`                                           | 1K/2K **300s**, 4K **600s**, multi-image более 5 минут | Сырой base64 в `inlineData.data`                                                                                               | `NB_OSS` бета-группа (см. ниже)                                                                                  |
| [Nano Banana 2](/ru/api-capabilities/nano-banana-2-image/overview)         | То же, что и выше                                                            | **360s**                                               | То же, что и выше                                                                                                              | Покрытие `NB_OSS`: обратитесь в поддержку                                                                        |
| [Nano Banana Lite](/ru/api-capabilities/nano-banana-lite-image/overview)   | То же, что и выше                                                            | **300s** (\~4s обычно, запас на пиковую нагрузку)      | То же, что и выше                                                                                                              | Покрытие `NB_OSS`: обратитесь в поддержку                                                                        |
| [FLUX](/ru/api-capabilities/flux/overview)                                 | `/v1/images/generations`                                                     | **60-120s**, 180s для flex-моделей                     | Только `data[0].url` (**URL — значение upstream по умолчанию**)                                                                | ⚠️ Действителен только около **10 минут**, без CORS — немедленно разверните на стороне сервера                   |
| [Seedream](/ru/api-capabilities/seedream-image/overview)                   | `/v1/images/generations` (унифицированный эндпоинт генерации/редактирования) | **60s** (4K + hd — около 30-60s)                       | По умолчанию `url` (**URL — значение upstream по умолчанию**); опционально `b64_json` (сырой base64, без префикса)             | ✅ BytePlus TOS, около 24 часов                                                                                   |

<Tip>
  `response_format` имеет **узкую область поддержки**: только GPT-Image-2-All / VIP и Seedream принимают его; официальный канал GPT-Image-2 возвращает 400 `unknown_parameter`, если вы его передадите. Если поддерживается, **всегда передавайте его явно**, а не полагайтесь на значение по умолчанию — исторически оно различалось между группами и при разных нагрузках.
</Tip>

## Тарификация и что влияет на цену

Самый частый вопрос о тарификации от новичков: «Каждое референсное изображение оплачивается по фиксированной ставке или более крупные изображения потребляют больше tokens?» Начните с трех интуитивных выводов:

<CardGroup cols={3}>
  <Card title="Стоимость определяется выходом" icon="trending-up">
    Возьмем gpt-image-2 в качестве примера: входной text \$5/M, image input \$8/M, **output \$30/M**. Главные рычаги цены — это всегда **размер и качество output** (quality × size); количество референсных изображений идет на втором месте.
  </Card>

  <Card title="Входные изображения — не по фиксированной ставке" icon="scaling">
    Входные изображения семейства GPT сопоставляются с tokens по **размерам/соотношению сторон** (чем больше, тем больше tokens, с нижним и верхним пределом), а **количество суммируется строго линейно**. У семейства Gemini все наоборот — output images стоят фиксированное количество tokens на каждый уровень разрешения.
  </Card>

  <Card title="Доверяйте возвращаемым usage" icon="receipt">
    И входные, и выходные tokens указаны в ответе: у семейства GPT — в `usage.input_tokens_details.image_tokens`, у семейства Gemini — в `usageMetadata.promptTokensDetails`. Сверяйте и рассчитывайте цену по ним — никогда не оценивайте по количеству изображений.
  </Card>
</CardGroup>

### Учет tokens: два семейства моделей

| Семейство                                     | Tokens входных изображений                                                                                                                                                                  | Tokens выходных изображений                                                                                                            |
| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| **Семейство GPT** (gpt-image-2 и др.)         | Динамически по размерам: квадратные изображения размером до 1024² включительно — все по 1024 tokens, 2048² и выше упираются в предел 1521 (проверено 2026-07); **N изображений = N × одно** | Определяется по `size` × `quality`: 1024² — от 196 tokens на низком уровне до нескольких тысяч на высоком                              |
| **Семейство Gemini** (все модели Nano Banana) | Учитываются в модальности IMAGE из `promptTokensDetails`                                                                                                                                    | **Фиксированное значение для каждого уровня разрешения**: 1120 на изображение при 1K/2K, 2000 при 4K, независимо от соотношения сторон |

### Интуиция по стоимости при нескольких входных изображениях

* Одно референсное изображение обходится примерно в **800-1600 image tokens ≈ \$0.008-0.012** (gpt-image-2, измерено, зависит от размеров/соотношения сторон);
* Количество суммируется линейно: **16 изображений ≈ \$0.13**, то есть примерно того же порядка, что и один `high` output (≈\$0.21) — стоимость входа больше не является незначительной в многоизображенческой fusion;
* **Tokens определяются размерами в пикселях, а не размером файла**: сжатие файлов помогает стабильности загрузки, но не экономит tokens; чтобы сэкономить tokens, уменьшайте количество изображений (слишком большие изображения все равно ограничиваются, так что бесконтрольного роста счетов тоже не будет).

Полная таблица измерений: [gpt-image-2 — Как несколько входных изображений влияют на цену](/ru/api-capabilities/gpt-image-2/overview#how-multiple-input-images-affect-the-price-verified-july-2026); учет tokens для семейства Gemini: [руководство по usageMetadata](/ru/api-capabilities/nano-banana-usage-metadata) и [ценообразование Nano Banana](/ru/api-capabilities/nano-banana-pricing).

## Настройка таймаута

### Почему стандартные таймауты ломают работу

Большинство HTTP-клиентов по умолчанию используют таймауты 30–60 секунд (`requests` сам по себе не имеет ограничения, но его часто оборачивают фреймворки, добавляющие \~30 с), тогда как генерация изображений — это действительно долгий запрос:

* GPT-Image-2 в качестве `high` с разрешением 2K/4K занимает **3–5 минут** от начала до конца;
* изображения серии Nano Banana в 4K обычно начинаются примерно с 50 секунд, а в пиковые периоды — дольше;
* запросы на слияние нескольких изображений и редактирование изображений, как правило, медленнее, чем text-to-image.

При стандартных настройках клиент разрывает соединение, пока сервер все еще нормально выполняет генерацию — вы видите волну «таймаутов», которые на самом деле являются **успешными запросами, от которых вы отключились сами**, и каждый из них тарифицируется.

### Уровни таймаута по моделям

```python theme={null}
# Set client timeouts (seconds) per model, not one global value
IMAGE_TIMEOUTS = {
    "gpt-image-2": 360,                      # high + 2K/4K measured at 3-5 min
    "gpt-image-2-all": 300,
    "gpt-image-2-vip": 300,
    "gemini-3-pro-image": 600,               # Nano Banana Pro, 600s covers 4K
    "gemini-3.1-flash-image-preview": 360,   # Nano Banana 2
    "gemini-3.1-flash-lite-image": 300,      # Nano Banana Lite
    "flux": 120,                             # 180 recommended for flex models
    "seedream": 60,                          # 4K + hd around 30-60s
}

import requests

def generate_image(model: str, payload: dict, api_key: str) -> dict:
    resp = requests.post(
        "https://api.apiyi.com/v1/images/generations",
        headers={"Authorization": f"Bearer {api_key}"},
        json={"model": model, **payload},
        timeout=IMAGE_TIMEOUTS.get(model, 300),  # 300s fallback for unknown models
    )
    resp.raise_for_status()
    return resp.json()
```

### Стратегия повторных попыток

Не каждая ошибка заслуживает повторной попытки — начните с того, как каждый случай тарифицируется:

| Сбой                                                | Тарифицируется?                             | Рекомендация                                                                                     |
| --------------------------------------------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| 429 / 503 (лимит запросов, перегрузка upstream)     | Не тарифицируется                           | Повторяйте с экспоненциальной задержкой между попытками (например, 5 с, 15 с, 45 с)              |
| Таймаут клиента / преждевременный разрыв соединения | **Тарифицируется**                          | Сначала увеличьте таймаут; если повторная попытка необходима, тщательно ограничьте число попыток |
| 400 / 403 (ошибки параметров или прав доступа)      | Не тарифицируется                           | Исправьте запрос перед повторной отправкой — слепые повторы бесполезны                           |
| Блокировка модерацией контента                      | **Зависит от модели** (см. примечание ниже) | Пересмотрите prompt; повторная отправка без изменений, скорее всего, снова будет заблокирована   |

<Info>
  **Тарификация при блокировке модерацией зависит от модели**: модели с тарификацией по token (официальный GPT-Image-2 и т. д.) обычно возвращают ошибку 400, когда срабатывает модерация, — **не тарифицируется**. Только **Nano Banana Pro с тарификацией за изображение** попадает под блокировку на стороне Google вида «HTTP 200, но генерация не удалась», и такой вызов **тарифицируется** — APIYI покрывает эти сбои не по вине пользователя по [Плану возмещения кредитов за неудачную генерацию](/ru/api-capabilities/nano-banana-pro-guarantee), который возмещает кредиты на основе подсчета по каждому изображению.
</Info>

## Работа с выводом base64

### Различия префикса

base64-данные **не одинаковы для разных серий** — это самая распространенная ловушка при новых интеграциях:

| Серия модели                | Поле base64                                     | Включает префикс `data:image/...;base64,`?                           |
| --------------------------- | ----------------------------------------------- | -------------------------------------------------------------------- |
| GPT-Image-2 (Официальный)   | `data[0].b64_json`                              | Без префикса (сырой base64)                                          |
| GPT-Image-2-All / VIP       | `data[0].b64_json`                              | Без префикса (проверено 2026-07; **ранние версии включали префикс**) |
| серия Nano Banana           | `candidates[0].content.parts[].inlineData.data` | Без префикса (сырой base64)                                          |
| Seedream (режим `b64_json`) | `data[0].b64_json`                              | Без префикса (сырой base64)                                          |

Поведение префикса менялось между версиями канала, поэтому **всегда сначала проверяйте `startsWith("data:")`**: удаляйте префикс перед декодированием (или используйте значение напрямую как `img src`), если он присутствует, а сырые значения декодируйте как есть — это позволяет избежать и ошибки с двойным префиксом, и сбоев декодирования для данных с префиксом.

### Декодирование в файл

```python theme={null}
import base64

b64 = response["data"][0]["b64_json"]
if b64.startswith("data:"):          # defensive strip: some channel versions included a data: prefix
    b64 = b64.split(",", 1)[1]
with open("output.png", "wb") as f:
    f.write(base64.b64decode(b64))
```

```javascript theme={null}
let b64 = response.data[0].b64_json;
if (b64.startsWith("data:")) {
  b64 = b64.slice(b64.indexOf(",") + 1);
}
require("fs").writeFileSync("output.png", Buffer.from(b64, "base64"));
```

### Ограничения рендеринга в Playground

ответы base64 часто занимают несколько мегабайт, и браузерный Playground может показать `unable to complete request` — это **не означает, что запрос не выполнен**. Запрос был успешно обработан и тарифицирован; браузер просто не может отрендерить строку такой длины. Проверьте результат через код или переключитесь на модель/параметр, который возвращает `url`.

## Предобработка входных изображений

Эндпоинты image-edit / reference-image (например, `/v1/images/edits` для gpt-image-2) принимают только **png / jpg / webp**. В продуктах, где пользователи могут загружать собственные фотографии, есть одна особенно коварная ловушка: **фотографии прямо с камеры телефона часто не являются стандартным JPEG**.

### Типичный симптом: 400 invalid\_image\_file

```json theme={null}
{
  "error": {
    "message": "Invalid image file or mode for image 1, please check your image file. ...",
    "code": "invalid_image_file"
  }
}
```

Обычно это вызвано **форматом MPO** (Multi-Picture Object, многокадровый JPEG-контейнер): `.jpg` файлы прямо с телефонов Huawei Mate-серии и похожих моделей встраивают HDR gain-map sub-frame и на самом деле являются MPO. Коварство в том, что файл начинается с того же заголовка `FFD8` — **расширение, HTTP Content-Type и команда `file` все сообщают JPEG** — и только разбор с учетом кадров показывает правду:

```python theme={null}
from PIL import Image
Image.open("photo.jpg").format   # "MPO" means you're hit; standard images return "JPEG"/"PNG"
```

Проверено в июле 2026 года (эндпоинт редактирования gpt-image-2): изображения MPO всегда отклоняются, тогда как то же изображение, перекодированное в стандартный JPEG/PNG, успешно проходит **с полным исходным разрешением (3072×4096)** — проблема в формате, а не в размере. Этот 400 возвращается быстро на этапе проверки входных данных и **не тарифицируется**.

### Рекомендация: перекодируйте на стороне сервера, единообразно

Вместо отладки фотографий по одной добавьте в ваш upload pipeline один шаг перекодирования — он также обрабатывает HEIC, CMYK и другие нестандартные входные данные:

```python theme={null}
from PIL import Image
import io

def normalize_image(raw: bytes) -> bytes:
    """Any source image → standard JPEG that passes image-edit format validation"""
    im = Image.open(io.BytesIO(raw))
    im.load()                      # multi-frame formats (MPO etc.): keep the first frame only
    if im.mode not in ("RGB", "RGBA"):
        im = im.convert("RGB")     # normalize CMYK / P and other modes to RGB
    out = io.BytesIO()
    im.save(out, format="JPEG", quality=92)
    return out.getvalue()
```

Во время перекодирования уменьшайте и размер payload (длинная сторона до 4096, качество JPEG 80-92) и держите каждое изображение меньше 1.5MB — это повышает успешность загрузки и скорость генерации, а качество результата не зависит от размера входного файла. См. [редактирование изображений gpt-image-2: требования к формату reference image и предварительная обработка](/ru/api-capabilities/gpt-image-2/image-edit#reference-image-format-requirements-and-preprocessing).

## Предварительная обработка формата входного изображения

Эндпоинты для редактирования изображений / работы с референсным изображением (например, `/v1/images/edits` у gpt-image-2) принимают в качестве входных данных только **png / jpg / webp**. В продуктах, где используются фотографии, сделанные пользователем, есть одна особенно коварная ловушка: **фотографии, прямо снятые на камеру телефона, часто не являются стандартным JPEG**.

### Типичный симптом: 400 invalid\_image\_file

```json theme={null}
{
  "error": {
    "message": "Invalid image file or mode for image 1, please check your image file. ...",
    "code": "invalid_image_file"
  }
}
```

Обычная причина — **формат MPO** (Multi-Picture Object, многофреймовый JPEG-контейнер): `.jpg` файлы, полученные прямо с телефонов серии Huawei Mate, содержат HDR gain-map sub-frame и на самом деле являются MPO. Коварство этих файлов в том, что заголовок у них тот же `FFD8` — **расширение, HTTP Content-Type и команда `file` все сообщают JPEG** — и распознать это может только разбор с учетом кадров:

```python theme={null}
from PIL import Image
Image.open("photo.jpg").format   # "MPO" means you're affected; standard files return "JPEG"/"PNG"
```

Проверено в июле 2026 года (эндпоинт редактирования gpt-image-2): файлы MPO всегда отклоняются; то же изображение, перекодированное в стандартный JPEG/PNG, успешно проходит **при полном исходном разрешении (3072×4096)** — проблема в формате, а не в размере. Этот 400 возвращается быстро на этапе валидации входных данных и **не тарифицируется**.

### Рекомендация: перекодируйте единообразно на стороне сервера

Вместо отладки изображений по одному добавьте один шаг перекодирования в ваш конвейер загрузки — он также покрывает HEIC, CMYK и другие нестандартные входные данные:

```python theme={null}
from PIL import Image
import io

def normalize_image(raw: bytes) -> bytes:
    """Any input image → standard JPEG that passes image-edit endpoint validation"""
    im = Image.open(io.BytesIO(raw))
    im.load()                      # multi-frame formats (MPO etc.): keep only the first frame
    if im.mode not in ("RGB", "RGBA"):
        im = im.convert("RGB")     # normalize CMYK / P etc. to RGB
    out = io.BytesIO()
    im.save(out, format="JPEG", quality=92)
    return out.getvalue()
```

Во время перекодирования сразу выполняйте сжатие (длина длинной стороны не более 4096px, качество JPEG 80-92) и удерживайте каждое изображение в пределах 1.5MB — успешность загрузки и скорость генерации изображений обе улучшаются, а качество результата не зависит от размера входного файла. См. [gpt-image-2 Image Edit — Требования к формату референсного изображения и предварительная обработка](/ru/api-capabilities/gpt-image-2/image-edit#reference-image-format-requirements-and-preprocessing).

## Получение URL-вывода вместо этого

Существует три пути, в порядке надежности:

1. **URL — это upstream-значение по умолчанию** — FLUX (действительно только около 10 минут, без заголовков CORS; скачайте и немедленно повторно разместите на server-side) и Seedream (BytePlus TOS, около 24 часов) нативно возвращают URL, без необходимости какой-либо настройки.
2. **Группы OSS (детерминированный вывод URL — рекомендуется для production)**:
   * `image2_OSS` группа: охватывает **GPT-Image-2-All / VIP** (коэффициент тарифа 1x, без доплаты); переключите свой token на эту группу, чтобы получать стабильный вывод URL без fallback на base64. **Официальный канал GPT-Image-2 пока не покрывается.**
   * `NB_OSS` beta-группа: охватывает серию Nano Banana, при этом URL изображения передается в поле `text` — см. [руководство по группе NB-OSS](/ru/api-capabilities/nano-banana-oss-group).
3. **Явный `response_format: "url"`** — его принимают только GPT-Image-2-All / VIP (R2 CDN, около 24 часов) и Seedream; поверхность **узкая**, а официальный канал GPT-Image-2 возвращает 400, если вы его передадите. Это переключатель на уровне запроса для группы по умолчанию — бизнесу, который зависит от URL, следует использовать группу OSS вместо этого.

**GPT-Image-2 (Official) в настоящее время вообще не имеет пути вывода URL** — только base64.

<Warning>
  Каждый URL изображения, который возвращают эти платформы, — это **временная ссылка** (от 10 минут до 24 часов). Все, что требует долгосрочного хранения — изображения продуктов, пользовательские создания, история — должно быть **немедленно повторно размещено в вашем собственном object storage / CDN** сразу после генерации, а ваш собственный URL должен быть сохранен в вашей базе данных.
</Warning>

## Устранение неполадок с таймаутами и разрывами соединения

Если вы уже увеличили таймаут SDK и все еще видите частые «таймауты», пройдите по этому чек-листу:

<Steps>
  <Step title="Проверьте фактический таймаут на стороне клиента">
    Фреймворки часто оборачивают HTTP-клиент еще одним слоем таймаута (лимиты worker'ов очереди задач, ограничения времени выполнения serverless). Любой слой, который короче времени генерации модели, прервет запрос.
  </Step>

  <Step title="Проверьте промежуточные звенья: nginx / балансировщики нагрузки / CDN">
    Самостоятельно размещенные reverse proxy (`proxy_read_timeout`), таймауты простоя cloud load balancer и таймауты origin у CDN **обычно по умолчанию составляют 60 секунд** и оборвут соединение раньше, чем это сделает ваш клиент. Для каждого перехода на пути длинного запроса нужно увеличить лимит.
  </Step>

  <Step title="Включите keep-alive, чтобы простаивающие соединения не сбрасывались">
    Соединения, по которым долго не передаются байты, могут незаметно разрываться устройствами NAT или firewall; TCP- или HTTP keep-alive значительно снижает риск.
  </Step>

  <Step title="Используйте request ID и логи консоли, чтобы проверить тарификацию">
    Запишите заголовок ответа `x-request-id` и найдите его в логах вызовов консоли APIYI. Если вызов там отображается, сервер завершил генерацию и выставил тарификацию за запрос — соединение было разорвано на вашей стороне пути.
  </Step>
</Steps>

## Хотите асинхронное управление в стиле задач?

Платформа не предоставляет async API, но вы можете самостоятельно построить асинхронную оболочку поверх синхронных эндпоинтов:

<CardGroup cols={3}>
  <Card title="Почему нет асинхронного API" icon="circle-help" href="/ru/faq/image-async-api">
    FAQ: Есть ли async API для изображений? Могу ли я получать результаты по task ID?
  </Card>

  <Card title="Создайте собственную асинхронную очередь" icon="list-checks" href="/ru/api-capabilities/image-async-queue">
    Руководство для инженеров: оберните синхронные вызовы в очередь задач с собственным task\_id, персистентностью и повторными попытками
  </Card>

  <Card title="Группа вывода URL NB-OSS" icon="cloud-upload" href="/ru/api-capabilities/nano-banana-oss-group">
    Переключите вывод Nano Banana на URL и сократите накладные расходы на передачу base64
  </Card>
</CardGroup>
