curl --request POST \
--url https://api.infery.ai/v1/images/generations \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"model": "<string>",
"prompt": "<string>",
"stream": false,
"n": 1,
"size": "<string>",
"quality": "<string>",
"response_format": "url",
"aspect_ratio": "<string>",
"image_size": "<string>",
"strength": 0.35,
"output_compression": 123,
"negative_prompt": "<string>",
"seed": 123,
"steps": 4,
"prompt_extend": false
}
'import requests
url = "https://api.infery.ai/v1/images/generations"
payload = {
"model": "<string>",
"prompt": "<string>",
"stream": False,
"n": 1,
"size": "<string>",
"quality": "<string>",
"response_format": "url",
"aspect_ratio": "<string>",
"image_size": "<string>",
"strength": 0.35,
"output_compression": 123,
"negative_prompt": "<string>",
"seed": 123,
"steps": 4,
"prompt_extend": False
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
model: '<string>',
prompt: '<string>',
stream: false,
n: 1,
size: '<string>',
quality: '<string>',
response_format: 'url',
aspect_ratio: '<string>',
image_size: '<string>',
strength: 0.35,
output_compression: 123,
negative_prompt: '<string>',
seed: 123,
steps: 4,
prompt_extend: false
})
};
fetch('https://api.infery.ai/v1/images/generations', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.infery.ai/v1/images/generations",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'model' => '<string>',
'prompt' => '<string>',
'stream' => false,
'n' => 1,
'size' => '<string>',
'quality' => '<string>',
'response_format' => 'url',
'aspect_ratio' => '<string>',
'image_size' => '<string>',
'strength' => 0.35,
'output_compression' => 123,
'negative_prompt' => '<string>',
'seed' => 123,
'steps' => 4,
'prompt_extend' => false
]),
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.infery.ai/v1/images/generations"
payload := strings.NewReader("{\n \"model\": \"<string>\",\n \"prompt\": \"<string>\",\n \"stream\": false,\n \"n\": 1,\n \"size\": \"<string>\",\n \"quality\": \"<string>\",\n \"response_format\": \"url\",\n \"aspect_ratio\": \"<string>\",\n \"image_size\": \"<string>\",\n \"strength\": 0.35,\n \"output_compression\": 123,\n \"negative_prompt\": \"<string>\",\n \"seed\": 123,\n \"steps\": 4,\n \"prompt_extend\": false\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.infery.ai/v1/images/generations")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"<string>\",\n \"prompt\": \"<string>\",\n \"stream\": false,\n \"n\": 1,\n \"size\": \"<string>\",\n \"quality\": \"<string>\",\n \"response_format\": \"url\",\n \"aspect_ratio\": \"<string>\",\n \"image_size\": \"<string>\",\n \"strength\": 0.35,\n \"output_compression\": 123,\n \"negative_prompt\": \"<string>\",\n \"seed\": 123,\n \"steps\": 4,\n \"prompt_extend\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.infery.ai/v1/images/generations")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"model\": \"<string>\",\n \"prompt\": \"<string>\",\n \"stream\": false,\n \"n\": 1,\n \"size\": \"<string>\",\n \"quality\": \"<string>\",\n \"response_format\": \"url\",\n \"aspect_ratio\": \"<string>\",\n \"image_size\": \"<string>\",\n \"strength\": 0.35,\n \"output_compression\": 123,\n \"negative_prompt\": \"<string>\",\n \"seed\": 123,\n \"steps\": 4,\n \"prompt_extend\": false\n}"
response = http.request(request)
puts response.read_body{
"created": 1713204900,
"data": [
{
"url": "https://example.com/image.png",
"b64_json": "<string>",
"revised_prompt": "<string>",
"file_id": "file_1hR9xTPZqK4mVLc2nJ7fY5wB"
}
],
"credits_used": 40
}{
"error": {
"message": "Model not found",
"type": "invalid_request_error",
"code": "model_not_found",
"param": "model",
"job_id": "job_1hR9xTPZqK4mVLc2nJ7fY5wB"
}
}{
"error": {
"message": "Model not found",
"type": "invalid_request_error",
"code": "model_not_found",
"param": "model",
"job_id": "job_1hR9xTPZqK4mVLc2nJ7fY5wB"
}
}{
"error": {
"message": "Model not found",
"type": "invalid_request_error",
"code": "model_not_found",
"param": "model",
"job_id": "job_1hR9xTPZqK4mVLc2nJ7fY5wB"
}
}Generate an image
POST /v1/images/generations — text-to-image generation.
curl --request POST \
--url https://api.infery.ai/v1/images/generations \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"model": "<string>",
"prompt": "<string>",
"stream": false,
"n": 1,
"size": "<string>",
"quality": "<string>",
"response_format": "url",
"aspect_ratio": "<string>",
"image_size": "<string>",
"strength": 0.35,
"output_compression": 123,
"negative_prompt": "<string>",
"seed": 123,
"steps": 4,
"prompt_extend": false
}
'import requests
url = "https://api.infery.ai/v1/images/generations"
payload = {
"model": "<string>",
"prompt": "<string>",
"stream": False,
"n": 1,
"size": "<string>",
"quality": "<string>",
"response_format": "url",
"aspect_ratio": "<string>",
"image_size": "<string>",
"strength": 0.35,
"output_compression": 123,
"negative_prompt": "<string>",
"seed": 123,
"steps": 4,
"prompt_extend": False
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
model: '<string>',
prompt: '<string>',
stream: false,
n: 1,
size: '<string>',
quality: '<string>',
response_format: 'url',
aspect_ratio: '<string>',
image_size: '<string>',
strength: 0.35,
output_compression: 123,
negative_prompt: '<string>',
seed: 123,
steps: 4,
prompt_extend: false
})
};
fetch('https://api.infery.ai/v1/images/generations', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.infery.ai/v1/images/generations",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'model' => '<string>',
'prompt' => '<string>',
'stream' => false,
'n' => 1,
'size' => '<string>',
'quality' => '<string>',
'response_format' => 'url',
'aspect_ratio' => '<string>',
'image_size' => '<string>',
'strength' => 0.35,
'output_compression' => 123,
'negative_prompt' => '<string>',
'seed' => 123,
'steps' => 4,
'prompt_extend' => false
]),
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.infery.ai/v1/images/generations"
payload := strings.NewReader("{\n \"model\": \"<string>\",\n \"prompt\": \"<string>\",\n \"stream\": false,\n \"n\": 1,\n \"size\": \"<string>\",\n \"quality\": \"<string>\",\n \"response_format\": \"url\",\n \"aspect_ratio\": \"<string>\",\n \"image_size\": \"<string>\",\n \"strength\": 0.35,\n \"output_compression\": 123,\n \"negative_prompt\": \"<string>\",\n \"seed\": 123,\n \"steps\": 4,\n \"prompt_extend\": false\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.infery.ai/v1/images/generations")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"<string>\",\n \"prompt\": \"<string>\",\n \"stream\": false,\n \"n\": 1,\n \"size\": \"<string>\",\n \"quality\": \"<string>\",\n \"response_format\": \"url\",\n \"aspect_ratio\": \"<string>\",\n \"image_size\": \"<string>\",\n \"strength\": 0.35,\n \"output_compression\": 123,\n \"negative_prompt\": \"<string>\",\n \"seed\": 123,\n \"steps\": 4,\n \"prompt_extend\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.infery.ai/v1/images/generations")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"model\": \"<string>\",\n \"prompt\": \"<string>\",\n \"stream\": false,\n \"n\": 1,\n \"size\": \"<string>\",\n \"quality\": \"<string>\",\n \"response_format\": \"url\",\n \"aspect_ratio\": \"<string>\",\n \"image_size\": \"<string>\",\n \"strength\": 0.35,\n \"output_compression\": 123,\n \"negative_prompt\": \"<string>\",\n \"seed\": 123,\n \"steps\": 4,\n \"prompt_extend\": false\n}"
response = http.request(request)
puts response.read_body{
"created": 1713204900,
"data": [
{
"url": "https://example.com/image.png",
"b64_json": "<string>",
"revised_prompt": "<string>",
"file_id": "file_1hR9xTPZqK4mVLc2nJ7fY5wB"
}
],
"credits_used": 40
}{
"error": {
"message": "Model not found",
"type": "invalid_request_error",
"code": "model_not_found",
"param": "model",
"job_id": "job_1hR9xTPZqK4mVLc2nJ7fY5wB"
}
}{
"error": {
"message": "Model not found",
"type": "invalid_request_error",
"code": "model_not_found",
"param": "model",
"job_id": "job_1hR9xTPZqK4mVLc2nJ7fY5wB"
}
}{
"error": {
"message": "Model not found",
"type": "invalid_request_error",
"code": "model_not_found",
"param": "model",
"job_id": "job_1hR9xTPZqK4mVLc2nJ7fY5wB"
}
}curl https://api.infery.ai/v1/images/generations \
-H "Authorization: Bearer $INFERY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "dall-e-3",
"prompt": "An isometric dev dashboard, neon green accents, dark theme",
"size": "1024x1024",
"n": 1
}'
Sample output

