В современном мире разработки приложений, где искусственный интеллект становится неотъемлемой частью пользовательского опыта, интеграция генерации изображений часто превращается в сложную техническую задачу. Представьте себе сценарий: вы хотите добавить в свое приложение функцию создания уникальных иллюстраций или вариаций продуктовых фото. На первый взгляд, это кажется простым — отправь промпт, получи картинку. Однако реальность такова, что экосистема AI-моделей фрагментирована. Десятки провайдеров, такие как OpenAI, Stability AI, Google и другие, предлагают свои собственные модели с уникальными эндпоинтами, форматами данных, системами биллинга и параметрами управления. Поддержка нескольких провайдеров требует написания множества адаптеров, что замедляет разработку и усложняет поддержку кодовой базы.
Здесь на сцену выходит OpenRouter, платформа, которая решает эту проблему путем предоставления единого унифицированного API. Вместо того чтобы писать отдельный код для каждой модели, разработчики могут использовать один формат запроса и один API-ключ для доступа к широкому спектру моделей генерации изображений. В этой статье мы подробно разберем, как интегрировать эту функциональность в свои проекты, используя примеры на Python и JavaScript. Мы пройдем путь от создания первого запроса до работы с референсными изображениями и оптимизации затрат, предоставляя вам полный набор инструментов для внедрения AI-генерации в ваши продукты.
01Подготовка к работе: Что вам понадобится
Прежде чем приступить к написанию кода, необходимо подготовить рабочую среду. Интеграция с OpenRouter не требует сложных настроек серверной инфраструктуры, но наличие определенных инструментов критически важно для успешного старта. Во-первых, вам потребуется аккаунт на платформе OpenRouter. Это базовое требование, так как именно через ваш аккаунт будут генерироваться API-ключи, необходимые для аутентификации запросов.
Во-вторых, убедитесь, что у вас установлена подходящая среда выполнения. Для примеров на Python требуется версия 3.x и установленный пакет requests, который является стандартом де-факто для работы с HTTP-запросами в Python. Если вы предпочитаете JavaScript, вам понадобится Node.js версии 18 или выше. Начиная с этой версии, Node.js предоставляет встроенный глобальный объект fetch, что избавляет от необходимости устанавливать сторонние библиотеки для работы с сетью. Также не забудьте подготовить текстовый редактор или IDE, в которой вам будет удобно писать и отлаживать код.
os.environ в Python или process.env в Node.js, что является лучшей практикой.02Шаг 1: Получение ключа и выбор модели
Первым практическим шагом является получение API-ключа. Перейдите на страницу управления ключами в личном кабинете OpenRouter и создайте новый ключ. После создания ключа важно сразу же экспортировать его в переменную окружения терминала, в котором вы планируете запускать скрипты. В Unix-подобных системах (Linux, macOS) это делается командой export OPENROUTER_API_KEY="sk-or-v1-...". В Windows команда будет отличаться, но суть остается той же: ключ должен быть доступен скрипту через переменную окружения.
Следующий важный этап — выбор модели. OpenRouter поддерживает множество моделей, способных генерировать изображения. Для начала работы мы рекомендуем использовать модель bytedance-seed/seedream-4.5. Она демонстрирует высокое качество генерации и хорошо подходит для общих задач. Однако важно понимать, что выбор модели определяет доступные функции. Разные модели поддерживают разные разрешения, количество выходных изображений и, что особенно важно, возможность использования референсных изображений (input references).

