Skip to main content
Beta: Comfy API v2 is at 0.1.x and the surface may still change. Changes within v2 will be additive; anything breaking would ship as v3.
The official, versioned HTTP API for running ComfyUI workflows from external applications: upload inputs, submit a workflow, observe execution, retrieve results. Most people should start with the Comfy SDKs, which wrap this API in Python and TypeScript. Call these endpoints directly if you are working in another language. The full endpoint documentation is in the API Reference pages of this section, generated from the OpenAPI specification.

Where v2 Runs

The same API is served by three surfaces, so one integration can move between them by changing the base URL. Comfy Cloud. The managed, multi-tenant service at https://cloud.comfy.org. Create an API key and you can submit any workflow. Cloud-specific features such as credits, model browsing, and queue management live on the v1 Cloud API, not on v2. Comfy API deployments. An environment you deploy through the Developer Platform gets its own dedicated endpoint at https://{deployment}.run.comfy.app, serving the same v2 API with the same API key. A Comfy API deployment runs workflows against one pinned environment, so it scales independently and GET /workflow returns the executed graph. See the Comfy API deployment guide for building and deploying. Open-source ComfyUI, via the proxy. During the beta, a self-hosted ComfyUI speaks v2 through comfy-api-proxy, a small open-source service that runs alongside it:
By default it proxies the ComfyUI on 127.0.0.1:8188 and serves the v2 API on 127.0.0.1:8189, binding to loopback only. Authentication is off by default, with an optional static bearer token. The proxy is a stopgap: once v2 stabilizes it moves into ComfyUI core and the proxy is no longer needed. See Your own ComfyUI in the SDK guide for configuration details.

Design Principles

  • Poll first. Every capability is reachable via plain GET polling. The SSE stream is a live enhancement, never the source of truth.
  • Everything is resumable. Submission is idempotent, and job state and outputs are retrievable by ID until expires_at. The URL you get back for an output is shorter-lived than that: see Output URLs and How Long They Last.
  • Content-addressed assets. Assets are UUID-identified records over blobs keyed by a server-computed blake3 hash, so identical inputs are not uploaded twice.
  • Follow links, do not build URLs. Responses embed their follow-up URLs.
See Design Notes for the reasoning behind these.

Base URLs

Endpoint Categories

Output URLs and How Long They Last

Three different lifetimes govern “the URL for my output” and they are not the same number. Any application that shows outputs to its own users has to plan for all three.

The Two URL Shapes

The practical consequence: Output.url is not a shareable link. Put it in an <img src> that your users’ browsers load and they get a 401, because their browser does not carry your API key. The signed URL is the one you can hand out. Self-hosted ComfyUI behind comfy-api-proxy has no signed URLs at all. The proxy serves the bytes from the content endpoint, normal authentication applies, and the SDKs report the expiry as null (Python: None).

Reading the Signed URL’s Expiry

On Comfy Cloud and Comfy API deployments a signed URL is minted with a validity of approximately 6 hours. That number is a server-side setting rather than part of the API contract, so treat it as an order of magnitude and never hard-code it. Read the expiry off the response you were given:
  • url_expires_at on an Asset response is the real expiry of the url in that same response.
  • getDownloadUrl() returns it alongside the URL, as expiresAt in TypeScript and expires_at in Python.

url_expires_at on a Job Output Is a Different Number

url_expires_at on an entry of a job’s outputs is not the signed URL’s expiry. On Comfy Cloud it repeats the job’s own expires_at, which today is the job’s created_at plus a fixed 30 day window. That window is a placeholder. The platform has no job retention or garbage-collection policy behind it yet, so the 30 days is a stand-in that lets the field be non-null, not a commitment about how long an output stays fetchable. Do not read it as a promise, and do not key a cache off it. This page will be updated if a real retention policy replaces it.

Showing an Output in Your Own Product

To still be showing an output a day later, do one of these:
  • Re-host the bytes. Download the output once and copy it into your own storage. Most applications end up here.
  • Re-mint on demand. Persist the asset id, then resolve it to a fresh URL (GET /api/v2/assets/{id}, or getDownloadUrl()) at the moment you render, and use that URL immediately.
  • Proxy it. Fetch Output.url from your own backend, which already holds the API key, and stream the bytes to your user.
What does not work is persisting a signed URL. It is good for hours, not days, so a stored copy keeps working through local testing and then breaks for your users once it expires.

Comfy Router

Comfy API v2 runs workflows as durable jobs you submit and poll. For direct model calls (one partner model, one request, the model’s native input and output), see the Comfy Router. Review the Router limitations first. Router is not generally available yet.