Create images
Generates images from a text prompt, optionally with reference images for image-to-image. It is compatible with images.generate in the OpenAI Images API: the official OpenAI SDKs work once you set the Base URL to https://api.lyrouter.com/v1, and the image comes back in the same response, with no polling. Three families are available: Seedream 5.0, GPT-Image and Gemini Image. Parameters and the returned format differ by family; see the per-model sections below.
/v1/images/generationsAuthentication
Send your API key in a request header:
Authorization: Bearer <API Key>
Bearer is case-sensitive. You can use x-api-key: <API Key> instead; when both are present, only Authorization is read. Create API keys on the workspace's API Keys page. Your API key is used only to authenticate with LYRouter and is never forwarded to the upstream provider. See Base URLs and authentication.
Headers
| Header | Required | Description |
|---|---|---|
Content-Type |
Yes | application/json |
X-Gateway-Strict-Parameters |
No | When set to true (lowercase only), a request containing any parameter the gateway would drop returns 400 unsupported_parameters immediately, without calling the upstream and without charge. For which parameters are dropped, see "How each model is handled" below |
Request body
The parameters shared by all models are listed below; whether each one takes effect for a given family is described in the model sections that follow.
| Parameter | Type | Required | Description |
|---|---|---|---|
model |
string | Yes | Image model ID, such as bytedance/doubao-seedream-5.0-lite. Only concrete model IDs work: a virtual model @vmodel/<name> or lyrouter/auto returns 403 on image endpoints. Find available models in the model marketplace, or call List models |
prompt |
string | Yes | The prompt. May be omitted for layer decomposition on Seedream pro |
size |
string | No | Output size, written as width × height (such as 2048x2048) or as a tier name (such as 2K). Accepted forms and ranges differ by model; see the model sections |
n |
integer | No | Number of images. Forwarded unchanged to GPT-Image, up to 10. Seedream currently cannot use it to generate several images at once: n is forwarded to the upstream, but only 1 image comes back, with no error and no entry in X-Gateway-Unsupported-Parameters; send several requests if you need several images. Dropped for Gemini |
quality |
string | See description | Generation quality, used by the GPT-Image family; values differ by model, and it is required for gpt-image-2; dropped for Gemini |
response_format |
string | No | url or b64_json; takes effect only on Seedream (default url). GPT-Image and Gemini always return b64_json, and the gateway drops this parameter |
image |
string | array | No | Reference images for image-to-image. Seedream accepts a public URL or data:image/<format>;base64,<data>; Gemini accepts them too, written as described in Edit images |
user |
string | No | End-user identifier. Forwarded unchanged to Seedream and GPT-Image; dropped for Gemini |
Other parameters not in the table are forwarded unchanged to Seedream and GPT-Image, and whether they take effect depends on the model; Gemini drops all of them.
How each model is handled
The gateway decides per model how to handle the request body, which determines which parameters take effect:
| Model family | Model IDs | Handling | Parameters dropped by the gateway | Returned image |
|---|---|---|---|---|
| Seedream 5.0 | bytedance/doubao-seedream-5.0-probytedance/doubao-seedream-5.0-lite |
Pass-through | None | url (default) or b64_json |
| GPT-Image | openai/gpt-image-2openai/gpt-image-2.5-flareopenai/gpt-image-2.5-sunburst |
Pass-through | response_format; the two 2.5 models also drop stream and stream_options |
b64_json |
| Gemini Image | google/gemini-3-pro-imagegoogle/gemini-3.1-flash-image |
Contract translation | Every parameter except model, prompt, size and image; size is also dropped when it cannot be matched |
b64_json |
- Pass-through: the body is forwarded unchanged with only the model name rewritten, so other parameters the provider supports can be sent as well. If the upstream does not accept a parameter, you get the upstream's own error.
- Contract translation: the gateway translates the parameters into the provider's format and drops those it cannot translate.
- Dropped parameters are listed in the
X-Gateway-Unsupported-Parametersresponse header and the request still runs; withX-Gateway-Strict-Parameters: trueit returns 400 instead. Parameters passed through to the upstream are not affected by this header.
For a comparison of model capabilities and use cases, see Multimodal capabilities. The model marketplace is authoritative for which models exist; the sections below list each family's parameters and limits.
Seedream 5.0 (pro / lite)
Seedream models on Volcengine Ark. Pass-through; returns an image URL by default; one generation takes about 20 s.
| Parameter | Type | Description |
|---|---|---|
size |
string | Defaults to 2K. Tier names are recommended, with the aspect ratio described in words in the prompt: 1K, 1.5K and 2K on pro; 2K, 3K and 4K on lite. You can also write widthxheight: pro requires total pixels within [921600, 4624220], lite requires at least 3686400 (the smallest square is 1920x1920, so the common 1024x1024 is rejected), and the aspect ratio must be within [1/16, 16] on both. Do not mix the two forms |
response_format |
string | url (default) or b64_json |
image |
string | array | Reference images: a public URL or data:image/<format>;base64,<data> (<format> must be lowercase), no more than 10 recommended; see the limits below |
output_format |
string | png or jpeg. With layer decomposition it controls only the base image; layers are always PNG |
background |
string | opaque (default) or transparent. Image-to-image only, with exactly 1 input image that has an alpha channel |
watermark |
boolean | true adds an "AI生成" (AI-generated) watermark in the bottom-right corner. The watermark is added by default when the parameter is omitted; send false if you do not want it |
layer_decomposition |
boolean | Pro only, default false. true splits 1 input image into 1 base image and up to 16 PNG layers with alpha channels; image becomes required and must be exactly 1 image, and size accepts tier names only (default auto) |
optimize_prompt_options.mode |
string | Pro only. standard (default) or fast (faster, slightly lower quality) |
Reference image limits:
| Limit | Image generation | Layer decomposition |
|---|---|---|
| Format | jpeg, png, webp, bmp, tiff, gif, heic, heif | png, jpeg |
| Total pixels (width × height) | [196, 36000000] | [262144, 36000000] |
| Width and height | At least 14 px | — |
| Aspect ratio (width/height) | [1/16, 16] | [1/16, 16] |
| Size per image | ≤ 30 MB | ≤ 30 MB |
| Number of images | No more than 10 recommended; the provider currently does not reject more, but the output may be abnormal | Exactly 1 |
- Pro supports interactive editing: mark the position to change in the
promptwith<point>x y</point>or<bbox>x1 y1 x2 y2</bbox>(coordinates normalized to 0–999). - A layer decomposition response returns the base image and the layers together in
data[], with fields such asz_index,bounding_box,nameanddescription; each request reserves 17 images of rate-limit quota and returns the unused part when it completes. For the pixel sizes of each tier, coordinate conversion and reassembly, see Multimodal capabilities. - Other Volcengine Ark parameters can be written directly in the body. With the OpenAI Python SDK, put them in
extra_body, for exampleextra_body={"watermark": False}.
Billing: per image. Pro is tiered by resolution: 1K and 1.5K (≤ 2.61 megapixels) are one tier and 2K is another; layer decomposition has two more tiers (also split into 1K/1.5K and 2K) and is billed by the number of images actually produced (base image + each layer); pro reference images are billed as a separate item, with the first reference image in each request free and each additional one billed per image (this counts input reference images, not output images). Lite has a single tier. 1.5K costs the same as 1K and looks better, so prefer 1.5K unless you have a reason not to.
curl https://api.lyrouter.com/v1/images/generations \
-H "Authorization: Bearer $LYROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "bytedance/doubao-seedream-5.0-lite",
"prompt": "A shiba inu in sunglasses on a surfboard, sunset sea, cinematic, wide landscape composition",
"size": "2K",
"watermark": false
}'
GPT-Image (2 / 2.5-flare / 2.5-sunburst)
Pass-through. Parameters match the OpenAI image API, and the result is always b64_json.
| Parameter | Type | Description |
|---|---|---|
quality |
string | Values differ by model; see the table below. Pass it explicitly for every GPT-Image model |
size |
string | widthxheight only; tier names are not accepted (4K returns Invalid size '4K'. Expected WIDTHxHEIGHT, for example '1824x1024'.). Must meet the four hard constraints below, or the request returns 400 |
n |
integer | Number of images, up to 10 |
background |
string | transparent, opaque or auto |
output_format |
string | Output format. gpt-image-2 accepts only png and jpeg, and webp returns 400 Invalid value: 'webp'. Supported values are: 'png' and 'jpeg'.; the 2.5 family accepts png, jpeg and webp |
moderation |
string | auto or low |
user |
string | End-user identifier |
response_format |
— | Dropped by the gateway and listed in the response header: this family always returns b64_json, and the upstream sometimes accepts the parameter and sometimes rejects it |
stream, stream_options |
— | Dropped by the gateway for the 2.5 family (an upstream stream makes the request fail); do not send stream to gpt-image-2 either |
quality values:
| Model | Values | Default |
|---|---|---|
gpt-image-2 |
low, medium, high, auto |
None; required: omitting it returns 400 intermittently (INVALID_REQUEST_BODY); auto behaves as low in measurements |
gpt-image-2.5-flare, gpt-image-2.5-sunburst |
low, medium, high, xhigh, max, auto |
low (auto behaves like low in measurements) |
Whether xhigh and max are available depends on the upstream account, so they may be rejected; if you get Invalid value: 'xhigh', use high instead.
The four hard constraints on size, checked by the provider; violating any one returns 400:
| Constraint | Provider error text | Examples |
|---|---|---|
| Width and height both divisible by 16 | Invalid size '<width>x<height>'. Width and height must both be divisible by 16. |
1008x1008 works; 1254x1254 and 1312x1199 are rejected |
| Longest edge no more than 3840 | Invalid size '<width>x<height>'. The longest edge must be less than or equal to 3840. |
3840x2160 works; 4096x4096 and 1024x4096 are rejected |
| At least about 1 M pixels in total | Invalid size '<width>x<height>'. Requested resolution is below the current minimum pixel budget. |
1008x1008 (about 1.02 M) works; 512x1024 (about 0.52 M) is rejected |
| At most about 8.3 M pixels in total | Invalid size '<width>x<height>'. Requested resolution exceeds the current pixel budget. |
3840x2160 (about 8.29 M) works; 3840x2176 (about 8.36 M) is rejected |
- Latency: one generation took about 20–60 s in measurements, occasionally longer (about 83 s at most); an upstream 400 caused by a bad parameter came back within 2 s. Set the client timeout in minutes, at least 300 s.
Billing: per token, with input text, input image and output priced separately; the upstream reports text and image tokens separately in usage.input_tokens_details, so a prompt of the same length costs a different amount with and without an image. Cache hits have their own price; usage from the 2.5 family has no cache fields, so that item does not occur for it.
Output tokens depend mainly on quality: at 1024x1024, the 2.5 family produces 196 output tokens at low and 7024 at max, so the top level is about 36 times the bottom one. A level with the same name is not the same amount on the two generations: high on the 2.5 family produces as many output tokens as medium on gpt-image-2, so compare models by tokens, not by level name. Also, for GPT-Image more pixels do not mean a higher cost (this applies to GPT-Image only): output tokens do not grow with pixel count; for example, 1024x1536 (about 1.57 million pixels) produces fewer output tokens than 1024x1024 (about 1.05 million pixels).
Gemini Image (3 Pro / 3.1 Flash)
Contract translation: the gateway translates the request into Gemini's native generateContent format, uses only the parameters marked as applied below, and drops the rest, listing them in the response header. The result is always b64_json and cannot be a URL. One generation took 20–250 s in measurements (gemini-3-pro-image), and occasionally had not returned after 300 s.
| Parameter | Applied | Description |
|---|---|---|
prompt |
Applied | Required; omitting it or sending it empty returns 400 prompt is required for this model |
size |
Applied | See the table below |
image |
Applied | Reference images, written as described in Edit images |
n |
Dropped | Send several requests if you need several images |
quality |
Dropped | Gemini has no equivalent parameter |
response_format |
Dropped | Only b64_json can be returned |
user and other parameters |
Dropped | — |
How you write size determines the aspect ratio and the resolution:
| Form | What the gateway does | Effect |
|---|---|---|
Tier name: 1K, 2K, 4K |
Passes it as the resolution tier | Controls resolution; the aspect ratio is the upstream default |
widthxheight, such as 1376x768 |
Matches the closest supported ratio (within 2%), then picks the resolution tier by rounding the long edge up | Controls both ratio and resolution |
Ratio more than 2% off, such as 1000x700 |
Sends none of size (neither ratio nor tier), and counts size as dropped |
Returns 200, produces an image and is billed as usual, but with the upstream's default ratio and resolution; the only signal is the response header X-Gateway-Unsupported-Parameters: size. Returns 400 in strict mode |
Ratio string, such as 16:9 |
Passes it unchanged as a tier name | The upstream does not recognize it and the request returns 400 (upstream_rejected). For 16:9, write a size with that ratio, such as 1376x768 |
The provider rejects the 512 tier in production, on both models; do not use it.
Supported aspect ratios: 1:1, 2:3, 3:2, 3:4, 4:3, 4:5, 5:4, 9:16, 16:9, 21:9, 1:4, 4:1, 1:8, 8:1. When you write a width and height, the tier is picked by rounding the long edge up, capped at 4K; a long edge of 704 or less is mapped to 512 by the gateway and may be rejected as well, so keep the long edge above 704. The same tier produces different output tokens on the two models:
| Long edge | Tier | gemini-3-pro-image output tokens |
gemini-3.1-flash-image output tokens |
|---|---|---|---|
| ≤ 1376 | 1K |
1120 | 1120 |
| ≤ 2816 | 2K |
1120 (the 2K tier has no effect; same as 1K) | 1680 |
| Larger (capped) | 4K |
2000 | 2520 |
The output size is chosen by the provider from the ratio and resolution tiers and does not equal the requested width and height; for example, gemini-3-pro-image returns a 5504x3072 image for a 4096x2304 request. Rely on the actual width and height of the returned image.
For example, 1024x1024 maps to 1:1 + 1K, and 2048x2048 maps to 1:1 + 2K. For 16:9 at 4K, write 4096x2304; do not copy 5632x3072: its ratio is 1.833, more than 2% off 16:9, so the whole size is dropped. In production, send X-Gateway-Strict-Parameters: true so that such a request returns 400 instead.
Billing: per token, with input, output and thinking priced separately; reference images count toward "input". Thinking tokens appear only when the upstream returns them (gemini-3-pro-image), in usage.output_tokens_details.reasoning_tokens, and usage.total_tokens includes them. Thinking tokens vary from call to call and are decided by the model: production measurements range from 115 to 316, with a median of about 220, about 1.5% of a call's cost. Budget about 220 per call.
{
"data": [{ "b64_json": "iVBORw0KGgoAAAANSUhEUgAA…" }],
"usage": {
"input_tokens": 7,
"output_tokens": 1120,
"total_tokens": 1339,
"output_tokens_details": { "reasoning_tokens": 212 }
}
}
Request examples
The examples below use openai/gpt-image-2 and save the returned Base64 image to a file. With Seedream, the image comes back as a URL by default: read data[0].url and download it promptly.
curl https://api.lyrouter.com/v1/images/generations \
--max-time 300 \
-H "Authorization: Bearer $LYROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-image-2",
"prompt": "A shiba inu in sunglasses on a surfboard, sunset sea, cinematic",
"size": "1024x1024",
"quality": "medium"
}'
import base64
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["LYROUTER_API_KEY"],
base_url="https://api.lyrouter.com/v1",
timeout=300,
)
result = client.images.generate(
model="openai/gpt-image-2",
prompt="A shiba inu in sunglasses on a surfboard, sunset sea, cinematic",
size="1024x1024",
quality="medium",
)
with open("shiba.png", "wb") as f:
f.write(base64.b64decode(result.data[0].b64_json))
print(result.usage)
import { writeFileSync } from "node:fs";
import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.LYROUTER_API_KEY,
baseURL: "https://api.lyrouter.com/v1",
timeout: 300_000,
});
const result = await client.images.generate({
model: "openai/gpt-image-2",
prompt: "A shiba inu in sunglasses on a surfboard, sunset sea, cinematic",
size: "1024x1024",
quality: "medium",
});
writeFileSync("shiba.png", Buffer.from(result.data[0].b64_json, "base64"));
console.log(result.usage);
Response
A successful request returns an object in the OpenAI Images format, with the images in the top-level data array; an error returns an error object. The two 200 examples below are Seedream (returning a URL) and GPT-Image (returning Base64); the 400 is Gemini receiving parameters it does not support with strict mode on; the 403 means the model is not enabled, or a virtual model or Auto was used.
{
"model": "doubao-seedream-5-0-260128",
"created": 1789454321,
"data": [
{
"url": "https://ark-acg-cn-beijing.tos-cn-beijing.volces.com/…",
"size": "1920x1920"
}
],
"usage": {
"generated_images": 1,
"output_tokens": 14400,
"total_tokens": 14400
}
}
{
"created": 1791950400,
"data": [
{ "b64_json": "iVBORw0KGgoAAAANSUhEUgAA…" }
],
"size": "1024x1024",
"quality": "medium",
"output_format": "png",
"background": "opaque",
"usage": {
"input_tokens": 29,
"input_tokens_details": { "text_tokens": 29, "image_tokens": 0 },
"output_tokens": 1756,
"total_tokens": 1785
}
}
{
"error": {
"message": "unsupported parameters for this model: n,quality",
"type": "invalid_request_error",
"code": "unsupported_parameters"
}
}
{
"error": {
"message": "Model is not available in the model plaza",
"type": "access_denied",
"code": "model_not_available"
}
}
| Field | Description |
|---|---|
created |
Unix timestamp (seconds). Not returned by Gemini |
model |
The provider-side model name (returned by Seedream), such as doubao-seedream-5-0-260128; it differs from the model ID in the request |
data |
Array of results; it is an array even for a single image |
data[].url |
Image download URL, returned by Seedream by default. It is a temporary URL signed by the provider and expires after about 24 hours; download and store the image promptly |
data[].b64_json |
The image encoded in Base64. Always returned by GPT-Image and Gemini; returned by Seedream when response_format is b64_json |
data[].size |
The size actually generated (returned by Seedream) |
data[].output_format |
The image format (returned by Seedream pro) |
size, quality, output_format, background |
The generation settings actually used (returned by GPT-Image) |
usage |
Metering information; the fields vary by model, see the table below |
Fields in usage
| Model family | Fields in usage |
Metered by |
|---|---|---|
| Seedream | generated_images (number of images), output_tokens, total_tokens; pro also returns input_images (number of input reference images) when reference images are sent |
Image |
| GPT-Image | input_tokens, input_tokens_details.text_tokens / image_tokens, output_tokens, total_tokens |
Token |
| Gemini | input_tokens, output_tokens, total_tokens, plus output_tokens_details.reasoning_tokens when there are thinking tokens |
Token |
Do not assume a field is always present; check before reading it. For how each model is billed, see the model sections above; prices are those shown in the model marketplace in the console, and the actual charge for each call is in the request logs.
Response headers
| Header | Description |
|---|---|
X-Gateway-Unsupported-Parameters |
Present when the gateway dropped parameters; the value is a comma-separated list of parameter names, such as n,quality. The request still ran, and the listed parameters did not take effect |
When quotas are configured, the response also carries the x-aigw-quota-* headers; see Gateway headers and extensions.
To read the dropped parameters (the Python and Node.js examples reuse client from the examples above):
curl -sS -D - -o result.json https://api.lyrouter.com/v1/images/generations \
--max-time 300 \
-H "Authorization: Bearer $LYROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"google/gemini-3.1-flash-image","prompt":"A single green leaf, flat design","size":"1376x768","n":2}'
# The response headers include: X-Gateway-Unsupported-Parameters: n
raw = client.images.with_raw_response.generate(
model="google/gemini-3.1-flash-image",
prompt="A single green leaf, flat design",
size="1376x768",
n=2,
)
print(raw.headers.get("X-Gateway-Unsupported-Parameters")) # n
result = raw.parse()
const { data: result, response } = await client.images
.generate({
model: "google/gemini-3.1-flash-image",
prompt: "A single green leaf, flat design",
size: "1376x768",
n: 2,
})
.withResponse();
console.log(response.headers.get("X-Gateway-Unsupported-Parameters")); // n
Gateway behavior
Compared with calling the upstream directly, calling through LYRouter differs in these ways:
-
Only the requested model is used: image endpoints never switch to another model. When the same model has several channels, the gateway tries the other channels in turn after a failure; virtual models, Auto smart routing and fallback to the workspace's Default Model do not apply to image endpoints. See Retries and fallback.
-
Dropped parameters and strict mode: the gateway drops only the parameters listed in "How each model is handled" above and lists them in the
X-Gateway-Unsupported-Parametersresponse header. In production, check this header, or sendX-Gateway-Strict-Parameters: trueso that a request containing a parameter that would be dropped returns 400 immediately, without calling the upstream and without charge. With the SDKs, pass it asextra_headers={"X-Gateway-Strict-Parameters": "true"}(Python) or the request option{ headers: { "X-Gateway-Strict-Parameters": "true" } }(Node.js). Parameters passed through to the upstream are not affected by this header; the upstream decides whether to accept them. -
Errors declared in a successful upstream response: when Gemini's upstream rejects a request, it may return HTTP 200 with no image. The gateway rewrites this into an error response, taking the status code from the error the upstream declared: when the upstream rejected the request,
error.codeisupstream_rejectedanderror.messageis the upstream's original text; when no image was produced, the code isupstream_no_artifactwithupstream_finish_reason(such asNO_IMAGEorSAFETY).upstream_statuskeeps the upstream's original 200. These errors are not retried on another channel; change the prompt or parameters as indicated:{ "error": { "message": "upstream produced no image (finishReason: NO_IMAGE)", "type": "invalid_request_error", "code": "upstream_no_artifact", "upstream_status": 200, "upstream_finish_reason": "NO_IMAGE", "generated_by": "ai-gateway" } } -
Upstream errors are returned unchanged: parameter errors for pass-through models come from the upstream, with the upstream's format and error codes; Seedream, for example, returns
{"error":{"code":"InvalidParameter","message":"..."}}. When the upstream returns an error status with no body, the gateway fills in an error body withupstream_statusandgenerated_by: "ai-gateway", plusupstream_request_idwhen the upstream supplied a request ID; give that ID to the provider when reporting an issue. -
Images are not stored in logs: Base64 images in requests and responses are replaced in the logs with a
[base64 <bytes>B #<CRC32>]summary. Not seeing the image in the log details does not mean the request failed; the image is in the response body. For models that return a URL, the URL is kept in the logs. -
Timeouts: image endpoints are synchronous. Seedream takes about 20 s, the GPT-Image family about 20–60 s in measurements, and Gemini 20–250 s in measurements, occasionally more than 300 s. Set the client timeout in minutes, at least 300 s, rather than the 30 s you use for text; after a client timeout, do not resubmit right away; first check the result of the previous request in the request logs.
Common errors
Errors returned by the gateway take the form {"error":{"message":"...","type":"...","code":"..."}}; parameter errors for pass-through models come from the upstream in the upstream's format.
| Status code | error.message |
error.code |
Cause and fix |
|---|---|---|---|
| 400 | you must provide a model parameter |
missing_model |
No model was given and the workspace has no Default Model. Always specify the model ID on image endpoints |
| 400 | unsupported parameters for this model: <names> |
unsupported_parameters |
X-Gateway-Strict-Parameters: true was sent and the request contains parameters that would be dropped. Remove the listed parameters, or use a model that supports them |
| 400 | prompt is required for this model |
invalid_parameter |
No prompt, or an empty one, was sent to Gemini |
| 400 | The upstream's text, such as Request contains an invalid argument. |
upstream_rejected |
Gemini's upstream rejected the request, for example because size was written as 16:9. Fix the parameters as the text says |
| 400 | upstream produced no image (finishReason: <reason>) |
upstream_no_artifact |
Gemini produced no image. Change the prompt or content according to upstream_finish_reason and retry |
| 400 | The parameter `size` specified in the request is not valid: image size must be at least 3686400 pixels |
InvalidParameter |
The size is below Seedream lite's minimum. Use the 2K tier or a larger size, such as 1920x1920 |
| 400 | Invalid size '<width>x<height>'. Width and height must both be divisible by 16. |
— | The GPT-Image width or height is not a multiple of 16; returned by the upstream |
| 400 | Invalid size '<width>x<height>'. The longest edge must be less than or equal to 3840., Invalid size '<width>x<height>'. Requested resolution is below the current minimum pixel budget., Invalid size '<width>x<height>'. Requested resolution exceeds the current pixel budget. |
— | The GPT-Image size has a longest edge above 3840, or its total pixel count is not between about 1 M and about 8.3 M; returned by the upstream. Adjust it against the four hard constraints on size above |
| 400 | Invalid size '4K'. Expected WIDTHxHEIGHT, for example '1824x1024'. |
— | A tier name was sent to GPT-Image. Write it as widthxheight |
| 400 | Invalid value: 'xhigh' |
— | The upstream account does not support the xhigh / max levels of quality (availability depends on the upstream account). Use high |
| 400 | The upstream's text | INVALID_REQUEST_BODY |
The GPT-Image request body is invalid; first check that quality is set: omitting it on gpt-image-2 returns 400 intermittently |
| 400 | This model does not support the images API |
unsupported_model_api |
The interfaces the model declares (api_types in List models) do not include the image endpoints, for example a chat model used on this endpoint. A chat model that declares no api_types does not trigger this error: the request is forwarded upstream and may return 404 upstream_not_found, or a 200 with no image (such as {"data":{"content":null}}). Use only image models on image endpoints |
| 403 | Model is not available in the model plaza |
model_not_available |
The workspace has not enabled this model, or @vmodel/<name> or lyrouter/auto was used. Ask an administrator to enable it in the model marketplace, or use a concrete model ID that is enabled |
- For 401 / 403 authentication issues, see 401 / 403: authentication and access; for 429, see 429: rate limits and quotas.
- 500 / 504 mean the connection to the upstream failed or the wait for the upstream timed out; the response body is an HTML page rather than JSON. See Timeouts and interrupted streams.
- For the full list, see Errors and request identifiers.