Skip to content
Open
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
190 changes: 190 additions & 0 deletions development/cloud/api-reference.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,196 @@ workflow = set_workflow_input(workflow, "6", "text", "a beautiful landscape")

---

## Jobs API

The Jobs API provides efficient endpoints for listing and retrieving job details. Use these endpoints instead of the legacy `/history` and `/queue` endpoints for better performance and richer filtering options.

### List Jobs

Retrieve a paginated list of jobs with optional filtering by status, workflow ID, or output type.

<CodeGroup>
```bash curl
# List all jobs (most recent first)
curl -X GET "$BASE_URL/api/jobs" \
-H "X-API-Key: $COMFY_CLOUD_API_KEY"

# Filter by status
curl -X GET "$BASE_URL/api/jobs?status=completed" \
-H "X-API-Key: $COMFY_CLOUD_API_KEY"

# Filter by output type and sort by execution time
curl -X GET "$BASE_URL/api/jobs?output_type=image&sort_by=execution_time&sort_order=desc" \
-H "X-API-Key: $COMFY_CLOUD_API_KEY"
```

```typescript TypeScript
interface JobEntry {
id: string;
status: "pending" | "in_progress" | "completed" | "failed" | "cancelled";
create_time: number;
preview_output?: Record<string, any>;
outputs_count?: number;
workflow_id?: string;
execution_start_time?: number;
execution_end_time?: number;
}

interface JobsListResponse {
jobs: JobEntry[];
pagination: {
offset: number;
limit: number;
total: number;
has_more: boolean;
};
}

async function listJobs(options: {
status?: string;
output_type?: "image" | "video" | "audio";
sort_by?: "create_time" | "execution_time";
sort_order?: "asc" | "desc";
offset?: number;
limit?: number;
} = {}): Promise<JobsListResponse> {
const params = new URLSearchParams();
if (options.status) params.set("status", options.status);
if (options.output_type) params.set("output_type", options.output_type);
if (options.sort_by) params.set("sort_by", options.sort_by);
if (options.sort_order) params.set("sort_order", options.sort_order);
if (options.offset !== undefined) params.set("offset", String(options.offset));
if (options.limit !== undefined) params.set("limit", String(options.limit));

const response = await fetch(`${BASE_URL}/api/jobs?${params}`, {
headers: getHeaders(),
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.json();
}

// List recent completed jobs
const { jobs, pagination } = await listJobs({ status: "completed", limit: 10 });
console.log(`Found ${pagination.total} completed jobs`);
```

```python Python
def list_jobs(
status: str = None,
output_type: str = None,
sort_by: str = "create_time",
sort_order: str = "desc",
offset: int = 0,
limit: int = 100
) -> dict:
"""List jobs with optional filtering.

Args:
status: Filter by status (pending, in_progress, completed, failed, cancelled)
output_type: Filter by output type (image, video, audio)
sort_by: Sort field (create_time or execution_time)
sort_order: Sort direction (asc or desc)
offset: Pagination offset
limit: Max items per page (1-1000)

Returns:
Dict with 'jobs' array and 'pagination' info
"""
params = {
"sort_by": sort_by,
"sort_order": sort_order,
"offset": offset,
"limit": limit
}
if status:
params["status"] = status
if output_type:
params["output_type"] = output_type

response = requests.get(
f"{BASE_URL}/api/jobs",
headers=get_headers(),
params=params
)
response.raise_for_status()
return response.json()

# List recent completed jobs
result = list_jobs(status="completed", limit=10)
print(f"Found {result['pagination']['total']} completed jobs")
```
</CodeGroup>

### Get Job Details

Retrieve complete details for a specific job including the workflow and full outputs.

<CodeGroup>
```bash curl
curl -X GET "$BASE_URL/api/jobs/{job_id}" \
-H "X-API-Key: $COMFY_CLOUD_API_KEY"
```

```typescript TypeScript
interface JobDetailResponse {
id: string;
status: "pending" | "in_progress" | "completed" | "failed" | "cancelled";
workflow?: Record<string, any>;
outputs?: Record<string, any>;
preview_output?: Record<string, any>;
outputs_count?: number;
create_time: number;
update_time: number;
workflow_id?: string;
execution_status?: Record<string, any>;
execution_meta?: Record<string, any>;
}

async function getJobDetails(jobId: string): Promise<JobDetailResponse> {
const response = await fetch(`${BASE_URL}/api/jobs/${jobId}`, {
headers: getHeaders(),
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.json();
}

// Get full job details including outputs
const job = await getJobDetails(promptId);
if (job.status === "completed" && job.outputs) {
console.log(`Job has ${job.outputs_count} outputs`);
}
```

```python Python
def get_job_details(job_id: str) -> dict:
"""Get complete job details including workflow and outputs.

Args:
job_id: The job/prompt ID

Returns:
Full job details including workflow and outputs
"""
response = requests.get(
f"{BASE_URL}/api/jobs/{job_id}",
headers=get_headers()
)
response.raise_for_status()
return response.json()

# Get full job details including outputs
job = get_job_details(prompt_id)
if job["status"] == "completed" and job.get("outputs"):
print(f"Job has {job.get('outputs_count', 0)} outputs")
```
</CodeGroup>

<Note>
**Legacy Endpoints:** The `/api/history`, `/api/history_v2`, and `/api/queue` endpoints are maintained for compatibility with local ComfyUI but the Jobs API is recommended for new integrations.
</Note>

---

## Checking Job Status

