# Image Generation

Generate and edit images through the OpenAI-compatible image APIs.

## Prefer asynchronous generation

For new integrations, use:

```http
POST /v1/images/generations/jobs
```

Create the job, save its ID, and poll for the result. This is the recommended flow for web pages, mobile clients, serverless functions, batch jobs, and reference-image editing because it avoids holding one synchronous request open for a long time.

Synchronous compatibility requests use:

```http
POST /v1/images/generations
```

The multipart image edit endpoint is retained for legacy clients:

```http
POST /v1/images/edits
```

New integrations should use the asynchronous JSON endpoint with `image` or `images` for URL or base64 reference images.

## Text-to-image

```bash
curl https://kaienapi.com/v1/images/generations/jobs \\
  -H "Authorization: Bearer <YOUR_API_KEY>" \\
  -H "Content-Type: application/json" \\
  -d '{
    "model": "gpt-image-2",
    "prompt": "Create a clean headphone product poster on a white background",
    "size": "1024x1024",
    "quality": "low",
    "format": "jpeg",
    "n": 1
  }'
```

## Reference images

For remote images, put public OSS or CDN URLs in the asynchronous JSON request:

```json
{
  "model": "gpt-image-2",
  "prompt": "Keep the subject from image 1 and use the background style from image 2.",
  "image": [
    "https://oss.example.com/subject.jpg",
    "https://oss.example.com/background.jpg"
  ],
  "size": "1024x1024",
  "quality": "standard",
  "format": "png",
  "n": 1
}
```

Resize large images before submission and make sure their URLs remain accessible while the job is running.

## Reading results

An image request may return an image URL, `b64_json`, or an asynchronous task ID. Do not hard-code only one response field. Save results that need long-term access to your own object storage.

## Polling jobs

1. Create a job with `POST /v1/images/generations/jobs`.
2. Save the returned `id` and current status.
3. Poll `GET /v1/images/generations/jobs/{job_id}` every two to three seconds initially.
4. Continue while the status is `queued` or `running`.
5. Read `data` when the status is `succeeded`.
6. Read `error.message` when the status is `failed`.

Stop polling only at a terminal state. On a temporary network failure, retry the next polling interval instead of creating a duplicate job.
