Fhddos exposes an OpenAI-compatible image API, so any code already calling the OpenAI Images API works without modification — just point base_url at https://aiapi.fhddos.com and swap your API key for your Fhddos token. You can generate images from text prompts, edit existing images with up to 14 reference inputs, and run either operation as an async task when you need fire-and-forget behaviour.
Quick Start
curl -X POST "https://aiapi.fhddos.com/v1/images/generations" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2",
"prompt": "A futuristic skyline at dusk",
"size": "1024x1024",
"quality": "medium"
}'
Image Generation — POST /v1/images/generations
Parameters
| Parameter | Type | Required | Description |
|---|
prompt | string | ✅ | Text description of the image to generate |
model | string | ✅ | gpt-image-2 or gpt-image-1 |
n | integer | | Number of images to generate. Default 1. See channel differences below |
size | string | | Resolution (see size rules). Default 1024x1024 |
quality | string | | low / medium / high / auto. Fhddos defaults to low when omitted |
background | string | | transparent / opaque / auto |
output_format | string | | png / jpeg |
output_compression | integer | | 0–100 (JPEG only) |
response_format | string | | url / b64_json. Default b64_json |
moderation | string | | low / auto |
user | string | | End-user identifier for audit purposes |
stream and partial_images are OpenAI-defined fields, but gpt-image-2 is marked Streaming: Not supported. Passing them is harmless — Fhddos ignores them and returns a standard JSON response.
Resolution Rules
gpt-image-2 accepts flexible custom resolutions via a widthxheight string or auto. Your size must satisfy all of these constraints:
| Constraint | Rule |
|---|
| Maximum edge | Either side ≤ 3840 px |
| Minimum total pixels | width × height ≥ 655,360 (~810×810) |
| Maximum total pixels | width × height ≤ 8,294,400 (~2880×2880) |
| Alignment | Both dimensions must be multiples of 16 |
| Aspect ratio | Longest side : shortest side ≤ 3:1 |
Common presets:
size | Use case |
|---|
auto | Let the model pick the best size for your prompt |
1024x1024 | General-purpose square — fastest to generate |
1536x1024 | Landscape (3:2) |
1024x1536 | Portrait (2:3) |
2048x2048 | 2K square |
2048x1152 | 2K widescreen (16:9) |
1152x2048 | 2K portrait (9:16) |
Fhddos passes the size value directly to the upstream model without pre-validating it. Sizes that violate the constraints above return an error from the upstream service. Resolutions above 2560×1440 are experimental.
Response Body
{
"created": 1762789802,
"data": [
{
"b64_json": "iVBORw0KGgoAAAANSUhEUg...",
"revised_prompt": "A futuristic skyline at dusk with neon lights"
}
],
"usage": {
"input_tokens": 12,
"output_tokens": 4096,
"total_tokens": 4108
}
}
| Field | Description |
|---|
data[].b64_json | Base64-encoded image (when response_format=b64_json) |
data[].url | Hosted image URL (when response_format=url) |
data[].revised_prompt | The prompt after model refinement |
usage | Token counts for billing reconciliation |
Channel Differences
Fhddos routes gpt-image-2 requests through two channel types:
| Behaviour | Direct (Official) | Standard-Group Compatible |
|---|
n parameter | Supports n ≥ 1 per OpenAI semantics | Only n=1 — n > 1 returns HTTP 400 |
response_format=url | Fhddos re-encodes as b64 then stores to object storage | Same |
response_format=b64_json | Field omitted (default is already b64) | Same |
| JSON edit requests | Passed through as-is | May be rewritten internally to multipart to ensure executability |
mask in edit | Supported | Partially supported — Fhddos returns a clear error if unavailable |
On standard-group compatible channels, any request with n > 1 is rejected immediately (HTTP 400). This prevents a “pay for many, receive fewer” billing mismatch. Split your request into multiple n=1 calls instead.
URL Output
By default Fhddos returns b64_json. Set response_format=url to receive a hosted URL:
result = client.images.generate(
model="gpt-image-2",
prompt="A clean studio product photo of a matte white ceramic mug",
size="1024x1024",
quality="low",
response_format="url",
)
print(result.data[0].url)
Fhddos applies a local fallback strategy for URL output:
- Requests the image as
b64_json (omitting response_format)
- Receives the base64 result and uploads it to Fhddos’s object storage
- Returns the accessible URL in
data[].url
The behaviour is deterministic — it does not silently fall back to b64_json:
- Object storage configured → returns
data[].url
- Object storage not configured → returns
image_url_not_available error
Image Editing — POST /v1/images/edits
You can provide reference images either as JSON (using URLs or file IDs) or as multipart file uploads.
curl -X POST "https://aiapi.fhddos.com/v1/images/edits" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2",
"prompt": "Change the style to watercolour",
"size": "1024x1024",
"quality": "medium",
"images": [
{ "image_url": "https://example.com/base-image.png" }
]
}'
curl -X POST "https://aiapi.fhddos.com/v1/images/edits" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2",
"prompt": "Use the subject from image 1, colours from image 2, and texture from image 3 to create a clean e-commerce hero shot",
"size": "1024x1024",
"quality": "high",
"images": [
{ "image_url": "https://example.com/reference-subject.png" },
{ "image_url": "https://example.com/reference-color.png" },
{ "image_url": "https://example.com/reference-texture.png" }
]
}'
curl -X POST "https://aiapi.fhddos.com/v1/images/edits" \
-H "Authorization: Bearer $TOKEN" \
-F "model=gpt-image-2" \
-F "image=@base.png" \
-F "mask=@mask.png" \
-F "prompt=Add a hot-air balloon in the sky"
curl -X POST "https://aiapi.fhddos.com/v1/images/edits" \
-H "Authorization: Bearer $TOKEN" \
-F "model=gpt-image-2" \
-F "prompt=Use the subject from image 1, colours from image 2, and texture from image 3" \
-F "quality=high" \
-F "size=1024x1024" \
-F "image[]=@reference-subject.png" \
-F "image[]=@reference-color.png" \
-F "image[]=@reference-texture.png"
Edit Parameters
| Parameter | Type | Required | Description |
|---|
prompt | string | ✅ | Edit instruction |
model | string | ✅ | gpt-image-2 |
images | array | | Up to 14 input images |
images[].image_url | string | | Publicly accessible URL of the image |
images[].file_id | string | | File ID from the Files API |
mask | object | | Mask object with image_url or file_id |
size | string | | Same resolution rules as generation. Default 1024x1024 |
quality | string | | low / medium / high / auto. Default low |
background | string | | transparent / opaque / auto |
input_fidelity | string | | high / low |
output_format | string | | png / jpeg |
output_compression | integer | | 0–100 |
response_format | string | | url / b64_json. Default b64_json |
n | integer | | Number of images to generate. Default 1 |
user | string | | End-user identifier |
Use either images[].image_url or images[].file_id for each entry — not both. On standard-group compatible channels, Fhddos may internally rewrite JSON edits to multipart to ensure the request executes. The external interface semantics are unchanged.
Async Image Tasks
For long-running generation or when you don’t want to block waiting for a response, Fhddos offers async endpoints. These create a task immediately and let you poll for results.
Async image tasks require object storage to be configured on your Fhddos instance. If storage is not configured, creating a task returns storage_not_configured.
Async tasks always return results as data[].url — even if you pass response_format=b64_json when creating the task. The URL is a signed link hosted in Fhddos’s object storage.
Supported Models
gpt-image-2
gpt-image-2-plus
Async Generation Workflow
Create the task
curl -X POST "https://aiapi.fhddos.com/v1/images/generations/async" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2",
"prompt": "A clean studio product photo of a matte white ceramic mug",
"size": "1024x1024",
"quality": "low",
"response_format": "url"
}'
Response:{
"id": "image_01KCRVET35FAVZME1CEEED9VBS",
"task_id": "image_01KCRVET35FAVZME1CEEED9VBS",
"object": "image.generation",
"created_at": 1700000000,
"status": "pending",
"progress": 0,
"model": "gpt-image-2",
"prompt": "A clean studio product photo of a matte white ceramic mug"
}
Poll for completion
curl "https://aiapi.fhddos.com/v1/images/generations/image_01KCRVET35FAVZME1CEEED9VBS" \
-H "Authorization: Bearer $TOKEN"
Completed response:{
"id": "image_01KCRVET35FAVZME1CEEED9VBS",
"task_id": "image_01KCRVET35FAVZME1CEEED9VBS",
"object": "image.generation",
"created_at": 1700000000,
"status": "completed",
"progress": 100,
"completed_at": 1700000066,
"expires_at": 1700086466,
"model": "gpt-image-2",
"data": [
{ "url": "https://example.com/signed-url.png" }
],
"usage": {
"prompt_tokens": 120,
"completion_tokens": 765,
"total_tokens": 885
}
}
Async Edit Workflow
Async edits support both multipart file uploads and JSON image_url / mask.image_url inputs.
Multipart Upload
JSON with image_url
curl -X POST "https://aiapi.fhddos.com/v1/images/edits/async" \
-H "Authorization: Bearer $TOKEN" \
-F "model=gpt-image-2" \
-F "prompt=Convert this to a clean e-commerce hero shot" \
-F "response_format=url" \
-F "image=@/path/to/base.png"
curl -X POST "https://aiapi.fhddos.com/v1/images/edits/async" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2-plus",
"prompt": "Keep the subject, replace background with a light grey studio backdrop",
"size": "1024x1024",
"images": [
{ "image_url": "https://example.com/base-image.png" }
]
}'
Poll the edit result at:
curl "https://aiapi.fhddos.com/v1/images/edits/{id}" \
-H "Authorization: Bearer $TOKEN"
Async edits do not support provider file_id inputs. If you include images[].file_id or mask.file_id, Fhddos returns unsupported_image_input at task creation time — no task is queued.
Task Statuses
| Status | Meaning |
|---|
pending | Queued, waiting for a worker |
in_progress | Background worker is executing the request |
completed | Done — read the result from data[].url |
failed | Failed — read error.code and error.message |
Billing
gpt-image-2 is billed by token consumption:
| Token type | Price |
|---|
| Text input | $5.00 / 1M tokens |
| Cached text input | $1.25 / 1M tokens |
| Image input | $8.00 / 1M tokens |
| Image output | $30.00 / 1M tokens |
Estimated cost per image (actual charges are token-based):
| Size | Low | Medium | High |
|---|
1024x1024 | $0.006 | $0.053 | $0.211 |
1024x1536 / 1536x1024 | $0.005 | $0.041 | $0.165 |
1024x768 / 768x1024 | $0.005 | $0.040 | $0.150 |
1920x1080 / 1080x1920 | $0.010 | $0.040 | $0.160 |
2048x2048 | $0.011 | $0.060 | $0.220 |
2560x1440 / 1440x2560 | $0.010 | $0.060 | $0.230 |
3840x2160 / 2160x3840 (4K) | $0.020 | $0.110 | $0.410 |
- Low — ideal for rapid iteration and draft previews at minimal cost
- Medium — the best price-to-quality ratio for most production workloads
- High — use when you need accurate text rendering or fine detail
- Batch API requests qualify for a 50% discount
Check the Model Pricing page in your Fhddos console for the rates applied to your account.
Error Codes
| Code | Cause |
|---|
image_url_not_available | response_format=url was requested but object storage is not configured |
n_not_supported | n > 1 was sent to a standard-group compatible channel — split into multiple n=1 requests |
no_image_generated | The upstream model returned a usage object but no image data — typically caused by a silent content filter or generation failure. The usage field is still populated for billing purposes |
content_policy_violation | The prompt or image failed content moderation |
suspected_black_image | The generated image appeared to be all-black and was blocked |
storage_not_configured | Async task creation requires object storage, which is not set up |
unsupported_image_input | Async edits do not accept file_id inputs |