Tutorial
How to Use the GPT Image 2 API: Text-to-Image and Image-to-Image Guide
What the GPT Image 2 API Offers Developers
The GPT Image 2 API gives you a single, consistent interface for generating images from prompts. Instead of stitching together multiple providers or maintaining separate SDKs, you send one HTTP request to HiAPI.ai and get image data back. That matters when you are building features like marketing asset generators, app onboarding illustrations, or user-facing creative tools where latency, uptime, and predictable request shapes all count.
There are two generation modes you will work with:
- Text-to-image: you supply a prompt and a target size, and the model produces an image from scratch.
- Image-to-image: you supply a prompt plus one or more reference images, and the model produces an image guided by those references.
Both modes share the same authentication and response structure, so once you have one working call, the second is a small delta rather than a new integration. This guide walks through the decision between the two variants, a minimal curl request, reference-image handling, requesting 4K output, a Python port, and the error-handling patterns that keep a production image pipeline from failing silently.
If you are building anything that needs image generation behind a stable API contract, the rest of this post is the shortest path from zero to a runnable request.
Text-to-Image vs Image-to-Image: Choosing a Variant
Before writing code, decide which variant your product actually needs. The choice is mostly about how much control you want over the output and how much the user is expected to supply.
When to use text-to-image
Text-to-image is the right default when:
- The user describes what they want in words and has no source material.
- You are generating placeholders, hero images, or variations from a fixed prompt template.
- You want the simplest possible payload — a prompt and a size — to keep request size small and latency predictable.
When to use image-to-image
Image-to-image is the right choice when the output must stay close to something that already exists:
- Restyling or re-rendering an uploaded product photo.
- Applying a consistent visual treatment across a set of reference assets.
- Guiding composition, palette, or subject so the result matches an existing brand or scene.
The practical rule
If the prompt alone fully determines the output, use text-to-image. If part of the intent lives in an image rather than in words — and describing it in the prompt would be lossy, verbose, or unreliable — use image-to-image and pass the reference.
A common mistake is reaching for image-to-image when a better prompt would do. Reference images add upload overhead and more ways for a request to fail validation. Start with text-to-image, and move to the reference variant only when you can point at a specific visual property the prompt fails to capture.
Making Your First Text-to-Image Request with curl
Start with curl. It removes SDK behavior from the equation, so when something fails you know the problem is auth or payload shape, not your client library.
Set your API key as an environment variable first, so it never lands in shell history or source control:
export HIAPI_API_KEY="your_api_key_here"
Then send a minimal request:
curl -X POST "https://api.hiapi.ai/v1/images/generations" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2",
"prompt": "A flat-design illustration of a lighthouse at dusk, soft gradient sky, minimal palette",
"size": "1024x1024"
}'
What to check in the response:
- HTTP status. A
200means the request was accepted and processed. Anything else, read the error body before changing anything. - Auth. A
401almost always means a missing, malformed, or expired key — confirm theAuthorizationheader format isBearerfollowed by the key. - Payload. A
400usually points at a field: a misspelled parameter, a size string the model does not accept, or a prompt that failed validation. - Image payload. Depending on the response mode, you will get either a URL you can fetch or base64 image data. Handle both so your client is not surprised later.
Once this call succeeds, you have proven three things at once: your key works, the endpoint path is right, and your JSON shape is acceptable. Every later change in this guide starts from this known-good baseline.
Guiding Output with Reference Images
Image-to-image requests keep the same envelope as text-to-image and add a reference image input. The prompt still carries the instruction — the reference carries the visual context.
The change in the request body is that you now supply image data alongside the prompt. In practice that means either a URL the service can fetch or an inline base64-encoded image, depending on which form your integration supports. Keep these rules in mind:
- Prompt and reference must agree. If the prompt describes a red product and the reference image is blue, the model has conflicting signals. Write the prompt as an instruction about the reference ("restyle this scene in watercolor") rather than a description that contradicts it.
- Send only what you need. One strong reference is usually better than several weak ones. Multiple references raise upload size and make it harder to reason about which one drove the output.
- Watch the request size. Base64-encoded images inflate payload size noticeably. If you are uploading large photos, that is the first place to look when a request is slow or rejected.
- Validate before sending. Check that the image is a supported format and that it decodes cleanly. A malformed base64 string produces an opaque failure that costs time to diagnose.
A working shape looks like this:
curl -X POST "https://api.hiapi.ai/v1/images/generations" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2",
"prompt": "Restyle this scene as a soft watercolor painting, keep composition intact",
"image": "https://example.com/reference.jpg",
"size": "1024x1024"
}'
Because the envelope is unchanged, the curl call you validated earlier is still your debugging tool: swap the body, keep the headers, and compare responses field by field.
Requesting 4K Output
Output resolution is expressed in the request, not assumed by the model. If you need high-resolution output, say so explicitly with the size parameter — do not expect a default to be large.
{
"model": "gpt-image-2",
"prompt": "A detailed isometric illustration of a city block, warm evening light",
"size": "3840x2160"
}
A few things to verify when you move to higher resolutions:
- Supported size strings. Size values are validated against what the model accepts. A size that is rejected is a
400, not a silent downscale — so confirm the exact dimension string your request needs rather than guessing near-misses. - Response size. 4K image data is substantially larger than a 1K result. If your response carries base64 or a URL you immediately download, budget for that in memory and in your timeout settings.
- Latency. Higher resolution takes longer to generate. Set client timeouts generously rather than letting a slow-but-successful request time out on your side.
- Cost model. Billing follows the size and volume of output you request, so be deliberate: generate at the resolution the feature actually needs, and downscale in your own pipeline if the UI does not require full resolution. Current pricing lives on the site's pricing panel.
- Upscale carefully. If you need output larger than the model produces, upscaling after generation is a separate step with its own quality trade-offs. Decide consciously which path you want.
Test 4K with a single known-good prompt before wiring it into a batch job, so a resolution-related failure does not get confused with an auth or payload problem.
Porting the Request to Python
Do not rewrite the request from scratch in Python. Port the exact body you already validated in curl, then confirm the response handling separately.
import os
import base64
import requests
API_KEY = os.environ["HIAPI_API_KEY"]
URL = "https://api.hiapi.ai/v1/images/generations"
payload = {
"model": "gpt-image-2",
"prompt": "A flat-design illustration of a lighthouse at dusk, soft gradient sky, minimal palette",
"size": "1024x1024",
}
response = requests.post(
URL,
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
},
json=payload,
timeout=120,
)
response.raise_for_status()
data = response.json()
item = data["data"][0]
if item.get("b64_json"):
image_bytes = base64.b64decode(item["b64_json"])
with open("output.png", "wb") as f:
f.write(image_bytes)
else:
image_url = item["url"]
image_bytes = requests.get(image_url, timeout=60).content
with open("output.png", "wb") as f:
f.write(image_bytes)
Notes on the port:
- Keep the key in the environment, exactly as with curl. Never inline it.
- Set an explicit timeout. Image generation is slower than a typical JSON API call; a default short timeout is a common source of false failures.
- Handle both response modes. Branching on
b64_jsonversusurlkeeps the code working regardless of how the response is configured. - Reuse the function. Wrap this in a small
generate_image(prompt, size)helper so text-to-image and image-to-image differ only in the optionalimagefield in the payload.
Because the payload dictionary is the same object you tested in curl, any behavior change you observe in Python is almost certainly client-side — headers, encoding, or timeout — which narrows debugging considerably.
Handling Errors and Validating Responses
Image generation is a failure-prone call by nature: it is slower than most API endpoints, it carries large payloads, and it depends on model availability. Treat it as something that will occasionally fail and needs to be retried, not as a single-shot operation.
A response checklist
- Check status before parsing. Call
raise_for_status()or inspect the status code, and read the error body — it usually names the offending field. - Validate the shape. Confirm
dataexists and is non-empty before indexing into it. Do not assumedata[0]is present. - Verify image bytes. After decoding, check that the output is non-empty and starts with a valid image signature. A zero-byte file is a silent failure that surfaces much later.
- Log the request id. Keep the response's request identifier in your logs so a failed generation can be traced without reproducing it.
Retry strategy
- Retry transient failures only. Timeouts, connection resets, and 5xx responses are worth retrying. A
401or400will fail identically every time — fix the request instead of retrying it. - Use exponential backoff with jitter. Start with a short delay and increase it; jitter prevents synchronized retries from a fleet of workers.
- Cap attempts. Two or three retries is usually enough. Beyond that, surface the error to the user or move the job to a dead-letter path.
- Make it idempotent. Since retrying can produce duplicate generations, store the result against the original job id so a retry never double-charges a user-visible operation.
Make it async-friendly
High-resolution generation takes time, so do not hold a request thread open if your architecture allows otherwise. Queue the job, return a job id to the caller, and have a worker perform the call with the retry policy above. This keeps your web tier responsive and confines slow, flaky work to a place where retries are cheap.
Wire these checks in from the first working call rather than after the first production incident — the cost of a small validation helper is far lower than debugging an empty image file three weeks later. With auth, payload shape, resolution, and retries all confirmed, the GPT Image 2 API becomes a dependable building block rather than a demo-only integration.
Related articles
View all articles →-
Tutorial
How to Call hailuo-2.3-fast/image-to-video via the HiAPI API: curl and Python
A first working request for the fast, low-cost image-to-video tier — from model ID to downloaded MP4
9 min read -
Tutorial
How to Use hailuo-2.3/text-to-video via the HiAPI API: curl, Python, and a Working Request
11 min read -
Tutorial
Kandinsky 6.0 Pro Text-to-Video on HiAPI: curl and Python Tutorial
A request-first walkthrough: build the prompt-to-clip call, submit it, poll for completion, and download the result
11 min read