Image Generation

POST /v1/images/generations

Generate one or more images from a text prompt. Compatible (with extensions) with the OpenAI Images API.

Headers

Header Required Description
Authorization Yes Bearer <api-key-or-jwt>
Content-Type Yes application/json
X-Quantized-Provider No Force a specific provider (openai, bedrock, gemini). Default is resolved per-model from the catalog.

Request body

Field Type Required Default Description
model string Yes Model identifier (e.g. dall-e-3, gpt-image-1, amazon.nova-canvas-v1:0, imagen-4.0-generate-001)
prompt string Yes Text description of the image to generate
n integer No 1 Number of images to generate. Range 1..10 at the serializer; per-model upper bounds are stricter (see Per-model constraints)
size string No "1024x1024" Image dimensions as WxH, or "auto". Normalized per-provider to the nearest supported aspect ratio
quality string No provider default One of standard, hd, low, medium, high, auto
style string No null vivid or natural. DALL-E 3 only — stripped on other models
background string No null transparent, opaque, auto. gpt-image-1 only — stripped on DALL-E
output_format string No null png, jpeg, webp. gpt-image-1 only — stripped on DALL-E
output_compression integer No null 0..100 JPEG/WebP quality. gpt-image-1 only
moderation string No null auto or low. gpt-image-1 only
seed integer No null Deterministic seed. Forwarded to Bedrock + Stability when present; DALL-E + gpt-image-1 don’t accept seeds today
negative_prompt string No null Text describing what to avoid. Forwarded to Bedrock Titan/Nova (negativeText) and Stability (negative_prompt). DALL-E + gpt-image-1 don’t accept negative prompts — silently dropped
user string No null End-user identifier forwarded to the provider for abuse monitoring
Strict validation

The serializer uses extra="forbid" — any field not listed above is rejected with 422. This keeps typos from being silently dropped.

Notable fields not accepted in this release: response_format (transport is forced to base64 — see below), messages, dimensions, image/mask (those belong to the not-yet-shipped /v1/images/edits endpoint).

Output transport is always base64

The router returns b64_json for every response. Read images from data[].b64_json. There is no data[].url field. OpenAI itself removed the response_format parameter from /v1/images/generations in 2026, so even on the upstream side everything is base64. Bedrock and Imagen have always been base64 natively, so the contract is uniform across providers.

Examples

cURL — DALL-E 3
cURL — gpt-image-1
Python (OpenAI SDK)
Python (httpx)
curl -X POST https://api.quantized.us/v1/images/generations \
  -H "Authorization: Bearer sk-quantized-YOUR-KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "dall-e-3",
    "prompt": "A whimsical watercolor of a sleepy hedgehog under a mushroom",
    "size": "1024x1024",
    "quality": "standard"
  }'
curl -X POST https://api.quantized.us/v1/images/generations \
  -H "Authorization: Bearer sk-quantized-YOUR-KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-1",
    "prompt": "A logo on a fully transparent background, single hedgehog character",
    "quality": "medium",
    "background": "transparent",
    "output_format": "png"
  }'
import base64
from openai import OpenAI

client = OpenAI(
    api_key="sk-quantized-YOUR-KEY",
    base_url="https://api.quantized.us/v1",
)

resp = client.images.generate(
    model="dall-e-3",
    prompt="A whimsical watercolor of a sleepy hedgehog",
    size="1024x1024",
    quality="standard",
)
img_bytes = base64.b64decode(resp.data[0].b64_json)
with open("hedgehog.png", "wb") as f:
    f.write(img_bytes)
import base64
import httpx

response = httpx.post(
    "https://api.quantized.us/v1/images/generations",
    headers={"Authorization": "Bearer sk-quantized-YOUR-KEY"},
    json={
        "model": "gpt-image-1",
        "prompt": "An overhead view of an open notebook with a pen",
        "size": "1024x1024",
        "quality": "low",
    },
    timeout=180,
)
data = response.json()
img_bytes = base64.b64decode(data["data"][0]["b64_json"])
print(f"image: {len(img_bytes)} bytes, watermark: {data['data'][0]['watermark']}")

