Image Generation
Generate and edit images with the platform's stable model IDs.
Model access is account-specific. Use the model list endpoint as the source of truth for models available to your API key.
The endpoint generates an image from text by default. When image or image_urls is present, models that support references automatically use image-to-image mode.
Create an image task
Endpoint: POST /v1/images/generations
curl -X POST 'https://silkdock.ai/v1/images/generations' \
-H 'Authorization: Bearer $SILKDOCK_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"model": "gpt-image-2",
"prompt": "A cinematic lighthouse by the sea at sunset, warm colors",
"size": "1024x1024",
"quality": "high",
"n": 1
}'Image tasks are asynchronous by default. Save the returned task ID and poll the status endpoint until the task is completed or failed.
Request parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
model | string | Yes | A public model ID from the capability table. Do not add provider or deployment prefixes. |
prompt | string | Yes | Image description or editing instruction. |
aspect_ratio | string | No | Aspect ratio written as width:height. Supported values are model-specific. |
resolution | string | No | Output resolution. Only send it when the model table explicitly lists values. |
size | string | No | Pixel dimensions such as 1024x1024, 1792x1024, or 1024x1792; some models also accept ratios such as 1:1, 16:9, 9:16, or 4:3. See the model page. |
quality | string | No | Model-specific quality. Common values are low, medium, and high. |
n | integer | No | Number of images. Default: 1; retrieve the account-specific limit from the model list endpoint. |
image | string | No | One reference image URL for image-to-image generation. |
image_urls | string[] | No | Multiple reference image URLs; only supported by models marked for multi-image reference. Some models accept up to 10 images. |
response_format | string | No | Model-specific response format. Send only when the selected model's documented contract supports it. |
output_format | string | No | Model-specific output format. GPT Image 2 supports png, jpeg, and webp; Qwen Image 2.0 and Qwen Image 3 output PNG only. |
wait_for_completion | boolean | No | false (default) creates an asynchronous task and returns its ID immediately; true blocks in the create request until completion. |
polling_timeout | number | No | Polling timeout when wait_for_completion is true; the underlying service default applies when omitted. |
Sending image or image_urls to a model without image-to-image support returns 400. Remove the reference field or select a compatible model.
Prompt enhancement
| Models | Field | Value |
|---|---|---|
qwen-image-2.0, qwen-image-2.0-pro | extra_body.prompt_extend | Boolean; defaults to true |
qwen-image-3 | extra_body.prompt_extend | Boolean; defaults to true |
qwen-image-3 | extra_body.prompt_extend_mode | direct (default), or agent for text-to-image only |
qwen-image-3 | extra_body.enable_thinking | Boolean; defaults to true and applies only when prompt enhancement is enabled |
seedream-v4.5, seedream-v5-lite | extra_body.optimize_prompt_options.mode | standard |
These image models do not support think_level, thinking_level, or reasoning_effort. Qwen Image 3 supports its documented enable_thinking boolean; do not treat that as support for generic reasoning fields.
Parameters and values not listed here or on the selected model page are not part of the stable public API.
Asynchronous response
By default, the gateway returns a pollable task even when the underlying model exposes only a synchronous API. This avoids holding frontend requests open during generation.
{
"created": 1720000000,
"data": [],
"id": "imggen_123",
"object": "image.generation",
"status": "processing",
"model": "gpt-image-2"
}Poll GET /v1/images/generations/{id} until status is completed, then read data[0].url or data[0].b64_json. Set wait_for_completion: true to retain blocking synchronous behavior:
{
"created": 1720000000,
"data": [
{
"url": "https://example.com/generated.png",
"revised_prompt": "A cinematic lighthouse at sunset"
}
]
}Asynchronous task state is stored in Redis and the proxy database. If Redis is unavailable, tasks can still be created and queried while the proxy database is available. If neither store is available, use wait_for_completion: true.
Model capabilities
| Model | Text to image | Image to image | Multi-image | Aspect ratios | resolution | quality | Reference field |
|---|---|---|---|---|---|---|---|
gpt-image-2 | Yes | Yes | No | 1:1, 4:3, 3:4, 3:2, 2:3, 16:9, 9:16 | standard, 1440p, 4k | low, medium, high | image |
gemini-3-pro-image-preview | Yes | Yes | No | 1:1, 5:4, 4:5, 4:3, 3:4, 3:2, 2:3, 16:9, 9:16, 21:9 | Automatic | Automatic | image |
gemini-3.1-flash-image-preview | Yes | Yes | No | 1:1, 5:4, 4:5, 4:3, 3:4, 3:2, 2:3, 16:9, 9:16, 21:9 | Controlled by quality | 512, low, medium, high | image |
seedream-v4.5 | Yes | Yes | No | 1:1, 4:3, 3:4, 16:9, 9:16, 21:9 | Do not send | low, medium, high | image |
seedream-v5-lite | Yes | Yes | No | 1:1, 4:3, 3:4, 16:9, 9:16, 21:9 | Do not send | low, medium, high | image |
qwen-image-2.0 | Yes | Yes | Yes | 1:1, 4:3, 3:4, 16:9, 9:16 | Do not send | Automatic | image / image_urls |
qwen-image-2.0-pro | Yes | Yes | Yes | 1:1, 4:3, 3:4, 16:9, 9:16 | Do not send | Automatic | image / image_urls |
qwen-image-3 | Yes | Yes | Yes, up to 3 | 1:8 through 8:1; use size for exact dimensions | Via size; total pixels from 512x512 through 2048x2048 | Automatic | image / image_urls |
For gemini-3.1-flash-image-preview, quality maps to output specification as follows: 512 to 512 px, low to 1K, medium to 2K, and high to 4K.
Image-to-image example
{
"model": "seedream-v5-lite",
"prompt": "Preserve the subject and convert the image to watercolor",
"image": "https://example.com/reference.png",
"aspect_ratio": "3:4",
"quality": "high"
}Code examples
curl -X POST 'https://silkdock.ai/v1/images/generations' \
-H 'Authorization: Bearer sk-xxx' \
-H 'Content-Type: application/json' \
-d '{"model":"gpt-image-2","prompt":"A white unicorn beneath a starry sky","n":1,"size":"1024x1024"}'const response = await fetch("https://silkdock.ai/v1/images/generations", {
method: "POST",
headers: { Authorization: "Bearer sk-xxx", "Content-Type": "application/json" },
body: JSON.stringify({ model: "gpt-image-2", prompt: "A white unicorn beneath a starry sky", n: 1, size: "1024x1024" }),
});
console.log(await response.json());import OpenAI from "openai";
const client = new OpenAI({ apiKey: "sk-xxx", baseURL: "https://silkdock.ai/v1" });
const response = await client.images.generate({
model: "gpt-image-2", prompt: "A white unicorn beneath a starry sky",
n: 1, size: "1024x1024", extra_body: { wait_for_completion: true },
});
console.log(response.data[0].url);from openai import OpenAI
client = OpenAI(api_key="sk-xxx", base_url="https://silkdock.ai/v1")
response = client.images.generate(
model="gpt-image-2", prompt="A white unicorn beneath a starry sky",
n=1, size="1024x1024", extra_body={"wait_for_completion": True},
)
print(response.data[0].url)CURL *curl = curl_easy_init();
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Bearer sk-xxx");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, "https://silkdock.ai/v1/images/generations");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "{\"model\":\"gpt-image-2\",\"prompt\":\"A white unicorn beneath a starry sky\",\"n\":1,\"size\":\"1024x1024\"}");
curl_easy_perform(curl);NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://silkdock.ai/v1/images/generations"]];
request.HTTPMethod = @"POST";
[request setValue:@"Bearer sk-xxx" forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
NSDictionary *payload = @{ @"model": @"gpt-image-2", @"prompt": @"A white unicorn beneath a starry sky", @"n": @1, @"size": @"1024x1024" };
request.HTTPBody = [NSJSONSerialization dataWithJSONObject:payload options:0 error:nil];
[[[NSURLSession sharedSession] dataTaskWithRequest:request] resume];HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://silkdock.ai/v1/images/generations"))
.header("Authorization", "Bearer sk-xxx").header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString("{\"model\":\"gpt-image-2\",\"prompt\":\"A white unicorn beneath a starry sky\",\"n\":1,\"size\":\"1024x1024\"}"))
.build();
System.out.println(HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString()).body());payload := strings.NewReader(`{"model":"gpt-image-2","prompt":"A white unicorn beneath a starry sky","n":1,"size":"1024x1024"}`)
req, _ := http.NewRequest("POST", "https://silkdock.ai/v1/images/generations", payload)
req.Header.Set("Authorization", "Bearer sk-xxx")
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))<?php
$ch = curl_init('https://silkdock.ai/v1/images/generations');
curl_setopt_array($ch, [CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer sk-xxx', 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode(['model' => 'gpt-image-2', 'prompt' => 'A white unicorn beneath a starry sky', 'n' => 1, 'size' => '1024x1024'])]);
echo curl_exec($ch);var request = URLRequest(url: URL(string: "https://silkdock.ai/v1/images/generations")!)
request.httpMethod = "POST"
request.setValue("Bearer sk-xxx", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try! JSONSerialization.data(withJSONObject: ["model": "gpt-image-2", "prompt": "A white unicorn beneath a starry sky", "n": 1, "size": "1024x1024"])
URLSession.shared.dataTask(with: request) { data, _, _ in print(String(data: data!, encoding: .utf8)!) }.resume()using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer sk-xxx");
var json = JsonSerializer.Serialize(new { model = "gpt-image-2", prompt = "A white unicorn beneath a starry sky", n = 1, size = "1024x1024" });
var response = await client.PostAsync("https://silkdock.ai/v1/images/generations", new StringContent(json, Encoding.UTF8, "application/json"));
Console.WriteLine(await response.Content.ReadAsStringAsync());uri = URI("https://silkdock.ai/v1/images/generations")
request = Net::HTTP::Post.new(uri, { "Authorization" => "Bearer sk-xxx", "Content-Type" => "application/json" })
request.body = { model: "gpt-image-2", prompt: "A white unicorn beneath a starry sky", n: 1, size: "1024x1024" }.to_json
puts Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(request) }.bodyval json = """{"model":"gpt-image-2","prompt":"A white unicorn beneath a starry sky","n":1,"size":"1024x1024"}"""
val request = Request.Builder().url("https://silkdock.ai/v1/images/generations")
.header("Authorization", "Bearer sk-xxx")
.post(json.toRequestBody("application/json".toMediaType())).build()
OkHttpClient().newCall(request).execute().use { println(it.body?.string()) }let response = reqwest::Client::new()
.post("https://silkdock.ai/v1/images/generations").bearer_auth("sk-xxx")
.json(&serde_json::json!({"model":"gpt-image-2","prompt":"A white unicorn beneath a starry sky","n":1,"size":"1024x1024"}))
.send().await?;
println!("{}", response.text().await?);POST /v1/images/generations HTTP/1.1
Host: silkdock.ai
Authorization: Bearer sk-xxx
Content-Type: application/json
{"model":"gpt-image-2","prompt":"A white unicorn beneath a starry sky","n":1,"size":"1024x1024"}final response = await http.post(
Uri.parse('https://silkdock.ai/v1/images/generations'),
headers: {'Authorization': 'Bearer sk-xxx', 'Content-Type': 'application/json'},
body: jsonEncode({'model': 'gpt-image-2', 'prompt': 'A white unicorn beneath a starry sky', 'n': 1, 'size': '1024x1024'}),
);
print(response.body);response <- request("https://silkdock.ai/v1/images/generations") |>
req_headers(Authorization = "Bearer sk-xxx") |>
req_body_json(list(model = "gpt-image-2", prompt = "A white unicorn beneath a starry sky", n = 1L, size = "1024x1024")) |>
req_perform()
resp_body_json(response)let body = {|{"model":"gpt-image-2","prompt":"A white unicorn beneath a starry sky","n":1,"size":"1024x1024"}|} in
let headers = Cohttp.Header.of_list [("Authorization", "Bearer sk-xxx"); ("Content-Type", "application/json")] in
Lwt_main.run (Cohttp_lwt_unix.Client.post ~headers ~body:(Cohttp_lwt.Body.of_string body)
(Uri.of_string "https://silkdock.ai/v1/images/generations"))Pricing
All prices are in USD.
| Model | Billing | Input | Output |
|---|---|---|---|
gpt-image-2 | Tokens | Text $5/M; cached text $1.25/M; image $8/M image tokens; cached image $2/M image tokens | Text $10/M; image $30/M image tokens |
gemini-3-pro-image-preview | Input + image | Text $2/M; reference image $0.0011/image | $0.134/image; text output $12/M |
gemini-3.1-flash-image-preview | Input + output specification | Text $0.25/M | See the specification table; text output $1.50/M |
seedream-v4.5 | Per image | - | $0.040/image |
seedream-v5-lite | Per image | - | $0.035/image |
qwen-image-2.0 | Per image | - | $0.035/image |
qwen-image-2.0-pro | Per image | - | $0.075/image |
qwen-image-3 | Input references + output images | $0.003125/reference image | $0.031250/image at 1K or 2K |
gpt-image-2 has no fixed per-image price because prompt, reference, output specification, and quality affect the actual token count.
gemini-3.1-flash-image-preview quality | Output | USD/image |
|---|---|---|
512 | 512 | $0.0450 |
low | 1K | $0.0672 |
medium | 2K | $0.1008 |
high | 4K | $0.1512 |
If quality is omitted, Gemini Flash uses its default 1K specification at $0.0672/image. Aspect ratio does not change this specification price.
Check an image task
Endpoint: GET /v1/images/generations/{task_id}
The task status is processing, completed, or failed. On completion, read the result from data[0].url or data[0].b64_json.
Last updated on