Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions development/api-development/quickstart.mdx
Original file line number Diff line number Diff line change
@@ -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).

Check warning on line 16 in development/api-development/quickstart.mdx

View check run for this annotation

Mintlify / Mintlify Validation (dripart) - vale-spellcheck

development/api-development/quickstart.mdx#L16

Did you really mean 'SDKs'?

## 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.

<CodeGroup>
```bash Python
python -m venv .venv

Check warning on line 33 in development/api-development/quickstart.mdx

View check run for this annotation

Mintlify / Mintlify Validation (dripart) - vale-spellcheck

development/api-development/quickstart.mdx#L33

'venv' is repeated!

Check warning on line 33 in development/api-development/quickstart.mdx

View check run for this annotation

Mintlify / Mintlify Validation (dripart) - vale-spellcheck

development/api-development/quickstart.mdx#L33

Did you really mean 'venv'?
source .venv/bin/activate
python -m pip install comfy-sdk
```

```bash TypeScript
npm init -y
npm install @comfyorg/sdk
```
</CodeGroup>

On Windows, activate the Python environment with `.venv\Scripts\Activate.ps1` in PowerShell.

Set your key in the same terminal:

<CodeGroup>
```bash macOS / Linux
export COMFY_API_KEY="comfyui-your-key"
```

```powershell Windows PowerShell
$env:COMFY_API_KEY = "comfyui-your-key"
```
</CodeGroup>

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

<CodeGroup>
```bash Python
python first_workflow.py
```

```bash TypeScript
node first_workflow.mts
```
</CodeGroup>

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.

<Note>
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.
</Note>

### 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).
22 changes: 10 additions & 12 deletions development/comfy-router/limitations.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,34 @@
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). |

Check warning on line 16 in development/comfy-router/limitations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (dripart) - vale-spellcheck

development/comfy-router/limitations.mdx#L16

Did you really mean 'idempotency'?

Check warning on line 16 in development/comfy-router/limitations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (dripart) - vale-spellcheck

development/comfy-router/limitations.mdx#L16

Did you really mean 'idempotency'?
| 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). |

Check warning on line 18 in development/comfy-router/limitations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (dripart) - vale-spellcheck

development/comfy-router/limitations.mdx#L18

Did you really mean 'rehosted'?

## 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.

