Core API
Image Generation API
Image requests use dedicated image endpoints. KHaiXAPI image services support OpenAI GPT Image models; the currently available model is gpt-image-2 for image generation and editing, with both synchronous and asynchronous tasks.
Endpoints and Model
| Purpose | Method and URL | Description |
|---|---|---|
| List models | GET https://api.khaix.net/v1/models | Returns currently available models |
| Synchronous task | POST https://api.khaix.net/v1/images/generations | Waits for generation to finish |
| Image editing | POST https://api.khaix.net/v1/images/edits | Uses a reference image or mask |
| Asynchronous task | POST https://api.khaix.net/v1/images/generations/async | Returns a task ID immediately |
| Asynchronous editing | POST https://api.khaix.net/v1/images/edits/async | Processes the reference image and mask in the background |
| Get task | GET https://api.khaix.net/v1/images/tasks/{task_id} | Returns status and the final result |
Use Authorization: Bearer $KHAIX_API_KEY for every request. Set the SDK Base URL to https://api.khaix.net/v1; when sending an HTTP request directly, use the complete URL shown above. Specify gpt-image-2 explicitly. Do not send it to a text-model endpoint or rely on a default model.
Parameters and Size Rules
The table lists the supported values and the current behavior of each parameter. Specify the model, size, and output format explicitly, then inspect the returned file instead of relying on the request alone.
| Parameter | Supported value or range | Usage note |
|---|---|---|
prompt | Required, up to 32,000 characters | Required for every request |
model | gpt-image-2 | Specify gpt-image-2 explicitly |
size | auto or a valid WIDTHxHEIGHT | Some sizes may be normalized |
quality | low, medium, high, auto | low, medium, and high are available |
output_format | png, jpeg, webp | JPEG and WebP requests return PNG |
output_compression | 0-100, only for JPEG/WebP | Not applied to the returned PNG |
background | opaque or auto | transparent is not supported |
moderation | auto or low | Requests are accepted |
n | 1-10; defaults to 1 | Sets the number of images requested; returned images and billing follow the generated image count |
stream | false or true | true is only for synchronous SSE; async tasks require false |
partial_images | 0-3, only with stream:true | Not available for async tasks |
user | Caller-defined end-user identifier | Request is accepted |
response_format | Should not be set for GPT Image | Do not send it |
Size Rules and Supported Sizes
Use pixel dimensions rather than string values such as “1K”, “2K”, or “4K”. Both dimensions must be multiples of 16, neither side may exceed 3840, the aspect ratio may not exceed 3:1, and total pixels should be between 655,360 and 8,294,400.
| Tier | Requested size | Output |
|---|---|---|
| 1K | 1024x1024 | Returns exactly 1024x1024 |
| 2K square | 2048x2048 | Returns exactly 2048x2048 |
| 2K landscape | 2048x1152 | May return 2560x1440; do not rely on exact dimensions |
| 4K landscape | 3840x2160 | Returns 3840x2160; use a longer timeout for this large request |
1K, 2K, and 4K Tiers
Billing tiers are determined by the longest image side: up to 1024 is 1K, over 1024 and up to 2048 is 2K, and over 2048 is 4K. The actual output size takes priority. If no output size can be identified, the requested size is used; if neither can be classified, the request defaults to 2K. When one request returns images in multiple tiers, the highest tier determines the request's billing tier.
| Tier | Longest-side rule | Common square (ratio) | Common landscape (ratio) | Common portrait (ratio) |
|---|---|---|---|---|
| 1K | Up to 1024 | 1024x1024 (1:1) | 1024x768 (4:3)1024x640 (16:10) | 768x1024 (3:4)640x1024 (10:16) |
| 2K | Over 1024, up to 2048 | 1536x1536 (1:1)2048x2048 (1:1) | 2048x1536 (4:3)2048x1152 (16:9)1536x1024 (3:2) | 1536x2048 (3:4)1152x2048 (9:16)1024x1536 (2:3) |
| 4K | Over 2048 | 2560x2560 (1:1)2880x2880 (1:1) | 3840x2160 (16:9)3072x2048 (3:2)2560x1440 (16:9) | 2160x3840 (9:16)2048x3072 (2:3)1440x2560 (9:16) |
Every example in this table satisfies the gpt-image-2 custom-size limits listed above, but the final tier follows the actual returned dimensions. For example, if a 2048x1152 request produces 2560x1440, the longest side exceeds 2048 and the result is handled as 4K.
Recommended combinations: use 1024x1024 for 1K; use 2048x2048 with quality=medium for a 2K square; use 3840x2160 with quality=high for a 4K landscape image. For 4K, set a longer synchronous timeout or use an asynchronous task.
Synchronous Tasks
The synchronous endpoint keeps the HTTP connection open until generation finishes. Generation usually takes about 1 to 2 minutes, and complex requests may take longer. Send the prompt as JSON and always specify model, size, and output_format.
curl https://api.khaix.net/v1/images/generations \
-H "Authorization: Bearer $KHAIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2",
"prompt": "Create an e-commerce hero image for a precision industrial sensor: brushed metal housing, seamless light-gray studio background, front three-quarter view, softbox lighting, the complete product centered, with no logo, readable text, or watermark",
"size": "1024x1024",
"quality": "high",
"background": "opaque",
"output_format": "png",
"n": 1
}'Stable fields include prompt, size, quality, background, output_format, moderation, and n. Do not send response_format, which is not applicable to this model.
PowerShell Request
$baseUrl = "https://api.khaix.net"
$headers = @{
Authorization = "Bearer $env:KHAIX_API_KEY"
"Content-Type" = "application/json"
}
$body = @{
model = "gpt-image-2"
prompt = "Create a professional product image of a precision industrial sensor on a light-gray background, with no logo, readable text, or watermark"
size = "1024x1024"
quality = "medium"
background = "opaque"
output_format = "png"
n = 1
} | ConvertTo-Json
$result = Invoke-RestMethod `
-Uri "$baseUrl/v1/images/generations" `
-Method Post -Headers $headers -Body $body -TimeoutSec 300Handling the Synchronous Result
The response may include data[].url or data[].b64_json. Support both fields and save the file according to its actual Content-Type.
$item = $result.data[0]
if ($item.url) {
Invoke-WebRequest -Uri $item.url -OutFile "generated-image.png"
} elseif ($item.b64_json) {
[IO.File]::WriteAllBytes(
"generated-image.png",
[Convert]::FromBase64String($item.b64_json)
)
} else {
throw "Response contains neither url nor b64_json"
}Image Editing
Edit requests can use JSON image URLs, including data:image/...;base64,..., or multipart file uploads. JSON edits use images[].image_url and optionally mask.image_url. OpenAI Files file_id values are not supported here. input_fidelity is not needed for gpt-image-2, so omit this field.
curl https://api.khaix.net/v1/images/edits \
-H "Authorization: Bearer $KHAIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2",
"prompt": "Replace the product image background with a seamless light-gray studio background. Preserve the sensor's metal finish, edges, and natural shadow, and add no logo, readable text, or watermark",
"images": [
{"image_url": "data:image/png;base64,BASE64_DATA"}
],
"mask": {
"image_url": "data:image/png;base64,MASK_BASE64_DATA"
},
"size": "1024x1024",
"n": 1
}'curl https://api.khaix.net/v1/images/edits \
-H "Authorization: Bearer $KHAIX_API_KEY" \
-F "model=gpt-image-2" \
-F "prompt=Replace the product image background with a seamless light-gray studio background. Preserve the sensor's metal finish, edges, and natural shadow, and add no logo, readable text, or watermark" \
-F "image=@sensor.png" \
-F "mask=@sensor-mask.png" \
-F "size=1024x1024"Asynchronous Tasks
A successful asynchronous submission returns HTTP 202 and a task ID immediately, while image generation or editing and object-storage upload continue in the background. The server must enable and fully configure asynchronous image object storage. Use the same API key for submission and polling.
| Operation | URL | Description |
|---|---|---|
| Create generation task | POST /v1/images/generations/async | Returns a task ID |
| Create edit task | POST /v1/images/edits/async | Supports an image and mask |
| Query task | GET /v1/images/tasks/{task_id} | Returns status and result |
Create a Generation Task
curl "https://api.khaix.net/v1/images/generations/async" \
-H "Authorization: Bearer $KHAIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2",
"prompt": "Create a professional product image of a precision industrial sensor, with no logo, readable text, or watermark",
"size": "2048x2048",
"quality": "low",
"background": "opaque",
"output_format": "png",
"moderation": "auto",
"n": 1
}'Create an Edit Task
An asynchronous edit accepts the same JSON or multipart payload as its synchronous counterpart; change only the endpoint to /v1/images/edits/async. The example below uses a JSON reference image. For multipart uploads, use the same image and mask file fields shown earlier.
curl "https://api.khaix.net/v1/images/edits/async" \
-H "Authorization: Bearer $KHAIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2",
"prompt": "Replace the product background with a seamless light-gray studio background while preserving product details",
"images": [
{"image_url": "data:image/png;base64,BASE64_DATA"}
],
"size": "1024x1024",
"n": 1
}'Submission Response
After validation succeeds and the task is stored, the server always returns HTTP 202. The initial state is processing:
{
"id": "imgtask_0123456789abcdef",
"task_id": "imgtask_0123456789abcdef",
"object": "image.generation.task",
"status": "processing",
"created_at": 1784092800,
"expires_at": 1784179200,
"poll_url": "/v1/images/tasks/imgtask_0123456789abcdef"
}Every successful submission includes Cache-Control: no-store, a relative polling path in Location, and Retry-After: 3. Do not send "stream": true with an asynchronous request; it returns HTTP 400 immediately.
Poll and Download
curl "https://api.khaix.net/v1/images/tasks/imgtask_0123456789abcdef" \
-H "Authorization: Bearer $KHAIX_API_KEY"Polling an existing task returns HTTP 200, so use the JSON status as the source of truth. A processing response includes Retry-After: 3. Poll at that interval, and do not submit a replacement after a client timeout because the original task may still complete and be billed.
| State | Meaning | Key fields |
|---|---|---|
processing | Generation, editing, or object-storage upload is in progress | created_at, expires_at |
completed | Image processing and object-storage upload both succeeded | http_status, result, image_url, completed_at |
failed | The upstream request, execution, or storage offload failed | http_status, error, completed_at |
There is no cancellation endpoint, and the API does not return cancelled or expired states. A task runs for at most 30 minutes. Tasks and results are retained for 24 hours after their latest state update. After expiration, for an unknown task ID, or when polling with another API key, the server returns HTTP 404 image task not found.
Completed and Failed Responses
{
"id": "imgtask_0123456789abcdef",
"task_id": "imgtask_0123456789abcdef",
"object": "image.generation.task",
"status": "completed",
"http_status": 200,
"image_url": "https://storage.example/image.png",
"result": {
"created": 1784092923,
"data": [{"url": "https://storage.example/image.png"}]
},
"created_at": 1784092800,
"completed_at": 1784092923,
"expires_at": 1784179323
}{
"id": "imgtask_0123456789abcdef",
"task_id": "imgtask_0123456789abcdef",
"object": "image.generation.task",
"status": "failed",
"http_status": 502,
"error": {
"type": "api_error",
"message": "Upstream request failed"
},
"created_at": 1784092800,
"completed_at": 1784092923,
"expires_at": 1784179323
}| Check | Requirement |
|---|---|
| Task state | status == completed |
| Result state | http_status is 2xx and result.data is not empty |
| File download | Every data[].url is reachable and returns a valid image/* |
| Resource lifetime | Without public_base_url, results use presigned temporary URLs whose lifetime is configurable and defaults to about 24 hours; with it, results use public links |
Whether the response contains a temporary or public URL, download and retain any required file promptly instead of treating that URL as the only permanent copy.
Image Billing
Image generation is billed by the number of images actually generated. Text tokens, quality, and image-input volume are not separate billing dimensions. The unit price for every image in a request follows that request's final tier: 1K, 2K, or 4K. n may be set from 1 to 10; when one request returns multiple images, billing is accumulated using the generated image count. Refer to the Model Plaza for current tier prices, multipliers, and available groups, and confirm image-generation permission for the current key in the console.
| Model | Billing method | Tier price |
|---|---|---|
gpt-image-2 | Each generated image is charged separately; if n=2 returns two images, billing is based on two images | The actual output determines the request's 1K / 2K / 4K tier, and the corresponding unit price is multiplied by the generated image count |
Example prices are for explanation only. Refer to the Model Plaza for current prices and to console request records for the actual amount charged. Recharges and payments are made in CNY, with CNY 1 providing USD 1 in usage credit. Account balances, model prices and multipliers, usage deductions, and request records are denominated in USD; CNY appears only in recharge amounts, payment orders, and payment records.
Common Errors
- 400: incompatible model:
gpt-image-2cannot be used in/v1/chat/completionsor text Responses examples. Use an Images endpoint instead. - 403: image generation not allowed: Check the current key's image permission in the console, then confirm the available model and group in the Model Plaza.
- 413: request body too large: Compress or resize the Base64 image, or use a multipart file upload.
- Empty result or 502: Keep the request ID, model, and UTC time, then check the request record and response details.
- 404: asynchronous tasks are disabled:
async image tasks are not enabledmeans the server must enable and fully configure asynchronous image object storage. - 404: task not found: Poll with the same API key that submitted the task. Unknown, expired, and other-key tasks all return
image task not found. - 404: path concatenation error: Ensure that the final request path contains only one
/v1segment and never/v1/v1/images. - Format or size differs from the request: Trust the response Content-Type, file signature, and actual dimensions; JPEG/WebP requests may return PNG and some landscape sizes may be normalized.