# ImageGPT - AI Agent Image Generation API > **ImageGPT is the image generation API built for AI agents.** Generate images by constructing a URL and using it as an img src. No API keys, no SDK installation, no backend code required. Works with Claude Code, ChatGPT, Cursor, and any LLM. 4 providers, 240+ edge nodes, <50ms cached responses. ## Quick Start To generate an image, construct a URL and use it as an img src: ```html Sunset ``` ## Project Configuration The project slug should be read from the `IMAGEGPT_PROJECT` environment variable. If not set, use `YOUR-PROJECT` as a placeholder. ```bash # Check if configured echo $IMAGEGPT_PROJECT ``` ## Base URL ``` https://{project}.imagegpt.host/image ``` Replace `{project}` with the value from `$IMAGEGPT_PROJECT` or `YOUR-PROJECT` if not set. ## URL Structure ``` https://{project}.imagegpt.host/image?prompt=YOUR_PROMPT&route=ROUTE&aspect_ratio=RATIO ``` ## Required Parameter | Parameter | Description | |-----------|-------------| | `prompt` | The text description of the image to generate. URL-encode special characters. | ## Optional Parameters | Parameter | Description | Default | |-----------|-------------|---------| | `route` | Quality/speed preset (see Routes below) | `quality/fast` | | `model` | Model alias (e.g., flux-2-dev). Aliases provide automatic provider failover. | None | | `aspect_ratio` | Image dimensions (see Aspect Ratios below) | the model's own default, usually `1:1` | | `format` | Output format: `png`, `jpeg`, `webp` | Model-dependent | ## Model Aliases Model aliases let you request a specific model by canonical name. The system automatically tries multiple providers for reliability and performance. Use `model=` instead of `route=` when you want a specific model. | Alias | Description | |-------|-------------| | `gemini-3-pro-image` | Gemini 3 Pro Image — flagship generation and editing | | `gemini-3.1-flash-image` | Gemini 3.1 Flash Image — high quality generation and editing | | `gemini-3.1-flash-lite-image` | Gemini 3.1 Flash Lite Image — fastest, most cost-effective Gemini (1K); editing and text | | `gemini-2.5-flash-image` | Gemini 2.5 Flash Image — fast multimodal generation | | `flux-2-dev` | Flux 2 Dev — high quality generation | | `flux-2-pro` | Flux 2 Pro — premium quality generation | | `flux-2-dev-turbo` | Flux 2 Dev Turbo — fast Flux 2 variant | | `flux-2-fast` | Flux 2 Fast — speed-optimised Flux 2 | | `flux-2-klein-4b` | Flux 2 Klein 4B — ultra-fast, 4B params | | `flux-2-klein-4b-distilled` | Flux 2 Klein 4B Distilled — fastest Klein | | `flux-2-klein-9b` | Flux 2 Klein 9B — higher quality Klein, 9B params | | `flux-1-schnell` | Flux 1 Schnell — fastest Flux model | | `flux-1.1-pro-ultra` | Flux 1.1 Pro Ultra — premium 4MP raw mode | | `recraft-v3` | Recraft V3 — versatile style-based generation | | `ideogram-v3` | Ideogram V3 — industry-leading text rendering | | `qwen-image-2512` | Qwen Image 2512 — excellent realism, multilingual text | | `seedream-4.5` | Seedream 4.5 — high quality with strong typography | | `glm-image` | GLM Image — excellent text rendering and realism | | `grok-imagine` | Grok Imagine — aesthetic photorealistic images | | `juggernaut-flux-pro` | Juggernaut Flux Pro — maximum photorealism | | `imagineart-1.5` | ImagineArt 1.5 — lifelike realism and text rendering | | `imagineart-1.5-pro` | ImagineArt 1.5 Pro — 4K professional-grade visuals | Example: `https://{project}.imagegpt.host/image?prompt=A%20sunset&model=flux-2-dev` ## Routes Routes provide automatic model selection with fallback. Use routes instead of specific models for reliability. | Route | Description | Best For | |-------|-------------|----------| | `quality/fast` | Fast quality route - prioritizes speed | Most use cases and real-time apps. The default when route is omitted. | | `quality/balanced` | Balanced quality route - balanced quality, cost, and speed | Higher quality needs without the full latency cost. | | `quality/high` | High quality route - prioritizes quality | Final output and marketing materials. | | `text/fast` | Fast text route - quick text generation (~9 credits) | Prototyping layouts that contain words. | | `text/balanced` | Balanced text route - good text accuracy with reasonable speed (~30 credits) | Production content with readable text. | | `text/high` | High text accuracy route - best readable text in images (~55 credits) | Signs, posters, logos, text overlays. | | `realistic/fast` | Fast realistic route - quick photorealistic generation (~8 credits) | Quick photoreal drafts. | | `realistic/balanced` | Balanced realistic route - good photorealism with reasonable speed (~9 credits) | Production realistic imagery. | | `realistic/high` | High realistic route - maximum photorealism (~52 credits) | Portraits and product shots. | ## Aspect Ratios Supported aspect ratios (universally supported across all models): - `1:1` - square - `16:9` - widescreen - `9:16` - portrait, mobile - `4:3` - standard landscape - `3:4` - standard portrait These five work on every model. Another eighteen — `3:2`, `4:5`, `21:9`, `1:2` and so on — are honoured wherever the serving model supports them, and land on the nearest ratio it does anywhere else. The spelling is forgiving: `16x9`, `16/9` and `1.7778` are all read as `16:9`. A value like `4:4` is not an error either — see Invalid Parameters below. There is no API-wide default. Omit `aspect_ratio` and the serving model's own default applies, which is `1:1` for most models. ## Invalid Parameters An unrecognized parameter value never fails the request. Because these URLs are written once and then fetched by every visitor of a page, a bad value is replaced with a documented default and a real image is still returned with HTTP 200. | Parameter | Fallback when the value is not recognized | |-----------|-------------------------------------------| | `aspect_ratio` | The nearest ratio the model supports, otherwise its default. `4:4` becomes `1:1`. | | `model` | The default route, `quality/fast` | | `route` | The default route, `quality/fast` | | `format` | The model's default output format | | `seed`, `similarity`, `image_input_strength` and other numbers | Clamped to the supported range, or dropped if not a number | | `image_url` | Dropped if malformed or unsupported by the model; the prompt alone is generated | Every substitution is reported in an `IGPT-Warning` response header, one per parameter: ``` HTTP/2 200 content-type: image/png igpt-warning: code=PARAM_COERCED; param=aspect_ratio; requested="4:4"; used="1:1" igpt-warning: code=PARAM_DROPPED; param=seed; requested="latest" ``` `PARAM_COERCED` means a substitute value was used; `PARAM_DROPPED` means the parameter was ignored. The header is also present on cache hits and on responses blocked by a security policy, so a `403` still tells you the parameters were wrong. The only requests that fail are ones that cannot be served at all — a missing `prompt`, an unknown or disabled project, a request blocked by a policy, or a project past its credit limit. Those return an SVG placeholder image sized to the requested aspect ratio, never JSON, with an `IGPT-Error: code=…; message="…"` header. The codes are `VALIDATION_ERROR` and `INVALID_HOSTNAME` (400), `PROJECT_NOT_FOUND` (404), `PROJECT_INACTIVE`, `POLICY_BLOCKED` and `FEATURE_UNAVAILABLE` (403), `SETUP_INCOMPLETE`, `TRIAL_CREDITS_EXHAUSTED`, `CREDIT_LIMIT_REACHED`, `PAYMENT_PAST_DUE` and `SUBSCRIPTION_CANCELED` (402), `LIMIT` and `PROVIDER_LIMIT` (429), and `ROUTE_EXHAUSTED`, `GENERATION_ERROR` or `INTERNAL_ERROR` (500). None of them is billed. ## URL Examples ### Basic image generation ``` https://{project}.imagegpt.host/image?prompt=A%20sunset%20over%20mountains ``` ### High-quality landscape ``` https://{project}.imagegpt.host/image?prompt=A%20cozy%20cabin%20in%20the%20woods&route=quality/high&aspect_ratio=16:9 ``` ### Image with readable text ``` https://{project}.imagegpt.host/image?prompt=A%20cafe%20sign%20that%20says%20Open%2024%20Hours&route=text/high ``` ## Building URLs in Code ### HTML ```html Sunset over mountains ``` ### React ```tsx function GeneratedImage({ prompt, route = "quality/fast", aspectRatio = "16:9" }: { prompt: string; route?: string; aspectRatio?: string; }) { const project = process.env.IMAGEGPT_PROJECT || "YOUR-PROJECT"; const params = new URLSearchParams({ prompt, route, aspect_ratio: aspectRatio, }); const src = `https://${project}.imagegpt.host/image?${params}`; return {prompt}; } // Usage ``` ### Vue ```vue ``` ### Svelte ```svelte {prompt} ``` ### JavaScript ```javascript function buildImageUrl(prompt, options = {}) { const project = process.env.IMAGEGPT_PROJECT || "YOUR-PROJECT"; const params = new URLSearchParams({ prompt, route: options.route || "quality/fast", aspect_ratio: options.aspectRatio || "16:9", ...options, }); return `https://${project}.imagegpt.host/image?${params}`; } // Usage const url = buildImageUrl("A sunset over mountains", { route: "quality/high", aspectRatio: "16:9", }); ``` ### TypeScript ```typescript interface ImageOptions { route?: "quality/fast" | "quality/balanced" | "quality/high" | "text/fast" | "text/balanced" | "text/high" | "realistic/fast" | "realistic/balanced" | "realistic/high"; aspectRatio?: "1:1" | "16:9" | "9:16" | "4:3" | "3:4"; format?: "png" | "jpeg" | "webp"; } function buildImageUrl(prompt: string, options: ImageOptions = {}): string { const project = process.env.IMAGEGPT_PROJECT || "YOUR-PROJECT"; const params = new URLSearchParams({ prompt, ...(options.route && { route: options.route }), ...(options.aspectRatio && { aspect_ratio: options.aspectRatio }), ...(options.format && { format: options.format }), }); return `https://${project}.imagegpt.host/image?${params}`; } // Usage const url = buildImageUrl("A sunset over mountains", { route: "quality/high", aspectRatio: "16:9", }); ``` ### Python ```python import os from urllib.parse import urlencode def build_image_url( prompt: str, route: str = "quality/fast", aspect_ratio: str = "16:9", **options ) -> str: project = os.environ.get("IMAGEGPT_PROJECT", "YOUR-PROJECT") params = urlencode({ "prompt": prompt, "route": route, "aspect_ratio": aspect_ratio, **options }) return f"https://{project}.imagegpt.host/image?{params}" # Usage url = build_image_url( "A sunset over mountains", route="quality/high", aspect_ratio="16:9" ) ``` ### Ruby ```ruby require 'uri' def build_image_url(prompt, route: "quality/fast", aspect_ratio: "16:9", **options) project = ENV.fetch("IMAGEGPT_PROJECT", "YOUR-PROJECT") params = URI.encode_www_form({ prompt: prompt, route: route, aspect_ratio: aspect_ratio, **options }) "https://#{project}.imagegpt.host/image?#{params}" end # Usage url = build_image_url( "A sunset over mountains", route: "quality/high", aspect_ratio: "16:9" ) ``` ### Go ```go package main import ( "net/url" "os" ) func BuildImageURL(prompt, route, aspectRatio string) string { project := os.Getenv("IMAGEGPT_PROJECT") if project == "" { project = "YOUR-PROJECT" } if route == "" { route = "quality/fast" } if aspectRatio == "" { aspectRatio = "16:9" } params := url.Values{} params.Set("prompt", prompt) params.Set("route", route) params.Set("aspect_ratio", aspectRatio) return "https://" + project + ".imagegpt.host/image?" + params.Encode() } // Usage // url := BuildImageURL("A sunset over mountains", "quality/high", "16:9") ``` ### Rust ```rust use url::Url; fn build_image_url(prompt: &str, route: Option<&str>, aspect_ratio: Option<&str>) -> String { let project = std::env::var("IMAGEGPT_PROJECT").unwrap_or_else(|_| "YOUR-PROJECT".to_string()); let route = route.unwrap_or("quality/fast"); let aspect_ratio = aspect_ratio.unwrap_or("16:9"); let mut url = Url::parse(&format!("https://{}.imagegpt.host/image", project)).unwrap(); url.query_pairs_mut() .append_pair("prompt", prompt) .append_pair("route", route) .append_pair("aspect_ratio", aspect_ratio); url.to_string() } // Usage // let url = build_image_url("A sunset over mountains", Some("quality/high"), Some("16:9")); ``` ### Elixir ```elixir defmodule ImageGPT do def build_image_url(prompt, opts \\ []) do project = System.get_env("IMAGEGPT_PROJECT", "YOUR-PROJECT") route = Keyword.get(opts, :route, "quality/fast") aspect_ratio = Keyword.get(opts, :aspect_ratio, "16:9") params = URI.encode_query(%{ "prompt" => prompt, "route" => route, "aspect_ratio" => aspect_ratio }) "https://#{project}.imagegpt.host/image?#{params}" end end # Usage # url = ImageGPT.build_image_url("A sunset over mountains", route: "quality/high", aspect_ratio: "16:9") ``` ## Handling User Input Generate images from user-provided prompts (e.g., form submissions, text inputs). ### HTML ```html
``` ### React ```tsx import { useState } from "react"; function ImageGenerator() { const [prompt, setPrompt] = useState(""); const [imageSrc, setImageSrc] = useState(null); const project = process.env.NEXT_PUBLIC_IMAGEGPT_PROJECT || "YOUR-PROJECT"; const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); if (!prompt.trim()) return; const params = new URLSearchParams({ prompt, route: "quality/fast", aspect_ratio: "16:9" }); setImageSrc(`https://${project}.imagegpt.host/image?${params}`); }; return (
setPrompt(e.target.value)} placeholder="Describe your image..." />
{imageSrc && {prompt}}
); } ``` ### Vue ```vue ``` ### Svelte ```svelte
{#if imageSrc} {prompt} {/if} ``` ### JavaScript ```javascript // Vanilla JS - attach to any form const project = "YOUR-PROJECT"; function setupImageGenerator(formId, inputId, containerId) { const form = document.getElementById(formId); const input = document.getElementById(inputId); const container = document.getElementById(containerId); form.addEventListener("submit", (e) => { e.preventDefault(); const prompt = input.value.trim(); if (!prompt) return; const params = new URLSearchParams({ prompt, route: "quality/fast", aspect_ratio: "16:9" }); const img = document.createElement("img"); img.src = `https://${project}.imagegpt.host/image?${params}`; img.alt = prompt; container.innerHTML = ""; container.appendChild(img); }); } // Usage: setupImageGenerator("my-form", "prompt-input", "image-output"); ``` ### TypeScript ```typescript const project = "YOUR-PROJECT"; interface ImageGeneratorConfig { formId: string; inputId: string; containerId: string; route?: string; aspectRatio?: string; } function setupImageGenerator(config: ImageGeneratorConfig): void { const { formId, inputId, containerId, route = "quality/fast", aspectRatio = "16:9" } = config; const form = document.getElementById(formId) as HTMLFormElement; const input = document.getElementById(inputId) as HTMLInputElement; const container = document.getElementById(containerId) as HTMLElement; form.addEventListener("submit", (e: Event) => { e.preventDefault(); const prompt = input.value.trim(); if (!prompt) return; const params = new URLSearchParams({ prompt, route, aspect_ratio: aspectRatio }); const img = document.createElement("img"); img.src = `https://${project}.imagegpt.host/image?${params}`; img.alt = prompt; container.innerHTML = ""; container.appendChild(img); }); } // Usage: setupImageGenerator({ formId: "my-form", inputId: "prompt-input", containerId: "image-output" }); ``` ## Caching Behavior - First request generates the image; every request after it is served from cache - Cached images are delivered from the nearest of 240+ edge nodes, typically in under 50ms - The cache key is a hash of the generation parameters — `prompt`, `route` or `model`, `aspect_ratio`, `seed`, `image_url`, `image_input_strength`, `preset` — scoped to your project - Change one of those and you get a new image. Anything else in the query string (including `format` and tracking parameters) returns the same image - Cache hits report `X-Cache: EDGE_HIT`, `R2_HIT` or `SIMILARITY_HIT`, carry `Cache-Control: public, max-age=31536000, immutable`, and are never billed - `cache=false` skips every layer and forces a fresh generation ## Error Handling A request that cannot be served does not return JSON. It returns an SVG placeholder image (`Content-Type: image/svg+xml`, `X-Image-Type: placeholder`, `Cache-Control: no-store`) sized to the aspect ratio you asked for, so a page layout still holds. The reason is in an `IGPT-Error` response header, formatted `code=; message="…"`. | HTTP Status | Codes | Action | |-------------|-------|--------| | `200` | — | Image returned (possibly with `IGPT-Warning` headers) | | `400` | `VALIDATION_ERROR`, `INVALID_HOSTNAME` | Add the missing `prompt`, or check the host | | `402` | `SETUP_INCOMPLETE`, `TRIAL_CREDITS_EXHAUSTED`, `CREDIT_LIMIT_REACHED`, `PAYMENT_PAST_DUE`, `SUBSCRIPTION_CANCELED` | Visit the dashboard (see `IGPT-Upgrade-Url`) | | `403` | `PROJECT_INACTIVE`, `POLICY_BLOCKED`, `FEATURE_UNAVAILABLE` | Check the project's policies and features | | `404` | `PROJECT_NOT_FOUND` | Check the project slug in the hostname | | `429` | `LIMIT`, `PROVIDER_LIMIT` | Back off; honour `Retry-After` when present | | `500` | `ROUTE_EXHAUSTED`, `GENERATION_ERROR`, `INTERNAL_ERROR` | Retry after a brief delay | None of these outcomes is billed. An unrecognised *value* is not an error: it is replaced with a documented default, a real image is still returned with HTTP 200, and the substitution comes back in an `IGPT-Warning` header (`code=PARAM_COERCED` or `code=PARAM_DROPPED`), one per parameter. ## Prompt Best Practices - Be specific and descriptive: "A golden retriever playing fetch in a sunny park" beats "dog" - Include style hints when relevant: "watercolor painting of...", "photorealistic...", "pixel art..." - For text in images, use the `text/*` routes and include the exact text in your prompt - The prompt is part of the cache key, so keep it stable when you want the same image back ## Rate Limits There is no plan-level rate limit. Request limits are per-project security policies you configure yourself (rate, concurrency, per-client credits, source and browser filters) and are off by default. A request blocked by a count policy returns `429` with `IGPT-Error: code=LIMIT`; a filter policy returns its own status with `code=POLICY_BLOCKED`. ## Credits - Generating an image spends credits; serving a cached one never does - Credit cost depends on the model that served the request and the size of the image - Trial: 7 days and 500 credits, with every feature enabled - Paid plans carry a monthly allowance — Developer 10,000, Indie 30,000, Business 100,000 credits - Overages are off by default: at the allowance a project hard-stops with `CREDIT_LIMIT_REACHED` until they are enabled in billing settings ## Integration Notes - Images are returned as binary data with appropriate Content-Type headers - All URLs use HTTPS only - Every response carries `Access-Control-Allow-Origin: *`, so a browser on any origin can load the image - The `prompt` parameter must be URL-encoded - Forward slashes in route values must be URL-encoded as `%2F` when used in query parameters - Example: `route=quality%2Ffast` (not `route=quality/fast`) - `GET https://{project}.imagegpt.host/health` answers without generating anything ## Related Resources - Documentation: https://imagegpt.cloud/docs - Agent setup: https://imagegpt.cloud/agents - Pricing: https://imagegpt.cloud/pricing - Concise version: https://imagegpt.cloud/llms.txt - Skill file for agents: https://imagegpt.cloud/SKILL.md