Чтобы узнать, какие параметры поддерживает конкретная модель, вы можете использовать эндпоинт GET /api/v1/images/models. Этот запрос вернет список всех доступных моделей с их техническими характеристиками. Хотя для базового туториала это не обязательно, эта информация станет незаменимой, когда вы начнете настраивать продвинутые сценарии использования, такие как изменение стиля или композиции изображения.
03Шаг 2: Отправка первого запроса на генерацию
Теперь, когда у нас есть ключ и модель, мы можем отправить первый запрос. API OpenRouter для генерации изображений работает через POST-запрос к эндпоинту https://openrouter.ai/api/v1/images. Тело запроса должно содержать как минимум два поля: model (название выбранной модели) и prompt (текстовое описание желаемого изображения). Аутентификация осуществляется путем передачи API-ключа в заголовке Authorization в формате Bearer.
Ниже приведен пример кода на Python. Обратите внимание на использование timeout=120. Генерация изображений — ресурсоемкая операция, которая может занимать время, поэтому установка таймаута предотвращает зависание скрипта в случае проблем с сетью или сервером.
import os
import requests
response = requests.post(
"https://openrouter.ai/api/v1/images",
headers={
"Authorization": f"Bearer {os.environ['OPENROUTER_API_KEY']}",
"Content-Type": "application/json"
},
json={
"model": "bytedance-seed/seedream-4.5",
"prompt": "A studio product photo of a matte black travel mug on a light gray background"
},
timeout=120
)
if not response.ok:
raise RuntimeError(f"{response.status_code}: {response.text}")
result = response.json()Для разработчиков на JavaScript код будет выглядеть следующим образом. Здесь мы используем асинхронную функцию fetch и обработку ошибок через try/catch или проверку статуса ответа.
const response = await fetch("https://openrouter.ai/api/v1/images", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.OPENROUTER_API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
model: "bytedance-seed/seedream-4.5",
prompt: "A studio product photo of a matte black travel mug on a light gray background"
})
});
if (!response.ok) {
throw new Error(`${response.status} ${await response.text()}`);
}
const result = await response.json();response.ok в JS, response.ok в requests) перед парсингом JSON. Если запрос не удался, тело ответа часто содержит полезное сообщение об ошибке, которое поможет быстро найти причину проблемы. Игнорирование этой проверки может привести к путанице с ошибками "missing field" позже в коде.04Шаг 3: Декодирование и сохранение изображения
После успешного выполнения запроса вы получите JSON-ответ. Однако изображение в нем представлено не в виде ссылки на файл, а в виде строки в формате Base64. Структура успешного ответа выглядит примерно так:

{
"data": [
{
"b64_json": "iVBORw0KGgoAAA...",
"media_type": "image/png"
}
],
"usage": {
"cost": 0.0123
}
}Поле data является массивом, так как один запрос может вернуть несколько вариантов изображений. Первое изображение находится по индексу data[0]. Строка b64_json содержит закодированные байты изображения. Поле media_type указывает формат изображения (PNG, JPEG, WebP), а usage.cost сообщает о стоимости запроса (если эта информация доступна для данной модели).
Чтобы сохранить изображение на диск, нам нужно декодировать Base64-строку обратно в байты и записать их в файл. Вот как это делается на Python:
import base64
import os
import requests
# ... (код запроса из Шага 2) ...
result = response.json()
images = result.get("data") or []
if not images or not images[0].get("b64_json"):
raise RuntimeError("The response did not contain image data")
image_bytes = base64.b64decode(images[0]["b64_json"])
with open("output.png", "wb") as output_file:
output_file.write(image_bytes)
print("Saved output.png")
if result.get("usage", {}).get("cost") is not None:
print(f"Request cost: ${result['usage']['cost']}")В JavaScript аналогичная задача решается с помощью модуля fs/promises:
import { writeFile } from "node:fs/promises";
// ... (код запроса из Шага 2) ...
const result = await response.json();
if (!result.data?.[0]?.b64_json) {
throw new Error("The response did not contain image data");
}
await writeFile(
"output.png",
Buffer.from(result.data[0].b64_json, "base64")
);
console.log("Saved output.png");
if (result.usage?.cost !== undefined) {
console.log(`Request cost: $${result.usage.cost}`);
}Обратите внимание, что мы открываем файл в режиме "wb" (write binary) в Python, чтобы избежать проблем с кодировкой текста. В JavaScript мы используем Buffer.from(..., "base64") для преобразования строки в байтовый буфер. Если формат изображения важен для вашего приложения, используйте значение из media_type для определения расширения файла (например, .jpg или .webp).
05Шаг 4: Использование референсных изображений
Одной из самых мощных функций API OpenRouter является поддержка референсных изображений (input references). Это позволяет модели использовать визуальный материал в качестве основы для генерации, а не полагаться исключительно на текстовый промпт. Это особенно полезно для создания вариаций продуктовых фотографий, где важно сохранить форму, материал или дизайн объекта, но изменить фон, освещение или стиль.