Response

{
  "created": 1777975004,
  "model": "dall-e-3",
  "data": [
    {
      "b64_json": "iVBORw0KGgoAAAANSUhEUgAA...",
      "revised_prompt": "A whimsical watercolor illustration ...",
      "seed": null,
      "watermark": "none",
      "flagged": false
    }
  ],
  "usage": {
    "images": 1,
    "input_tokens": null,
    "output_tokens": null,
    "total_tokens": null,
    "megapixels": null,
    "credits_used": 640000,
    "credits_remaining": 99360000
  }
}

Response fields

Field Type Description
created integer Unix timestamp from the upstream provider (0 if the provider doesn’t supply one — Bedrock, Imagen)
model string Model id echoed from the request (with any provider prefix preserved)
data array One entry per generated image, in upstream order
data[].b64_json string Base64-encoded image bytes (PNG by default, JPEG/WebP if requested on gpt-image-1)
data[].revised_prompt string or null Upstream-rewritten prompt. Populated on DALL-E 3 + Gemini Flash Image; null on other models
data[].seed integer or null Seed used by upstream when reported (Bedrock Stability echoes the seed; others return null)
data[].watermark string One of c2pa, provenance, synthid, none — see Watermarking
data[].flagged boolean true if upstream content moderation blocked the image (currently exercised by Bedrock Titan/Nova path)
usage.images integer Number of images successfully generated. Equals data.length; can be 0 when flagged is true
usage.input_tokens integer or null Input token count — gpt-image-1 + Gemini Flash Image only
usage.output_tokens integer or null Output (image) token count — gpt-image-1 + Gemini Flash Image only
usage.total_tokens integer or null Sum of input + output tokens — gpt-image-1 + Gemini Flash Image only
usage.megapixels number or null Megapixels rendered — Bedrock + Imagen surrogate when token counts aren’t available
usage.credits_used integer Micro-credits consumed by this request
usage.credits_remaining integer or null Micro-credits remaining (null for unlimited licenses)
No streaming

Image generation endpoints are not streamable on any provider. stream: true is not accepted.

Watermarking

Different providers/models embed different provenance metadata. The watermark enum in each data[] entry lets clients disclose this to end users if needed.

Value Standard Models
c2pa C2PA Content Credentials gpt-image-1 family
provenance AWS provenance metadata Amazon Titan Image v2, Nova Canvas
synthid Google SynthID Google Imagen 4, Gemini Flash Image
none No watermark DALL-E 2, DALL-E 3, Bedrock Stability
Educational disclosure

Quantized targets education customers. If your application surfaces images to students, consider rendering a disclosure when watermark != "none". The C2PA and SynthID standards are designed to be detectable downstream, but a textual disclosure removes ambiguity.

Per-model constraints

Each model has stricter limits than the serializer’s generic [1, 10] range for n and unrestricted size. The router does not enforce these — they’re handled by upstream:

Model Max n Sizes quality values Pricing Notes
dall-e-2 Retired by OpenAI in 2026. Catalog row exists but is inactive — requests return 400 No active providers
dall-e-3 Retired by OpenAI in 2026. Catalog row exists but is inactive — requests return 400 No active providers
gpt-image-1 1 up to 3840px on the longer edge low, medium, high, auto token-priced (~$0.005 to ~$0.21 per 1024² image) Org verification required. Always base64 + C2PA. Accepts background, output_format, output_compression, moderation. The only active OpenAI image model today
amazon.titan-image-generator-v2:0 5 512x512, 1024x1024 standard, premium $0.008–$0.014 per image Accepts negative_prompt, seed
amazon.nova-canvas-v1:0 5 up to 2048x2048 standard, premium $0.040–$0.080 per image Same body as Titan
stability.stable-image-core-v1:0 1 aspect-ratio-based (1:1, 16:9, …) $0.030 per image Region-restricted to us-west-2
stability.stable-image-ultra-v1:0 1 aspect-ratio-based $0.080 per image Region-restricted to us-west-2
stability.sd3-5-large-v1:0 1 aspect-ratio-based $0.065 per image Region-restricted to us-west-2
imagen-4.0-fast-generate-001 4 1K (aspect ratios: 1:1, 3:4, 4:3, 9:16, 16:9) $0.020 per image SynthID watermark
imagen-4.0-generate-001 4 1K, 2K $0.040 per image SynthID watermark
imagen-4.0-ultra-generate-001 4 1K, 2K $0.060 per image SynthID watermark
gemini-2.5-flash-image 1 chat-style (no size knob) token-priced (~$0.039 per 1024²) Routes through :generateContent. Returns text + image parts