nano-banana).
Works unchanged with the OpenAI SDK: client.images.generate(...).
Response formats
response_format: "url"(default) → a URL, ephemeral (~1 hour). Download within that window if you need to keep it.response_format: "b64_json"→ inline base64 PNG. DALL-E models honour this; GPT Image models always return base64 regardless.
file_id next to each url — already a permanent handle on bytes in your workspace storage. When file_id is absent, upload the decoded bytes via POST /v1/files to persist them.
A generation that runs past the 5-minute wait budget answers 504 with a job_id in the error body rather than an image. The job continues and is still billed; collect the result from GET /v1/images/jobs/{job_id}.
Supported models
See Models catalog filtered to image modality. OpenAI (DALL·E), Google (Imagen, Gemini Image), xAI (Grok Image), Alibaba (Qwen Image), Suno-music, FLUX (self-hosted) — all accessed by slug.Aspect ratios and sizes
Per-model; common values:1024x1024, 1792x1024, 1024x1792, 512x512. Check a model’s _infery.allowed_params.sizes in GET /v1/models.Authorizations
API key in format: Bearer inf_***
Body
Model ID to use for generation
Text prompt describing the image to generate
Read the generation as Server-Sent Events instead of waiting for a JSON body. A BODY field, and a real boolean — the handler reads body.stream. /v1/music/generations made the opposite choice and takes its flag as the QUERY parameter ?stream=true, so the two are not interchangeable: ?stream=true is ignored here, and a stream key in music’s body is ignored there. A streaming request also never takes the durable media-job path and has no fallback, because the SSE headers are flushed before the provider is called.
Number of images (model-specific max: DALL-E 3=1, Imagen=4, GPT Image=4, DALL-E 2=10)
Image size. DALL-E: 256x256-1792x1024. GPT Image: 1024x1024/1024x1536/1536x1024/auto
DALL-E: standard/hd. GPT Image: low/medium/high/auto
DALL-E only
vivid, natural DALL-E only. GPT Image always returns b64_json
url, b64_json Aspect ratio (Google models, see /v1/models for allowed values)
Output resolution: Imagen Standard/Ultra "1K"|"2K", Gemini 3 image "1K"|"2K"|"4K"
How much an existing image steers the result. Clamped to the range the chosen model's own input schema declares and dropped entirely for a model that does not declare it, so on this endpoint it is silently inert almost everywhere rather than an error.
This is the image-EDIT parameter (POST /v1/images/edits), accepted here because both routes share one schema-grounded parameter gate. If you are editing an image, send it there instead — this endpoint takes no input image, so on almost every model there is nothing for it to steer.
0.35
Person generation policy (Google models)
dont_allow, allow_adult, allow_all Background type (GPT Image models only)
transparent, opaque, auto Output file format (GPT Image models only)
png, webp, jpeg Compression 0-100 (GPT Image, jpeg/webp only)
Match style of input images (GPT Image 1/1.5 only)
high, low Content filter level (GPT Image only)
auto, low What to exclude from the image (Imagen 4)
Seed for reproducibility (Imagen 4)
Diffusion steps. Refused with 400 unless it is a whole number in 1–100 — this endpoint's own ceiling, checked before anything is billed, not the chosen model's (read that from GET /v1/models, and expect it to be far lower: FLUX defaults to 4).
It is a BILLING dimension on per-megapixel models, which is why the ceiling exists: the cost is megapixels × $/MP × max(1, steps ÷ the model's default steps), so asking for more steps than the default multiplies the price of the call rather than leaving it unchanged.
Only the Together path forwards it to a provider. On every other image source it still validates and still prices, but the image comes back rendered with the model's own step count.
1 <= x <= 1004
Let the model rewrite the prompt before rendering. Read by the Alibaba/DashScope path only, which treats an absent value as true; every other image source ignores it.
It also SELECTS A PRICE on z-image-turbo, where prompt extension is the expensive mode: the credit hold and the settle look that model's rate up under extend, or under noextend when this is explicitly false. Sending false is how you ask for the cheaper rate.
false
Response
Without stream (the default) this is application/json — one result object, shown below.
With stream: true IN THE BODY it is text/event-stream instead: a sequence of data: <json>\n\n lines terminated by a literal data: [DONE]. OpenAPI 3.0 has no vocabulary for "repeat this, then terminate with a sentinel", so the text/event-stream schema below describes the JSON payload of a SINGLE data: line — never the whole body — which is the precedent chat/completions (PR #766) and music/generations (#819) set.
One schema rather than music’s three-member oneOf, because there is one frame shape here: status is a STATE, not a discriminant. Frames run queued → processing → a terminal completed or failed, and the images arrive on the completed frame’s data — there is no separate result frame after it.
Two things the stream does NOT carry, both of which the JSON body does. credits_used: settlement runs AFTER the stream is closed, so a streamed generation never reports what it cost in band — the x-request-id response header is what ties the call to its usage record. And file_id on an artifact: registering images as durable files belongs to the media-job path, which a streaming request never takes.
Unix timestamp, in seconds, of when the result was produced.
1713204900
One entry per produced image, in the order the provider returned them.
Show child attributes
Show child attributes
Credits actually settled for this request (1 credit = $0.01). May be fractional.
40