Skip to main content
API Reference for openai/gpt-image-2, served by Comfy Router from OpenAI.

Quick start

Create a key in your Comfy workspace and export it as COMFY_API_KEY. The Python and TypeScript snippets use the Comfy SDKs (pip install comfy-sdk and npm install @comfyorg/sdk); the cURL snippet is the same call over raw HTTP. Model ID: openai/gpt-image-2 Endpoint: POST https://api.comfy.org/v2/models/openai/gpt-image-2
The same body, sent to POST https://api.comfy.org/v2/models/openai/gpt-image-2/requests. Router answers 201 with a request_id as soon as the run is admitted, and the result is collected once it is ready, from this process or another one. Queued delivery walks through status, cancellation and collection.

Serving providers

This model is served by Comfy Router directly unless the request names another provider. The providers below serve it too, on the same endpoint and with the same model ID, selected with the model_provider query parameter.
  • Comfy (default): POST https://api.comfy.org/v2/models/openai/gpt-image-2
  • fal, as fal/fal-gpt-image-2: POST https://api.comfy.org/v2/models/openai/gpt-image-2?model_provider=fal
  • Runware, as runware/runware-gpt-image-2: POST https://api.comfy.org/v2/models/openai/gpt-image-2?model_provider=runware
  • WaveSpeed, as wavespeed/wavespeed-gpt-image-2: POST https://api.comfy.org/v2/models/openai/gpt-image-2?model_provider=wavespeed
strict_mode defaults to false, so Router translates the native request body documented on this page into the provider’s own schema and translates the response back. See model_provider, strict_mode and fallback_provider in the API reference, and Serving providers for every model routed this way.

Schema

Input

string
Background transparencyPossible values: transparent, opaque
string | string[]
The source image(s) to edit. PRESENCE OF THIS FIELD SELECTS THE EDIT OPERATION — omit it entirely for text-to-image generation. The model’s published example is the GENERATION call, which omits this field. Adding image is the whole of the difference between the two modes — same endpoint, same model id — except that an edit prompt describes the CHANGE you want rather than the scene, so the edit body below reads differently from the generation example even though only this field is structurally new. It is copyable exactly as printed: {"prompt": "give the rocketship rainbow coloring", "image": ["data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg=="], "size": "1024x1024"} — the payload is a complete 1x1 PNG, not an abbreviation, and this body is pinned as an accepted case in Router’s own request-validation tests. Swap in your own image’s bytes. Accepts one image or an array of them; gpt-image-1 and later take up to 16, which Router enforces from this schema before dispatching.
string
One image, as either an https URL Router fetches on the caller’s behalf or a data:image/<format>;base64,<payload> URI carrying the bytes inline. Accepted image types are png, webp and jpeg, and that set is ENFORCED at resolve time rather than left to the provider — an svg, gif, avif or tiff is refused here, naming the image you sent, instead of becoming a partner error two hops from the cause. Prefer the URL form. A base64 payload inflates roughly 4/3 and the whole request body is capped at 100 MiB, so the inline form caps out near a 75 MB source image; a URL sidesteps that entirely. The per-image and per-request media ceilings stated at the end of this description are tighter than the body cap, so for an image of any real size they are what you meet first. THE URL MUST RESOLVE WITHOUT YOUR CREDENTIALS. Router fetches it server-side and sends no caller credential with the request, so a presigned URL — one whose signature is in the query string — is the supported form. An authenticated endpoint such as /api/assets/{id}/content answers Router 401 rather than the image; request that URL yourself and pass the signed URL it redirects to. THE FETCH IS CONFINED TO A NAMED SET OF HOSTS rather than the open internet, and the same list is re-applied to every redirect hop as well as to the URL you send — so a URL on any other host, or one that redirects off the list, is refused before any provider is contacted. Today that list is Comfy’s own asset delivery only: a signed storage.googleapis.com URL under a Comfy asset bucket, which is the form /api/assets/{id}/content redirects you to. A partner CDN or a plain https host is NOT on the list. TWO WIDENINGS ARE BEING ROLLED OUT AND ARE BOTH OFF BY DEFAULT TODAY. They ship behind ONE switch and are enabled together, so treat everything below as forthcoming rather than as something to build against yet — ask before you rely on either. The FIRST is the bucket POST /customers/storage signs your upload into. Until the rollout reaches your environment an upload URL from that endpoint is refused here, even though the bucket is Comfy’s own and the host is the same one — so “upload to Comfy, then pass the URL” does NOT work yet, and the form that does is the signed URL /api/assets/{id}/content redirects to. The SECOND is ENABLED PER ACCOUNT rather than for everyone at once, because the bucket behind these hosts is yours rather than ours: even once the switch above is on, an account that has not had third-party inbound media enabled is refused, and told so in those words rather than told the host is unsupported. Ask your Comfy contact to enable it for your account. It additionally admits these third-party object-storage hosts, where the bucket is yours and Router makes no ownership claim on it: Cloudflare R2 (<account>.r2.cloudflarestorage.com, <id>.r2.dev), Amazon S3 (s3.amazonaws.com and s3.<region>.amazonaws.com, in either the path-style or the <bucket>.-prefixed form), Azure Blob Storage (<account>.blob.core.windows.net) and Alibaba Cloud OSS (<bucket>.oss-<region>.aliyuncs.com, including the oss-accelerate endpoint). Those are object-storage endpoints specifically: a general-purpose endpoint on the same provider domain, such as an Alibaba Function Compute trigger, is not on the list and is refused. The example below shows the shape only: a real value also carries the signing query parameters, which are deliberately omitted here because a published example lives in the spec forever and a real signature is both a leaked credential and a link that stops working. Each image is capped at 25 MiB and one request’s images at 64 MiB in total.
string
The gpt-image model to run. Router splices the addressed model id in, so a caller addressing /v2/models/openai/gpt-image-2 does not send this.
string
Content moderation settingPossible values: low, auto
integer
The number of images to generate (1-10).Range: 1 to 10
integer
Compression level for JPEG or WebP (0-100)Range: 0 to 100
string
Format of the output imagePossible values: png, webp, jpeg
string
required
A text description of the image to generate, or of the edit to make to image.
string
The quality of the generated or edited imagePossible values: low, medium, high, xhigh, max, standard, hd, auto
string
Size of the image (e.g., 1024x1024, 1536x1024, auto)
string
A unique identifier for end-user monitoring
Generated from the schema Router serves at GET /v2/models/openai/gpt-image-2/openapi.json, the same document it validates a call against before the request reaches the provider.

