diff --git a/development/api-development/quickstart.mdx b/development/api-development/quickstart.mdx new file mode 100644 index 000000000..af7604038 --- /dev/null +++ b/development/api-development/quickstart.mdx @@ -0,0 +1,91 @@ +--- +title: "Run your first workflow" +description: "Run a sample workflow on Comfy Cloud and download its output with Python or TypeScript." +--- + +Run a complete workflow from code and save its output as `first-result.png`. This sample creates a **512 × 512 solid blue image** using two built-in nodes. It verifies authentication, workflow execution, and output download without requiring a model, an input image, or custom nodes. + +To generate an image by calling a hosted model directly, start with the [Comfy Router quickstart](/development/comfy-router/quickstart). + +## Before you start + +- A [Comfy API key](/development/api-development/getting-an-api-key). +- A [paid Comfy Cloud subscription](/development/deploy/cloud). Cloud workflow API access is not included in the free tier. +- Python 3.10 or newer, or Node.js 22.18 or newer for the TypeScript example. + +This guide uses Comfy Cloud, the SDKs' default target. If you previously set `COMFY_BASE_URL`, unset it to use Cloud. For an existing Comfy API deployment or a self-hosted instance, see [Choosing a base URL](/development/api-development/sdks#choosing-a-base-url). + +## 1. Download the sample + +Create a folder for the example. Download [workflow_api.json](/files/api-first-result/workflow_api.json) and the script for your language into that folder: + +- [Python: first_workflow.py](/files/api-first-result/first_workflow.py) +- [TypeScript: first_workflow.mts](/files/api-first-result/first_workflow.mts) + +The workflow is already in API format. Node `"1"` creates the blue image and node `"2"` saves it. The scripts read outputs from that exact SaveImage node, so you do not need to find or edit a node ID. + +## 2. Install the SDK and set your key + +Open a terminal in the folder where you saved the files. + + +```bash Python +python -m venv .venv +source .venv/bin/activate +python -m pip install comfy-sdk +``` + +```bash TypeScript +npm init -y +npm install @comfyorg/sdk +``` + + +On Windows, activate the Python environment with `.venv\Scripts\Activate.ps1` in PowerShell. + +Set your key in the same terminal: + + +```bash macOS / Linux +export COMFY_API_KEY="comfyui-your-key" +``` + +```powershell Windows PowerShell +$env:COMFY_API_KEY = "comfyui-your-key" +``` + + +Keep your API key in your server environment. Do not include it in browser code or commit it to source control. + +## 3. Run and view the result + + +```bash Python +python first_workflow.py +``` + +```bash TypeScript +node first_workflow.mts +``` + + +The script submits the workflow, waits for it to finish, and downloads the image. When it prints `Saved` followed by a path, open `first-result.png` from that location. You should see a solid blue square. Running the sample again replaces that local file. + + + This is a workflow connection check. It does not use a generative model. The same submit, wait, and download steps work with your own generation workflows. + + +### If the request fails + +- **Missing key or unauthorized:** check that `COMFY_API_KEY` is set in the terminal running the script and contains an active key. +- **Access or credit error:** check your Cloud subscription and available credits before retrying. +- **Workflow file not found:** keep `workflow_api.json` next to the downloaded script. +- **Unexpected endpoint:** check `COMFY_BASE_URL`. Unset it for this Cloud example. + +For error handling and job progress, see the [SDK guide](/development/api-development/sdks). + +## 4. Run your own generation workflow + +Build or choose a workflow in the ComfyUI editor, run it successfully there, and [export it in API format](/development/api-development/workflow-api-format). Replace `workflow_api.json` with your export and update `get_outputs("2")` in Python or `getOutputs("2")` in TypeScript to use your workflow's SaveImage node ID. Check that the target environment has the models and custom nodes your workflow uses. + +To host workflows with your own models and custom nodes, create a [Comfy API deployment](/development/serverless/overview). To change workflow inputs, upload files, or watch progress, continue to [Comfy SDKs](/development/api-development/sdks). diff --git a/development/comfy-router/limitations.mdx b/development/comfy-router/limitations.mdx index c377726ee..96b10b3ad 100644 --- a/development/comfy-router/limitations.mdx +++ b/development/comfy-router/limitations.mdx @@ -4,26 +4,24 @@ sidebarTitle: "Capabilities and limits" description: "Choose Router or a partner proxy, plan for long-running calls, and understand recovery, rate limits, and asset storage." --- -Router runs a partner model through one synchronous HTTP call. Use it when your application can wait for a finished result and handle the model's own input and output fields. +Router supports synchronous and queued delivery. Synchronous delivery returns the finished result in one response. Queued delivery returns a request handle and is rolling out by workspace. ## What Router supports | Requirement | Router support | Alternative or next step | | --- | --- | --- | | Generate with one request | `POST /v2/models/{provider}/{model}` returns the finished result. | Start with the [Quickstart](/development/comfy-router/quickstart). | -| Submit a job and collect it later | No general job/status API or completion webhook. | Run Router from a worker, or use a partner proxy with submit-and-poll operations. | -| Show progress or stream output | No live progress, streaming, or preview frames during the call. | Show an indeterminate state, or use a supported proxy operation. | -| Recover after a lost connection | Same-key collection is available when Router retained a handle to an accepted generation. | Preserve the key and follow [retry guidance](/development/comfy-router/api#retry-outcomes). | +| Submit a request and collect it later | Supported through `POST /v2/models/{provider}/{model}/requests` and rolling out by workspace. | See [Queued delivery](/development/comfy-router/queue). | +| Show progress or stream output | Queued delivery reports queue state and can include queue position, but no percentage progress, streaming output, or preview frames. | Poll the returned `status_url`, or use a supported proxy operation for provider-specific progress. | +| Recover after a lost connection | After receiving a queued request handle, use its returned URLs. If submission is interrupted before that, retry with the same idempotency key. Synchronous calls can sometimes be collected the same way. | Preserve the idempotency key and follow [retry guidance](/development/comfy-router/api#retry-outcomes). | | Reconcile Comfy charges | No universal Comfy cost or credit-balance field on the response. | Use [workspace billing](https://platform.comfy.org). | | Store results permanently | Asset URLs can expire, including rehosted and replayed URLs. | Download the assets; see [result assets](/development/comfy-router/reference#result-assets). | -## No queued submission +## Queued delivery availability -Router holds the connection while the model runs. For asynchronous providers, it submits the job and polls internally. Queued delivery (submit, get a `request_id`, poll, collect) is in a gated preview: see [Queued delivery](/development/comfy-router/queue). Outside the preview, Router does not expose a job ID, status endpoint, callback, or webhook. +Queued delivery returns a `request_id` and URLs for status, result collection, and cancellation. It is rolling out by workspace; workspaces without access receive `403` with `not_enabled`. Cancellation is best effort, and Router does not provide a completion webhook. See [Queued delivery](/development/comfy-router/queue) for examples and the full lifecycle. -If your request cannot stay open long enough, call Router from a worker and track the job in your application. Use a [partner proxy](#router-does-not-cover-every-partner-operation) when you need the provider's submit-and-poll controls. - -## Calls are cut off at a server deadline +## Synchronous calls are cut off at a server deadline Router's default deadline is **10 minutes**, configurable by the deployment. Set your client timeout above it so Router can return its error and request ID first. @@ -48,11 +46,11 @@ The request-rate limit applies to invocation and catalog/schema reads, including Cache catalog and schema reads. Revalidate schemas with `ETag` and `If-None-Match`. See [Headers](/development/comfy-router/headers) for retry and committed-spend fields. -## No progress while a call runs +## No live progress while a request runs -Router returns a final response, with no streamed tokens, server-sent events, percentage updates, or intermediate preview frames. A provider's internal polling state is not forwarded during the request. +Synchronous delivery returns only the final response. Queued delivery exposes queue state and can include queue position, but neither mode provides streamed tokens, server-sent events, percentage updates, or intermediate preview frames. A provider's internal progress is not forwarded. -Show an indeterminate progress indicator. If you need progress or streaming, use a partner-proxy operation that exposes it. +Show an indeterminate progress indicator after a queued request begins running. If you need provider-specific progress or streaming, use a partner-proxy operation that exposes it. diff --git a/development/overview.mdx b/development/overview.mdx index dc58feb41..5a22ffc14 100644 --- a/development/overview.mdx +++ b/development/overview.mdx @@ -5,9 +5,22 @@ description: "Using ComfyUI as a Developer" ComfyUI is a modular GenAI inference engine that can be run as a server, accessed via API, extended with custom nodes, and managed from the command line. Most API work follows two steps: get ComfyUI running somewhere, then run workflows against it from your application. - - Generate your first image with a Comfy API key in Python, TypeScript, or cURL. - +## Use cases + + + + Generate with hosted models through Comfy Router. + + + Deploy ComfyUI on the Developer Platform or your own infrastructure. + + + Run workflows from your application with an SDK or the HTTP API. + + + Connect AI agents to ComfyUI with MCP and Comfy CLI. + + ## Quick Start @@ -60,50 +73,3 @@ The fastest way to try the workflow API is to run a workflow against Comfy Cloud When you need your own models and custom nodes behind the endpoint, create a [Comfy API deployment](/development/serverless/overview), a serverless endpoint managed through the Developer Platform. The same SDK code works against it; only the base URL changes. - -## Deploy ComfyUI - -Learn how to deploy and scale ComfyUI, on the Developer Platform or your own infrastructure. - - - Compare Comfy API deployments, Comfy Cloud, and self-hosting, and pick the right target. - - -See also: [Comfy API deployments](/development/serverless/overview) · [Comfy Cloud](/development/deploy/cloud) · [Self-Hosting Options](/development/deploy/self-hosting) - -## Run Workflows - -Learn how to run workflows using our SDKs and the v2 HTTP API. They work against Comfy Cloud, Comfy API deployments, and your own ComfyUI instance. - - - See which client works with which deployment, starting with the Python and TypeScript SDKs. - - -See also: [Comfy SDKs](/development/api-development/sdks) · [API Proxy for Self-Hosted](/development/comfyui-server/api-proxy) · [Comfy API v2 Reference](/api-reference/v2/overview) - -## Agent Tools / MCP - -Connect AI agents to ComfyUI via the Model Context Protocol (MCP). Start with the hosted Cloud MCP, or use Local MCP and Comfy CLI for other setups. - - - Compare Cloud MCP, Local MCP, and Comfy CLI, and find the right setup for your AI agent integration. - - -See also: [Comfy MCP](/agent-tools/mcp) for cloud and local connections - -## More - - - - The raw REST and WebSocket API of the ComfyUI server: routes, messages, and startup flags. - - - Install, update, and manage ComfyUI from the terminal. - - - Extend ComfyUI with Python backends and JavaScript UI extensions. - - - Package and publish custom nodes through the Comfy Registry. - - diff --git a/docs.json b/docs.json index 856d618c6..f35e9d41c 100644 --- a/docs.json +++ b/docs.json @@ -3036,6 +3036,7 @@ "group": "Run Workflows", "pages": [ "development/run-workflows/overview", + "development/api-development/quickstart", "development/api-development/sdks", "development/comfyui-server/api-proxy", "development/api-development/workflow-api-format", diff --git a/files/api-first-result/first_workflow.mts b/files/api-first-result/first_workflow.mts new file mode 100644 index 000000000..068a5e4d5 --- /dev/null +++ b/files/api-first-result/first_workflow.mts @@ -0,0 +1,21 @@ +import { fileURLToPath } from "node:url"; +import { resolve } from "node:path"; +import { Comfy } from "@comfyorg/sdk"; + +const apiKey = process.env.COMFY_API_KEY; +if (!apiKey) { + throw new Error("Set COMFY_API_KEY to your Comfy API key before running this example."); +} + +// Keep the downloaded workflow alongside this script. +const workflowPath = fileURLToPath(new URL("./workflow_api.json", import.meta.url)); +const client = new Comfy({ apiKey }); +const workflow = await client.workflows.fromFile(workflowPath); +const job = await client.run(workflow); +// Node 2 is SaveImage in the bundled workflow. +const output = job.getOutputs("2")[0]; +if (!output) { + throw new Error("The workflow finished without an image from SaveImage (node 2)."); +} +await output.toFile("first-result.png"); +console.log(`Saved ${resolve("first-result.png")}`); diff --git a/files/api-first-result/first_workflow.py b/files/api-first-result/first_workflow.py new file mode 100644 index 000000000..68ef2aec3 --- /dev/null +++ b/files/api-first-result/first_workflow.py @@ -0,0 +1,20 @@ +import os +from pathlib import Path + +from comfy_sdk import Comfy + +api_key = os.environ.get("COMFY_API_KEY") +if not api_key: + raise SystemExit("Set COMFY_API_KEY to your Comfy API key before running this example.") + +# Keep the downloaded workflow alongside this script. +workflow_path = Path(__file__).with_name("workflow_api.json") +with Comfy(api_key=api_key) as client: + workflow = client.workflows.from_file(workflow_path) + job = client.run(workflow) + # Node 2 is SaveImage in the bundled workflow. + outputs = job.get_outputs("2") + if not outputs: + raise RuntimeError("The workflow finished without an image from SaveImage (node 2).") + output_path = outputs[0].to_file("first-result.png") + print(f"Saved {output_path.resolve()}") diff --git a/files/api-first-result/workflow_api.json b/files/api-first-result/workflow_api.json new file mode 100644 index 000000000..8d5fea656 --- /dev/null +++ b/files/api-first-result/workflow_api.json @@ -0,0 +1,18 @@ +{ + "1": { + "class_type": "EmptyImage", + "inputs": { + "width": 512, + "height": 512, + "batch_size": 1, + "color": 3368703 + } + }, + "2": { + "class_type": "SaveImage", + "inputs": { + "images": ["1", 0], + "filename_prefix": "comfy-first-result" + } + } +}