GPT Image API Docs
One API key for image generation and image editing. Quick start, endpoints, authentication, request fields, responses, and errors.
Overview
GPT Image API gives you image generation and image editing behind one account and one API key. Requests use familiar OpenAI-style field names (model, prompt, size, quality), which lowers migration cost, while model providers stay abstracted behind a stable API surface. GPT Image 2 is designed for text-heavy images — spelling, placement, and small or dense copy should still be reviewed before publishing.
Quick start
1. Create an API key
Sign in to the dashboard and create a key from Settings → API Keys. Store the value in your server environment and never expose it in browser-side code.
GPT_IMAGE_API_KEY=sk_...
2. Choose a model
| Use case | Model id | Endpoint |
|---|---|---|
| GPT image generation and editing | gpt-image-2 | /v1/images/generations, /v1/images/edits |
3. Make your first request
curl https://api.gptimageapi.dev/v1/images/generations \
-H "Authorization: Bearer $GPT_IMAGE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2",
"prompt": "A cinematic product photo of a ceramic coffee cup",
"size": "1:1"
}'
Successful responses return generated asset URLs in data[].url.
Authentication
GPT Image API uses API keys with standard Bearer authentication.
Authorization: Bearer $GPT_IMAGE_API_KEY
Key safety:
- Never put an API key in client-side JavaScript — call GPT Image API from your backend.
- Rotate keys from Settings → API Keys when a teammate leaves or a secret is exposed.
- Use separate keys for development, staging, and production.
Invalid or missing credentials return 401 Unauthorized:
{
"error": {
"code": "unauthorized",
"message": "Invalid API key."
}
}
Endpoints
| Workload | Synchronous endpoint | Async endpoint |
|---|---|---|
| Text-to-image | POST /v1/images/generations | POST /v1/async/images/generations |
| Image editing | POST /v1/images/edits | POST /v1/async/images/edits |
| Task result | — | GET /v1/tasks/{id} |
Image requests support the standard OpenAI-compatible synchronous endpoints. Long-running image tasks can be submitted asynchronously and polled with GET /v1/tasks/{id} until they reach completed or failed.
Image generation
POST /v1/images/generations
| Field | Type | Required | Description |
|---|---|---|---|
model | string | Yes | Image model id, such as gpt-image-2 or gpt-image-1.5. |
prompt | string | Yes | Text prompt describing the desired image. |
size | string | No | Output shape. GPT Image models use auto, preset sizes, or custom WIDTHxHEIGHT values. |
quality | string | No | Quality tier when supported: low, medium, high, or auto. |
Image edits
POST /v1/images/edits
| Field | Type | Required | Description |
|---|---|---|---|
model | string | Yes | Editing-capable image model id. |
prompt | string | Yes | Text instruction describing the edit. |
image | string or string[] | Yes | Input image URL. Send an array when the model supports multiple references. File uploads and base64 data are not supported. |
size | string | No | Output shape (same rules as image generation). |
quality | string | No | Quality tier when supported. |
Get task result
GET /v1/tasks/{id}
Task statuses: submitted, processing, completed, or failed. Each task reports progress from 0 to 100 and a credits_cost after completion.
Response format
Image responses follow the OpenAI image shape:
{
"created": 1766880000,
"data": [
{
"url": "https://cdn.gptimageapi.dev/generated/image.png"
}
]
}
Task submissions return a task id immediately:
{
"status": "submitted",
"id": "task_01KPQ7J7DWB7QZ3WCEK3YVPBRA",
"progress": 0,
"created_at": 1703884800,
"model": "gpt-image-2"
}
Quality tiers and credits
Credit cost is set by the output size and quality tier when the model supports them:
| Size (by longest edge) | low | medium | high |
|---|---|---|---|
| 1K (≤1536px) | 1 credit | 4 credits | 16 credits |
| 2K (≤2048px) | 2 credits | 18 credits | 80 credits |
| 4K (≤3840px) | 4 credits | 36 credits | 160 credits |
quality=auto is billed as high, and size=auto defaults to the 1K tier. Model availability and credit rules can change, so review the live pricing page before production requests and check account activity in Credits.
Errors
| HTTP status | Type | Meaning |
|---|---|---|
400 | invalid_request_error | Missing or invalid request field. |
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_credits | The account does not have enough credits. |
404 | model_not_found | The model id is unknown or unavailable. |
422 | prompt_rejected | The prompt or input violates model policy. |
429 | rate_limited | Too many requests in a short period. |
500 | internal_error | Unexpected server error. |
503 | model_unavailable | Provider is temporarily unavailable. |
Retry only transient errors (429, 500, 503) with exponential backoff. For 402 insufficient_credits, route users to Credits or Billing so they can resolve it without leaving your product flow.
Code examples
Node.js
const response = await fetch('https://api.gptimageapi.dev/v1/images/generations', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.GPT_IMAGE_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'gpt-image-2',
prompt: 'A cinematic product photo of a ceramic coffee cup',
size: '1:1',
}),
});
if (!response.ok) {
throw new Error(await response.text());
}
const result = await response.json();
console.log(result.data?.[0]?.url ?? result);
Python
import os
import requests
response = requests.post(
"https://api.gptimageapi.dev/v1/images/generations",
headers={
"Authorization": f"Bearer {os.environ['GPT_IMAGE_API_KEY']}",
"Content-Type": "application/json",
},
json={
"model": "gpt-image-2",
"prompt": "A cinematic product photo of a ceramic coffee cup",
"size": "1:1",
},
)
response.raise_for_status()
result = response.json()
print(result["data"][0]["url"])
Async image generation (Node.js)
Submit the task, then poll GET /v1/tasks/{id} until it completes:
// 1. Submit the async task
const submit = await fetch('https://api.gptimageapi.dev/v1/async/images/generations', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.GPT_IMAGE_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'gpt-image-2',
prompt: 'A cinematic product photo of a ceramic coffee cup',
size: '1:1',
}),
});
const task = await submit.json();
console.log(task.id); // task_01KPQ7J7DWB7QZ3WCEK3YVPBRA
// 2. Poll until the task completes
let status = task.status;
while (status === 'submitted' || status === 'processing') {
await new Promise((resolve) => setTimeout(resolve, 2000));
const poll = await fetch(`https://api.gptimageapi.dev/v1/tasks/${task.id}`, {
headers: { Authorization: `Bearer ${process.env.GPT_IMAGE_API_KEY}` },
});
const result = await poll.json();
status = result.status;
if (status === 'completed') {
console.log(result.result?.data?.[0]?.url ?? result);
} else if (status === 'failed') {
throw new Error(result.error?.message ?? 'Task failed');
}
}
Async image generation (Python)
import os
import time
import requests
headers = {"Authorization": f"Bearer {os.environ['GPT_IMAGE_API_KEY']}"}
# 1. Submit the async task
submit = requests.post(
"https://api.gptimageapi.dev/v1/async/images/generations",
headers={**headers, "Content-Type": "application/json"},
json={
"model": "gpt-image-2",
"prompt": "A cinematic product photo of a ceramic coffee cup",
"size": "1:1",
},
)
submit.raise_for_status()
task = submit.json()
print(task["id"])
# 2. Poll until the task completes
while task["status"] in ("submitted", "processing"):
time.sleep(2)
task = requests.get(f"https://api.gptimageapi.dev/v1/tasks/{task['id']}", headers=headers).json()
if task["status"] == "completed":
print(task["result"]["data"][0]["url"])
else:
raise RuntimeError(task.get("error", {}).get("message", "Task failed"))
Next steps
- Try the Playground to experiment with prompts before writing code.
- Review Pricing for credit packages and current model costs.
- Manage keys, credits, and usage records in the dashboard.
