Skip to main content
GET
https://api.comfycontrol.app
/
v1
/
workflow
/
{id}
/
subscribe
Subscribe to Workflow Updates
curl --request GET \
  --url https://api.comfycontrol.app/v1/workflow/{id}/subscribe \
  --header 'Authorization: Bearer <token>'
{
  "401": {},
  "404": {},
  "status": "<string>",
  "prompt": {},
  "queue_number": 123,
  "outputs": [
    {}
  ],
  "outputs[].id": "<string>",
  "outputs[].workflow_id": "<string>",
  "outputs[].src": "<string>",
  "cause": {},
  "cause.node_type": "<string>",
  "cause.exception_type": "<string>",
  "cause.exception_message": "<string>",
  "started_at": "<string>",
  "completed_at": "<string>"
}

Overview

Subscribe to real-time updates for a workflow execution using Server-Sent Events (SSE). This provides live progress updates, status changes, and output information as the workflow executes.
This endpoint uses Server-Sent Events (SSE) for real-time updates. The connection remains open until the workflow reaches a terminal state or the maximum update limit is reached.

Path Parameters

id
string
required
The unique identifier (UUID) of the workflow to monitor.

Response

This endpoint streams events in Server-Sent Events format. Each event contains a JSON payload with workflow status information.

Event Data Format

status
string
Current status of the workflow.Possible values: accepted, uploaded, queued, running, completed, cancelled, invalid, failed
prompt
object
ComfyUI prompt information (structure varies based on workflow).
queue_number
integer
Current position in the execution queue (null if not queued).
outputs
array
Array of output media objects (populated when status is completed).
outputs[].id
string
Output file identifier.
outputs[].workflow_id
string
Workflow UUID.
outputs[].src
string
Signed URL to the output file.
cause
object
Error information (only present if status is failed).
cause.node_type
string
The ComfyUI node that caused the failure.
cause.exception_type
string
Type of exception.
cause.exception_message
string
Detailed error message.
started_at
string
ISO 8601 timestamp when execution started.
completed_at
string
ISO 8601 timestamp when execution completed.

Example Event Stream

data: {"status":"queued","prompt":null,"queue_number":3,"outputs":[],"cause":null,"started_at":null,"completed_at":null}

data: {"status":"running","prompt":{"prompt_id":"abc123"},"queue_number":1,"outputs":[],"cause":null,"started_at":"2024-01-15T14:30:05Z","completed_at":null}

data: {"status":"completed","prompt":{"prompt_id":"abc123"},"queue_number":null,"outputs":[{"id":"output-1","workflow_id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","src":"https://storage.comfycontrol.app/outputs/..."}],"cause":null,"started_at":"2024-01-15T14:30:05Z","completed_at":"2024-01-15T14:32:15Z"}

Connection Behavior

  • Update Interval: ~2 seconds between updates
  • Maximum Updates: 120 updates (~4 minutes)
  • Auto-Close: Connection automatically closes when workflow reaches a terminal state (completed, failed, cancelled)
  • Reconnection: Client should reconnect if connection drops unexpectedly

Error Responses

401
error
Unauthorized - invalid or missing authentication token.
404
error
Not Found - workflow with the specified ID does not exist or does not belong to your account.

Notes

  • Use this endpoint instead of polling for real-time updates
  • Connection closes automatically when workflow completes
  • Maximum connection time is ~4 minutes (120 updates × 2 seconds)
  • For long-running workflows, reconnect if max updates is reached
  • Outputs are included in the final event when status becomes completed
  • SSE is supported by most modern HTTP clients and browsers
  • Connection may be closed by network timeouts or proxies - implement reconnection logic
  • Each event is a complete status snapshot, not a delta

Example Client Code

import requests
import json

def monitor_workflow(workflow_id, token):
    url = f"https://api.comfycontrol.app/v1/workflow/{workflow_id}/subscribe"
    headers = {"Authorization": f"Bearer {token}"}
    
    with requests.get(url, headers=headers, stream=True) as response:
        for line in response.iter_lines():
            if line and line.startswith(b'data: '):
                data = json.loads(line[6:])
                print(f"Status: {data['status']}")
                
                if data['status'] in ['completed', 'failed', 'cancelled']:
                    print("Workflow finished")
                    break