Image Generation
POST /v1/images/generations
OpenAI-compatible image generation. The primary model is gpt-image-2. Two modes are supported:
- Synchronous — the request blocks until the image is ready and returns it directly (best for low concurrency / interactive use).
- Asynchronous — submit and immediately receive a job ID, then poll for the result (best for high volume / avoiding long-held connections).
Synchronous: POST /v1/images/generations
Request parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
model |
string | Yes | Model ID, e.g. gpt-image-2. |
prompt |
string | Yes | Text prompt describing the image. |
n |
integer | No | Number of images. Only 1 is currently supported (default 1). |
size |
string | No | Image size, e.g. 1024x1024, 1536x1024 (supported by gpt-image-2; not all models). |
quality |
string | No | Quality hint (supported by gpt-image-2; not all models). |
Note:
gpt-image-2does not acceptresponse_format; the gateway drops it automatically, so you don't need to send it.
Example
cURL
curl https://api.portal.aiin1.ai/v1/images/generations \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"model": "gpt-image-2",
"prompt": "a red fox running in snow, studio lighting",
"n": 1
}'Python
import openai
client = openai.OpenAI(
api_key="YOUR_API_KEY",
base_url="https://api.portal.aiin1.ai/v1",
)
resp = client.images.generate(
model="gpt-image-2",
prompt="a red fox running in snow, studio lighting",
n=1,
)
b64 = resp.data[0].b64_json # base64-encoded PNGResponse
The image is returned inline as base64:
{
"created": 1730000000,
"data": [
{
"b64_json": "iVBORw0KGgoAAAANSUhEUgAA...",
"revised_prompt": "..."
}
]
}To display in a browser, prefix it: data:image/png;base64,<b64_json>.
Asynchronous: POST /v1/images/generations/async
The request body is identical to the synchronous route (model / prompt / n / size / quality), but it returns a job ID immediately instead of blocking. Use this for batch generation or when the client shouldn't hold a long connection open.
1. Submit
curl https://api.portal.aiin1.ai/v1/images/generations/async \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"model": "gpt-image-2",
"prompt": "a red fox running in snow",
"n": 1
}'Returns 202 Accepted:
{
"id": "nximg_xxxxxxxx",
"status": "queued",
"created": 1730000000,
"object": "image.generation.async"
}2. Poll: GET /v1/images/generations/async/{job_id}
curl https://api.portal.aiin1.ai/v1/images/generations/async/nximg_xxxxxxxx \
-H "Authorization: Bearer YOUR_API_KEY"status transitions: queued → processing → succeeded (or failed). Poll every 1–2 seconds; generation usually takes seconds to tens of seconds.
In progress:
{ "id": "nximg_xxxxxxxx", "status": "processing", "created": 1730000000 }Succeeded:
{
"id": "nximg_xxxxxxxx",
"status": "succeeded",
"created": 1730000000,
"data": [
{
"url": "https://<bucket>.r2.cloudflarestorage.com/...&X-Amz-Signature=...",
"revised_prompt": "..."
}
]
}Failed:
{
"id": "nximg_xxxxxxxx",
"status": "failed",
"created": 1730000000,
"error": { "type": "upstream_error", "message": "generation failed", "code": "..." }
}About
url: unlike the synchronous route (inline base64), the async route returns a signed download URL on success (valid for ~2 hours). Download or re-host it within the validity window; an expired URL requires regenerating. Failed jobs are not billed.
Field reference
| Field | Description |
|---|---|
id |
Job ID (nximg_ prefix), used for polling. Bound to your API key's organization — others cannot access it. |
status |
queued / processing / succeeded / failed. |
data[].url |
Signed image download URL on success (~2h validity). |
data[].revised_prompt |
Model-revised prompt (may be empty). |