| name | openrouter-image-api |
| description | Complete reference for generating images with OpenRouter's dedicated Image API. ALWAYS use this skill when the user mentions: "openrouter image", "openrouter image generation", "generate images with openrouter", "openrouter /api/v1/images", "image models on openrouter", "openrouter flux", "openrouter dalle", "openrouter gpt-image", "openrouter stable diffusion", "openrouter seedream", "openrouter recraft", "text-to-image via openrouter", or any request to list, discover, or use image-generating models through OpenRouter. Also trigger when the user asks about image-to-image (img2img) via OpenRouter, streaming image generation, aspect ratio or resolution options, or provider-specific image params on OpenRouter. If they're building an app that generates images and OpenRouter is in the mix at all — use this skill.
|
OpenRouter Image Generation API
OpenRouter provides a dedicated Image API at /api/v1/images (separate from the chat
completions endpoint) for text-to-image and image-to-image generation.
Base URL: https://openrouter.ai
Image endpoint: POST /api/v1/images
Image models list: GET /api/v1/images/models
Quick Start
const response = await fetch("https://openrouter.ai/api/v1/images", {
method: "POST",
headers: {
"Authorization": `Bearer ${OPENROUTER_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "black-forest-labs/flux-1.1-pro",
prompt: "a red panda astronaut floating in space, studio lighting",
}),
});
const result = await response.json();
Response images are returned as base64-encoded bytes in data[0].b64_json.
Model Discovery
Dedicated Image Models Endpoint (preferred)
GET https://openrouter.ai/api/v1/images/models
Returns all image-capable models with full capability descriptors, per-endpoint pricing, and
supported parameters. Always use this to check what a model supports before using it.
General Models API (filtered)
GET https://openrouter.ai/api/v1/models?output_modalities=image
Per-Endpoint Details
GET https://openrouter.ai/api/v1/images/models/{model-id}/endpoints
Returns provider-by-provider breakdown with definitive supported params, pricing, and
passthrough options. Use this when you need to know exact cost or provider-specific params.
→ See references/models.md for the current model list with capabilities and pricing.
Request Parameters
| Parameter | Type | Required | Description |
|---|
model | string | ✅ | Model slug (e.g. black-forest-labs/flux-1.1-pro) |
prompt | string | ✅ | Text description of the desired image |
n | integer | — | Number of images (1–10, not all models support >1) |
resolution | string | — | Tier: 512, 1K, 2K, 4K |
aspect_ratio | string | — | 1:1, 16:9, 9:16, 4:3, 3:4, 3:2, 2:3, 4:5, 5:4, 1:2, 2:1, 9:21, 21:9, etc. |
size | string | — | Convenience shorthand — tier ("2K") or explicit ("2048x2048") |
quality | string | — | auto, low, medium, high |
output_format | string | — | png, jpeg, webp |
background | string | — | auto, transparent, opaque (transparent requires png/webp) |
output_compression | integer | — | 0–100 for webp/jpeg only |
seed | integer | — | Deterministic generation (where supported) |
stream | boolean | — | SSE streaming for progressive renders |
input_references | array | — | Reference images for img2img |
provider.options | object | — | Provider-specific passthrough params |
Always check supported_parameters from the models endpoint — not every model supports
every field. Unsupported params are silently ignored or may error.
Response Format
Standard (buffered)
{
"created": 1748372400,
"data": [
{ "b64_json": "<base64-encoded-image>" }
],
"usage": {
"prompt_tokens": 0,
"completion_tokens": 4175,
"total_tokens": 4175,
"cost": 0.04
}
}
For vector outputs (e.g. Recraft SVG models), media_type is included:
{ "b64_json": "...", "media_type": "image/svg+xml" }
Decoding in TypeScript
const imgData = result.data[0].b64_json;
const buffer = Buffer.from(imgData, "base64");
await fs.writeFile("output.png", buffer);
const img = document.createElement("img");
img.src = `data:image/png;base64,${imgData}`;
Image Configuration
Resolution & Aspect Ratio
{
model: "bytedance-seed/seedream-4.5",
prompt: "a landscape photo",
resolution: "2K",
aspect_ratio: "16:9"
}
resolution and aspect_ratio can be combined
size is a convenience alias — pass "2K" or "2048x2048". Don't mix size with
resolution/aspect_ratio — conflicting values are rejected.
Quality & Format
{
model: "openai/gpt-image-1",
prompt: "a product photo on white background",
quality: "high",
output_format: "png",
background: "transparent"
}
Multiple Images
{ model: "openai/gpt-image-1", prompt: "a cute cat", n: 4 }
Image-to-Image (Reference Images)
Pass reference images via input_references:
{
model: "openai/gpt-image-1",
prompt: "make this scene look like a watercolor painting",
input_references: [
{
type: "image_url",
image_url: {
url: "https://example.com/photo.jpg"
}
}
]
}
Number of accepted references varies by provider — check supported_parameters.
Streaming Image Generation
Models with supports_streaming: true return partial renders via SSE:
const response = await fetch("https://openrouter.ai/api/v1/images", {
method: "POST",
headers: { "Authorization": `Bearer ${KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
model: "openai/gpt-image-1",
prompt: "a detailed landscape painting",
stream: true,
}),
});
for await (const chunk of response.body!) {
const text = new TextDecoder().decode(chunk);
for (const line of text.split("\n")) {
if (!line.startsWith("data: ") || line === "data: [DONE]") continue;
const event = JSON.parse(line.slice(6));
if (event.type === "image_generation.partial_image") {
} else if (event.type === "image_generation.completed") {
} else if (event.type === "error") {
}
}
}
SSE event types:
image_generation.partial_image — progressive render chunk
image_generation.completed — final image + usage/cost
error — generation failed
data: [DONE] — stream end sentinel
Provider-Specific Options
Pass provider-specific params using the provider_slug from the endpoints API:
{
model: "black-forest-labs/flux.2-pro",
prompt: "a dramatic portrait",
provider: {
options: {
"black-forest-labs": {
steps: 40,
guidance: 3
}
}
}
}
Check allowed_passthrough_parameters in the endpoint record for accepted keys.
Capability Descriptor Types
When reading supported_parameters from the API:
| Type | Shape | Meaning |
|---|
enum | { type: "enum", values: ["1K","2K","4K"] } | Only these values accepted |
range | { type: "range", min: 0, max: 100 } | Any integer in range |
boolean | { type: "boolean" } | Supported (present = yes, absent = no) |
An absent key means that parameter is unsupported by that endpoint.
Pricing Notes
- Pricing is per-endpoint (provider), not per model
billable types: output_image, input_image, input_reference
unit types: image, megapixel, token
- Resolution-tiered models have variant tiers (e.g.
2k, 4k) in the pricing array
usage.cost in the response is the actual USD charged
Gotchas & Common Issues
- ❌ Wrong endpoint — image generation uses
/api/v1/images, NOT /api/v1/chat/completions
- ❌ Unsupported params silently vary — always check
supported_parameters first
- ❌ Conflicting size params — don't use
size together with resolution/aspect_ratio
- ❌ Transparent background — only works with
output_format: "png" or "webp"
- ❌ n > 1 — not universally supported; check model caps
- ✅ Model IDs change — always fetch
/api/v1/images/models at runtime for current list
Reference Files
references/models.md — Current image models, providers, key capabilities, and pricing tiers
references/examples.md — Full TypeScript/Node.js code examples for common patterns