335 lines
11 KiB
Markdown
335 lines
11 KiB
Markdown
---
|
|
title: "Cloud API Overview"
|
|
description: "Programmatic access to Comfy Cloud for running workflows, managing files, and monitoring execution"
|
|
---
|
|
|
|
import PollJobCompletion from '/snippets/cloud/poll-job-completion.mdx'
|
|
import WebSocketProgress from '/snippets/cloud/websocket-progress.mdx'
|
|
import DownloadOutputs from '/snippets/cloud/download-outputs.mdx'
|
|
import CompleteExample from '/snippets/cloud/complete-example.mdx'
|
|
import GetApiKey from '/snippets/get-api-key.mdx'
|
|
|
|
<Warning>
|
|
**Experimental API:** This API is experimental and subject to change. Endpoints, request/response formats, and behavior may be modified without notice.
|
|
</Warning>
|
|
|
|
# Comfy Cloud API
|
|
|
|
The Comfy Cloud API provides programmatic access to run workflows on Comfy Cloud infrastructure. The API is compatible with local ComfyUI's API, making it easy to migrate existing integrations.
|
|
|
|
<Note>
|
|
**Subscription Required:** Running workflows via the API requires an active Comfy Cloud subscription. See [pricing plans](https://www.comfy.org/cloud/pricing?utm_source=docs&utm_campaign=cloud-api) for details.
|
|
</Note>
|
|
|
|
## Base URL
|
|
|
|
```
|
|
https://cloud.comfy.org
|
|
```
|
|
|
|
## Authentication
|
|
|
|
All API requests require an API key passed via the `X-API-Key` header.
|
|
|
|
### Getting an API Key
|
|
|
|
<GetApiKey />
|
|
|
|
<Warning>
|
|
Keep your API key secure. Never commit it to version control or share it publicly.
|
|
</Warning>
|
|
|
|
### Using the API Key
|
|
|
|
Pass your API key in the `X-API-Key` header with every request:
|
|
|
|
<CodeGroup>
|
|
```bash curl
|
|
curl -X GET "https://cloud.comfy.org/api/user" \
|
|
-H "X-API-Key: $COMFY_CLOUD_API_KEY"
|
|
```
|
|
|
|
```typescript TypeScript
|
|
const API_KEY = process.env.COMFY_CLOUD_API_KEY!;
|
|
|
|
const response = await fetch("https://cloud.comfy.org/api/user", {
|
|
headers: { "X-API-Key": API_KEY },
|
|
});
|
|
const user = await response.json();
|
|
```
|
|
|
|
```python Python
|
|
import os
|
|
import requests
|
|
|
|
API_KEY = os.environ["COMFY_CLOUD_API_KEY"]
|
|
headers = {"X-API-Key": API_KEY}
|
|
|
|
response = requests.get(
|
|
"https://cloud.comfy.org/api/user",
|
|
headers=headers
|
|
)
|
|
```
|
|
</CodeGroup>
|
|
|
|
## Core Concepts
|
|
|
|
### Workflows
|
|
|
|
ComfyUI workflows are JSON objects describing a graph of nodes. The API accepts workflows in the "API format" (node IDs as keys with class_type, inputs, etc.) as produced by the ComfyUI frontend's "Save (API Format)" option.
|
|
|
|
### Jobs
|
|
|
|
When you submit a workflow, a **job** is created. Jobs are executed asynchronously:
|
|
1. Submit workflow via `POST /api/prompt`
|
|
2. Receive a `prompt_id` (job ID)
|
|
3. Monitor progress via WebSocket or poll for status
|
|
4. Retrieve outputs when complete
|
|
|
|
### Parallel Execution (Concurrent Jobs)
|
|
|
|
API users can submit multiple workflows concurrently without waiting for previous jobs to complete. Simply send multiple `POST /api/prompt` requests — no special headers or parameters are needed. The dispatcher will run them in parallel up to your subscription tier's limit.
|
|
|
|
| Subscription Tier | Concurrent Jobs |
|
|
|-------------------|-----------------|
|
|
| Free | 1 |
|
|
| Standard | 1 |
|
|
| Creator | 3 |
|
|
| Pro | 5 |
|
|
|
|
Jobs submitted beyond your concurrency limit will queue normally and execute automatically as slots free up.
|
|
|
|
<Info>
|
|
Parallel execution is currently available via the API only. See [pricing plans](https://www.comfy.org/cloud/pricing?utm_source=docs&utm_campaign=cloud-api) for subscription details.
|
|
</Info>
|
|
|
|
#### Example: Submitting Multiple Jobs in Parallel
|
|
|
|
<CodeGroup>
|
|
```python Python
|
|
import os
|
|
import json
|
|
import asyncio
|
|
import aiohttp
|
|
|
|
BASE_URL = "https://cloud.comfy.org"
|
|
API_KEY = os.environ["COMFY_CLOUD_API_KEY"]
|
|
|
|
async def submit_workflow(session, workflow):
|
|
"""Submit a single workflow and return the prompt_id."""
|
|
async with session.post(
|
|
f"{BASE_URL}/api/prompt",
|
|
headers={"X-API-Key": API_KEY, "Content-Type": "application/json"},
|
|
json={"prompt": workflow},
|
|
) as response:
|
|
result = await response.json()
|
|
return result["prompt_id"]
|
|
|
|
async def main():
|
|
with open("workflow_api.json") as f:
|
|
base_workflow = json.load(f)
|
|
|
|
# Create variations by changing the seed
|
|
workflows = []
|
|
for seed in [42, 123, 456]:
|
|
workflow = json.loads(json.dumps(base_workflow))
|
|
workflow["3"]["inputs"]["seed"] = seed
|
|
workflows.append(workflow)
|
|
|
|
# Submit all workflows concurrently
|
|
async with aiohttp.ClientSession() as session:
|
|
prompt_ids = await asyncio.gather(
|
|
*[submit_workflow(session, wf) for wf in workflows]
|
|
)
|
|
|
|
for pid in prompt_ids:
|
|
print(f"Job submitted: {pid}")
|
|
|
|
# Poll or use WebSocket to monitor each job...
|
|
|
|
asyncio.run(main())
|
|
```
|
|
|
|
```typescript TypeScript
|
|
const BASE_URL = "https://cloud.comfy.org";
|
|
const API_KEY = process.env.COMFY_CLOUD_API_KEY!;
|
|
|
|
async function submitWorkflow(
|
|
workflow: Record<string, any>
|
|
): Promise<string> {
|
|
const response = await fetch(`${BASE_URL}/api/prompt`, {
|
|
method: "POST",
|
|
headers: { "X-API-Key": API_KEY, "Content-Type": "application/json" },
|
|
body: JSON.stringify({ prompt: workflow }),
|
|
});
|
|
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
return (await response.json()).prompt_id;
|
|
}
|
|
|
|
async function main() {
|
|
const base = JSON.parse(
|
|
await Deno.readTextFile("workflow_api.json")
|
|
);
|
|
|
|
// Create variations by changing the seed
|
|
const seeds = [42, 123, 456];
|
|
const workflows = seeds.map((seed) => {
|
|
const wf = structuredClone(base);
|
|
wf["3"].inputs.seed = seed;
|
|
return wf;
|
|
});
|
|
|
|
// Submit all workflows concurrently
|
|
const promptIds = await Promise.all(
|
|
workflows.map((wf) => submitWorkflow(wf))
|
|
);
|
|
|
|
for (const pid of promptIds) {
|
|
console.log(`Job submitted: ${pid}`);
|
|
}
|
|
|
|
// Poll or use WebSocket to monitor each job...
|
|
}
|
|
|
|
main();
|
|
```
|
|
</CodeGroup>
|
|
|
|
### Outputs
|
|
|
|
Generated content (images, videos, audio) is stored in cloud storage. Output files can be downloaded via the `/api/view` endpoint, which returns a 302 redirect to a temporary signed URL.
|
|
|
|
## Quick Start
|
|
|
|
Here's a complete example showing how to submit a workflow, monitor its progress, and retrieve outputs:
|
|
|
|
### Step 1: Submit a Workflow
|
|
|
|
<CodeGroup>
|
|
```bash curl
|
|
curl -X POST "https://cloud.comfy.org/api/prompt" \
|
|
-H "X-API-Key: $COMFY_CLOUD_API_KEY" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"prompt": '"$(cat workflow_api.json)"'}'
|
|
```
|
|
|
|
```typescript TypeScript
|
|
const BASE_URL = "https://cloud.comfy.org";
|
|
const API_KEY = process.env.COMFY_CLOUD_API_KEY!;
|
|
|
|
// Load your workflow (exported from ComfyUI in API format)
|
|
const workflow = JSON.parse(await Deno.readTextFile("workflow_api.json"));
|
|
|
|
// Submit the workflow
|
|
const response = await fetch(`${BASE_URL}/api/prompt`, {
|
|
method: "POST",
|
|
headers: { "X-API-Key": API_KEY, "Content-Type": "application/json" },
|
|
body: JSON.stringify({ prompt: workflow }),
|
|
});
|
|
const result = await response.json();
|
|
const promptId = result.prompt_id;
|
|
console.log(`Job submitted: ${promptId}`);
|
|
```
|
|
|
|
```python Python
|
|
import os
|
|
import requests
|
|
import json
|
|
|
|
BASE_URL = "https://cloud.comfy.org"
|
|
API_KEY = os.environ["COMFY_CLOUD_API_KEY"]
|
|
|
|
def get_headers():
|
|
return {"X-API-Key": API_KEY, "Content-Type": "application/json"}
|
|
|
|
# Load your workflow (exported from ComfyUI in API format)
|
|
with open("workflow_api.json") as f:
|
|
workflow = json.load(f)
|
|
|
|
# Submit the workflow
|
|
response = requests.post(
|
|
f"{BASE_URL}/api/prompt",
|
|
headers=get_headers(),
|
|
json={"prompt": workflow}
|
|
)
|
|
result = response.json()
|
|
prompt_id = result["prompt_id"]
|
|
print(f"Job submitted: {prompt_id}")
|
|
```
|
|
</CodeGroup>
|
|
|
|
### Step 2: Monitor Job Progress
|
|
|
|
You can monitor job completion using either polling or WebSocket for real-time updates.
|
|
|
|
#### Option A: Polling (Simple)
|
|
|
|
<PollJobCompletion />
|
|
|
|
#### Option B: WebSocket (Real-time Progress)
|
|
|
|
For real-time progress updates and to collect output metadata:
|
|
|
|
<WebSocketProgress />
|
|
|
|
<Note>
|
|
See [WebSocket Reference](/development/cloud/api-reference#websocket-for-real-time-progress) for detailed message types and handling binary preview images.
|
|
</Note>
|
|
|
|
### Step 3: Download Outputs
|
|
|
|
Once the job completes, download the generated files. The `outputs` object returned from WebSocket (or available via the history endpoint) contains output data organized by node ID. Each node's output may contain `images`, `video`, or `audio` arrays with file metadata.
|
|
|
|
**Example outputs structure:**
|
|
```json
|
|
{
|
|
"9": {
|
|
"images": [
|
|
{
|
|
"filename": "ComfyUI_00001_.png",
|
|
"subfolder": "",
|
|
"type": "output"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
The node ID (`"9"` in this example) corresponds to the SaveImage or other output nodes in your workflow. You can find these IDs by opening your workflow JSON file and looking for nodes with `class_type` like `SaveImage`, `VHS_VideoCombine`, etc.
|
|
|
|
<DownloadOutputs />
|
|
|
|
<Info>
|
|
The `/api/view` endpoint returns a 302 redirect to a temporary signed URL. Your HTTP client must follow redirects to download the file.
|
|
</Info>
|
|
|
|
### Complete Example
|
|
|
|
Here's a full end-to-end example combining all three steps:
|
|
|
|
<CompleteExample />
|
|
|
|
## Available Endpoints
|
|
|
|
| Category | Description |
|
|
|----------|-------------|
|
|
| [Workflows](/development/cloud/api-reference#running-workflows) | Submit workflows, check status |
|
|
| [Jobs](/development/cloud/api-reference#checking-job-status) | Monitor job status and queue |
|
|
| [Inputs](/development/cloud/api-reference#uploading-inputs) | Upload images, masks, and other inputs |
|
|
| [Outputs](/development/cloud/api-reference#downloading-outputs) | Download generated content |
|
|
| [WebSocket](/development/cloud/api-reference#websocket-for-real-time-progress) | Real-time progress updates |
|
|
| [Object Info](/development/cloud/api-reference#object-info) | Available nodes and their definitions |
|
|
|
|
## Next Steps
|
|
|
|
The quick start above covers the basics of submitting workflows and retrieving results. For more advanced use cases, refer to the [Cloud API Reference](/development/cloud/api-reference):
|
|
|
|
- **[Uploading Input Files](/development/cloud/api-reference#uploading-inputs)** - Upload images, masks, or other user-provided content for workflows that require external inputs
|
|
- **[Modifying Workflow Inputs](/development/cloud/api-reference#modify-workflow-inputs)** - Dynamically change workflow parameters like prompts, seeds, or node settings before submission
|
|
- **[Using Partner Nodes](/development/cloud/api-reference#using-partner-nodes)** - Call external AI services (Flux Pro, Ideogram, etc.) that require additional API key configuration
|
|
- **[Queue Management](/development/cloud/api-reference#queue-management)** - Monitor queue status, cancel jobs, or interrupt running executions
|
|
- **[Error Handling](/development/cloud/api-reference#error-handling)** - Handle HTTP errors, execution failures, and understand exception types
|
|
|
|
Additional resources:
|
|
- [OpenAPI Specification](/development/cloud/openapi) - Machine-readable API spec for code generation
|