Overview#
We provide gpt-image-1, gpt-image-1.5, gpt-image-2 and gpt-image-2-preview API.Usage & Pricing#
gpt-image-2-preview#
This is a preview version model, each generation costs $0.10 / image (flat per-call fee — independent of size, quality, or token count).Token-Based Models (gpt-image-1, gpt-image-1.5, gpt-image-2)#
All three share the same text-token rate; image input and image output rates differ per model.| Model | Text input | Text cached input | Image input | Image cached input | Image output |
|---|
| gpt-image-1 | $5.00 / 1M | $1.25 / 1M | $10.00 / 1M | $1.25 / 1M* | $40.00 / 1M |
| gpt-image-1.5 | $5.00 / 1M | $1.25 / 1M | $8.00 / 1M | $1.25 / 1M* | $32.00 / 1M |
| gpt-image-2 | $5.00 / 1M | $1.25 / 1M | $8.00 / 1M | $1.25 / 1M* | $30.00 / 1M |
* Image cached input is billed at the same rate as text cached input because our billing system uses a single cached-token rate per model. In practice this only affects repeated image-edit calls that reuse the same reference image within the cache window.Estimated Cost per Image#
These are estimates for output images at common resolutions and quality settings. Input prompt cost is negligible for typical short prompts.gpt-image-1 ($40 / 1M output)#
| Resolution | Low Quality | Medium Quality | High Quality |
|---|
| 1024×1024 | ~$0.011 | ~$0.042 | ~$0.167 |
| 1024×1536 | ~$0.016 | ~$0.063 | ~$0.250 |
| 1536×1024 | ~$0.016 | ~$0.063 | ~$0.250 |
gpt-image-1.5 ($32 / 1M output)#
| Resolution | Low Quality | Medium Quality | High Quality |
|---|
| 1024×1024 | ~$0.009 | ~$0.034 | ~$0.133 |
| 1024×1536 | ~$0.013 | ~$0.051 | ~$0.200 |
| 1536×1024 | ~$0.013 | ~$0.051 | ~$0.200 |
gpt-image-2 ($30 / 1M output)#
| Resolution | Low Quality | Medium Quality | High Quality |
|---|
| 1024×1024 | ~$0.008 | ~$0.032 | ~$0.125 |
| 1024×1536 | ~$0.012 | ~$0.048 | ~$0.188 |
| 1536×1024 | ~$0.012 | ~$0.048 | ~$0.188 |
Key Points#
Higher resolutions and quality settings consume more output tokens and cost more per image.
Processing an image you provide (as input) is billed at the image-input rate (per model above), which is significantly cheaper than generating one from scratch.
gpt-image-2-preview is the only flat-rate model — all others scale with actual token usage.
These are estimates; the exact token count for a specific image may vary.
Default Parameter Values#
When a parameter is omitted in the request, the following defaults apply:| Parameter | Default | Note |
|---|
size | 1024x1024 | |
n | 1 | |
quality | low (token-billed models) | Omitting quality now defaults to low (cheapest tier). Pass medium / high / auto explicitly for higher fidelity. Note: auto lets the upstream pick a much higher token count (observed several× to ~15× the low cost), so only use it when you want maximum quality regardless of price. |
quality | standard (gpt-image-2-preview) | Flat-rate; quality choice does not affect price. |
response_format | b64_json | Pass response_format=url to get a hosted URL instead. |
output_format | png | |
Simple Example#
curl --location 'https://api.piapi.ai/v1/images/generations' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {your-api-key}' \
--data '{
"model": "gpt-image-2",
"prompt": "A cute baby sea otter",
"n": 1,
"size": "1024x1024",
"quality": "low",
"output_format": "jpeg"
}'
Image Edit with Reference Image#
Use the /v1/images/edits endpoint to transform an existing image with a natural-language prompt. The request must be multipart/form-data — the reference image is uploaded as a file field named image.Example (gpt-image-2-preview)#
Sample Response (HTTP 200)#
{
"data": [
{
"url": "https://imagefil.scdn.app/assets/codex/d69c5648-f0d0-4cd3-8860-0d7b1733d274.png"
}
],
"created": 1776956146,
"usage": {
"total_tokens": 1889,
"input_tokens": 1124,
"output_tokens": 765,
"input_tokens_details": {
"text_tokens": 19,
"image_tokens": 1105
}
}
}
Verified sample roundtrip (~100 s end-to-end):Tips#
If response_format is omitted, the response comes back as b64_json. Pass response_format=url when you want a hosted link instead of inline base64.
Processing a reference image you provide is billed at the input-image token rate (per-model table above), which is significantly cheaper than generating one from scratch.
Typical latency is 40–100 s depending on input image size and prompt complexity.
Asynchronous API#
The endpoints above are synchronous: one HTTP call blocks until the image is ready (30–120 s), which can hit gateway timeouts on slow generations. For long-running jobs you can use the asynchronous variant instead — submit the job, get a task_id back immediately, then poll for the result.Both APIs generate identical images and bill identically. Pick whichever fits your client:Synchronous (sections above) — simplest; one request, one image. Best when your HTTP client tolerates a 30–120 s wait.
Asynchronous (this section) — submit → poll. Best for batch jobs, serverless/edge clients with short request timeouts, or when you'd otherwise risk a gateway 5xx on slow calls.
⚠️ The async base URL is different#
This is the easiest thing to get wrong. The two APIs live on different path prefixes:| API | Base URL | Prefix | Auth header |
|---|
| Synchronous | https://api.piapi.ai/v1 | /v1 (no /api) | Authorization: Bearer sk-... |
| Asynchronous | https://api.piapi.ai/api/v1 | /api/v1 (with /api) | X-API-KEY: <your-key> |
Simple rule: sync = /v1, async = /api/v1. The async prefix has the extra /api. Confirm the exact async host for your account — it may be provisioned on a separate gateway.
Authentication (async)#
The async endpoints take a single header — X-API-KEY: <your-key> — the same key you use for the synchronous API (it may be sent with or without the sk- prefix). You do not need a separate token. The gateway forwards that key to the image backend, so billing lands on your account exactly as it does for a synchronous call.1. Submit a job#
POST https://api.piapi.ai/api/v1/images/generations/async
POST https://api.piapi.ai/api/v1/images/edits/async
The request body is identical to the synchronous endpoints (same model, prompt, size, quality, n, …).Returns 200 immediately with a task shell (status: pending):{
"task_id": "b1e7f0c2-...",
"task_type": "gpt-image-generation",
"status": "pending",
"output": null
}
2. Poll for the result#
GET https://api.piapi.ai/api/v1/task/{task_id}
Header: X-API-KEY: <your-account-key>
Only the account that created the task can query it. status moves pending → processing → completed | failed.When completed, output holds the standard OpenAI image response:{
"task_id": "b1e7f0c2-...",
"status": "completed",
"output": {
"created": 1751000000,
"data": [ { "b64_json": "iVBORw0KGgo..." } ],
"usage": { "total_tokens": 1234, "input_tokens": 12, "output_tokens": 1222 }
}
}
When failed, the upstream error is preserved in output.error_body:{
"status": "failed",
"output": { "error_body": { "error": { "message": "...", "type": "..." } } }
}
Behavior & limits (async)#
No auto-retry. A failed task is final — submit a new task rather than expecting a retry. To avoid double-billing the same intent, poll the existing task_id instead of blindly resubmitting.
Results kept for 60 minutes. Fetch your result within 60 minutes of submission — after that the task_id and its image data expire (results carry full base64 image payloads, so they are not retained long-term).
Concurrency cap. Up to 100 in-flight tasks; over the limit, submission is rejected with a too-many-requests shell.
Billing. The async layer adds no charge of its own, exactly as the synchronous call would be. All the pricing and quality guidance above applies unchanged.
Quality defaults to low. Omitting quality now bills at the cheapest low tier (verified in production). Pass medium / high for more fidelity, or auto to let the upstream decide — note auto can cost several× to ~15× a low image, so set it deliberately.
Image edits (async)#
Submit edits as multipart/form-data, with the reference image as a file field named image (same shape as the synchronous /v1/images/edits). The submit returns a task_id; poll it like any other async task.Then GET /api/v1/task/{task_id} until completed; output.data[0].b64_json holds the edited image. A JSON body with the image inline ("image": "data:image/png;base64,...") is also accepted if you prefer not to send a file part.Modified at 2026-07-06 22:31:57