Output

object[]
string
Base64 encoded image data
string
Revised prompt
string
URL of the image
object
integer
object
integer
integer
integer
object
integer
integer
integer
string
Whether the generated image’s background is opaque or transparent, as OpenAI resolved it for this generation. The request parameter defaults to auto, so this is where a caller who did not pin it learns which one was produced.
integer
Unix timestamp, in seconds, of when the generation completed. It is the one member OpenAI declares REQUIRED on an image-generation response, so it is present whenever OpenAI is the producer; a fal- or wavespeed-served openai/gpt-image-2 response omits it entirely, like the other four resolved-parameter members. Declared int64 because a present-day epoch value is close enough to 2^31 that an unformatted integer generates a 32-bit field in many SDK generators.Format: int64
string
The encoding of the bytes in data[].b64_json — png, webp or jpeg. It is the format OpenAI actually encoded, which is the request’s output_format when one was sent and png when none was, so a decoder can key off it rather than re-deriving the format from the request.
string
The quality tier the generation actually ran at — OpenAI reports one of low, medium, high, xhigh or max. It is the RESOLVED tier, not an echo of the request, whose own quality defaults to auto.
string
The pixel dimensions the generation actually ran at, as <width>x<height>. It is the RESOLVED size: the request’s size defaults to auto and explicitly admits auto, so this is the only place the dimensions actually used are reported.

Examples

Input

Output

Before you ship

The SDKs create an Idempotency-Key and reuse it for automatic retries. For manual retries, reuse the original key. Router can hold the connection for up to 10 minutes. When a request fails, Router sends an X-Comfy-Error-Type response header explaining why. A 422 means Router rejected the input before calling the provider, and a 413 means the request body was larger than Router accepts. Download generated assets promptly because result URLs can expire. Any size limit named in a field description above is the provider’s own bound on that field, quoted from the provider’s specification. Router applies a separate cap to the whole request body, which base64-encoded media counts against: see request body size. This page documents one partner model called through Comfy Router. The same comfy-sdk / @comfyorg/sdk package also ships a second client, for running a whole ComfyUI workflow graph on Comfy Cloud: Comfy(api_key=...) / new Comfy({ apiKey }), with client.workflows, client.assets and client.jobs. See Comfy SDKs.

Headers

Authentication, idempotency, request IDs, error buckets, retry pacing, spend limits.

Using the Router API

Model discovery, validation errors, retries, and billing.

Limitations

What Router does not do today, and what to use instead.