Poll for job completion.
Expand Down
73 changes: 70 additions & 3 deletions development/comfyui-server/comms_routes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,12 @@ The prompt queue is defined in `execution.py`, which also defines the `PromptExe
| `/prompt` | post | submit a prompt to the queue |
| `/object_info` | get | retrieve details of all node types |
| `/object_info/{node_class}` | get | retrieve details of one node type |
| `/history` | get | retrieve the queue history |
| `/history/{prompt_id}` | get | retrieve the queue history for a specific prompt |
| `/jobs` | get | list jobs with filtering, sorting, and pagination (recommended) |
| `/jobs/{job_id}` | get | get full details for a specific job (recommended) |
| `/history` | get | retrieve the queue history (legacy) |
| `/history/{prompt_id}` | get | retrieve the queue history for a specific prompt (legacy) |
| `/history` | post | clear history or delete history item |
| `/queue` | get | retrieve the current state of the execution queue |
| `/queue` | get | retrieve the current state of the execution queue (legacy) |
| `/queue` | post | manage queue operations (clear pending/running) |
| `/interrupt` | post | stop the current workflow execution |
| `/free` | post | free memory by unloading specified models |
Expand All @@ -51,6 +53,71 @@ The prompt queue is defined in `execution.py`, which also defines the `PromptExe
| `/users` | get | get user information |
| `/users` | post | create a new user (multi-user mode only) |

### Jobs API

The Jobs API (`/jobs`) provides a unified interface for listing and retrieving job information with filtering, sorting, and pagination. It is the recommended way to query job status and history.

#### List Jobs

`GET /jobs` returns a paginated list of jobs with optional filtering:

| Parameter | Type | Description |
|-----------|------|-------------|
| `status` | string | Filter by status (comma-separated): `pending`, `in_progress`, `completed`, `failed`, `cancelled` |
| `workflow_id` | string | Filter by workflow ID |
| `sort_by` | string | Sort field: `created_at` (default), `execution_duration` |
| `sort_order` | string | Sort direction: `asc`, `desc` (default) |
| `limit` | integer | Maximum items to return |
| `offset` | integer | Items to skip (default: 0) |

**Response:**
```json
{
"jobs": [
{
"id": "prompt-uuid",
"status": "completed",
"create_time": 1706540000,
"workflow_id": "workflow-uuid",
"outputs_count": 2,
"preview_output": {"filename": "output.png", "type": "output"},
"execution_start_time": 1706540001000,
"execution_end_time": 1706540005000
}
],
"pagination": {
"offset": 0,
"limit": 100,
"total": 42,
"has_more": false
}
}
```

#### Get Job Details

`GET /jobs/{job_id}` returns full details for a specific job including outputs and workflow:

```json
{
"id": "prompt-uuid",
"status": "completed",
"create_time": 1706540000,
"outputs": {
"9": {"images": [{"filename": "output.png", "type": "output"}]}
},
"workflow": {
"prompt": {...},
"extra_data": {...}
},
"execution_status": {...}
}
```

<Note>
The Jobs API consolidates data from the queue and history into a single unified format. Use `/jobs` instead of separately querying `/queue` and `/history` endpoints.
</Note>

### WebSocket Communication

The `/ws` endpoint provides real-time bidirectional communication between the client and server. This is used for:
Expand Down
18 changes: 9 additions & 9 deletions snippets/cloud/complete-example.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ async function main() {
await new Promise((resolve) => setTimeout(resolve, 2000));
}

// 4. Get outputs via history endpoint
const historyRes = await fetch(`${BASE_URL}/api/history_v2/${prompt_id}`, {
// 4. Get outputs via Jobs API
const jobRes = await fetch(`${BASE_URL}/api/jobs/${prompt_id}`, {
headers: { "X-API-Key": API_KEY },
});
const history = await historyRes.json();
const outputs = history.outputs;
const job = await jobRes.json();
const outputs = job.outputs;

// 5. Download output files
for (const nodeOutputs of Object.values(outputs)) {
Expand Down Expand Up @@ -104,13 +104,13 @@ def main():
raise RuntimeError(f"Job {status}")
time.sleep(2)

# 4. Get outputs via history endpoint
history_res = requests.get(
f"{BASE_URL}/api/history_v2/{prompt_id}",
# 4. Get outputs via Jobs API
job_res = requests.get(
f"{BASE_URL}/api/jobs/{prompt_id}",
headers={"X-API-Key": API_KEY}
)
history = history_res.json()
outputs = history["outputs"]
job = job_res.json()
outputs = job["outputs"]

# 5. Download output files
for node_outputs in outputs.values():
Expand Down
18 changes: 9 additions & 9 deletions snippets/zh/cloud/complete-example.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ async function main() {
await new Promise((resolve) => setTimeout(resolve, 2000));
}

// 4. 通过历史端点获取输出
const historyRes = await fetch(`${BASE_URL}/api/history_v2/${prompt_id}`, {
// 4. 通过 Jobs API 获取输出
const jobRes = await fetch(`${BASE_URL}/api/jobs/${prompt_id}`, {
headers: { "X-API-Key": API_KEY },
});
const history = await historyRes.json();
const outputs = history.outputs;
const job = await jobRes.json();
const outputs = job.outputs;

// 5. 下载输出文件
for (const nodeOutputs of Object.values(outputs)) {
Expand Down Expand Up @@ -104,13 +104,13 @@ def main():
raise RuntimeError(f"任务 {status}")
time.sleep(2)

# 4. 通过历史端点获取输出
history_res = requests.get(
f"{BASE_URL}/api/history_v2/{prompt_id}",
# 4. 通过 Jobs API 获取输出
job_res = requests.get(
f"{BASE_URL}/api/jobs/{prompt_id}",
headers={"X-API-Key": API_KEY}
)
history = history_res.json()
outputs = history["outputs"]
job = job_res.json()
outputs = job["outputs"]

# 5. 下载输出文件
for node_outputs in outputs.values():
Expand Down
Loading