Discovery via /v1/models

Image-gen-capable models are listed in GET /v1/models alongside chat models. Filter for image generation by:

  • supported_features contains "image_generation" (recommended, semantic):
    image_models = [m for m in models if "image_generation" in m.get("supported_features", [])]
    
  • output_modality.image == true — image models declare image output; LLMs and embedding models do not.

The catalog also exposes per-model pricing in cost (JSONB — shape varies by model: per_image, per_image_by_size, per_image_by_size_quality, or per_token).

Providers

Provider Slug Default? Status
OpenAI Direct openai Yes Active for gpt-image-1 only. DALL-E 2 and DALL-E 3 catalog rows are present but inactive — OpenAI retired both models in 2026
AWS Bedrock bedrock No Catalog rows seeded but is_active=false — pending ops to re-enable Titan/Nova in AWS Console and switch the region to us-west-2 for Stability
Google Gemini gemini No Catalog rows seeded but is_active=false — pending the Gemini API project being upgraded to a paid tier

Routing is resolved per-model from the catalog. The default for image_generation is OpenAI, but if you request amazon.nova-canvas-v1:0 (once active) the router automatically picks the bedrock provider — no X-Quantized-Provider header needed.

# Once Bedrock is active, this routes through Bedrock automatically:
curl -X POST https://api.quantized.us/v1/images/generations \
  -H "Authorization: Bearer sk-quantized-YOUR-KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "amazon.nova-canvas-v1:0", "prompt": "a hedgehog"}'
No native passthrough endpoints

Unlike embeddings, image generation does not expose /v1/aws-bedrock/images/generations or /v1/gemini/images/generations native passthroughs. The unified /v1/images/generations is the only image endpoint — each provider adapts to that shape internally.

Errors

Status Condition
400 Modality mismatch — the requested model has output_modality.image == false (e.g. an LLM or embedding model id)
400 X-Quantized-Provider slug has no ProviderModel row for the requested model
400 Model exists in the catalog but no active ProviderModel rows (e.g. Bedrock/Gemini models awaiting ops re-enable)
401 Invalid or missing API key
402 Insufficient credits
404 Unknown model id
422 Validation error — missing required field, unsupported enum value, out-of-range integer, or any field not in the documented schema (extra="forbid")
503 Upstream provider unavailable (timeout, rate limit, auth failure on the upstream key, gpt-image-1 org-verification failure)
Content moderation = 200 with flagged

When upstream (currently Bedrock Titan/Nova) blocks a generation for content-policy reasons, it returns 200 with an empty images array and an inline error string instead of a 4xx. The router surfaces this as a successful response with data: [{flagged: true, ...}] and usage.images: 0. Billing is $0 for blocked generations (no images were generated). Check data[0].flagged if you need to detect this case programmatically.

Out of scope on this endpoint

The following are not accepted by /v1/images/generations in this release:

  • Image edits (/v1/images/edits) — requires multipart upload and mask handling
  • Image variations (/v1/images/variations) — DALL-E 2 only
  • response_format: "url" — transport is forced to b64_json
  • Streaming — no provider streams image bytes
  • CDN rehosting — base64 only, no signed URLs

These may be added in a future release.