`504` / `deadline_exceeded` means Router stopped waiting; `504` / `provider_timeout` means the provider timed out. A timeout or lost connection does not prove that a generation was unbilled, and it does not cancel accepted provider work. Read [timeouts and collection](/development/comfy-router/api#timeouts-and-collection) before retrying.

Check warning on line 28 in development/comfy-router/limitations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (dripart) - vale-spellcheck

development/comfy-router/limitations.mdx#L28

Did you really mean 'unbilled'?

<span id="no-way-to-resume-a-call-you-lost" />

## Recovery depends on the provider

Router can retain a provider handle for an accepted submit-and-poll generation. Reuse the same `Idempotency-Key` to collect it later; completed replayable responses can also come from the key record.

Check warning on line 34 in development/comfy-router/limitations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (dripart) - vale-spellcheck

development/comfy-router/limitations.mdx#L34

Did you really mean 'replayable'?

Not every disconnected call is recoverable. Preserve the request and key before sending, then use the [retry outcome table](/development/comfy-router/api#retry-outcomes). A new key creates a new call and may incur another charge.

Expand All @@ -48,11 +46,11 @@

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.

<span id="no-cost-or-credit-figures-on-a-response" />

Expand All @@ -70,7 +68,7 @@

Input and output fields vary by model. Moving from a provider SDK or proxy can change both the route and how you read the result.

Some assets are rehosted on Comfy storage; others are provider URLs or inline bytes. See [Result assets](/development/comfy-router/reference#result-assets) for lifetimes and replay behavior.

Check warning on line 71 in development/comfy-router/limitations.mdx

View check run for this annotation

Mintlify / Mintlify Validation (dripart) - vale-spellcheck

development/comfy-router/limitations.mdx#L71

Did you really mean 'rehosted'?

## Next

Expand Down
66 changes: 16 additions & 50 deletions development/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,26 @@

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.

<Card title="Call a hosted model with Comfy Router" icon="rocket" href="/development/comfy-router/quickstart">
Generate your first image with a Comfy API key in Python, TypeScript, or cURL.
</Card>
## Use cases

<CardGroup cols={2}>
<Card title="Call a hosted model" icon="rocket" href="/development/comfy-router/quickstart">
Generate with hosted models through Comfy Router.
</Card>
<Card title="Deploy ComfyUI" icon="map" href="/development/deploy/overview">
Deploy ComfyUI on the Developer Platform or your own infrastructure.
</Card>
<Card title="Run workflows" icon="play" href="/development/run-workflows/overview">
Run workflows from your application with an SDK or the HTTP API.
</Card>
<Card title="Connect AI agents" icon="robot" href="/agent-tools">
Connect AI agents to ComfyUI with MCP and Comfy CLI.
</Card>
</CardGroup>

## Quick Start

The fastest way to try the workflow API is to run a workflow against Comfy Cloud. The SDKs point at Comfy Cloud by default. You'll need a workflow, an [API key](/development/api-development/getting-an-api-key), and a [paid Comfy Cloud subscription](/development/deploy/cloud).

Check warning on line 27 in development/overview.mdx

View check run for this annotation

Mintlify / Mintlify Validation (dripart) - vale-spellcheck

development/overview.mdx#L27

Did you really mean 'SDKs'?

<Steps>
<Step title="Get a workflow">
Expand All @@ -31,7 +44,7 @@
<Step title="Run it">
<CodeGroup>
```python Python
from comfy_sdk import Comfy

Check warning on line 47 in development/overview.mdx

View check run for this annotation

Mintlify / Mintlify Validation (dripart) - vale-spellcheck

development/overview.mdx#L47

Did you really mean 'comfy_sdk'?

client = Comfy(api_key="comfyui-...") # Comfy Cloud is the default target

Expand All @@ -57,53 +70,6 @@
`"9"` is the ID of the output node in your workflow file. See the [SDK guide](/development/api-development/sdks) for inputs, progress events, and error handling.
</Step>
<Step title="Deploy your own ComfyUI">
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.

Check warning on line 73 in development/overview.mdx

View check run for this annotation

Mintlify / Mintlify Validation (dripart) - vale-spellcheck

development/overview.mdx#L73

Did you really mean 'serverless'?
</Step>
</Steps>

## Deploy ComfyUI

Learn how to deploy and scale ComfyUI, on the Developer Platform or your own infrastructure.

<Card title="Deployment Overview" icon="map" href="/development/deploy/overview">
Compare Comfy API deployments, Comfy Cloud, and self-hosting, and pick the right target.
</Card>

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.

<Card title="Running Workflows" icon="play" href="/development/run-workflows/overview">
See which client works with which deployment, starting with the Python and TypeScript SDKs.
</Card>

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.

<Card title="MCP Overview" icon="robot" href="/agent-tools">
Compare Cloud MCP, Local MCP, and Comfy CLI, and find the right setup for your AI agent integration.
</Card>

See also: [Comfy MCP](/agent-tools/mcp) for cloud and local connections

## More

<CardGroup cols={2}>
<Card title="Self-Hosted Server API" icon="server" href="/development/comfyui-server/comms_overview">
The raw REST and WebSocket API of the ComfyUI server: routes, messages, and startup flags.
</Card>
<Card title="Comfy CLI" icon="terminal" href="/comfy-cli/getting-started">
Install, update, and manage ComfyUI from the terminal.
</Card>
<Card title="Custom Nodes" icon="puzzle-piece" href="/custom-nodes/overview">
Extend ComfyUI with Python backends and JavaScript UI extensions.
</Card>
<Card title="Registry" icon="box-open" href="/registry/overview">
Package and publish custom nodes through the Comfy Registry.
</Card>
</CardGroup>
1 change: 1 addition & 0 deletions docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
21 changes: 21 additions & 0 deletions files/api-first-result/first_workflow.mts
Original file line number Diff line number Diff line change
@@ -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")}`);
20 changes: 20 additions & 0 deletions files/api-first-result/first_workflow.py
Original file line number Diff line number Diff line change
@@ -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()}")
18 changes: 18 additions & 0 deletions files/api-first-result/workflow_api.json
Original file line number Diff line number Diff line change
@@ -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"
}
}
}
Loading