Для использования референса необходимо добавить поле input_references в тело запроса. Значение этого поля — массив объектов, каждый из которых содержит URL изображения. Для локальных файлов этот URL должен быть в формате Data URL, который включает тип медиа и Base64-кодированные данные файла.
Ниже приведен пример на Python, где мы читаем локальный файл product.jpg, кодируем его в Base64 и формируем Data URL:
import base64
import os
import requests
# Читаем локальный файл
with open("product.jpg", "rb") as reference_file:
reference_base64 = base64.b64encode(reference_file.read()).decode("utf-8")
# Формируем Data URL
reference_data_url = f"data:image/jpeg;base64,{reference_base64}"
response = requests.post(
"https://openrouter.ai/api/v1/images",
headers={
"Authorization": f"Bearer {os.environ['OPENROUTER_API_KEY']}",
"Content-Type": "application/json"
},
json={
"model": "openai/gpt-image-1",
"prompt": (
"Keep the product shape and materials. Place it on a warm stone "
"surface with soft morning light and a clean commercial style."
),
"input_references": [
{
"type": "image_url",
"image_url": {
"url": reference_data_url,
},
},
],
},
timeout=120
)
# ... (код сохранения результата) ...GET /api/v1/images/models, чтобы убедиться, что input_references указан в supported_parameters.Этот подход позволяет сохранять узнаваемость бренда или продукта, одновременно давая творческую свободу модели в отношении композиции и стиля. Например, вы можете взять фото кроссовка и попросить модель поместить его на лунную поверхность или в футуристический город, сохраняя при этом точную детализацию самого кроссовка.
06Шаг 5: Рефакторинг для повторного использования
Когда ваш код работает стабильно, пришло время сделать его более модульным и удобным для повторного использования. Хорошей практикой является вынесение констант, которые редко меняются, в отдельный конфигурационный файл или переменные окружения. Сюда входят: slug модели, настройки маршрутизации провайдера, таймауты и директория для вывода.
Промпты, референсные изображения и пользовательские параметры должны оставаться в теле запроса, так как они меняются с каждой генерацией. Такой подход делает ваш код чище, упрощает тестирование и позволяет легко переключаться между моделями или провайдерами без изменения основной логики приложения. Вы можете создать функцию generate_image(prompt, reference=None), которая будет инкапсулировать всю логику отправки запроса и сохранения результата.

07Устранение неполадок и контроль затрат
Даже при тщательной разработке могут возникать ошибки. Вот наиболее частые проблемы и способы их решения:
- Отсутствует поле
data[0].b64_json: Сначала проверьте тело ответа на ошибки. Убедитесь, что вы отправили POST-запрос именно на/api/v1/imagesи выбрали модель, поддерживающую генерацию изображений. Некоторые модели OpenRouter предназначены только для текста или кода. - Ошибка 401 Unauthorized: Это почти всегда проблема с ключом. Проверьте, что переменная окружения
OPENROUTER_API_KEYустановлена и доступна скрипту. Не печатайте ключ в логах, но убедитесь, что он не пустой. Попробуйте экспортировать его заново в терминале. - Ошибка при использовании референса: Убедитесь, что модель поддерживает
input_references. Также проверьте формат Data URL. Он должен начинаться сdata:image/jpeg;base64,(илиimage/png) и содержать корректную Base64-строку без лишних пробелов или переносов строк. - Неожиданная стоимость: Перед запуском пакетных генераций ознакомьтесь с тарифами модели. Если модель поддерживает поле
usage.cost, логируйте его вместе с именем файла и промптом. Это поможет вам анализировать эффективность и планировать бюджет.
08Часто задаваемые вопросы
Могу ли я использовать OpenRouter для генерации изображений?
Да. Отправьте POST-запрос на /api/v1/images с моделью, поддерживающей генерацию изображений, промптом и вашим API-ключом. В ответе вы получите Base64-данные изображения, которые нужно декодировать и сохранить локально.
Как лучше всего описывать промпты?
Будьте конкретны. Описывайте субъект, окружение, композицию, освещение и стиль. Например, вместо "красивый кот" используйте "портрет рыжего кота в стиле масляной живописи, мягкое боковое освещение, детализированная шерсть". Чем точнее описание, тем лучше результат.
Какой API лучше для генерации изображений?
Выбор зависит от ваших требований к качеству, контролю, поддержке референсов, задержке и цене. OpenRouter является отличным выбором, если вам нужен доступ к множеству моделей через один API-ключ и единый формат запросов, что упрощает разработку и масштабирование.
09Что это значит на практике
Интеграция API генерации изображений через OpenRouter открывает широкие возможности для разработчиков. Вы можете создавать динамические иллюстрации для блогов, генерировать уникальные аватары для пользователей, создавать вариации продуктовых фото для интернет-магазинов без необходимости фотосессий, или даже использовать AI для прототипирования дизайна интерфейсов. Главное преимущество подхода OpenRouter — гибкость. Вы не привязаны к одному провайдеру и можете экспериментировать с разными моделями, выбирая оптимальное соотношение качества и стоимости. Следуйте приведенным в статье шагам, используйте лучшие практики обработки ошибок и контроля затрат, и вы сможете быстро внедрить мощные функции генерации изображений в свои приложения.
Источник: OpenRouter ↗
