ComfyUI/openapi.yaml

9925 lines
408 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

components:
schemas:
AcceptInviteResponse:
description: Response returned after successfully accepting a workspace invitation.
properties:
workspace_id:
description: ID of the workspace joined
type: string
workspace_name:
description: Name of the workspace joined
type: string
required:
- workspace_id
- workspace_name
type: object
Asset:
description: Represents a user-owned asset (image, video, or other generated output).
properties:
asset_hash:
description: Blake3 hash of the asset content
pattern: ^blake3:[a-f0-9]{64}$
type: string
created_at:
description: Timestamp when the asset was created
format: date-time
type: string
display_name:
description: Display name of the asset. Mirrors name for backwards compatibility.
nullable: true
type: string
id:
description: Unique identifier for the asset
format: uuid
type: string
is_immutable:
description: Whether this asset is immutable (cannot be modified or deleted)
type: boolean
job_id:
description: ID of the job that created this asset, if available
format: uuid
nullable: true
type: string
last_access_time:
description: Timestamp when the asset was last accessed
format: date-time
type: string
metadata:
additionalProperties: true
description: System-managed metadata from download sources (HuggingFace, CivitAI, etc.) - read-only, not user-modifiable
readOnly: true
type: object
mime_type:
description: MIME type of the asset
type: string
name:
description: Name of the asset file
type: string
preview_id:
description: ID of the preview asset if available
format: uuid
nullable: true
type: string
preview_url:
description: URL for asset preview/thumbnail
format: uri
type: string
prompt_id:
deprecated: true
description: 'Deprecated: use job_id instead. ID of the prompt that created this asset, if available'
format: uuid
nullable: true
type: string
size:
description: Size of the asset in bytes
format: int64
type: integer
tags:
description: Tags associated with the asset
items:
type: string
type: array
updated_at:
description: Timestamp when the asset was last updated
format: date-time
type: string
user_metadata:
additionalProperties: true
description: Custom user metadata for the asset
type: object
required:
- id
- name
- size
- created_at
- updated_at
type: object
AssetCreated:
allOf:
- $ref: '#/components/schemas/Asset'
- properties:
created_new:
description: Whether this was a new asset creation (true) or returned existing (false)
type: boolean
required:
- created_new
type: object
description: Response returned when a new asset is successfully created.
AssetDownloadResponse:
description: Acknowledgement of an async asset download task; clients poll GET /api/tasks/{task_id} for status.
properties:
message:
description: Human-readable message
example: Download task created. Use task_id to track progress.
type: string
status:
description: Current task status
enum:
- created
- running
- completed
- failed
type: string
task_id:
description: Task ID for tracking download progress via GET /api/tasks/{task_id}
format: uuid
type: string
required:
- task_id
- status
type: object
AssetInfo:
description: Lightweight asset reference used in workflow publishing payloads.
properties:
id:
description: Asset identifier.
type: string
in_library:
description: Whether the caller already owns this asset.
type: boolean
model:
description: Whether this asset is a model.
type: boolean
name:
type: string
preview_url:
description: Signed URL for previewing the asset.
type: string
public:
description: Whether this is a public (platform-provided) asset.
type: boolean
storage_url:
type: string
required:
- id
- name
- preview_url
- storage_url
- model
- public
- in_library
type: object
AssetMetadataResponse:
description: Metadata for a remotely hosted asset resolved by URL.
properties:
content_length:
description: Size of the asset in bytes (-1 if unknown)
example: 4294967296
format: int64
type: integer
content_type:
description: MIME type of the asset
example: application/octet-stream
type: string
filename:
description: Suggested filename for the asset from source
example: realistic-vision-v5.safetensors
type: string
name:
description: Display name or title for the asset from source
example: Realistic Vision v5.0
type: string
preview_image:
description: Preview image as base64-encoded data URL
example: data:image/jpeg;base64,/9j/4AAQSkZJRg...
type: string
tags:
description: Tags for categorization from source
example:
- models
- checkpoint
items:
type: string
type: array
validation:
allOf:
- $ref: '#/components/schemas/ValidationResult'
description: Validation results for the file
required:
- content_length
type: object
AssetTagHistogramResponse:
description: Histogram of tag counts used for refining asset search results.
properties:
tag_counts:
additionalProperties:
type: integer
description: Map of tag names to their occurrence counts on matching assets
example:
checkpoint: 32
lora: 193
vae: 6
type: object
required:
- tag_counts
type: object
AssetUpdated:
description: Response returned when an existing asset is successfully updated.
properties:
asset_hash:
description: Blake3 hash of the asset content
pattern: ^blake3:[a-f0-9]{64}$
type: string
display_name:
description: Display name of the asset. Mirrors name for backwards compatibility.
nullable: true
type: string
id:
description: Asset ID
format: uuid
type: string
mime_type:
description: Updated MIME type of the asset
type: string
name:
description: Updated name of the asset
type: string
tags:
description: Tags associated with the asset
items:
type: string
type: array
updated_at:
description: Timestamp of the update
format: date-time
type: string
user_metadata:
additionalProperties: true
description: Updated custom metadata
type: object
required:
- id
- updated_at
type: object
BillingBalanceResponse:
description: Current credit balance and usage details for a workspace.
properties:
amount_micros:
description: The total remaining balance in microamount (1/1,000,000 of the currency unit)
format: double
type: number
cloud_credit_balance_micros:
description: The remaining balance from cloud credits in microamount
format: double
type: number
currency:
description: Currency code
example: usd
type: string
effective_balance_micros:
description: The effective balance (total balance minus pending charges). Can be negative if pending charges exceed the balance.
format: double
type: number
pending_charges_micros:
description: The total amount of pending/unbilled charges from draft invoices in microamount
format: double
type: number
prepaid_balance_micros:
description: The remaining balance from prepaid commits in microamount
format: double
type: number
required:
- amount_micros
- currency
type: object
BillingEvent:
description: A single billing event such as a charge, credit, or adjustment.
properties:
createdAt:
description: When the event occurred
format: date-time
type: string
event_id:
description: Unique event identifier
type: string
event_type:
description: Type of billing event (e.g., subscription.created, payment.succeeded)
type: string
params:
additionalProperties: true
description: Event-specific parameters
type: object
required:
- event_type
- event_id
- createdAt
type: object
BillingEventsResponse:
description: Paginated list of billing events for a workspace.
properties:
events:
items:
$ref: '#/components/schemas/BillingEvent'
type: array
limit:
description: Items per page
type: integer
page:
description: Current page number (1-indexed)
type: integer
total:
description: Total number of events
type: integer
totalPages:
description: Total number of pages
type: integer
required:
- total
- events
- page
- limit
- totalPages
type: object
BillingOpStatusResponse:
description: Status of an asynchronous billing operation.
properties:
completed_at:
description: When the operation completed (success or failure)
format: date-time
type: string
error_message:
description: Error message if status is failed
type: string
id:
description: Unique identifier for the billing operation
type: string
started_at:
description: When the operation was initiated
format: date-time
type: string
status:
description: Current status of the operation
enum:
- pending
- succeeded
- failed
type: string
required:
- id
- status
- started_at
type: object
BillingPlansResponse:
description: List of available billing plans for subscription.
properties:
current_plan_slug:
description: Current plan slug if subscribed
type: string
plans:
items:
$ref: '#/components/schemas/Plan'
type: array
required:
- plans
type: object
BillingStatus:
description: Payment lifecycle status
enum:
- awaiting_payment_method
- pending_payment
- paid
- payment_failed
- inactive
type: string
BillingStatusResponse:
description: Current billing and subscription status for a workspace.
properties:
billing_status:
$ref: '#/components/schemas/BillingStatus'
cancel_at:
description: When the subscription will become inactive (if canceled)
format: date-time
type: string
has_funds:
description: Whether the workspace has available credits
type: boolean
is_active:
description: Whether the workspace has an active subscription
type: boolean
plan_slug:
description: Plan identifier (e.g., standard-monthly, team-pro-annual)
type: string
renewal_date:
description: When the current billing period ends and the next one begins
format: date-time
type: string
subscription_duration:
$ref: '#/components/schemas/SubscriptionDuration'
subscription_status:
description: Subscription activity status (scheduled subscriptions are not returned)
enum:
- active
- ended
- canceled
type: string
subscription_tier:
$ref: '#/components/schemas/SubscriptionTier'
required:
- is_active
- has_funds
type: object
BindingErrorResponse:
description: Error shape returned when request binding or validation fails before the handler runs.
properties:
message:
type: string
required:
- message
type: object
BulkRevokeAPIKeysResponse:
description: Response after bulk-revoking API keys for a workspace member.
properties:
revoked_count:
description: Number of API keys that were revoked
minimum: 0
type: integer
required:
- revoked_count
type: object
CancelSubscriptionRequest:
description: Request body for cancelling the current subscription.
properties:
idempotency_key:
description: |
Client-provided key to prevent duplicate operations.
If a billing op with this key already exists, returns the existing op instead of creating a new one.
type: string
type: object
CancelSubscriptionResponse:
description: Response after successfully cancelling a subscription.
properties:
billing_op_id:
description: Billing operation ID to poll for status via GET /api/billing/ops/{id}
type: string
cancel_at:
description: The date when the subscription will end (end of current billing period)
format: date-time
type: string
required:
- cancel_at
- billing_op_id
type: object
CreateHubProfileRequest:
description: Request body for creating a new Hub profile.
properties:
avatar_token:
description: |
Token (from /api/hub/assets/upload-url) for an avatar image. Omit to have no avatar.
type: string
description:
type: string
display_name:
type: string
username:
description: Unique URL-safe slug for the hub profile. Immutable after creation.
type: string
website_urls:
description: List of website URLs.
items:
type: string
type: array
workspace_id:
description: ID of the workspace to create the hub profile for. The authenticated user must belong to this workspace.
type: string
required:
- workspace_id
- username
type: object
CreateInviteRequest:
description: Request body for inviting a user to a workspace.
properties:
email:
description: Email address to invite
format: email
type: string
required:
- email
type: object
CreateSecretRequest:
description: Request body for creating a new user secret.
properties:
name:
description: User-provided label for the secret
maxLength: 255
minLength: 1
type: string
provider:
description: Optional provider identifier (e.g., huggingface, civitai)
maxLength: 64
type: string
secret_value:
description: The plaintext secret to encrypt and store
minLength: 1
type: string
required:
- name
- secret_value
type: object
CreateSessionResponse:
description: Response after creating a session cookie
properties:
expiresIn:
description: Session expiration time in seconds (5 days)
type: integer
success:
description: Whether the session was created successfully
type: boolean
required:
- success
type: object
CreateTopupRequest:
description: Request body for purchasing a one-time credit top-up.
properties:
amount_cents:
description: Amount to charge and grant as credits (in cents). Minimum $5.00.
format: int64
minimum: 500
type: integer
idempotency_key:
description: |
Client-provided key to prevent duplicate operations.
If a billing op with this key already exists, returns the existing op instead of creating a new one.
type: string
required:
- amount_cents
type: object
CreateTopupResponse:
description: Response after successfully purchasing a credit top-up.
properties:
amount_cents:
description: Amount being charged in cents
format: int64
type: integer
billing_op_id:
description: Billing operation ID to poll for status via GET /api/billing/ops/{id}
type: string
status:
description: Current status of the top-up
enum:
- pending
- completed
- failed
type: string
topup_id:
description: Unique identifier for the top-up request (same as billing_op_id, deprecated)
type: string
required:
- topup_id
- status
- amount_cents
- billing_op_id
type: object
CreateWorkflowRequest:
description: Request body for creating a new saved workflow.
properties:
default_view:
description: Default view mode
enum:
- workflow
- app
type: string
description:
description: Description of the workflow
type: string
forked_from_workflow_id:
description: ID of the source workflow if forked
type: string
forked_from_workflow_version_id:
description: ID of the source workflow version if forked
type: string
name:
description: Display name for the workflow
type: string
workflow_json:
additionalProperties: true
description: The ComfyUI workflow JSON
type: object
required:
- workflow_json
type: object
CreateWorkflowVersionRequest:
description: Request body for creating a new version of a saved workflow.
properties:
base_version:
description: The version number this change is based on (for optimistic concurrency)
type: integer
workflow_json:
additionalProperties: true
description: The updated ComfyUI workflow JSON
type: object
required:
- base_version
- workflow_json
type: object
CreateWorkspaceAPIKeyRequest:
description: Request body for creating a new workspace-scoped API key.
properties:
description:
description: User-provided description of the key's purpose. Limit is byte-based (UTF-8 encoding); 5000 bytes equals 5000 ASCII characters or fewer multi-byte characters.
maxLength: 5000
type: string
expires_at:
description: Optional expiration timestamp
format: date-time
type: string
name:
description: User-provided label for the key
type: string
required:
- name
type: object
CreateWorkspaceAPIKeyResponse:
description: Response containing the newly created workspace API key.
properties:
created_at:
description: When the key was created
format: date-time
type: string
description:
description: User-provided description of the key's purpose. Limit is byte-based (UTF-8 encoding); 5000 bytes equals 5000 ASCII characters or fewer multi-byte characters.
maxLength: 5000
type: string
expires_at:
description: When the key expires (if set)
format: date-time
type: string
id:
description: API key ID
format: uuid
type: string
key:
description: The full plaintext API key (only shown once)
type: string
key_prefix:
description: First 8 chars after prefix for display
type: string
name:
description: User-provided label
type: string
required:
- id
- name
- description
- key
- key_prefix
- created_at
type: object
CreateWorkspaceRequest:
description: Request body for creating a new workspace.
properties:
name:
description: Display name for the workspace
example: My Team Workspace
maxLength: 100
minLength: 1
type: string
required:
- name
type: object
DeleteSessionResponse:
description: Response after deleting a session cookie
properties:
success:
description: Whether the session was deleted successfully
type: boolean
required:
- success
type: object
ErrorResponse:
description: Standard error response with a machine-readable code and human-readable message.
properties:
code:
type: string
message:
type: string
required:
- code
- message
type: object
ExchangeTokenRequest:
description: |
Optional request body for the token exchange endpoint. The Firebase JWT
being exchanged is supplied via the `Authorization: Bearer` header; this
body only carries workspace-selection input.
properties:
workspace_id:
description: Workspace ID to get token for. Defaults to personal workspace if omitted.
example: w-a1b2c3d4-5678-90ab-cdef-1234567890ab
type: string
type: object
ExchangeTokenResponse:
description: Response containing the issued Cloud JWT and its expiry.
properties:
expires_at:
description: Token expiration time (RFC 3339)
format: date-time
type: string
permissions:
description: Permission strings for the role
example:
- owner:*
items:
type: string
type: array
role:
description: User's role in the workspace
enum:
- owner
- member
type: string
token:
description: Cloud JWT token
type: string
workspace:
$ref: '#/components/schemas/WorkspaceSummary'
required:
- token
- expires_at
- workspace
- role
- permissions
type: object
ExecutionError:
description: Detailed execution error information from ComfyUI
properties:
current_inputs:
additionalProperties: true
description: Input values at time of failure (empty object if not available)
type: object
current_outputs:
additionalProperties: true
description: Output values at time of failure (empty object if not available)
type: object
exception_message:
description: Human-readable error message
type: string
exception_type:
description: Python exception type (e.g., "RuntimeError")
type: string
node_id:
description: ID of the node that failed
type: string
node_type:
description: Type name of the node (e.g., "KSampler")
type: string
traceback:
description: Array of traceback lines (empty array if not available)
items:
type: string
type: array
required:
- node_id
- node_type
- exception_message
- exception_type
- traceback
- current_inputs
- current_outputs
type: object
ExportDownloadURLResponse:
description: Response containing a signed download URL for an exported asset archive.
properties:
expires_at:
description: When the signed URL expires
format: date-time
type: string
url:
description: Signed URL for downloading the export ZIP file
type: string
required:
- url
type: object
FeedbackRequest:
description: Request to submit user feedback
properties:
content:
description: The feedback content or message
type: string
metadata:
additionalProperties: true
description: Additional metadata about the feedback
type: object
rating:
description: User's rating of ComfyUI Cloud experience (1-5 stars)
maximum: 5
minimum: 1
type: integer
type:
description: Type of feedback being submitted
enum:
- missing_nodes
- general
- missing_models
type: string
required:
- type
type: object
FeedbackResponse:
description: Response after submitting feedback
type: object
ForkWorkflowRequest:
description: Request body for forking an existing workflow into the user's account.
properties:
name:
description: Name for the forked workflow
type: string
source_version:
description: Version number to fork from
type: integer
required:
- source_version
type: object
GetUserDataResponseFull:
description: List of user data file entries (each with path, size, and modification time) returned when full_info=true.
items:
$ref: '#/components/schemas/GetUserDataResponseFullFile'
type: array
GetUserDataResponseFullFile:
description: Individual file entry within a full user data response.
properties:
modified:
description: UNIX timestamp of the last modification in milliseconds.
format: int64
type: integer
path:
description: File name or path relative to the user directory.
type: string
size:
description: File size in bytes.
type: integer
type: object
GlobalSubgraphData:
description: Full data for a global subgraph blueprint
properties:
data:
description: The full subgraph JSON data as a string
type: string
info:
description: Additional information about the subgraph
properties:
node_pack:
description: The node pack/module that provides this subgraph
type: string
required:
- node_pack
type: object
name:
description: Display name of the subgraph blueprint
type: string
source:
description: Source type of the subgraph - "templates" for workflow templates or "custom_node" for custom node subgraphs
type: string
required:
- source
- name
- info
- data
type: object
GlobalSubgraphInfo:
description: Metadata for a global subgraph blueprint (without full data)
properties:
data:
description: The full subgraph JSON data (may be empty in list view)
type: string
info:
description: Additional information about the subgraph
properties:
node_pack:
description: The node pack/module that provides this subgraph
type: string
required:
- node_pack
type: object
name:
description: Display name of the subgraph blueprint
type: string
source:
description: Source type of the subgraph - "templates" for workflow templates or "custom_node" for custom node subgraphs
type: string
required:
- source
- name
- info
type: object
HistoryDetailEntry:
description: History entry with full prompt data
properties:
meta:
additionalProperties: true
description: Metadata about the execution and nodes
type: object
outputs:
additionalProperties: true
description: Output data from execution (generated images, files, etc.)
type: object
prompt:
description: Full prompt execution data
properties:
extra_data:
additionalProperties: true
description: Additional execution data
type: object
outputs_to_execute:
description: Output nodes to execute
items:
type: string
type: array
priority:
description: Execution priority
format: double
type: number
prompt:
additionalProperties: true
description: The workflow nodes
type: object
prompt_id:
description: The prompt ID
type: string
type: object
status:
additionalProperties: true
description: Execution status and timeline information
type: object
type: object
HistoryDetailResponse:
additionalProperties:
$ref: '#/components/schemas/HistoryDetailEntry'
description: |
Detailed execution history response for a specific prompt.
Returns a dictionary with prompt_id as key and full history data as value.
type: object
HistoryEntry:
description: History entry with prompt_id and execution data
properties:
create_time:
description: Job creation timestamp (Unix timestamp in milliseconds)
format: int64
type: integer
meta:
additionalProperties: true
description: Metadata about the execution and nodes
type: object
outputs:
additionalProperties: true
description: Output data from execution (generated images, files, etc.)
type: object
prompt:
description: Filtered prompt execution data (lightweight format)
properties:
extra_data:
additionalProperties: true
description: Additional execution data (workflow removed from extra_pnginfo)
type: object
priority:
description: Execution priority
format: double
type: number
prompt_id:
description: The prompt ID
type: string
type: object
prompt_id:
description: Unique identifier for this prompt execution
type: string
status:
additionalProperties: true
description: Execution status and timeline information
type: object
workflow_id:
description: UUID identifying the workflow graph definition
type: string
required:
- prompt_id
type: object
HistoryManageRequest:
additionalProperties: false
description: Request to manage history operations
properties:
clear:
description: If true, clear all history for the authenticated user
type: boolean
delete:
description: Array of job IDs to delete from history
items:
type: string
type: array
type: object
HistoryResponse:
description: |
Execution history response with history array.
Returns an object with a "history" key containing an array of history entries.
Each entry includes prompt_id as a property along with execution data.
properties:
history:
description: Array of history entries ordered by creation time (newest first)
items:
$ref: '#/components/schemas/HistoryEntry'
type: array
required:
- history
type: object
HubAssetUploadUrlRequest:
description: Request body for requesting a signed upload URL for a Hub asset.
properties:
content_type:
description: |
MIME type of the file (e.g. "image/jpeg", "video/mp4"). Validated against a whitelist; the canonical file extension is derived from this value.
type: string
filename:
description: Original filename for display purposes. Not used in the storage key.
type: string
required:
- filename
- content_type
type: object
HubAssetUploadUrlResponse:
description: Response containing a signed upload URL and the target asset path.
properties:
public_url:
description: The public URL where the file will be accessible after upload.
type: string
token:
description: Signed token to pass in the publish request. Has a server-determined TTL.
type: string
upload_url:
description: Presigned R2 URL for uploading the file via PUT.
type: string
required:
- upload_url
- public_url
- token
type: object
HubLabelInfo:
description: Metadata for a single Hub label.
properties:
description:
description: Optional description of the label.
type: string
display_name:
description: Human-readable display name.
type: string
name:
description: Slug identifier.
type: string
type:
description: Label category.
enum:
- tag
- model
- custom_node
type: string
required:
- name
- display_name
- type
type: object
HubLabelListResponse:
description: List of available Hub labels for categorizing workflows.
properties:
labels:
description: Available labels filtered by type (or all if no type specified).
items:
$ref: '#/components/schemas/HubLabelInfo'
type: array
required:
- labels
type: object
HubProfile:
description: Full public profile for a Hub creator.
properties:
avatar_url:
description: Public URL of the profile avatar image.
type: string
description:
type: string
display_name:
type: string
username:
type: string
website_urls:
description: List of website URLs.
items:
type: string
type: array
required:
- username
type: object
HubProfileSummary:
description: Abbreviated Hub profile used in workflow listings.
properties:
avatar_url:
description: Public URL of the profile avatar image.
type: string
display_name:
type: string
username:
type: string
required:
- username
type: object
HubUsernameCheckResponse:
description: Response indicating whether a Hub username is available.
properties:
available:
description: Whether the username is available for the caller's workspace.
type: boolean
suggestions:
description: Up to 5 available alternative usernames (only present when unavailable).
items:
type: string
type: array
username:
description: The username that was checked.
type: string
validation_error:
description: If the username format is invalid, describes the format requirement.
type: string
required:
- username
- available
type: object
HubWorkflowDetail:
description: Full Hub workflow detail including versions, assets, and statistics.
properties:
assets:
description: Published assets. Each asset's id is the published asset ID (not the original private asset ID).
items:
$ref: '#/components/schemas/AssetInfo'
type: array
custom_nodes:
items:
$ref: '#/components/schemas/LabelRef'
type: array
description:
type: string
metadata:
additionalProperties: true
type: object
models:
items:
$ref: '#/components/schemas/LabelRef'
type: array
name:
type: string
profile:
$ref: '#/components/schemas/HubProfileSummary'
publish_time:
format: date-time
nullable: true
type: string
sample_image_urls:
items:
type: string
type: array
share_id:
type: string
status:
$ref: '#/components/schemas/HubWorkflowStatus'
tags:
items:
$ref: '#/components/schemas/LabelRef'
type: array
thumbnail_comparison_url:
type: string
thumbnail_type:
enum:
- image
- video
- image_comparison
type: string
thumbnail_url:
type: string
tutorial_url:
type: string
workflow_id:
type: string
workflow_json:
additionalProperties: true
type: object
required:
- share_id
- workflow_id
- name
- workflow_json
- assets
- profile
- status
type: object
HubWorkflowListResponse:
description: Paginated list of Hub workflows matching search criteria.
properties:
next_cursor:
description: Cursor for the next page, empty if no more results.
type: string
workflows:
description: Array of HubWorkflowSummary (default) or HubWorkflowDetail (when detail=true).
items:
anyOf:
- $ref: '#/components/schemas/HubWorkflowSummary'
- $ref: '#/components/schemas/HubWorkflowDetail'
type: array
required:
- workflows
type: object
HubWorkflowStatus:
description: Public workflow status. NULL in the database is represented as pending in API responses.
enum:
- pending
- approved
- rejected
- deprecated
type: string
HubWorkflowSummary:
description: Abbreviated Hub workflow metadata used in search and listing results.
properties:
custom_nodes:
items:
$ref: '#/components/schemas/LabelRef'
type: array
description:
type: string
metadata:
additionalProperties: true
type: object
models:
items:
$ref: '#/components/schemas/LabelRef'
type: array
name:
type: string
profile:
$ref: '#/components/schemas/HubProfileSummary'
publish_time:
format: date-time
nullable: true
type: string
sample_image_urls:
items:
type: string
type: array
share_id:
type: string
status:
$ref: '#/components/schemas/HubWorkflowStatus'
tags:
items:
$ref: '#/components/schemas/LabelRef'
type: array
thumbnail_comparison_url:
type: string
thumbnail_type:
enum:
- image
- video
- image_comparison
type: string
thumbnail_url:
type: string
tutorial_url:
type: string
required:
- share_id
- name
- profile
- status
type: object
HubWorkflowTemplateEntry:
description: Entry in the curated workflow template gallery shown on the home page.
properties:
contentTemplate:
description: Content template used for generation (tutorial, showcase, comparison, breakthrough)
type: string
date:
description: Publication date in YYYY-MM-DD format
type: string
description:
type: string
extendedDescription:
description: AI-generated extended description of the workflow
type: string
faqItems:
description: AI-generated FAQ items
items:
properties:
answer:
type: string
question:
type: string
required:
- question
- answer
type: object
type: array
howToUse:
description: AI-generated step-by-step usage instructions
items:
type: string
type: array
includeOnDistributions:
items:
type: string
type: array
io:
properties:
inputs:
items:
additionalProperties: true
type: object
type: array
outputs:
items:
additionalProperties: true
type: object
type: array
type: object
isEssential:
description: Whether the template belongs to a module marked as essential.
type: boolean
logos:
items:
additionalProperties: true
type: object
type: array
mediaSubtype:
type: string
mediaType:
type: string
metaDescription:
description: AI-generated SEO meta description (under 160 chars)
type: string
models:
items:
type: string
type: array
name:
description: Slug identifier for the template
type: string
openSource:
type: boolean
profile:
$ref: '#/components/schemas/HubProfileSummary'
requiresCustomNodes:
items:
type: string
type: array
searchRank:
description: Search ranking score reported upstream.
format: int64
type: integer
shareId:
description: Share ID for linking to the hub workflow detail
type: string
size:
description: Workflow asset size in bytes.
format: int64
type: integer
status:
$ref: '#/components/schemas/HubWorkflowStatus'
suggestedUseCases:
description: AI-generated suggested use cases
items:
type: string
type: array
tags:
items:
type: string
type: array
thumbnailComparisonUrl:
description: Public URL of the comparison thumbnail
type: string
thumbnailUrl:
description: Public URL of the primary thumbnail
type: string
thumbnailVariant:
type: string
title:
type: string
tutorialUrl:
type: string
usage:
description: Usage count reported upstream.
format: int64
type: integer
vram:
description: Approximate VRAM requirement in bytes.
format: int64
type: integer
required:
- name
- title
- status
type: object
ImportPublishedAssetsRequest:
description: Request body for importing assets from a published workflow.
properties:
published_asset_ids:
description: IDs of published assets (inputs and models) to import.
items:
type: string
type: array
share_id:
description: |
Optional. Share ID of the published workflow these assets belong to.
When provided (non-null, non-empty): all published_asset_ids must
belong to this share's workflow version; returns
400/CodeInvalidAssets if the share is not found or any asset does
not belong to it.
When omitted, null, or empty string: no share-scoped validation is
performed and the assets are validated only against global rules
(legacy behaviour, preserved for clients that have not yet adopted
share_id).
nullable: true
type: string
required:
- published_asset_ids
type: object
ImportPublishedAssetsResponse:
description: Response after importing published workflow assets.
properties:
assets:
items:
$ref: '#/components/schemas/AssetInfo'
type: array
required:
- assets
type: object
JobCancelResponse:
description: Response for POST /api/jobs/{job_id}/cancel. Returned on both fresh cancels and idempotent no-ops.
properties:
cancelled:
description: |
True when a cancel event was successfully dispatched by this call.
False when the job was already in a terminal or cancelling state,
in which case the call is a no-op (still 200 — idempotent).
type: boolean
required:
- cancelled
type: object
JobDetailResponse:
description: Full job details including workflow and outputs
properties:
create_time:
description: Job creation timestamp (Unix timestamp in milliseconds)
format: int64
type: integer
execution_error:
allOf:
- $ref: '#/components/schemas/ExecutionError'
description: Detailed execution error from ComfyUI (only for failed jobs with structured error data)
execution_meta:
additionalProperties: true
description: Node-level execution metadata (only for terminal states)
type: object
execution_status:
additionalProperties: true
description: ComfyUI execution status and timeline (only for terminal states)
type: object
id:
description: Unique job identifier
format: uuid
type: string
outputs:
additionalProperties: true
description: Full outputs object from ComfyUI (only for terminal states)
type: object
outputs_count:
description: Total number of output files (omitted for non-terminal states)
type: integer
preview_output:
additionalProperties: true
description: Primary preview output (only for terminal states)
type: object
status:
description: User-friendly job status
enum:
- pending
- in_progress
- completed
- failed
- cancelled
type: string
update_time:
description: Last update timestamp (Unix timestamp in milliseconds)
format: int64
type: integer
workflow:
additionalProperties: true
description: |
Full ComfyUI workflow (10-100KB, omitted if not available).
Sensitive credentials are redacted before the response is returned:
`extra_data.api_key_comfy_org`, when present, is replaced with the
literal string `"[REDACTED]"`. The field is preserved (not removed)
so existence checks still pass, but the value is not usable.
type: object
workflow_id:
description: UUID identifying the workflow graph definition
type: string
required:
- id
- status
- create_time
- update_time
type: object
JobEntry:
description: Lightweight job data for list views (workflow and full outputs excluded)
properties:
create_time:
description: Job creation timestamp (Unix timestamp in milliseconds)
format: int64
type: integer
execution_end_time:
description: Workflow execution completion timestamp (Unix milliseconds, only present for terminal states)
format: int64
type: integer
execution_error:
allOf:
- $ref: '#/components/schemas/ExecutionError'
description: Detailed execution error from ComfyUI (only for failed jobs with structured error data)
execution_start_time:
description: Workflow execution start timestamp (Unix milliseconds, only present for terminal states)
format: int64
type: integer
id:
description: Unique job identifier
format: uuid
type: string
outputs_count:
description: Total number of output files (omitted for non-terminal states)
type: integer
preview_output:
additionalProperties: true
description: Primary preview output (only present for terminal states)
type: object
status:
description: User-friendly job status
enum:
- pending
- in_progress
- completed
- failed
- cancelled
type: string
workflow_id:
description: UUID identifying the workflow graph definition
type: string
required:
- id
- status
- create_time
type: object
JobStatusResponse:
description: Job status information
properties:
assigned_inference:
description: The inference instance assigned to this job (if any)
nullable: true
type: string
created_at:
description: When the job was created
format: date-time
type: string
error_message:
description: Error message if the job failed
nullable: true
type: string
id:
description: The job ID
format: uuid
type: string
last_state_update:
description: When the job status was last changed
format: date-time
type: string
status:
description: Current job status
enum:
- waiting_to_dispatch
- pending
- in_progress
- completed
- error
- cancelled
type: string
updated_at:
description: When the job was last updated
format: date-time
type: string
required:
- id
- status
- created_at
- updated_at
type: object
JobsListResponse:
description: Paginated list of jobs for the authenticated user.
properties:
jobs:
description: Array of jobs ordered by specified sort field
items:
$ref: '#/components/schemas/JobEntry'
type: array
pagination:
$ref: '#/components/schemas/PaginationInfo'
required:
- jobs
- pagination
type: object
JwkKey:
description: A single JSON Web Key entry within a JWKS response.
properties:
alg:
example: ES256
type: string
crv:
example: P-256
type: string
kid:
example: cloud-jwt-key-1
type: string
kty:
example: EC
type: string
use:
example: sig
type: string
x:
description: Base64url-encoded X coordinate
type: string
"y":
description: Base64url-encoded Y coordinate
type: string
required:
- kty
- crv
- kid
- use
- alg
- x
- "y"
type: object
JwksResponse:
description: JSON Web Key Set containing the public keys used to verify Cloud JWTs.
properties:
keys:
items:
$ref: '#/components/schemas/JwkKey'
type: array
required:
- keys
type: object
LabelRef:
description: Reference to a Hub label by ID.
properties:
display_name:
description: Human-readable display name (e.g. "Video Generation", "Flux").
type: string
name:
description: Slug identifier (e.g. "video-generation", "flux").
type: string
required:
- name
- display_name
type: object
ListAssetsResponse:
description: Paginated list of assets belonging to the authenticated user.
properties:
assets:
description: List of assets matching the query
items:
$ref: '#/components/schemas/Asset'
type: array
has_more:
description: Whether more assets are available beyond this page
type: boolean
next_cursor:
description: |
Opaque cursor to pass as the `after` query parameter to fetch the
next page. Omitted from the response when there are no more results.
type: string
total:
description: Total number of assets matching the filters
type: integer
required:
- assets
- total
- has_more
type: object
ListInvitesResponse:
description: List of pending invitations for the current workspace.
properties:
invites:
items:
$ref: '#/components/schemas/PendingInvite'
type: array
required:
- invites
type: object
ListMembersResponse:
description: List of members in the current workspace.
properties:
members:
items:
$ref: '#/components/schemas/Member'
type: array
pagination:
$ref: '#/components/schemas/PaginationInfo'
required:
- members
- pagination
type: object
ListTagsResponse:
description: Paginated list of available asset tags.
properties:
has_more:
description: Whether more tags are available
type: boolean
tags:
description: List of tags
items:
$ref: '#/components/schemas/TagInfo'
type: array
total:
description: Total number of tags
type: integer
required:
- tags
- total
- has_more
type: object
ListWorkspaceAPIKeysResponse:
description: List of API keys associated with the current workspace.
properties:
api_keys:
items:
$ref: '#/components/schemas/WorkspaceAPIKeyInfo'
type: array
required:
- api_keys
type: object
ListWorkspacesResponse:
description: Paginated list of workspaces the authenticated user belongs to.
properties:
workspaces:
items:
$ref: '#/components/schemas/WorkspaceWithRole'
type: array
required:
- workspaces
type: object
Member:
description: Workspace member with profile and role information.
properties:
email:
description: User's email address
format: email
type: string
id:
description: User ID
type: string
joined_at:
description: When the user joined the workspace
format: date-time
type: string
name:
description: User's display name
type: string
role:
description: User's role in the workspace
enum:
- owner
- member
type: string
required:
- id
- name
- email
- role
- joined_at
type: object
ModelFile:
description: Represents a model file with metadata
properties:
name:
description: The filename of the model
example: model.safetensors
type: string
pathIndex:
description: Index of the path where this model is located
example: 0
type: integer
required:
- name
- pathIndex
type: object
ModelFolder:
description: Represents a folder containing models
properties:
folders:
description: List of paths where models of this type are stored
example:
- checkpoints
items:
type: string
type: array
name:
description: The name of the model folder
example: checkpoints
type: string
required:
- name
- folders
type: object
NodeInfo:
description: Metadata describing a single ComfyUI node type and its inputs/outputs.
properties:
api_node:
description: Whether this is an API node
type: boolean
category:
description: Category of the node
type: string
deprecated:
description: Whether the node is deprecated
type: boolean
description:
description: Description of the node
type: string
display_name:
description: Display name of the node
type: string
experimental:
description: Whether the node is experimental
type: boolean
input:
additionalProperties: true
description: Input specifications for the node
type: object
input_order:
additionalProperties:
items:
type: string
type: array
description: Order of inputs for display
type: object
name:
description: Internal name of the node
type: string
output:
description: Output types of the node
items:
type: string
type: array
output_is_list:
description: Whether each output is a list
items:
type: boolean
type: array
output_name:
description: Names of the outputs
items:
type: string
type: array
output_node:
description: Whether this is an output node
type: boolean
output_tooltips:
description: Tooltips for outputs
items:
type: string
type: array
python_module:
description: Python module implementing the node
type: string
type: object
OAuthAuthorizationServerMetadata:
description: OAuth 2.1 authorization-server metadata (RFC 8414).
properties:
authorization_endpoint:
format: uri
type: string
code_challenge_methods_supported:
items:
type: string
type: array
grant_types_supported:
items:
type: string
type: array
issuer:
format: uri
type: string
jwks_uri:
format: uri
type: string
registration_endpoint:
description: |
RFC 7591 §3.1 Dynamic Client Registration endpoint. Advertised so MCP-spec-compliant clients can auto-discover and self-register without operator involvement. Present only when DCR is enabled.
format: uri
type: string
response_types_supported:
items:
type: string
type: array
scopes_supported:
items:
type: string
type: array
token_endpoint:
format: uri
type: string
token_endpoint_auth_methods_supported:
items:
type: string
type: array
required:
- issuer
- authorization_endpoint
- token_endpoint
- jwks_uri
- response_types_supported
- grant_types_supported
- code_challenge_methods_supported
- token_endpoint_auth_methods_supported
type: object
OAuthAuthorizeRedirectResponse:
description: Redirect target produced after a JSON consent submission. The frontend must navigate the browser to this URL so custom-scheme client callbacks work without relying on fetch-visible 302 headers.
properties:
redirect_url:
description: OAuth client redirect URI with either code+state for allow, or error+state for deny.
format: uri
type: string
required:
- redirect_url
type: object
OAuthConsentChallenge:
description: |
Server-side state describing the OAuth consent decision the user is being asked to make. Returned by GET /oauth/authorize when a valid Cloud session exists; the frontend renders the consent UI from this payload and POSTs the decision back. Browser never sees the original OAuth params on resume.
properties:
client_display_name:
description: Human-readable name of the OAuth client requesting authorization, from oauth_clients.display_name.
type: string
csrf_token:
description: Per-row CSRF token bound to this authorization request (not to the session). Must be echoed back on POST.
type: string
oauth_request_id:
description: Opaque server-side identifier for the authorization-request row. Carried back unchanged in the consent submission.
format: uuid
type: string
resource_display_name:
description: Human-readable name of the protected resource, from oauth_resources.display_name.
type: string
scopes:
description: Scopes the client is requesting for this resource. The frontend should present these for the user to approve.
items:
type: string
type: array
workspaces:
description: Workspaces the user can select from. Membership is re-checked on POST.
items:
$ref: '#/components/schemas/OAuthConsentChallengeWorkspace'
type: array
required:
- oauth_request_id
- csrf_token
- client_display_name
- resource_display_name
- scopes
- workspaces
type: object
OAuthConsentChallengeWorkspace:
description: |
One workspace option presented in the OAuth consent challenge. Promoted to a named schema so the generated Go type is referenceable in handlers and tests rather than re-declared as an anonymous struct at every callsite.
properties:
id:
type: string
name:
type: string
role:
enum:
- owner
- member
type: string
type:
enum:
- personal
- team
type: string
required:
- id
- name
- type
- role
type: object
OAuthProtectedResourceMetadata:
description: OAuth 2.1 protected-resource metadata (RFC 9728).
properties:
authorization_servers:
items:
format: uri
type: string
type: array
bearer_methods_supported:
items:
type: string
type: array
resource:
format: uri
type: string
scopes_supported:
items:
type: string
type: array
required:
- resource
- authorization_servers
- scopes_supported
type: object
OAuthRegisterBadRequestResponse:
description: |
Union of the two 400 shapes /oauth/register can emit. `OAuthRegisterError` is the handler-shaped RFC 7591 §3.2.2 error; `BindingErrorResponse` is the strict-server binding-layer error fired when the request body fails OpenAPI-schema validation before the handler runs.
oneOf:
- $ref: '#/components/schemas/OAuthRegisterError'
- $ref: '#/components/schemas/BindingErrorResponse'
OAuthRegisterError:
description: RFC 7591 §3.2.2 error response.
properties:
error:
enum:
- invalid_redirect_uri
- invalid_client_metadata
type: string
error_description:
nullable: true
type: string
required:
- error
type: object
OAuthRegisterRequest:
additionalProperties: false
description: |
RFC 7591 §2 client metadata document. Only the fields the server honors are listed; presence of `scope` or `resource_grants` in the request is rejected (`invalid_client_metadata`) because those are server-owned for dynamic clients. `additionalProperties: false` mirrors the runtime middleware that rejects any unknown metadata key.
properties:
application_type:
description: |
RFC 7591 §2 application_type. **OPTIONAL** — omit the field to default to `native` (the loopback-friendly policy), rather than the RFC's nominal `web` default; the MCP SDK's DCR client omits it. `native` for desktop / CLI / MCP-spec-strict clients (loopback redirects); `web` for hosted clients (HTTPS only, host must be allowlisted). The realistic MCP-client population is overwhelmingly native/loopback, so defaulting to `web` would silently bounce those clients off the wrong redirect policy. A *present* value must be one of the enum members; any other value rejects with `invalid_client_metadata`. (The server has no runtime enum validation and defensively coerces a null/empty value to `native`, but spec-validating clients should omit the field rather than send `""` — the enum does not permit it.)
enum:
- native
- web
type: string
client_name:
description: Human-readable name shown in the consent UI. Reserved-name list rejects impersonation of major MCP clients.
maxLength: 100
type: string
client_uri:
description: '**REJECTED IF PRESENT.** Unsupported RFC 7591 metadata for this public MCP-client phase.'
nullable: true
type: string
contacts:
description: '**REJECTED IF PRESENT.** Unsupported RFC 7591 metadata for this public MCP-client phase.'
items:
type: string
nullable: true
type: array
grant_types:
description: Optional. Defaults to `["authorization_code","refresh_token"]`.
items:
enum:
- authorization_code
- refresh_token
type: string
type: array
jwks:
additionalProperties: true
description: '**REJECTED IF PRESENT.** Unsupported RFC 7591 metadata for this public MCP-client phase.'
nullable: true
type: object
jwks_uri:
description: '**REJECTED IF PRESENT.** Unsupported RFC 7591 metadata for this public MCP-client phase.'
nullable: true
type: string
logo_uri:
description: '**REJECTED IF PRESENT.** Unsupported RFC 7591 metadata for this public MCP-client phase.'
nullable: true
type: string
policy_uri:
description: '**REJECTED IF PRESENT.** Unsupported RFC 7591 metadata for this public MCP-client phase.'
nullable: true
type: string
redirect_uris:
description: 15 redirect URIs. Validated against `application_type` policy.
items:
type: string
maxItems: 5
minItems: 1
type: array
resource_grants:
additionalProperties:
items:
type: string
type: array
description: |
**REJECTED IF PRESENT.** Same reason as `scope`. The set of resources and scopes a dynamic client may request is server-policy, not request-driven.
nullable: true
type: object
response_types:
description: Optional. Defaults to `["code"]`.
items:
enum:
- code
type: string
type: array
scope:
description: |
**REJECTED IF PRESENT.** Dynamic clients do not pick scopes — the server assigns scopes from the active MCP resource's published list. Sending `scope` in the registration body is treated as a privilege-escalation attempt and returns `invalid_client_metadata`. The field is documented here so clients see a well-defined error rather than silent drop.
nullable: true
type: string
software_id:
description: '**REJECTED IF PRESENT.** Unsupported RFC 7591 metadata for this public MCP-client phase.'
nullable: true
type: string
software_version:
description: '**REJECTED IF PRESENT.** Unsupported RFC 7591 metadata for this public MCP-client phase.'
nullable: true
type: string
token_endpoint_auth_method:
description: Public clients only this phase — must be `none` if present. The server forces `none` regardless.
enum:
- none
type: string
tos_uri:
description: '**REJECTED IF PRESENT.** Unsupported RFC 7591 metadata for this public MCP-client phase.'
nullable: true
type: string
required:
- redirect_uris
type: object
OAuthRegisterResponse:
description: RFC 7591 §3.2.1 successful registration response.
properties:
application_type:
enum:
- native
- web
type: string
client_id:
description: Server-generated client_id. Always carries the `comfy-dyn-` prefix.
type: string
client_id_issued_at:
description: Unix timestamp (seconds) when the client was registered.
format: int64
type: integer
client_name:
type: string
grant_types:
items:
type: string
type: array
redirect_uris:
items:
type: string
type: array
response_types:
items:
type: string
type: array
token_endpoint_auth_method:
enum:
- none
type: string
required:
- client_id
- client_id_issued_at
- redirect_uris
- grant_types
- response_types
- token_endpoint_auth_method
- application_type
type: object
OAuthTokenError:
description: RFC 6749 §5.2 error response.
properties:
error:
description: 'RFC 6749 §5.2 error code: invalid_request, invalid_client, invalid_grant, unauthorized_client, unsupported_grant_type, invalid_scope.'
type: string
error_description:
description: Human-readable, no leak of internal storage state.
type: string
required:
- error
type: object
OAuthTokenResponse:
description: RFC 6749 §5.1 successful token response.
properties:
access_token:
description: Resource-bound Cloud JWT (audience matches the protected resource).
type: string
expires_in:
description: Access token lifetime in seconds.
type: integer
refresh_token:
description: Opaque refresh token. Rotates on every successful refresh; presenting an already-rotated token revokes the entire family.
type: string
scope:
description: Space-delimited scopes granted with this token.
type: string
token_type:
enum:
- Bearer
type: string
required:
- access_token
- token_type
- expires_in
- refresh_token
- scope
type: object
PaginationInfo:
description: Offset/limit-based pagination metadata included in list responses.
properties:
has_more:
description: Whether more items are available beyond this page
type: boolean
limit:
description: Items per page
minimum: 1
type: integer
offset:
description: Current offset (0-based)
minimum: 0
type: integer
total:
description: Total number of items matching filters
minimum: 0
type: integer
required:
- offset
- limit
- total
- has_more
type: object
PaymentPortalRequest:
description: Request body for generating a payment portal session URL.
properties:
return_url:
description: URL to redirect after the user exits the portal
type: string
type: object
PaymentPortalResponse:
description: Response containing a redirect URL to the payment portal.
properties:
url:
description: Stripe Billing Portal URL
type: string
required:
- url
type: object
PendingInvite:
description: An outstanding workspace invitation that has not yet been accepted.
properties:
email:
description: Email address of the invited user
format: email
type: string
expires_at:
description: When the invite expires
format: date-time
type: string
id:
description: Invite ID
type: string
invited_at:
description: When the invite was created
format: date-time
type: string
token:
description: Invite token for constructing invite links. Empty for expired invites.
type: string
required:
- id
- email
- invited_at
- expires_at
type: object
Plan:
description: Billing plan details including pricing, limits, and features.
properties:
availability:
$ref: '#/components/schemas/PlanAvailability'
credits_cents:
description: Per-member credits in cents (base + one seat)
example: 10000
format: int64
type: integer
duration:
$ref: '#/components/schemas/SubscriptionDuration'
max_seats:
description: Maximum number of seats allowed for this plan
example: 20
format: int64
type: integer
price_cents:
description: Per-member price in cents (base + one seat)
example: 10000
format: int64
type: integer
seat_summary:
$ref: '#/components/schemas/PlanSeatSummary'
slug:
description: Plan identifier (e.g., "pro-monthly", "team-standard-annual")
example: pro-monthly
type: string
tier:
$ref: '#/components/schemas/SubscriptionTier'
required:
- slug
- tier
- duration
- price_cents
- credits_cents
- max_seats
- availability
- seat_summary
type: object
PlanAvailability:
description: Availability and eligibility information for a billing plan.
properties:
available:
description: Whether the workspace can subscribe to this plan
type: boolean
reason:
$ref: '#/components/schemas/PlanAvailabilityReason'
required:
- available
type: object
PlanAvailabilityReason:
description: Reason why a plan is unavailable
enum:
- same_plan
- incompatible_transition
- requires_team
- requires_personal
- exceeds_max_seats
type: string
PlanSeatSummary:
description: Summary of seat costs based on current workspace members
properties:
seat_count:
description: Total number of seats (owner + members) that would be charged
example: 5
type: integer
total_cost_cents:
description: Total cost for all seats in cents
example: 50000
format: int64
type: integer
total_credits_cents:
description: Total credits granted for all seats in cents
example: 50000
format: int64
type: integer
required:
- seat_count
- total_cost_cents
- total_credits_cents
type: object
PreviewPlanInfo:
description: Plan information for preview display
properties:
credits_cents:
description: Per-seat credits in cents
example: 10000
format: int64
type: integer
duration:
$ref: '#/components/schemas/SubscriptionDuration'
period_end:
description: Current billing period end (only for current_plan)
format: date-time
type: string
period_start:
description: Current billing period start (only for current_plan)
format: date-time
type: string
price_cents:
description: Per-seat price in cents
example: 10000
format: int64
type: integer
seat_summary:
$ref: '#/components/schemas/PlanSeatSummary'
slug:
description: Plan slug
example: team-pro-monthly
type: string
tier:
$ref: '#/components/schemas/SubscriptionTier'
required:
- slug
- tier
- duration
- price_cents
- credits_cents
- seat_summary
type: object
PreviewSubscribeRequest:
description: Request body for previewing the cost of a plan subscription change.
properties:
plan_slug:
description: Target plan slug to preview subscribing to
example: team-pro-monthly
type: string
required:
- plan_slug
type: object
PreviewSubscribeResponse:
description: Itemized cost preview for a pending subscription change.
properties:
allowed:
description: Whether this subscription change is allowed
type: boolean
cost_next_period_cents:
description: Amount that will be charged at next billing period in cents
example: 10000
format: int64
type: integer
cost_today_cents:
description: Amount to charge today in cents (0 for downgrades)
example: 5000
format: int64
type: integer
credits_next_period_cents:
description: Credits that will be granted at next billing period in cents
example: 10000
format: int64
type: integer
credits_today_cents:
description: Credits granted today in cents (prorated for mid-period upgrades)
example: 5000
format: int64
type: integer
current_plan:
$ref: '#/components/schemas/PreviewPlanInfo'
effective_at:
description: When the change takes effect
format: date-time
type: string
is_immediate:
description: Whether the change takes effect immediately (true) or at period end (false)
type: boolean
new_plan:
$ref: '#/components/schemas/PreviewPlanInfo'
reason:
description: Reason why the change is not allowed (only present if allowed=false)
type: string
transition_type:
description: Type of subscription transition
enum:
- new_subscription
- upgrade
- downgrade
- duration_change
type: string
required:
- allowed
- transition_type
- effective_at
- is_immediate
- cost_today_cents
- cost_next_period_cents
- credits_today_cents
- credits_next_period_cents
- new_plan
type: object
PromptErrorResponse:
additionalProperties: true
description: Error response for ComfyUI prompt execution.
type: object
PromptInfo:
description: Metadata about the currently running and queued prompts.
properties:
exec_info:
properties:
queue_remaining:
description: Number of items remaining in the queue
type: integer
type: object
type: object
PromptRequest:
description: Request body for submitting a ComfyUI workflow prompt for execution.
properties:
extra_data:
additionalProperties: true
description: Extra data to be associated with the prompt
type: object
front:
description: If true, adds the prompt to the front of the queue
type: boolean
number:
description: Priority number for the queue (lower numbers have higher priority)
type: number
partial_execution_targets:
description: List of node names to execute
items:
type: string
type: array
prompt:
additionalProperties: true
description: The workflow graph to execute
type: object
workflow_id:
description: UUID identifying the cloud workflow entity to associate with this job
type: string
workflow_version_id:
description: UUID identifying the workflow version to associate with this job
type: string
required:
- prompt
type: object
PromptResponse:
description: Response returned after successfully queuing a workflow prompt.
properties:
node_errors:
additionalProperties: true
description: Any errors in the nodes of the prompt
type: object
number:
description: Priority number in the queue
type: number
prompt_id:
description: Unique identifier for the prompt execution
format: uuid
type: string
type: object
PublishHubWorkflowRequest:
description: Request body for publishing or updating a workflow on the Hub.
properties:
asset_ids:
description: IDs of assets (inputs and models) to snapshot.
items:
type: string
type: array
custom_nodes:
description: Custom node slugs. Must exist in hub_labels.
items:
type: string
type: array
description:
description: Workflow description for the hub listing.
type: string
metadata:
additionalProperties: true
description: Arbitrary metadata (size, vram, open_source, etc.). Reserved keys (extended_description, meta_description, how_to_use, suggested_use_cases, faq_items, content_template) are backend-managed and will be stripped if supplied.
type: object
models:
description: Model slugs. Must exist in hub_labels.
items:
type: string
type: array
name:
description: Display name for the published workflow on the hub.
type: string
sample_image_tokens_or_urls:
description: |
Array of tokens or existing public URLs from the previous published version. Full replacement (PUT semantics). Omit or pass [] to have no sample images.
items:
type: string
type: array
tags:
description: Searchable tag slugs. Must exist in hub_labels.
items:
type: string
type: array
thumbnail_comparison_token_or_url:
description: |
Token or existing public URL from the previous published version. Omit to have no comparison image.
type: string
thumbnail_token_or_url:
description: |
Token (from /api/hub/assets/upload-url) for a new upload, or an existing public URL from the previous published version. Omit to have no thumbnail.
type: string
thumbnail_type:
enum:
- image
- video
- image_comparison
type: string
tutorial_url:
description: URL to a tutorial for this workflow.
type: string
username:
description: Username of the hub profile to publish under. The authenticated user must belong to the workspace that owns this profile.
type: string
workflow_filename:
description: Userdata path of the workflow file (e.g. "workflows/my-flow.json").
type: string
required:
- username
- name
- workflow_filename
- asset_ids
type: object
PublishWorkflowAssetsRequest:
description: Request body for publishing workflow assets to the Hub.
properties:
asset_ids:
description: IDs of assets (inputs and models) to snapshot.
items:
type: string
type: array
required:
- asset_ids
type: object
PublishedWorkflowDetail:
description: Full detail of a publicly published workflow on the Hub.
properties:
assets:
description: Published assets with their library status for the caller.
items:
$ref: '#/components/schemas/AssetInfo'
type: array
listed:
type: boolean
name:
description: Human-readable workflow name.
type: string
publish_time:
format: date-time
nullable: true
type: string
share_id:
type: string
workflow_id:
type: string
workflow_json:
additionalProperties: true
description: The workflow JSON content at publish time.
type: object
required:
- share_id
- workflow_id
- name
- listed
- workflow_json
- assets
type: object
QueueInfo:
description: Queue information with pending and running jobs
properties:
queue_pending:
description: Array of pending job items (ordered by creation time, oldest first)
items:
description: |
Queue item tuple format: [job_number, prompt_id, workflow_json, output_node_ids, metadata]
- [0] job_number (integer): Position in queue (1-based)
- [1] prompt_id (string): Job UUID
- [2] workflow_json (object): Full ComfyUI workflow
- [3] output_node_ids (array): Node IDs to return results from
- [4] metadata (object): Contains {create_time: <milliseconds>}
items: {}
maxItems: 5
minItems: 5
type: array
type: array
queue_running:
description: Array of currently running job items
items:
description: |
Queue item tuple format: [job_number, prompt_id, workflow_json, output_node_ids, metadata]
- [0] job_number (integer): Position in queue (1-based)
- [1] prompt_id (string): Job UUID
- [2] workflow_json (object): Full ComfyUI workflow
- [3] output_node_ids (array): Node IDs to return results from
- [4] metadata (object): Contains {create_time: <milliseconds>}
items: {}
maxItems: 5
minItems: 5
type: array
type: array
type: object
QueueManageRequest:
additionalProperties: false
description: Request to manage queue operations
properties:
clear:
description: If true, clear all pending jobs from the queue
type: boolean
delete:
description: Array of PENDING job IDs to cancel
items:
type: string
type: array
type: object
QueueManageResponse:
description: Response after a queue management action (delete or clear).
properties:
cleared:
description: Whether the queue was cleared
type: boolean
deleted:
description: Array of job IDs that were successfully cancelled
items:
type: string
type: array
type: object
ResubscribeRequest:
description: Request body for reactivating a previously cancelled subscription.
properties:
idempotency_key:
description: |
Client-provided key to prevent duplicate operations.
If a billing op with this key already exists, returns the existing op instead of creating a new one.
type: string
type: object
ResubscribeResponse:
description: Response after successfully resubscribing to a billing plan.
properties:
billing_op_id:
description: Billing operation ID to poll for status via GET /api/billing/ops/{id}
type: string
message:
description: Human-readable confirmation message
type: string
status:
description: The subscription status after resubscribing
enum:
- active
type: string
required:
- status
- billing_op_id
type: object
SecretListResponse:
description: List of user secrets with metadata only.
properties:
data:
items:
$ref: '#/components/schemas/SecretResponse'
type: array
required:
- data
type: object
SecretResponse:
description: User secret metadata (the secret value itself is never returned after creation).
properties:
created_at:
description: When the secret was created
format: date-time
type: string
id:
description: Unique identifier for the secret
format: uuid
type: string
last_used_at:
description: When the secret was last used for decryption
format: date-time
type: string
name:
description: User-provided label for the secret
type: string
provider:
description: Provider identifier (e.g., huggingface, civitai)
type: string
updated_at:
description: When the secret was last updated
format: date-time
type: string
required:
- id
- name
- created_at
- updated_at
type: object
SubscribeRequest:
description: Request body for subscribing a workspace to a billing plan.
properties:
cancel_url:
description: |
URL to redirect if user cancels the payment method flow.
If not provided, return_url is used for both success and cancel.
example: https://cloud.comfy.org/billing
type: string
idempotency_key:
description: |
Client-provided key to prevent duplicate operations.
If a billing op with this key already exists, returns the existing op instead of creating a new one.
example: sub-abc123-1234567890
type: string
plan_slug:
description: Target plan slug to subscribe to
example: team-pro-monthly
type: string
return_url:
description: |
URL to redirect after payment method is added successfully.
Required if workspace has no payment method on file.
example: https://cloud.comfy.org/billing/success
type: string
required:
- plan_slug
type: object
SubscribeResponse:
description: Response after successfully subscribing to a billing plan.
properties:
billing_op_id:
description: Billing operation ID to poll for status via GET /api/billing/ops/{id}
type: string
effective_at:
description: When the subscription became/becomes active (present when status=subscribed or pending_payment)
format: date-time
type: string
payment_method_url:
description: URL to redirect user to add payment method (present when status=needs_payment_method)
type: string
status:
description: |
Status of the subscription operation:
- subscribed: Subscription is active immediately
- needs_payment_method: User must add payment method via payment_method_url
- pending_payment: Upgrade initiated, waiting for payment to complete
enum:
- subscribed
- needs_payment_method
- pending_payment
type: string
required:
- status
- billing_op_id
type: object
SubscriptionDuration:
description: Billing period (uppercase to match comfy-api)
enum:
- MONTHLY
- ANNUAL
type: string
SubscriptionTier:
description: Subscription tier (uppercase to match comfy-api)
enum:
- FREE
- STANDARD
- CREATOR
- PRO
- FOUNDERS_EDITION
type: string
SystemStatsResponse:
description: System statistics response
properties:
devices:
items:
properties:
name:
description: Device name
type: string
type:
description: Device type
type: string
vram_free:
description: Free VRAM in bytes
type: number
vram_total:
description: Total VRAM in bytes
type: number
required:
- name
- type
type: object
type: array
system:
properties:
argv:
description: Command line arguments
items:
type: string
type: array
cloud_version:
description: Cloud ingest service version (commit hash)
type: string
comfyui_frontend_version:
description: ComfyUI frontend version (commit hash or tag)
type: string
comfyui_version:
description: ComfyUI version
type: string
embedded_python:
description: Whether using embedded Python
type: boolean
os:
description: Operating system
type: string
python_version:
description: Python version
type: string
pytorch_version:
description: PyTorch version
type: string
ram_free:
description: Free RAM in bytes
type: number
ram_total:
description: Total RAM in bytes
type: number
workflow_templates_version:
description: Workflow templates version
type: string
required:
- os
- python_version
- embedded_python
- comfyui_version
- pytorch_version
- argv
- ram_total
- ram_free
type: object
required:
- system
- devices
type: object
TagInfo:
description: Metadata for a single tag that can be applied to assets.
properties:
count:
description: Number of assets using this tag
type: integer
name:
description: Tag name
type: string
required:
- name
- count
type: object
TagsModificationResponse:
description: Response after adding, updating, or removing tags on an asset.
properties:
added:
description: Tags that were successfully added (for add operation)
items:
type: string
type: array
already_present:
description: Tags that were already present (for add operation)
items:
type: string
type: array
not_present:
description: Tags that were not present (for remove operation)
items:
type: string
type: array
removed:
description: Tags that were successfully removed (for remove operation)
items:
type: string
type: array
total_tags:
description: All tags on the asset after the operation
items:
type: string
type: array
required:
- total_tags
type: object
TaskEntry:
description: Task data for list views
properties:
completed_at:
description: When task completed or failed (null if not finished)
format: date-time
type: string
create_time:
description: Task creation timestamp
format: date-time
type: string
id:
description: Unique task identifier
format: uuid
type: string
started_at:
description: When task execution started (null if not started)
format: date-time
type: string
status:
description: Current task status
enum:
- created
- running
- completed
- failed
type: string
task_name:
description: Task type name (e.g., model_upload)
type: string
required:
- id
- task_name
- status
- create_time
type: object
TaskResponse:
description: Full task details including payload and result
properties:
completed_at:
description: When task completed or failed (null if not finished)
format: date-time
type: string
create_time:
description: Task creation timestamp
format: date-time
type: string
error_message:
description: Error message on failure (null if not failed)
type: string
id:
description: Unique task identifier
format: uuid
type: string
idempotency_key:
description: Caller-provided key for idempotent task creation
type: string
payload:
additionalProperties: true
description: Task input data
type: object
result:
additionalProperties: true
description: Task output data (null if not completed)
type: object
started_at:
description: When task execution started (null if not started)
format: date-time
type: string
status:
description: Current task status
enum:
- created
- running
- completed
- failed
type: string
task_name:
description: Task type name (e.g., model_upload)
type: string
update_time:
description: Task last update timestamp
format: date-time
type: string
required:
- id
- idempotency_key
- task_name
- payload
- status
- create_time
- update_time
type: object
TasksListResponse:
description: Paginated list of background tasks for the authenticated user.
properties:
pagination:
$ref: '#/components/schemas/PaginationInfo'
tasks:
description: Array of tasks ordered by create_time
items:
$ref: '#/components/schemas/TaskEntry'
type: array
required:
- tasks
- pagination
type: object
UpdateHubProfileRequest:
description: Request body for updating an existing Hub profile.
properties:
avatar_token:
description: |
Token (from /api/hub/assets/upload-url) for a new avatar image. Omit or send null to leave unchanged; send empty string "" to remove.
nullable: true
type: string
description:
type: string
display_name:
type: string
website_urls:
description: List of website URLs.
items:
type: string
type: array
type: object
UpdateSecretRequest:
description: Request body for updating an existing user secret.
properties:
name:
description: New name for the secret
maxLength: 255
minLength: 1
type: string
secret_value:
description: New secret value (API key, token, etc.)
minLength: 1
type: string
type: object
UpdateWorkflowRequest:
description: Request body for updating an existing saved workflow.
properties:
default_view:
description: New default view mode
enum:
- workflow
- app
type: string
description:
description: New description
type: string
name:
description: New display name
type: string
type: object
UpdateWorkspaceRequest:
description: Request body for updating an existing workspace's settings.
properties:
name:
description: New display name for the workspace
example: New Team Name
maxLength: 100
minLength: 1
type: string
type: object
UserDataResponseFull:
description: User data listing entry with file metadata (path, size, modification time).
properties:
modified:
description: UNIX timestamp of the last modification in milliseconds.
format: int64
type: integer
path:
type: string
size:
type: integer
type: object
UserResponse:
description: User information response
properties:
id:
description: Firebase UID of the authenticated user
type: string
status:
description: User status (always "active" for authenticated users)
type: string
required:
- id
- status
type: object
ValidationError:
description: Details of a single validation error encountered during asset operations.
properties:
code:
description: Machine-readable error code
example: FORMAT_NOT_ALLOWED
type: string
field:
description: Field that failed validation
example: format
type: string
message:
description: Human-readable error message
example: 'File format "PickleTensor" is not allowed. Allowed formats: [SafeTensor]'
type: string
required:
- code
- message
- field
type: object
ValidationResult:
description: Result of validating a set of asset operations.
properties:
errors:
description: Blocking validation errors that prevent download
items:
$ref: '#/components/schemas/ValidationError'
type: array
is_valid:
description: Overall validation status (true if all checks passed)
example: true
type: boolean
warnings:
description: Non-blocking validation warnings (informational only)
items:
$ref: '#/components/schemas/ValidationError'
type: array
required:
- is_valid
type: object
WorkflowApiAssetsRequest:
description: Request body for querying assets associated with a workflow.
properties:
workflow_api_json:
additionalProperties: true
type: object
required:
- workflow_api_json
type: object
WorkflowApiAssetsResponse:
description: Response containing assets associated with a workflow.
properties:
assets:
items:
$ref: '#/components/schemas/AssetInfo'
type: array
required:
- assets
type: object
WorkflowForkedFrom:
description: Reference to the parent workflow from which this workflow was forked.
properties:
workflow_id:
type: string
workflow_version_id:
type: string
type: object
WorkflowListResponse:
description: Paginated list of saved workflows.
properties:
data:
items:
$ref: '#/components/schemas/WorkflowResponse'
type: array
pagination:
$ref: '#/components/schemas/PaginationInfo'
required:
- data
- pagination
type: object
WorkflowPublishInfo:
description: Publishing metadata for a workflow shared to the Hub.
properties:
assets:
description: Published assets (inputs and models).
items:
$ref: '#/components/schemas/AssetInfo'
type: array
listed:
type: boolean
publish_time:
format: date-time
nullable: true
type: string
share_id:
type: string
workflow_id:
type: string
required:
- workflow_id
- share_id
- listed
- assets
type: object
WorkflowResponse:
description: Full workflow entity including metadata and version history.
properties:
created_at:
format: date-time
type: string
created_by:
type: string
default_view:
enum:
- workflow
- app
type: string
description:
type: string
forked_from:
$ref: '#/components/schemas/WorkflowForkedFrom'
id:
type: string
latest_version:
type: integer
name:
type: string
updated_at:
format: date-time
type: string
required:
- id
- latest_version
- created_by
- created_at
- updated_at
type: object
WorkflowVersionContentResponse:
description: Full workflow version including the serialized workflow JSON.
properties:
created_at:
format: date-time
type: string
created_by:
type: string
dependency_asset_ids:
items:
type: string
type: array
id:
type: string
version:
type: integer
workflow_json:
additionalProperties: true
type: object
required:
- id
- version
- workflow_json
- created_by
- created_at
type: object
WorkflowVersionResponse:
description: Metadata for a single workflow version.
properties:
created_at:
format: date-time
type: string
created_by:
type: string
id:
type: string
latest_version:
type: integer
version:
type: integer
required:
- id
- version
- latest_version
- created_by
- created_at
type: object
Workspace:
description: Full workspace entity with configuration and ownership details.
properties:
created_at:
format: date-time
type: string
id:
example: w-a1b2c3d4-5678-90ab-cdef-1234567890ab
type: string
name:
example: My Team
type: string
type:
enum:
- personal
- team
type: string
required:
- id
- name
- type
- created_at
type: object
WorkspaceAPIKeyInfo:
description: Metadata for a workspace-scoped API key (secret is never returned).
properties:
created_at:
description: When the key was created
format: date-time
type: string
description:
description: User-provided description of the key's purpose. Limit is byte-based (UTF-8 encoding); 5000 bytes equals 5000 ASCII characters or fewer multi-byte characters.
maxLength: 5000
type: string
expires_at:
description: When the key expires (if set)
format: date-time
type: string
id:
description: API key ID
format: uuid
type: string
key_prefix:
description: First 8 chars after prefix for display
type: string
last_used_at:
description: Last time the key was used
format: date-time
type: string
name:
description: User-provided label
type: string
revoked_at:
description: When the key was revoked (if revoked)
format: date-time
type: string
user_id:
description: User who created this key
type: string
workspace_id:
description: Workspace this key belongs to
type: string
required:
- id
- workspace_id
- user_id
- name
- description
- key_prefix
- created_at
type: object
WorkspaceSummary:
description: Abbreviated workspace metadata used in list responses.
properties:
id:
example: w-a1b2c3d4-5678-90ab-cdef-1234567890ab
type: string
name:
example: My Team
type: string
type:
enum:
- personal
- team
type: string
required:
- id
- name
- type
type: object
WorkspaceWithRole:
description: Workspace entity annotated with the requesting user's role.
properties:
created_at:
description: When the workspace was created
format: date-time
type: string
id:
example: w-a1b2c3d4-5678-90ab-cdef-1234567890ab
type: string
joined_at:
description: When the user joined the workspace (same as created_at for the workspace creator)
format: date-time
type: string
name:
example: My Team
type: string
role:
enum:
- owner
- member
type: string
subscription_tier:
$ref: '#/components/schemas/SubscriptionTier'
type:
enum:
- personal
- team
type: string
required:
- id
- name
- type
- role
- created_at
- joined_at
type: object
securitySchemes:
ApiKeyAuth:
description: |
API key authentication. Keys are prefixed with 'comfyui-' and can be
generated from user account settings. Example: 'comfyui-abc123...'
in: header
name: X-API-Key
type: apiKey
BearerAuth:
bearerFormat: JWT
description: |
Firebase JWT token authentication. Obtain a token by authenticating
with Firebase and pass it in the Authorization header.
scheme: bearer
type: http
CookieAuth:
description: |
Session cookie authentication. Set automatically after successful
login via the /api/auth/session endpoint.
in: cookie
name: session
type: apiKey
info:
description: |
API for ComfyUI - A powerful and modular UI for Stable Diffusion.
This API allows you to interact with ComfyUI programmatically, including:
- Retrieving prompt information
- Retrieving node information
license:
name: GNU General Public License v3.0
url: https://github.com/Comfy-Org/ComfyUI/blob/master/LICENSE
title: ComfyUI API
version: 1.0.0
openapi: 3.0.3
paths:
/.well-known/jwks.json:
get:
description: Public keys for validating Cloud JWTs
operationId: getJwks
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/JwksResponse'
description: JWKS response
headers:
Cache-Control:
description: Caching directive (e.g., "public, max-age=86400")
schema:
type: string
security: []
summary: Get JSON Web Key Set
tags:
- auth
/.well-known/oauth-authorization-server:
get:
description: Public metadata document for OAuth 2.1 clients. Cached 5 minutes.
operationId: getOAuthAuthorizationServer
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthAuthorizationServerMetadata'
description: Authorization-server metadata
headers:
Cache-Control:
description: 'Caching directive: "public, max-age=300"'
schema:
type: string
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: OAuth disabled
security: []
summary: OAuth 2.1 authorization-server metadata (RFC 8414)
tags:
- oauth
/.well-known/oauth-protected-resource:
get:
description: Public metadata describing the currently advertised protected resource. Cached 5 minutes. MCP is the only seeded active resource in the initial rollout.
operationId: getOAuthProtectedResource
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthProtectedResourceMetadata'
description: Protected-resource metadata
headers:
Cache-Control:
description: 'Caching directive: "public, max-age=300"'
schema:
type: string
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: OAuth disabled or no active resource configured
security: []
summary: OAuth 2.1 protected-resource metadata (RFC 9728)
tags:
- oauth
/api/assets:
get:
description: |
Retrieves a paginated list of assets belonging to the authenticated user.
Supports filtering by tags, name, metadata, and sorting options.
operationId: listAssets
parameters:
- description: Filter assets that have ALL of these tags
explode: false
in: query
name: include_tags
schema:
items:
type: string
type: array
style: form
- description: Exclude assets that have ANY of these tags
explode: false
in: query
name: exclude_tags
schema:
items:
type: string
type: array
style: form
- description: Filter assets where name contains this substring (case-insensitive)
in: query
name: name_contains
schema:
type: string
- description: JSON object for filtering by metadata fields
in: query
name: metadata_filter
schema:
type: string
- description: Maximum number of assets to return (1-500)
in: query
name: limit
schema:
default: 20
maximum: 500
minimum: 1
type: integer
- description: Number of assets to skip for pagination
in: query
name: offset
schema:
default: 0
minimum: 0
type: integer
- description: Field to sort by
in: query
name: sort
schema:
default: created_at
enum:
- name
- created_at
- updated_at
- size
- last_access_time
type: string
- description: Sort order
in: query
name: order
schema:
default: desc
enum:
- asc
- desc
type: string
- description: Whether to include public/shared assets in results
in: query
name: include_public
schema:
default: true
type: boolean
- description: Filter assets by exact content hash
in: query
name: asset_hash
schema:
type: string
- description: |
Opaque cursor for keyset pagination. Pass the `next_cursor` value
from the previous response to fetch the next page. When provided,
`offset` is ignored. Cursor pagination is only supported with
`sort` values `created_at`, `updated_at`, `name`, or `size`;
requests combining `after` with other sort fields return 400.
The cursor must have been minted under the same `sort` value used
in the follow-up request.
in: query
name: after
schema:
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/ListAssetsResponse'
description: Success - Assets returned
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Invalid request parameters
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: List user assets
tags:
- file
post:
description: |
Uploads a new asset to the system with associated metadata.
Supports two upload methods:
1. Direct file upload (multipart/form-data)
2. URL-based upload (application/json with source: "url")
If an asset with the same hash already exists, returns the existing asset.
operationId: uploadAsset
requestBody:
content:
application/json:
schema:
properties:
name:
description: Display name for the asset (used to determine file extension)
type: string
preview_id:
description: Optional preview asset ID
format: uuid
type: string
tags:
description: Freeform tags for the asset. Common types include "models", "input", "output", and "temp", but any tag can be used in any order.
items:
type: string
type: array
url:
description: HTTP/HTTPS URL to download the asset from
format: uri
type: string
user_metadata:
additionalProperties: true
description: Custom metadata to store with the asset
type: object
required:
- url
- name
type: object
multipart/form-data:
schema:
properties:
file:
description: The asset file to upload
format: binary
type: string
id:
description: Optional asset ID for idempotent creation. If provided and asset exists, returns existing asset.
format: uuid
type: string
mime_type:
description: MIME type of the asset (e.g., "image/png", "video/mp4")
type: string
name:
description: Display name for the asset
type: string
preview_id:
description: Optional preview asset ID. If not provided, images will use their own ID as preview.
format: uuid
type: string
tags:
description: Freeform tags for the asset. Common types include "models", "input", "output", and "temp", but any tag can be used in any order.
items:
type: string
type: array
user_metadata:
description: Custom JSON metadata as a string
type: string
required:
- file
type: object
required: true
responses:
"201":
content:
application/json:
schema:
$ref: '#/components/schemas/AssetCreated'
description: Asset created successfully
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Invalid request (bad file, invalid URL, invalid content type, etc.)
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Source URL requires authentication or access denied
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Source URL not found
"413":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: File too large
"415":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unsupported media type
"422":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Download failed due to network error or timeout
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Upload a new asset
tags:
- file
/api/assets/{id}:
delete:
description: |
Deletes an asset and its content from storage.
Both the database record and storage content are deleted.
operationId: deleteAsset
parameters:
- description: Asset ID
in: path
name: id
required: true
schema:
format: uuid
type: string
responses:
"204":
description: Asset deleted successfully
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Asset not found
"409":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Asset cannot be deleted because it is referenced by another resource (e.g., workflow version)
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Delete asset
tags:
- file
get:
description: Retrieves detailed information about a specific asset
operationId: getAssetById
parameters:
- description: Asset ID
in: path
name: id
required: true
schema:
format: uuid
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/Asset'
description: Asset details retrieved successfully
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Asset not found
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Get asset details
tags:
- file
put:
description: |
Updates an asset's metadata. At least one field must be provided.
Only name, mime_type, preview_id, and user_metadata can be updated.
For tag management, use the dedicated PUT /api/assets/{id}/tags endpoint.
operationId: updateAsset
parameters:
- description: Asset ID
in: path
name: id
required: true
schema:
format: uuid
type: string
requestBody:
content:
application/json:
schema:
minProperties: 1
properties:
mime_type:
description: Updated MIME type of the asset
type: string
name:
description: New display name for the asset
type: string
preview_id:
description: Updated preview asset ID
format: uuid
type: string
user_metadata:
additionalProperties: true
description: Updated custom metadata
type: object
type: object
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/AssetUpdated'
description: Asset updated successfully
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Invalid request (no fields provided)
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Asset not found
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Update asset metadata
tags:
- file
/api/assets/{id}/tags:
delete:
description: Removes one or more tags from an existing asset
operationId: removeAssetTags
parameters:
- description: Asset ID
in: path
name: id
required: true
schema:
format: uuid
type: string
requestBody:
content:
application/json:
schema:
properties:
tags:
description: Tags to remove from the asset
items:
type: string
minItems: 1
type: array
required:
- tags
type: object
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/TagsModificationResponse'
description: Tags removed successfully
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Invalid request
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Asset not found
"422":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Validation error (e.g., reserved tag)
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Remove tags from asset
tags:
- file
post:
description: Adds one or more tags to an existing asset
operationId: addAssetTags
parameters:
- description: Asset ID
in: path
name: id
required: true
schema:
format: uuid
type: string
requestBody:
content:
application/json:
schema:
properties:
tags:
description: Tags to add to the asset
items:
type: string
minItems: 1
type: array
required:
- tags
type: object
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/TagsModificationResponse'
description: Tags added successfully
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Invalid request
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Asset not found
"422":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Validation error (e.g., reserved tag)
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Add tags to asset
tags:
- file
put:
description: Adds and removes tags from an asset in a single operation
operationId: updateAssetTags
parameters:
- description: Asset ID
in: path
name: id
required: true
schema:
format: uuid
type: string
requestBody:
content:
application/json:
schema:
description: At least one of add or remove must contain items. Empty arrays are allowed when the other array has items.
minProperties: 1
properties:
add:
description: Tags to add to the asset. Can be empty if remove has items.
items:
type: string
type: array
remove:
description: Tags to remove from the asset. Can be empty if add has items.
items:
type: string
type: array
type: object
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/TagsModificationResponse'
description: Tags updated successfully
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Invalid request
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Asset not found
"422":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Reserved tag validation error
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Update asset tags
tags:
- file
/api/assets/download:
post:
description: |
Initiates a background download job for large files from Huggingface or Civitai.
If the file already exists in storage, the asset record is created immediately and returned (200 OK).
If the file doesn't exist, a background task is created and the task ID is returned (202 Accepted).
The frontend can track progress using GET /api/tasks/{task_id}.
operationId: createAssetDownload
requestBody:
content:
application/json:
schema:
properties:
preview_id:
description: Optional preview asset ID to associate with the downloaded asset
example: 550e8400-e29b-41d4-a716-446655440000
format: uuid
type: string
source_url:
description: URL of the file to download (must be from huggingface.co, civitai.com, or civitai.red)
example: https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/main/v1-5-pruned.safetensors
format: uri
type: string
tags:
description: Optional tags for the asset (e.g., ["model", "checkpoint"])
items:
type: string
type: array
user_metadata:
additionalProperties: true
description: Optional user-defined metadata to attach to the asset
type: object
required:
- source_url
type: object
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/AssetCreated'
description: File already exists in storage - asset created/returned immediately
"202":
content:
application/json:
schema:
$ref: '#/components/schemas/AssetDownloadResponse'
description: Accepted - Download task created and processing in background
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Invalid URL or unsupported source
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"422":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Validation errors
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Initiate background download for large files
tags:
- file
/api/assets/export:
post:
description: |
Initiates a background task to export a ZIP file from assets resolved by job IDs and/or selected by asset IDs.
The frontend can track progress using GET /api/tasks/{task_id}.
At least one of `job_ids` or `asset_ids` must be provided.
operationId: createAssetExport
requestBody:
content:
application/json:
schema:
properties:
asset_ids:
description: Asset IDs to include in the ZIP bundle. Additive to the assets associated with provided job IDs.
example:
- 833a1b5c-beab-436a-ae8e-f07e7cd7b2c4
items:
type: string
type: array
job_asset_name_filters:
additionalProperties:
items:
type: string
minItems: 1
type: array
description: |
Optional per-job asset name filters. When provided for a job ID,
only assets whose name matches one of the specified names are included.
Job IDs present in `job_ids` but absent from this map include all their assets.
example:
833a1b5c-beab-436a-ae8e-f07e7cd7b2c4:
- ComfyUI_00001_.png
- ComfyUI_00003_.png
type: object
job_ids:
description: Job IDs to include *all associated assets* of the jobs in the ZIP bundle.
example:
- 833a1b5c-beab-436a-ae8e-f07e7cd7b2c4
items:
type: string
type: array
naming_strategy:
default: group_by_job_time
description: |
Strategy for naming files in the ZIP:
- group_by_job_id: Group assets by job ID as a parent directory (e.g., "833a1b5c-beab-436a-ae8e-f07e7cd7b2c4/ComfyUI_00001_.png")
- preserve: Use original asset names, skip duplicates (first one wins)
- asset_id: Use the asset ID as the filename (e.g., "833a1b5c-beab-436a-ae8e-f07e7cd7b2c4.png")
- group_by_job_time: Group by job creation timestamp (e.g., "2026-03-26T16-13-00/ComfyUI_00001_.png")
enum:
- group_by_job_id
- preserve
- asset_id
- group_by_job_time
type: string
type: object
required: true
responses:
"202":
content:
application/json:
schema:
$ref: '#/components/schemas/AssetDownloadResponse'
description: Accepted - Export task created and processing in background
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Invalid request
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Initiate background ZIP export for multiple assets
tags:
- file
x-runtime:
- cloud
/api/assets/exports/{exportName}:
get:
description: |
Returns a URL for downloading the export file.
The export must have been created by the authenticated user.
operationId: downloadExport
parameters:
- description: Export filename with extension (e.g., "021e55cd-9785-4ac7-ac39-f4010138e3bc.zip")
in: path
name: exportName
required: true
schema:
pattern: ^[a-zA-Z0-9_-]+\.zip$
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/ExportDownloadURLResponse'
description: Signed URL for downloading the export
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Invalid export name
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Export not found or not owned by user
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Get a URL for downloading an export file
tags:
- file
x-runtime:
- cloud
/api/assets/from-hash:
post:
description: |
Creates a new asset reference using an existing asset's hash.
This avoids re-uploading the file content when the asset already exists in storage.
The user can provide their own metadata and tags for the reference.
operationId: createAssetFromHash
requestBody:
content:
application/json:
schema:
properties:
hash:
description: Hash of the existing asset. Supports Blake3 (blake3:) or SHA256 (sha256:) formats
pattern: ^(blake3|sha256):[a-f0-9]{64}$
type: string
mime_type:
description: MIME type of the asset (e.g., "image/png", "video/mp4")
type: string
name:
description: Display name for the asset reference (optional)
type: string
tags:
description: Freeform tags for the asset. Common types include "models", "input", "output", and "temp", but any tag can be used in any order.
items:
type: string
minItems: 1
type: array
user_metadata:
additionalProperties: true
description: Custom metadata for this asset reference
type: object
required:
- hash
- tags
type: object
required: true
responses:
"201":
content:
application/json:
schema:
$ref: '#/components/schemas/AssetCreated'
description: Asset reference created successfully
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Invalid request (bad hash format, invalid tags, etc.)
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Source asset with given hash not found
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Create asset reference from existing hash
tags:
- file
/api/assets/from-workflow:
post:
description: |
Given a workflow in API format, returns the assets (inputs) and
models referenced by the workflow.
operationId: postAssetsFromWorkflow
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/WorkflowApiAssetsRequest'
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/WorkflowApiAssetsResponse'
description: Success
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Bad request
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Not found
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Get assets and models referenced in a workflow
tags:
- file
x-runtime:
- cloud
/api/assets/hash/{hash}:
head:
description: |
Checks if an asset exists in the system by its blake3 hash.
Returns 200 if the asset exists, 404 if it doesn't.
operationId: checkAssetByHash
parameters:
- description: Blake3 hash of the asset in format 'blake3:hex_digest'
in: path
name: hash
required: true
schema:
example: blake3:a1b2c3d4e5f67890123456789012345678901234567890123456789012345678
pattern: ^blake3:[a-f0-9]{64}$
type: string
responses:
"200":
description: Asset exists
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Invalid hash format
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"404":
description: Asset not found
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Check if asset exists by hash
tags:
- file
/api/assets/import:
post:
description: |
Imports the specified published assets into the caller's asset library.
New DB records reference the same storage objects; no file copying occurs.
Assets the caller already owns (by hash) are deduplicated.
The `id` field on each returned AssetInfo is the caller's newly created
private asset ID, not the published_asset_id supplied in the request.
operationId: importPublishedAssets
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/ImportPublishedAssetsRequest'
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/ImportPublishedAssetsResponse'
description: Successfully imported assets
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Bad request
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Import published assets into the caller's library
tags:
- file
/api/assets/prune:
post:
description: '[local-only] Starts a background job that removes asset entries whose underlying content no longer exists on disk. Local ComfyUI only; cloud assets live in GCS.'
operationId: pruneAssets
responses:
"200":
content:
application/json:
schema:
properties:
marked:
description: Number of assets marked as missing
type: integer
status:
type: string
type: object
description: Prune result
summary: Mark assets whose backing files no longer exist on disk
x-runtime:
- local
/api/assets/remote-metadata:
get:
description: |
Retrieves metadata for an asset from a remote download URL without downloading the entire file.
Supports various sources including CivitAI and other model repositories.
Uses HEAD requests or API calls to fetch metadata efficiently.
This endpoint is for previewing metadata before downloading, not for getting metadata of existing assets.
operationId: getRemoteAssetMetadata
parameters:
- description: Download URL to retrieve metadata from
in: query
name: url
required: true
schema:
example: https://civitai.com/api/download/models/123456
format: uri
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/AssetMetadataResponse'
description: Metadata retrieved successfully
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Invalid URL or missing required parameter
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"422":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Failed to retrieve metadata from source
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Get asset metadata from remote URL
tags:
- file
x-runtime:
- cloud
/api/assets/seed:
post:
description: '[local-only] Starts a background job that scans configured directories and registers assets not yet in the asset database. Local ComfyUI only.'
operationId: seedAssets
requestBody:
content:
application/json:
schema:
properties:
roots:
description: Root folder paths to scan (if omitted, scans all)
items:
type: string
type: array
type: object
responses:
"200":
content:
application/json:
schema:
properties:
status:
type: string
type: object
description: Seed started
summary: Trigger asset scan/seed from filesystem
x-runtime:
- local
/api/assets/seed/cancel:
post:
description: '[local-only] Requests cancellation of the currently-running asset seed job. Local ComfyUI only.'
operationId: cancelAssetSeed
responses:
"200":
content:
application/json:
schema:
properties:
status:
type: string
type: object
description: Scan cancelled
summary: Cancel an in-progress asset scan
x-runtime:
- local
/api/assets/seed/status:
get:
description: '[local-only] Returns progress/status of the most recent asset seed job. Local ComfyUI only.'
operationId: getAssetSeedStatus
responses:
"200":
content:
application/json:
schema:
additionalProperties: true
description: Scan progress details (files scanned, total, status, etc.)
type: object
description: Scan progress
summary: Get asset scan progress
x-runtime:
- local
/api/assets/tags/refine:
get:
description: |
Returns a histogram of tags appearing on assets matching the given filters.
Useful for refining asset searches by showing available tags and their counts.
Only returns tags with non-zero counts (tags that exist on matching assets).
operationId: getAssetTagHistogram
parameters:
- description: Filter assets that have ALL of these tags
explode: false
in: query
name: include_tags
schema:
items:
type: string
type: array
style: form
- description: Exclude assets that have ANY of these tags
explode: false
in: query
name: exclude_tags
schema:
items:
type: string
type: array
style: form
- description: Filter assets where name contains this substring (case-insensitive)
in: query
name: name_contains
schema:
type: string
- description: JSON object for filtering by metadata fields
in: query
name: metadata_filter
schema:
type: string
- description: Maximum number of tags to return (1-1000, default 100)
in: query
name: limit
schema:
default: 100
maximum: 1000
minimum: 1
type: integer
- description: Whether to include public/shared assets in results
in: query
name: include_public
schema:
default: true
type: boolean
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/AssetTagHistogramResponse'
description: Success - Tag histogram returned
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Invalid request parameters
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Get tag histogram for filtered assets
tags:
- file
/api/auth/session:
delete:
description: |
Clears the session cookie and optionally revokes the session on the server.
This logs the user out of their current session.
operationId: deleteSession
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/DeleteSessionResponse'
description: Session deleted successfully
headers:
Set-Cookie:
description: Session cookie cleared (Max-Age=-1)
schema:
type: string
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security: []
summary: Delete session cookie (logout)
tags:
- auth
post:
description: |
Creates a session cookie from the Firebase ID token in the Authorization header.
Returns a Set-Cookie header with a secure, HttpOnly session cookie that expires in 2 hours.
A new session cookie is created on every call.
Authentication: Requires Authorization header with Bearer token or API key.
Cookie authentication is not allowed for this endpoint.
operationId: createSession
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/CreateSessionResponse'
description: Session created successfully
headers:
Set-Cookie:
description: Session cookie with 2-hour expiration
schema:
type: string
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Bad request - Invalid or old ID token
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized - Authentication required
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security:
- ApiKeyAuth: []
- BearerAuth: []
summary: Create a session cookie
tags:
- auth
/api/auth/token:
post:
description: |
Exchanges a Firebase JWT for a workspace-scoped Cloud JWT.
If workspace_id is omitted, returns a token for the user's personal workspace.
operationId: exchangeToken
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/ExchangeTokenRequest'
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/ExchangeTokenResponse'
description: Token exchanged successfully
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Invalid or expired Firebase JWT
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Workspace not found or user not a member
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security:
- BearerAuth: []
summary: Exchange Firebase JWT for Cloud JWT
tags:
- auth
/api/billing/balance:
get:
description: |
Returns the current credit balance for the workspace from Metronome.
This is a GET endpoint that may occasionally write (to update has_funds status).
operationId: getBillingBalance
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/BillingBalanceResponse'
description: Credit balance
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security:
- BearerAuth: []
summary: Get credit balance
tags:
- billing
/api/billing/events:
get:
description: |
Returns paginated billing events for the workspace.
Events include subscription changes, payments, and credit adjustments.
operationId: getBillingEvents
parameters:
- description: Page number (1-indexed)
in: query
name: page
schema:
default: 1
minimum: 1
type: integer
- description: Number of events per page
in: query
name: limit
schema:
default: 20
maximum: 100
minimum: 1
type: integer
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/BillingEventsResponse'
description: Paginated billing events
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security:
- BearerAuth: []
summary: Get billing events
tags:
- billing
/api/billing/ops/{id}:
get:
description: |
Returns the current status of a billing operation.
All billing mutations (subscribe, cancel, topup, plan change) return a billing_op_id.
Use this endpoint to poll for completion status.
Status values:
- pending: Operation is in progress
- succeeded: Operation completed successfully
- failed: Operation failed, see error_message for details
operationId: getBillingOpStatus
parameters:
- description: The billing operation ID
in: path
name: id
required: true
schema:
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/BillingOpStatusResponse'
description: Billing operation status
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Billing operation not found
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security:
- BearerAuth: []
summary: Get billing operation status
tags:
- billing
/api/billing/payment-portal:
post:
description: |
Returns a Stripe Billing Portal URL for managing payment methods.
The user can add, update, or remove payment methods in the portal.
operationId: getPaymentPortal
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/PaymentPortalRequest'
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/PaymentPortalResponse'
description: Success
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Bad request (e.g., missing return_url)
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security:
- BearerAuth: []
summary: Get payment portal URL
tags:
- billing
/api/billing/plans:
get:
description: |
Returns all subscription plans with pricing and availability for the workspace.
Availability indicates whether the workspace can subscribe to each plan.
operationId: getBillingPlans
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/BillingPlansResponse'
description: Available plans with pricing
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security:
- BearerAuth: []
summary: Get available subscription plans
tags:
- billing
/api/billing/preview-subscribe:
post:
description: |
Returns a preview of the subscription transition including:
- Cost to charge today (for upgrades/new subscriptions)
- Cost at next billing period
- Credits granted today (prorated for upgrades)
- Credits granted at next billing period
This endpoint does not execute any billing operations.
Use it to show the user what will happen before they confirm.
operationId: previewSubscribe
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/PreviewSubscribeRequest'
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/PreviewSubscribeResponse'
description: Subscription preview
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Invalid request (e.g., invalid plan slug, seats below minimum)
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security:
- BearerAuth: []
summary: Preview what will happen when subscribing to a plan
tags:
- billing
/api/billing/status:
get:
description: |
Returns the current billing status for the workspace.
Requires workspace-scoped authentication.
operationId: getBillingStatus
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/BillingStatusResponse'
description: Billing status
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Workspace not found
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security:
- BearerAuth: []
summary: Get billing status
tags:
- billing
/api/billing/subscribe:
post:
description: |
Subscribes the workspace to the specified plan. Flow depends on payment method:
**If workspace has payment method:**
- Creates subscription immediately
- Returns status="subscribed" with effective_at timestamp
**If workspace needs payment method:**
- Creates scheduled subscription (status=scheduled)
- Returns status="needs_payment_method" with payment_method_url
- After payment method is added via checkout, subscription is finalized
For existing subscriptions, this performs a plan change (upgrade/downgrade).
operationId: subscribe
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/SubscribeRequest'
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/SubscribeResponse'
description: Subscription created or payment method needed
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Invalid request (e.g., invalid plan slug, incompatible plan)
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security:
- BearerAuth: []
summary: Subscribe to a billing plan
tags:
- billing
/api/billing/subscription/cancel:
post:
description: |
Cancels the workspace's active subscription at the end of the current billing period.
The subscription remains active until the period ends, then transitions to ended.
Returns the date when the subscription will end.
operationId: cancelSubscription
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/CancelSubscriptionRequest'
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/CancelSubscriptionResponse'
description: Subscription cancellation scheduled
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Invalid request (e.g., no active subscription)
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security:
- BearerAuth: []
summary: Cancel the current subscription
tags:
- billing
/api/billing/subscription/resubscribe:
post:
description: |
Reverses a scheduled subscription cancellation before the period ends.
If the subscription has a cancel_at date set (scheduled to cancel at period end),
this clears the cancellation and resumes the subscription.
This operation:
1. Clears the cancel_at date on the subscription
2. Sets subscription status back to active
3. Clears the ending_before on the Metronome recurring commit
Can only be called while the subscription is still in the cancellation grace period
(before the period ends). After period end, you must subscribe again.
operationId: resubscribe
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/ResubscribeRequest'
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/ResubscribeResponse'
description: Subscription resumed successfully
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Invalid request (e.g., no active subscription, not in cancellation grace period)
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security:
- BearerAuth: []
summary: Resubscribe (undo cancel) before period ends
tags:
- billing
/api/billing/topup:
post:
description: |
Initiates a credit top-up for the workspace. Creates a payment-gated prepaid commit
in Metronome that triggers an immediate Stripe charge. Credits are held until
payment completes.
Requires the workspace to have a valid payment method on file. If no payment method
exists, returns an error directing the user to add one via the payment portal.
The response includes a billing_op_id that can be used to poll for status via
GET /api/billing/ops/{id}.
operationId: createTopup
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/CreateTopupRequest'
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/CreateTopupResponse'
description: Top-up initiated successfully
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Bad request (invalid amount, no payment method)
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security:
- BearerAuth: []
summary: Create a credit top-up
tags:
- billing
/api/embeddings:
get:
description: '[local-only] Returns the list of text-encoder embeddings available on disk. Local ComfyUI only; the cloud runtime does not serve this.'
operationId: getEmbeddings
responses:
"200":
content:
application/json:
schema:
items:
type: string
type: array
description: Embedding names
summary: List available embedding names
x-runtime:
- local
/api/experiment/models:
get:
description: |
Returns a list of model folders available in the system.
This is an experimental endpoint that replaces the legacy /models endpoint.
operationId: getModelFolders
responses:
"200":
content:
application/json:
schema:
items:
$ref: '#/components/schemas/ModelFolder'
type: array
description: Success - List of model folders
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security: []
summary: Get available model folders
tags:
- file
/api/experiment/models/{folder}:
get:
description: |
Returns a list of models available in the specified folder.
This is an experimental endpoint that provides enhanced model information.
operationId: getModelsInFolder
parameters:
- description: The folder name to list models from
in: path
name: folder
required: true
schema:
example: checkpoints
type: string
responses:
"200":
content:
application/json:
schema:
items:
$ref: '#/components/schemas/ModelFile'
type: array
description: Success - List of models in the folder
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Folder not found or no models in folder
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security: []
summary: Get models in a specific folder
tags:
- file
/api/extensions:
get:
description: |
Returns the list of custom node web extension JS files available for
loading by the ComfyUI frontend. Paths are relative to the web root
(e.g. `/extensions/VHS.core.js`).
operationId: getExtensions
responses:
"200":
content:
application/json:
schema:
description: URL paths (relative to web root) of available extension JS files
items:
type: string
type: array
description: JSON array of extension file paths
security: []
summary: List custom node JS extensions
tags:
- node
/api/features:
get:
description: Returns the server's feature capabilities
operationId: getFeatures
responses:
"200":
content:
application/json:
schema:
additionalProperties: true
properties:
max_upload_size:
description: Maximum upload size in bytes
type: integer
supports_preview_metadata:
description: Whether the server supports preview metadata
type: boolean
type: object
description: Success
headers:
Cache-Control:
description: Short-lived private cache to deduplicate rapid-fire calls from the frontend
schema:
type: string
Vary:
description: Cache key includes auth headers so anonymous and authenticated responses are stored separately
schema:
type: string
security:
- ApiKeyAuth: []
- BearerAuth: []
- CookieAuth: []
- {}
summary: Get server feature flags
tags:
- node
/api/feedback:
post:
description: Submit feedback about the ComfyUI service
operationId: submitFeedback
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/FeedbackRequest'
required: true
responses:
"201":
content:
application/json:
schema:
$ref: '#/components/schemas/FeedbackResponse'
description: Feedback submitted successfully
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Invalid request
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Submit user feedback
tags:
- feedback
/api/files/mask-layers:
get:
description: |
Given a mask file (any of the 4 layers), returns all related mask layer files.
This is used by the mask editor to load the paint, mask, and painted layers
when reopening a previously edited mask.
operationId: getMaskLayers
parameters:
- description: Hash filename of any mask layer file
in: query
name: filename
required: true
schema:
example: abc123def456.png
type: string
responses:
"200":
content:
application/json:
schema:
properties:
mask:
description: Filename of the mask layer
nullable: true
type: string
paint:
description: Filename of the paint strokes layer
nullable: true
type: string
painted:
description: Filename of the painted image layer
nullable: true
type: string
painted_masked:
description: Filename of the final composite layer
nullable: true
type: string
type: object
description: Success - Related mask layers returned
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: File not found or not a mask file
summary: Get related mask layer files
tags:
- file
/api/free:
post:
description: '[local-only] Frees GPU memory by unloading models and/or freeing the resident model cache. Local ComfyUI only; cloud manages GPU lifecycle per-pod.'
operationId: freeMemory
requestBody:
content:
application/json:
schema:
properties:
free_memory:
description: Run garbage collection and free cached memory
type: boolean
unload_models:
description: Unload all models from VRAM/RAM
type: boolean
type: object
responses:
"200":
description: Memory freed
summary: Free GPU memory and/or unload models
x-runtime:
- local
/api/global_subgraphs:
get:
description: |
Returns a list of globally available subgraph blueprints.
These are pre-built workflow components that can be used as nodes.
The data field contains a promise that resolves to the full subgraph JSON.
operationId: getGlobalSubgraphs
responses:
"200":
content:
application/json:
schema:
additionalProperties:
$ref: '#/components/schemas/GlobalSubgraphInfo'
type: object
description: Success - Map of subgraph IDs to their metadata
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security: []
summary: Get available subgraph blueprints
tags:
- workflow
/api/global_subgraphs/{id}:
get:
description: Returns the full data for a specific subgraph blueprint by ID
operationId: getGlobalSubgraph
parameters:
- description: The unique identifier of the subgraph blueprint
in: path
name: id
required: true
schema:
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/GlobalSubgraphData'
description: Success - Full subgraph data
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Subgraph not found
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security: []
summary: Get a specific subgraph blueprint
tags:
- workflow
/api/history:
post:
deprecated: true
description: |
**Deprecated.** Superseded by the job-management endpoints under
`/api/jobs`. Planned for removal no earlier than a future major
release; sunset timeline TBD.
Clear all history for the authenticated user or delete specific job IDs.
Supports clearing all history or deleting specific job IDs.
operationId: manageHistory
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/HistoryManageRequest'
required: true
responses:
"200":
description: Success - History management operation completed
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Invalid request parameters
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized - Authentication required
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Manage execution history
tags:
- workflow
/api/history_v2:
get:
deprecated: true
description: |
**Deprecated.** Superseded by `GET /api/jobs`, which returns the same
execution records in a paginated, filterable format. Planned for removal
no earlier than a future major release; sunset timeline TBD.
Retrieve execution history for the authenticated user with pagination support.
Returns a lightweight history format with filtered prompt data (workflow removed from extra_pnginfo).
operationId: getHistory
parameters:
- description: Maximum number of items to return
in: query
name: max_items
schema:
type: integer
- description: Starting position (default 0)
in: query
name: offset
schema:
default: 0
type: integer
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/HistoryResponse'
description: Success - Execution history retrieved
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized - Authentication required
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Get execution history (v2)
tags:
- workflow
/api/history_v2/{prompt_id}:
get:
deprecated: true
description: |
**Deprecated.** Superseded by `GET /api/jobs/{job_id}`, which returns
the same execution record. Planned for removal no earlier than a future
major release; sunset timeline TBD.
Retrieve detailed execution history for a specific prompt ID.
Returns full history data including complete prompt information.
operationId: getHistoryForPrompt
parameters:
- description: The prompt ID to retrieve history for
in: path
name: prompt_id
required: true
schema:
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/HistoryDetailResponse'
description: Success - History for prompt retrieved
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized - Authentication required
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Prompt not found
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Get history for specific prompt
tags:
- workflow
/api/hub/assets/upload-url:
post:
description: |
Returns a presigned R2 upload URL and a signed token.
The token is signed with the authenticated caller's user ID; no existing hub profile is required.
The frontend uploads the file directly to R2 using the presigned URL,
then passes the token in the create profile, update profile, or publish request.
operationId: createHubAssetUploadUrl
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/HubAssetUploadUrlRequest'
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/HubAssetUploadUrlResponse'
description: Presigned upload URL and token
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Bad request (e.g. unsupported content type)
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Not found
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Get a presigned upload URL for hub assets
tags:
- hub
/api/hub/labels:
get:
description: Returns hub labels (tags, models, custom nodes) that can be used when publishing workflows. Filter by type to get a specific category.
operationId: listHubLabels
parameters:
- description: Filter by label type. Omit to return all labels.
in: query
name: type
schema:
enum:
- tag
- model
- custom_node
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/HubLabelListResponse'
description: List of labels
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Bad request (e.g. invalid type parameter)
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: List available hub labels
tags:
- hub
/api/hub/profiles:
post:
description: Creates a hub profile for the specified workspace. Username is immutable after creation.
operationId: createHubProfile
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/CreateHubProfileRequest'
required: true
responses:
"201":
content:
application/json:
schema:
$ref: '#/components/schemas/HubProfile'
description: Hub profile created
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Bad request (e.g. invalid username)
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Not found
"409":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Username already taken or profile already exists
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Create hub profile
tags:
- hub
/api/hub/profiles/{username}:
get:
description: Returns the public hub profile for the given username.
operationId: getHubProfileByUsername
parameters:
- description: The hub profile username.
in: path
name: username
required: true
schema:
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/HubProfile'
description: Hub profile
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Profile not found
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security: []
summary: Get a public hub profile by username
tags:
- hub
patch:
description: Updates the hub profile identified by username. The authenticated user must belong to the workspace that owns the profile. Username cannot be changed.
operationId: updateHubProfile
parameters:
- description: The hub profile username to update.
in: path
name: username
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateHubProfileRequest'
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/HubProfile'
description: Hub profile updated
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Bad request (e.g. missing body, invalid avatar token)
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: No hub profile exists with this username
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Update hub profile
tags:
- hub
/api/hub/profiles/check:
get:
description: |
Checks whether a username is available for the caller's workspace.
If the username is taken by another workspace, returns up to 5 available suggestions.
If the username format is invalid, returns a validation error.
operationId: checkHubUsername
parameters:
- in: query
name: username
required: true
schema:
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/HubUsernameCheckResponse'
description: Username availability result
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Not found
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Check username availability
tags:
- hub
/api/hub/profiles/me:
get:
description: Returns the hub profile for the authenticated user's workspace.
operationId: getMyHubProfile
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/HubProfile'
description: Hub profile
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: No hub profile exists
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Get current user's hub profile
tags:
- hub
/api/hub/workflows:
get:
description: Returns paginated hub workflows with optional search and filtering.
operationId: listHubWorkflows
parameters:
- in: query
name: cursor
schema:
type: string
- in: query
name: limit
schema:
default: 20
maximum: 100
minimum: 1
type: integer
- description: Search by workflow name
in: query
name: search
schema:
type: string
- description: Filter by tag
in: query
name: tag
schema:
type: string
- description: Filter by profile username
in: query
name: username
schema:
type: string
- description: When true, returns full HubWorkflowDetail objects in the workflows array instead of summaries. Requires limit <= 20.
in: query
name: detail
schema:
default: false
type: boolean
- description: Filter by status (e.g. ?status=pending,approved). Defaults to approved if omitted.
explode: false
in: query
name: status
schema:
items:
$ref: '#/components/schemas/HubWorkflowStatus'
type: array
style: form
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/HubWorkflowListResponse'
description: Paginated list of hub workflows
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Bad request (e.g. malformed pagination cursor)
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Profile not found (when filtering by username)
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security: []
summary: Browse hub workflows
tags:
- hub
post:
description: Publishes a workflow to the hub with metadata, thumbnail, and sample images.
operationId: publishHubWorkflow
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/PublishHubWorkflowRequest'
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/HubWorkflowDetail'
description: Workflow published to hub
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Bad request
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Workflow or profile not found
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Publish a workflow to the hub
tags:
- hub
/api/hub/workflows/{share_id}:
delete:
description: Removes a workflow from the hub listing.
operationId: deleteHubWorkflow
parameters:
- description: The share ID of the hub workflow to unpublish.
in: path
name: share_id
required: true
schema:
type: string
responses:
"204":
description: Successfully unpublished
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Workflow not found
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Unpublish a workflow from the hub
tags:
- hub
get:
description: Returns full details of a hub workflow including workflow JSON and assets.
operationId: getHubWorkflow
parameters:
- description: The share ID of the hub workflow.
in: path
name: share_id
required: true
schema:
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/HubWorkflowDetail'
description: Hub workflow detail
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Workflow not found
"413":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Workflow JSON too large
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security: []
summary: Get hub workflow detail
tags:
- hub
/api/hub/workflows/index:
get:
description: Returns all listed hub workflows in the same format as workflow_templates index.json. No pagination — returns the full list.
operationId: listHubWorkflowIndex
parameters:
- description: Filter by status (e.g. ?status=pending,approved). Defaults to approved if omitted.
explode: false
in: query
name: status
schema:
items:
$ref: '#/components/schemas/HubWorkflowStatus'
type: array
style: form
responses:
"200":
content:
application/json:
schema:
items:
$ref: '#/components/schemas/HubWorkflowTemplateEntry'
type: array
description: List of hub workflow template entries
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security: []
summary: List hub workflows in template index format
tags:
- hub
/api/i18n:
get:
description: '[local-only] Returns translation file URLs contributed by custom nodes, keyed by locale. Local ComfyUI only; cloud serves translations from GCS.'
operationId: getI18n
responses:
"200":
content:
application/json:
schema:
additionalProperties: true
description: Nested map of locale to translation key-value pairs
type: object
description: Translation map
summary: Get internationalisation translation strings
x-runtime:
- local
/api/interrupt:
post:
description: |
Cancel all currently RUNNING jobs for the authenticated user.
This will interrupt any job that is currently in 'in_progress' status.
Note: This endpoint only affects running jobs. To cancel pending jobs, use /api/queue.
operationId: interruptJob
responses:
"200":
description: Success - Job interrupted or no running job found
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized - Authentication required
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Interrupt currently running jobs
tags:
- queue
/api/invites/{token}/accept:
post:
description: Accepts an invite and adds the user as a member of the workspace.
operationId: acceptWorkspaceInvite
parameters:
- description: Invite token
in: path
name: token
required: true
schema:
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/AcceptInviteResponse'
description: Invite accepted, user is now a member
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Email does not match invite
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Invite not found or expired
"409":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Already a member of this workspace
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security:
- BearerAuth: []
summary: Accept a workspace invite
tags:
- workspaces
/api/job/{job_id}/status:
get:
deprecated: true
description: |
**Deprecated.** Superseded by `GET /api/jobs/{job_id}` (plural path).
Clients should migrate; the endpoint is retained for backward
compatibility but will be removed in a future release.
operationId: getJobStatus
parameters:
- description: The unique ID of the job
in: path
name: job_id
required: true
schema:
format: uuid
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/JobStatusResponse'
description: Success - Job status returned
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Forbidden - job belongs to another user
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Job not found
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Get job status (deprecated)
tags:
- job
/api/jobs:
get:
description: |
Retrieve a paginated list of jobs for the authenticated user.
Returns lightweight job data optimized for list views.
Workflow and full outputs are excluded to reduce payload size.
operationId: listJobs
parameters:
- description: Filter by one or more statuses (comma-separated). If not provided, returns all jobs.
example: pending,in_progress
in: query
name: status
schema:
type: string
- description: Filter by workflow ID (exact match)
example: 550e8400-e29b-41d4-a716-446655440000
in: query
name: workflow_id
schema:
type: string
- description: Filter by output media type (only applies to completed jobs with outputs)
example: image
in: query
name: output_type
schema:
enum:
- image
- video
- audio
- 3d
type: string
- description: Field to sort by (create_time = when job was submitted, execution_time = how long workflow took to run)
example: execution_time
in: query
name: sort_by
schema:
default: create_time
enum:
- create_time
- execution_time
type: string
- description: Sort direction (asc = ascending, desc = descending)
in: query
name: sort_order
schema:
default: desc
enum:
- asc
- desc
type: string
- description: Pagination offset (0-based)
in: query
name: offset
schema:
default: 0
minimum: 0
type: integer
- description: Maximum items per page (1-1000)
in: query
name: limit
schema:
default: 100
maximum: 1000
minimum: 1
type: integer
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/JobsListResponse'
description: Success - Jobs retrieved
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized - Authentication required
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: List jobs with pagination and filtering
tags:
- workflow
/api/jobs/{job_id}:
get:
description: |
Retrieve complete details for a specific job including workflow and outputs.
Used for detail views, workflow re-execution, and debugging.
operationId: getJobDetail
parameters:
- description: Job identifier (UUID)
in: path
name: job_id
required: true
schema:
format: uuid
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/JobDetailResponse'
description: Success - Job details retrieved
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized - Authentication required
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Forbidden - Job does not belong to user
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Job not found
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Get full job details
tags:
- workflow
/api/jobs/{job_id}/cancel:
post:
description: |
Cancel a specific job for the authenticated user.
Idempotent: a job that is already in a terminal state (completed, failed,
cancelled) or already cancelling is treated as a successful no-op and
returns 200. Only truly missing or cross-user jobs return 404.
operationId: cancelJob
parameters:
- description: Job identifier (UUID)
in: path
name: job_id
required: true
schema:
format: uuid
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/JobCancelResponse'
description: Success - Cancel request accepted (or job was already terminal)
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/BindingErrorResponse'
description: Bad Request - job_id is not a valid UUID (emitted by request validation before the handler runs)
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized - Authentication required
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Job not found for this user
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error - cancellation failed
summary: Cancel a job
tags:
- workflow
/api/node_replacements:
get:
description: |
Returns mappings of unsupported node class names to their cloud-installed replacements.
Used by the frontend to offer "Quick Fix" when a workflow contains missing nodes.
operationId: getNodeReplacements
responses:
"200":
content:
application/json:
schema:
additionalProperties: true
type: object
description: Success - Node replacement mappings
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security: []
summary: Get node replacement mappings
tags:
- node
/api/object_info:
get:
description: Returns information about all available nodes
operationId: getNodeInfo
responses:
"200":
content:
application/json:
schema:
additionalProperties:
$ref: '#/components/schemas/NodeInfo'
type: object
description: Success
summary: Get all node information
tags:
- node
/api/prompt:
get:
description: Returns information about the current prompt in the execution queue
operationId: getPromptInfo
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/PromptInfo'
description: Success
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Get information about current prompt execution
tags:
- workflow
post:
description: |
Submit a workflow to be executed by the backend.
The workflow is a JSON object describing the nodes and their connections.
operationId: executePrompt
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/PromptRequest'
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/PromptResponse'
description: Success - Prompt accepted
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/PromptErrorResponse'
description: Invalid prompt
"402":
content:
application/json:
schema:
$ref: '#/components/schemas/PromptErrorResponse'
description: Payment required - Insufficient credits
"429":
content:
application/json:
schema:
$ref: '#/components/schemas/PromptErrorResponse'
description: Payment required - User has not paid
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/PromptErrorResponse'
description: Internal server error
"503":
content:
application/json:
schema:
$ref: '#/components/schemas/PromptErrorResponse'
description: Service unavailable
summary: Submit a workflow for execution
tags:
- workflow
/api/queue:
get:
description: Returns information about running and pending items in the queue
operationId: getQueueInfo
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/QueueInfo'
description: Success
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Invalid request parameters
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Invalid request parameters
summary: Get queue information
tags:
- queue
post:
description: |
Cancel specific PENDING jobs by ID or clear all pending jobs in the queue.
Note: This endpoint only affects pending jobs. To cancel running jobs, use /api/interrupt.
operationId: manageQueue
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/QueueManageRequest'
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/QueueManageResponse'
description: Success
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Invalid request parameters
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Manage queue operations
tags:
- queue
/api/secrets:
get:
description: Returns all secrets for the authenticated user in the current workspace. Does not return plaintext secret values.
operationId: listSecrets
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/SecretListResponse'
description: Success
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
"503":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Service unavailable - feature is disabled
summary: List user secrets
tags:
- secrets
post:
description: Store an encrypted secret (e.g., HuggingFace or Civitai API key) for the authenticated user in the current workspace.
operationId: createSecret
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/CreateSecretRequest'
required: true
responses:
"201":
content:
application/json:
schema:
$ref: '#/components/schemas/SecretResponse'
description: Secret created successfully
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Invalid request
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"409":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Conflict - secret with this name or provider already exists
"422":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Validation error
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
"503":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Service unavailable - secrets feature disabled
summary: Create a new secret
tags:
- secrets
/api/secrets/{id}:
delete:
description: Remove a secret and its encrypted value from storage.
operationId: deleteSecret
parameters:
- description: The UUID of the secret
in: path
name: id
required: true
schema:
format: uuid
type: string
responses:
"204":
description: Secret deleted successfully
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Forbidden - user does not own this secret
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Secret not found
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
"503":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Service unavailable - secrets feature disabled
summary: Delete secret
tags:
- secrets
get:
description: Returns metadata for a specific secret. Does not return the plaintext secret value.
operationId: getSecret
parameters:
- description: The UUID of the secret
in: path
name: id
required: true
schema:
format: uuid
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/SecretResponse'
description: Success
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Forbidden - user does not own this secret
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Secret not found
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
"503":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Service unavailable - secrets feature disabled
summary: Get secret metadata
tags:
- secrets
patch:
description: Update an existing secret's name and/or value. Both fields are optional; only provided fields will be updated.
operationId: updateSecret
parameters:
- description: The UUID of the secret
in: path
name: id
required: true
schema:
format: uuid
type: string
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateSecretRequest'
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/SecretResponse'
description: Secret updated successfully
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Invalid request
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Forbidden - user does not own this secret
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Secret not found
"409":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Conflict - a secret with this name already exists
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
"503":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Service unavailable - secrets feature disabled
summary: Update secret
tags:
- secrets
/api/settings:
get:
description: Returns all settings for the authenticated user
operationId: getAllSettings
responses:
"200":
content:
application/json:
schema:
additionalProperties: true
description: User settings as key-value pairs
type: object
description: Success
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
summary: Get all user settings
tags:
- settings
post:
description: Update multiple settings (merge with existing)
operationId: updateMultipleSettings
requestBody:
content:
application/json:
schema:
additionalProperties: true
description: Settings to update as key-value pairs
type: object
text/plain:
schema:
description: JSON string of settings to update
type: string
required: true
responses:
"200":
content:
application/json:
schema:
additionalProperties: true
description: Updated user settings
type: object
description: Success
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Invalid request
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
summary: Update multiple settings
tags:
- settings
/api/settings/{id}:
get:
description: Returns a specific setting value by its id
operationId: getSettingById
parameters:
- description: Setting id to retrieve
in: path
name: id
required: true
schema:
type: string
responses:
"200":
content:
application/json:
schema:
description: Setting value response
properties:
value:
description: The setting value
type: object
description: Success
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Setting not found
summary: Get a specific setting by id
tags:
- settings
post:
description: Update a specific setting by its id
operationId: updateSettingById
parameters:
- description: Setting id to update
in: path
name: id
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
description: New value for the setting
text/plain:
schema:
description: JSON string of the new setting value
type: string
required: true
responses:
"200":
content:
application/json:
schema:
description: Updated setting value response
properties:
value:
description: The updated setting value
type: object
description: Success
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Invalid request
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
summary: Update a specific setting by id
tags:
- settings
/api/system_stats:
get:
description: Returns system statistics including ComfyUI version, device info, and system resources
operationId: getSystemStats
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/SystemStatsResponse'
description: Success
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
security: []
summary: Get system statistics
tags:
- system
/api/tags:
get:
description: |
Retrieves a list of all tags used across assets.
Includes usage counts and filtering options.
operationId: listTags
parameters:
- description: Filter tags by prefix
in: query
name: prefix
schema:
type: string
- description: Maximum number of tags to return (1-1000)
in: query
name: limit
schema:
default: 100
maximum: 1000
minimum: 1
type: integer
- description: Number of tags to skip for pagination
in: query
name: offset
schema:
default: 0
minimum: 0
type: integer
- description: Sort order for tags
in: query
name: order
schema:
default: count_desc
enum:
- count_desc
- name_asc
type: string
- description: Include tags with zero usage count
in: query
name: include_zero
schema:
default: false
type: boolean
- description: Whether to include public/shared assets when counting tags
in: query
name: include_public
schema:
default: true
type: boolean
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/ListTagsResponse'
description: Tags retrieved successfully
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Invalid request parameters
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: List all tags
tags:
- file
/api/tasks:
get:
description: |
Retrieve a paginated list of background tasks for the authenticated user.
Supports filtering by task type, status, and creation time.
operationId: listTasks
parameters:
- description: Filter by task type name (exact match)
example: model_upload
in: query
name: task_name
schema:
type: string
- description: Filter by idempotency key (exact match). For best performance, specify task_name as well.
example: upload-model-abc123
in: query
name: idempotency_key
schema:
type: string
- description: Filter by one or more statuses (comma-separated)
example: created,running
in: query
name: status
schema:
type: string
- description: Filter tasks created after this timestamp (RFC3339 format)
example: "2024-01-01T00:00:00Z"
in: query
name: created_after
schema:
format: date-time
type: string
- description: Filter tasks created before this timestamp (RFC3339 format)
example: "2024-12-31T23:59:59Z"
in: query
name: created_before
schema:
format: date-time
type: string
- description: Sort direction (asc = ascending, desc = descending by create_time)
in: query
name: sort_order
schema:
default: desc
enum:
- asc
- desc
type: string
- description: Pagination offset (0-based)
in: query
name: offset
schema:
default: 0
minimum: 0
type: integer
- description: Maximum items per page (1-100)
in: query
name: limit
schema:
default: 20
maximum: 100
minimum: 1
type: integer
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/TasksListResponse'
description: Success - Tasks retrieved
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized - Authentication required
"422":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Validation error - Invalid filter values
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: List background tasks
tags:
- task
/api/tasks/{task_id}:
get:
description: |
Retrieve full details for a specific background task.
operationId: getTask
parameters:
- description: Task identifier (UUID)
in: path
name: task_id
required: true
schema:
format: uuid
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/TaskResponse'
description: Success - Task details retrieved
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized - Authentication required
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Task not found (also returned for ownership failures to avoid leaking task existence)
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Get task details
tags:
- task
/api/upload/image:
post:
description: |
Upload an image file to cloud storage.
Image limits:
- Maximum file size: 50 MB
- Maximum width/height per edge: 16384 px
- Maximum total pixel count: 64 megapixels (67108864 pixels)
Uploads that exceed any of these limits are rejected with HTTP 400.
operationId: uploadImage
requestBody:
content:
multipart/form-data:
schema:
properties:
image:
description: The image file to upload
format: binary
type: string
overwrite:
description: Whether to overwrite existing file (true/false)
type: string
subfolder:
description: Optional subfolder path
type: string
type:
description: Upload type (defaults to "output")
type: string
required:
- image
type: object
required: true
responses:
"200":
content:
application/json:
schema:
properties:
name:
description: Filename of the uploaded image
type: string
subfolder:
description: Subfolder path where image was saved
type: string
type:
description: Type of upload (e.g., "output")
type: string
type: object
description: Image uploaded successfully
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Bad request
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Upload an image file
tags:
- file
/api/upload/mask:
post:
description: |
Upload a mask image to be applied to an existing image.
Image limits apply to both the uploaded mask and the referenced
original image:
- Maximum file size: 50 MB
- Maximum width/height per edge: 16384 px
- Maximum total pixel count: 64 megapixels (67108864 pixels)
Uploads that exceed any of these limits are rejected with HTTP 400.
operationId: uploadMask
requestBody:
content:
multipart/form-data:
schema:
properties:
image:
description: The mask image file to upload
format: binary
type: string
original_ref:
description: JSON string containing reference to the original image
type: string
required:
- image
- original_ref
type: object
required: true
responses:
"200":
content:
application/json:
schema:
properties:
name:
description: Filename of the uploaded mask
type: string
subfolder:
description: Subfolder path where mask was saved
type: string
type:
description: Type of upload (e.g., "output")
type: string
type: object
description: Mask uploaded successfully
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Bad request
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Upload a mask image
tags:
- file
/api/user:
get:
description: Returns information about the currently authenticated user
operationId: getUser
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/UserResponse'
description: Success
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
summary: Get current user information
tags:
- user
/api/userdata:
get:
description: Returns a list of user data files in the specified directory, optionally recursively and with full metadata.
operationId: getUserdata
parameters:
- description: The directory to list files from.
in: query
name: dir
schema:
type: string
- description: Whether to list files recursively.
in: query
name: recurse
schema:
default: false
type: boolean
- description: Whether to split file information by type.
in: query
name: split
schema:
default: false
type: boolean
- description: Whether to return full file metadata.
in: query
name: full_info
schema:
default: false
type: boolean
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/GetUserDataResponseFull'
description: A list of user data files.
"400":
content:
text/plain:
schema:
type: string
description: Bad request (e.g., invalid filename).
"401":
content:
text/plain:
schema:
type: string
description: Unauthorized.
"404":
content:
text/plain:
schema:
type: string
description: File not found or invalid path.
"500":
content:
text/plain:
schema:
type: string
description: General error
summary: List user data files
tags:
- user
/api/userdata/{file}:
delete:
description: |
Delete a user data file from the database. The file parameter should be
the relative path within the user's data directory.
operationId: deleteUserdataFile
parameters:
- description: The file path to delete (URL encoded if necessary).
in: path
name: file
required: true
schema:
type: string
responses:
"204":
description: File deleted successfully (No Content).
"401":
content:
text/plain:
schema:
type: string
description: Unauthorized.
"404":
content:
text/plain:
schema:
type: string
description: File not found.
"500":
content:
text/plain:
schema:
type: string
description: Internal server error.
summary: Delete a user data file
tags:
- user
get:
description: Returns the requested user data file if it exists.
operationId: getUserdataFile
parameters:
- description: The filename of the user data to retrieve.
in: path
name: file
required: true
schema:
type: string
responses:
"200":
content:
application/octet-stream:
schema:
format: binary
type: string
description: Successfully retrieved the file.
"400":
content:
text/plain:
schema:
type: string
description: Bad request (e.g., invalid filename).
"401":
content:
text/plain:
schema:
type: string
description: Unauthorized.
"404":
content:
text/plain:
schema:
type: string
description: File not found or invalid path.
"500":
content:
text/plain:
schema:
type: string
description: General error
summary: Get user data file
tags:
- user
post:
description: |
Upload a file to a user's data directory. Optional query parameters allow
control over overwrite behavior and response detail.
operationId: postUserdataFile
parameters:
- description: The target file path (URL encoded if necessary).
in: path
name: file
required: true
schema:
type: string
- description: If "false", prevents overwriting existing files. Defaults to "true".
in: query
name: overwrite
schema:
default: "true"
enum:
- "true"
- "false"
type: string
- description: If "true", returns detailed file info; if "false", returns only the relative path.
in: query
name: full_info
schema:
default: "false"
enum:
- "true"
- "false"
type: string
requestBody:
content:
application/octet-stream:
schema:
format: binary
type: string
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/UserDataResponseFull'
description: File uploaded successfully.
"400":
content:
text/plain:
schema:
type: string
description: Missing or invalid 'file' parameter.
"401":
content:
text/plain:
schema:
type: string
description: Unauthorized.
"403":
content:
text/plain:
schema:
type: string
description: The requested path is not allowed.
"409":
content:
text/plain:
schema:
type: string
description: File already exists and overwrite is set to false.
"500":
content:
text/plain:
schema:
type: string
description: General error
summary: Upload or update a user data file
tags:
- user
/api/userdata/{file}/move/{dest}:
post:
description: |
Move or rename a file within a user's data directory, with options for
controlling overwrite behavior and response format.
operationId: moveUserdataFile
parameters:
- description: The source file path (URL encoded if necessary).
in: path
name: file
required: true
schema:
type: string
- description: The destination file path (URL encoded if necessary).
in: path
name: dest
required: true
schema:
type: string
- description: If "false", prevents overwriting existing files. Defaults to "true".
in: query
name: overwrite
schema:
default: "true"
enum:
- "true"
- "false"
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/UserDataResponseFull'
description: File moved successfully.
"400":
content:
text/plain:
schema:
type: string
description: Missing or invalid parameters.
"401":
content:
text/plain:
schema:
type: string
description: Unauthorized.
"404":
content:
text/plain:
schema:
type: string
description: Source file not found.
"409":
content:
text/plain:
schema:
type: string
description: Destination file already exists and overwrite is set to false.
"500":
content:
text/plain:
schema:
type: string
description: General error
summary: Move or rename a user data file
tags:
- user
/api/userdata/{file}/publish:
get:
description: Returns the publish status and share info for a workflow identified by its userdata path.
operationId: getUserdataFilePublish
parameters:
- description: The workflow file path within the user's data directory (URL encoded if necessary).
in: path
name: file
required: true
schema:
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/WorkflowPublishInfo'
description: Publish info (publish_time is null if never published)
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Workflow not found
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Get publish info for a workflow file
tags:
- workflows
post:
description: Creates a new published_workflow record from the latest version and snapshots the provided assets.
operationId: postUserdataFilePublish
parameters:
- description: The workflow file path within the user's data directory (URL encoded if necessary).
in: path
name: file
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/PublishWorkflowAssetsRequest'
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/WorkflowPublishInfo'
description: Workflow published
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Bad request
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Workflow not found
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Publish a workflow file
tags:
- workflows
/api/users:
get:
description: |
ComfyUI legacy users endpoint. Returns information about how user
data is stored. In cloud this is always server-managed, so callers
receive a constant response indicating server-side storage.
operationId: getUsersInfo
responses:
"200":
content:
application/json:
schema:
properties:
migrated:
description: Whether user data has been migrated (always true in cloud)
type: boolean
storage:
description: Where user data is stored (always "server" in cloud)
type: string
required:
- storage
- migrated
type: object
description: Userdata storage information
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
summary: ComfyUI userdata storage info
tags:
- user
/api/vhs/queryvideo:
get:
description: |
VHS custom node endpoint that returns metadata about a video file
(frame count, fps, resolution, duration). Currently returns default
placeholder values; real ffprobe integration is a follow-up.
operationId: getVhsQueryVideo
parameters:
- description: Name of the video file to query
in: query
name: filename
required: true
schema:
type: string
responses:
"200":
content:
application/json:
schema:
properties:
source:
description: Source video metadata
properties:
duration:
description: Duration in seconds
type: number
fps:
description: Frames per second
type: number
frames:
description: Total frame count
type: integer
size:
description: '[width, height] in pixels'
items:
type: integer
maxItems: 2
minItems: 2
type: array
required:
- size
- fps
- frames
- duration
type: object
required:
- source
type: object
description: Video metadata
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/BindingErrorResponse'
description: |
Missing required query parameter. Produced by the oapi-codegen
wrapper via echo.NewHTTPError, so the body shape matches Echo's
default HTTPError serialization rather than ErrorResponse.
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
security:
- ApiKeyAuth: []
- BearerAuth: []
- CookieAuth: []
summary: Query VHS video metadata
tags:
- file
/api/view:
get:
description: |
Retrieve and view a file from the ComfyUI file system.
This endpoint is typically used to view generated images or other output files.
Cookie auth is allowed on this endpoint because it's used by img/video tags in browsers.
operationId: viewFile
parameters:
- description: Name of the file to view
in: query
name: filename
required: true
schema:
example: ComfyUI_00004_.png
type: string
- description: Subfolder path where the file is located
in: query
name: subfolder
schema:
example: tests/foo/bar
type: string
- description: Type of file (e.g., output, input, temp)
in: query
name: type
schema:
example: output
type: string
- description: Full path to the file (used for temp files)
in: query
name: fullpath
schema:
type: string
- description: Format of the file
in: query
name: format
schema:
type: string
- description: Frame rate for video files
in: query
name: frame_rate
schema:
type: integer
- description: Workflow identifier
in: query
name: workflow
schema:
type: string
- description: Timestamp parameter
in: query
name: timestamp
schema:
example: 1234567890
type: integer
- description: |
Image channel to extract from PNG images.
- 'rgb': Return only RGB channels (alpha set to fully opaque)
- 'a' or 'alpha': Return alpha channel as grayscale image
- If not specified, return original image unchanged via redirect
in: query
name: channel
schema:
example: rgb
type: string
- description: |
Maximum dimension (width or height) to resize the image to, preserving aspect ratio.
The image is fit within a res x res box. Returns a JPEG thumbnail.
Only applies to raster image files (PNG, JPEG, WebP, GIF).
in: query
name: res
schema:
example: 256
maximum: 1024
minimum: 64
type: integer
responses:
"200":
content:
image/jpeg:
schema:
description: Resized JPEG thumbnail (returned when res parameter is used)
format: binary
type: string
image/png:
schema:
description: Processed PNG image with extracted channel
format: binary
type: string
description: Success - File content returned (used when channel or res parameter is present)
"302":
description: Redirect to GCS signed URL
headers:
Cache-Control:
description: Cache directive for the redirect response
schema:
type: string
Location:
description: Signed URL to access the file in GCS
schema:
type: string
Vary:
description: Headers that affect response caching
schema:
type: string
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Invalid request parameters
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: File not found or unauthorized
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security:
- ApiKeyAuth: []
- BearerAuth: []
- CookieAuth: []
summary: View a file
tags:
- file
/api/workflow_templates:
get:
description: Returns available workflow templates
operationId: getWorkflowTemplates
responses:
"200":
content:
application/json:
schema:
description: Empty object for workflow templates
type: object
description: Success
security: []
summary: Get available workflow templates
tags:
- workflow
/api/workflows:
get:
description: Returns a paginated list of workflows for the authenticated user in the current workspace.
operationId: listWorkflows
parameters:
- in: query
name: limit
schema:
default: 20
maximum: 100
type: integer
- in: query
name: offset
schema:
default: 0
type: integer
- description: Search workflows by name (case-insensitive substring match)
in: query
name: name
schema:
type: string
- description: Filter by default view type
in: query
name: default_view
schema:
enum:
- workflow
- app
type: string
- description: Sort field
in: query
name: sort
schema:
default: create_time
enum:
- create_time
- update_time
- name
type: string
- description: Sort order
in: query
name: order
schema:
default: desc
enum:
- asc
- desc
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/WorkflowListResponse'
description: Success
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: List workflows
tags:
- workflows
post:
description: Creates a new workflow with its first version.
operationId: createWorkflow
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/CreateWorkflowRequest'
required: true
responses:
"201":
content:
application/json:
schema:
$ref: '#/components/schemas/WorkflowResponse'
description: Workflow created successfully
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"422":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Validation error
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Create a new workflow
tags:
- workflows
/api/workflows/{workflow_id}:
delete:
description: Soft-deletes a workflow.
operationId: deleteWorkflow
parameters:
- description: The UUID of the workflow to delete.
in: path
name: workflow_id
required: true
schema:
type: string
responses:
"204":
description: Workflow deleted successfully
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Workflow not found
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Delete workflow
tags:
- workflows
get:
description: Retrieves workflow metadata by ID.
operationId: getWorkflow
parameters:
- description: The UUID of the workflow.
in: path
name: workflow_id
required: true
schema:
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/WorkflowResponse'
description: Success
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Forbidden
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Workflow not found
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Get workflow
tags:
- workflows
patch:
description: Updates mutable workflow metadata (name, description, default_view).
operationId: updateWorkflow
parameters:
- description: The UUID of the workflow to update.
in: path
name: workflow_id
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateWorkflowRequest'
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/WorkflowResponse'
description: Success
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Workflow not found
"422":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Validation error
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Update workflow metadata
tags:
- workflows
/api/workflows/{workflow_id}/content:
get:
description: Retrieves the latest version of a workflow and its JSON content.
operationId: getWorkflowContent
parameters:
- description: The UUID of the workflow whose content should be retrieved.
in: path
name: workflow_id
required: true
schema:
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/WorkflowVersionContentResponse'
description: Success
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Forbidden
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Workflow not found
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Get workflow content
tags:
- workflows
/api/workflows/{workflow_id}/fork:
post:
description: Creates a new workflow by forking from an existing version.
operationId: forkWorkflow
parameters:
- description: The UUID of the source workflow to fork from.
in: path
name: workflow_id
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/ForkWorkflowRequest'
required: true
responses:
"201":
content:
application/json:
schema:
$ref: '#/components/schemas/WorkflowResponse'
description: Workflow forked successfully
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Forbidden
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Source workflow or version not found
"422":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Validation error
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Fork a workflow
tags:
- workflows
/api/workflows/{workflow_id}/versions:
post:
description: Creates a new workflow version with updated workflow JSON. Uses optimistic concurrency via base_version.
operationId: createWorkflowVersion
parameters:
- description: The UUID of the workflow to create a new version for.
in: path
name: workflow_id
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/CreateWorkflowVersionRequest'
required: true
responses:
"201":
content:
application/json:
schema:
$ref: '#/components/schemas/WorkflowVersionResponse'
description: Version created successfully
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Forbidden - not the workflow owner
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Workflow not found
"409":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Version conflict - base_version does not match latest
"422":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Validation error
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Create a new version
tags:
- workflows
/api/workflows/published/{share_id}:
get:
description: |
Returns the published workflow details including the status of each
published asset relative to the caller's library. Authentication is required.
operationId: getPublishedWorkflow
parameters:
- description: The share ID of the published workflow.
in: path
name: share_id
required: true
schema:
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/PublishedWorkflowDetail'
description: Published workflow details with asset statuses
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Share not found
"413":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Workflow JSON too large
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
summary: Get a published workflow by share ID
tags:
- workflows
/api/workspace/api-keys:
get:
description: |
Returns API keys for the workspace. Owners see all keys; members see only their own.
The workspace is determined from the authenticated user's token.
operationId: listWorkspaceAPIKeys
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/ListWorkspaceAPIKeysResponse'
description: List of API keys
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Forbidden
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security:
- BearerAuth: []
summary: List workspace API keys
tags:
- workspaces
post:
description: |
Creates a new workspace-scoped API key. The plaintext key is returned once
and cannot be retrieved again. Any workspace member can create keys.
The workspace is determined from the authenticated user's token.
operationId: createWorkspaceAPIKey
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/CreateWorkspaceAPIKeyRequest'
required: true
responses:
"201":
content:
application/json:
schema:
$ref: '#/components/schemas/CreateWorkspaceAPIKeyResponse'
description: API key created (plaintext returned once)
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Not a workspace member
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Workspace not found
"422":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Validation error
"429":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Key limit reached
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security:
- BearerAuth: []
summary: Create a workspace API key
tags:
- workspaces
/api/workspace/api-keys/{id}:
delete:
description: |
Revokes a workspace API key by ID. Owners can revoke any key;
members can only revoke their own keys.
operationId: revokeWorkspaceAPIKey
parameters:
- description: API key ID to revoke
in: path
name: id
required: true
schema:
format: uuid
type: string
responses:
"204":
description: API key revoked
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Not authorized to revoke this key
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: API key not found
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security:
- BearerAuth: []
summary: Revoke a workspace API key
tags:
- workspaces
/api/workspace/invites:
get:
description: |
Returns all pending invites for a workspace. Requires owner role.
The workspace is determined from the authenticated user's token.
operationId: listWorkspaceInvites
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/ListInvitesResponse'
description: List of pending invites
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Owner role required
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security:
- BearerAuth: []
summary: List pending invites
tags:
- workspaces
post:
description: |
Creates an invite for a new member. Requires owner role.
The workspace is determined from the authenticated user's token.
operationId: createWorkspaceInvite
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/CreateInviteRequest'
required: true
responses:
"201":
content:
application/json:
schema:
$ref: '#/components/schemas/PendingInvite'
description: Invite created
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Owner role required or personal workspace (invites not allowed)
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Workspace not found
"409":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Invite already exists
"422":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Validation error
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security:
- BearerAuth: []
summary: Create a workspace invite
tags:
- workspaces
/api/workspace/invites/{inviteId}:
delete:
description: |
Deletes a pending invite. Requires owner role.
The workspace is determined from the authenticated user's token.
operationId: revokeWorkspaceInvite
parameters:
- description: Invite ID to revoke
in: path
name: inviteId
required: true
schema:
type: string
responses:
"204":
description: Invite revoked
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Owner role required
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Workspace or invite not found
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security:
- BearerAuth: []
summary: Revoke a workspace invite
tags:
- workspaces
/api/workspace/leave:
post:
description: |
Removes the current user from the workspace. Cannot leave as the only owner.
The workspace is determined from the authenticated user's token.
operationId: leaveWorkspace
responses:
"204":
description: Successfully left workspace
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Cannot leave as the only owner or cannot leave personal workspace
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Workspace not found or not a member
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security:
- BearerAuth: []
summary: Leave a workspace
tags:
- workspaces
/api/workspace/members:
get:
description: |
Returns paginated list of workspace members. Requires membership.
The workspace is determined from the authenticated user's token.
operationId: listWorkspaceMembers
parameters:
- description: Pagination offset (0-based)
in: query
name: offset
schema:
default: 0
minimum: 0
type: integer
- description: Maximum number of members to return
in: query
name: limit
schema:
default: 20
maximum: 100
minimum: 1
type: integer
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/ListMembersResponse'
description: List of members
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Not a member of this workspace
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Workspace not found
"422":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Validation error
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security:
- BearerAuth: []
summary: List workspace members
tags:
- workspaces
/api/workspace/members/{user_id}/api-keys:
delete:
description: |
Revokes all active API keys for a specific member in the workspace.
Only workspace owners can perform this action. Useful for offboarding.
The workspace is determined from the authenticated user's token.
operationId: bulkRevokeWorkspaceMemberAPIKeys
parameters:
- description: Firebase UID of the member whose keys to revoke (must be non-empty)
in: path
name: user_id
required: true
schema:
minLength: 1
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/BulkRevokeAPIKeysResponse'
description: Keys revoked successfully
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Not authorized (must be workspace owner)
"422":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Validation error (e.g. empty user_id)
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security:
- BearerAuth: []
summary: Bulk revoke a member's API keys
tags:
- workspaces
/api/workspace/members/{userId}:
delete:
description: |
Removes a member from the workspace. Requires owner role.
The workspace is determined from the authenticated user's token.
operationId: removeWorkspaceMember
parameters:
- description: User ID to remove
in: path
name: userId
required: true
schema:
type: string
responses:
"204":
description: Member removed
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Owner role required or cannot remove yourself
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Workspace or member not found
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security:
- BearerAuth: []
summary: Remove a member from workspace
tags:
- workspaces
/api/workspaces:
get:
description: Returns all workspaces the authenticated user is a member of
operationId: listWorkspaces
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/ListWorkspacesResponse'
description: List of workspaces
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Feature not enabled for user
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security:
- BearerAuth: []
summary: List user's workspaces
tags:
- workspaces
post:
description: Creates a new team workspace with the authenticated user as owner
operationId: createWorkspace
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/CreateWorkspaceRequest'
required: true
responses:
"201":
content:
application/json:
schema:
$ref: '#/components/schemas/Workspace'
description: Workspace created
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Feature not enabled for user
"422":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Validation error
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security:
- BearerAuth: []
summary: Create a team workspace
tags:
- workspaces
/api/workspaces/{id}:
delete:
description: |
Soft deletes a workspace. Requires owner role.
Cannot delete personal workspaces.
operationId: deleteWorkspace
parameters:
- description: Workspace ID (w-{uuid} format)
in: path
name: id
required: true
schema:
type: string
responses:
"204":
description: Workspace deleted
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Owner role required or cannot delete personal workspace
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Workspace not found
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security:
- BearerAuth: []
summary: Delete workspace
tags:
- workspaces
get:
description: Returns details of a specific workspace
operationId: getWorkspace
parameters:
- description: Workspace ID (w-{uuid} format)
in: path
name: id
required: true
schema:
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/Workspace'
description: Workspace details
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Workspace not found or user not a member
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security:
- BearerAuth: []
summary: Get workspace details
tags:
- workspaces
patch:
description: Updates workspace properties. Requires owner role.
operationId: updateWorkspace
parameters:
- description: Workspace ID (w-{uuid} format)
in: path
name: id
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateWorkspaceRequest'
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/Workspace'
description: Workspace updated
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Unauthorized
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Owner role required
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Workspace not found
"422":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Validation error
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Internal server error
security:
- BearerAuth: []
summary: Update workspace
tags:
- workspaces
/health:
get:
description: |
Returns `200 OK` if the database is reachable and dynamic config has
loaded, otherwise `503 Service Unavailable`. Used by the GKE ingress
for health checks. Response body is plain text for probe simplicity.
operationId: getHealth
responses:
"200":
content:
text/plain:
schema:
example: OK
type: string
description: Service is healthy
"503":
content:
text/plain:
schema:
example: Service Unavailable
type: string
description: Service is unhealthy
security: []
summary: Health probe for Kubernetes readiness/liveness
tags:
- system
/internal/folder_paths:
get:
description: '[local-only] Returns the filesystem paths ComfyUI loads models and assets from, keyed by folder type. Local ComfyUI only; cloud pods have ephemeral storage.'
operationId: getInternalFolderPaths
responses:
"200":
content:
application/json:
schema:
additionalProperties:
items:
items:
type: string
type: array
type: array
description: Map of folder type name to list of path entries
type: object
description: Dictionary of folder type to paths
summary: Get configured folder paths
x-runtime:
- local
/internal/logs:
get:
description: '[local-only] Returns ComfyUI log entries from the in-memory log buffer. Local ComfyUI only; cloud logs flow to Datadog.'
operationId: getInternalLogs
responses:
"200":
content:
text/plain:
schema:
type: string
description: Log text
summary: Get server logs as text
x-runtime:
- local
/internal/logs/raw:
get:
description: '[local-only] Returns the raw ComfyUI log buffer plus size metadata. Local ComfyUI only; cloud logs flow to Datadog.'
operationId: getInternalLogsRaw
responses:
"200":
content:
application/json:
schema:
properties:
entries:
items:
properties:
m:
description: Message
type: string
t:
description: Timestamp
type: number
type: object
type: array
size:
properties:
cols:
type: integer
rows:
type: integer
type: object
type: object
description: Structured log data
summary: Get raw structured log entries
x-runtime:
- local
/internal/logs/subscribe:
patch:
description: '[local-only] Subscribes or unsubscribes the current client from live log streaming over the WebSocket. Local ComfyUI only.'
operationId: subscribeToLogs
requestBody:
content:
application/json:
schema:
properties:
clientId:
description: WebSocket client ID
type: string
enabled:
description: Enable or disable log streaming for this client
type: boolean
required:
- clientId
- enabled
type: object
required: true
responses:
"200":
description: Subscription updated
summary: Subscribe or unsubscribe a WebSocket client to log streaming
x-runtime:
- local
/oauth/authorize:
get:
description: |
Two modes:
- **Initial entry** (OAuth params present): validates client/redirect/resource/scopes, persists a server-side `oauth_authorization_requests` row, and either redirects (no session / unverified email) to the configured frontend login URL carrying only the opaque `oauth_request_id`, or returns the JSON consent challenge for the frontend to render.
- **Resume** (`oauth_request_id` present): loads the server-side row, fails closed if expired/consumed/unknown, returns the JSON consent challenge. Browser-replayed OAuth params are intentionally ignored.
The frontend (BE-638) renders the consent UI from the JSON payload and POSTs the user's decision back to this endpoint.
operationId: getOAuthAuthorize
parameters:
- in: query
name: response_type
schema:
type: string
- in: query
name: client_id
schema:
type: string
- in: query
name: redirect_uri
schema:
type: string
- in: query
name: scope
schema:
type: string
- description: |
RFC 6749 §10.12 marks `state` as RECOMMENDED. Our hardening makes
it REQUIRED on the initial-entry path (omitted only on the resume
path where `oauth_request_id` is supplied instead). This parameter
is `required: false` at the spec level only because the operation
is dual-mode (initial entry vs. resume); the runtime parser
(services/ingest/server/implementation/oauth/protocol/request.go)
rejects empty `state` on the initial-entry path with a stable
`invalid_request` 400.
in: query
name: state
schema:
type: string
- in: query
name: code_challenge
schema:
type: string
- in: query
name: code_challenge_method
schema:
type: string
- in: query
name: resource
schema:
type: string
- in: query
name: oauth_request_id
schema:
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthConsentChallenge'
description: |
Consent challenge payload (cookie present, email verified). Frontend renders the consent UI from this payload and POSTs back to /oauth/authorize.
"302":
description: Redirect to login (no session / unverified email) or to registered redirect_uri (pre-validated client error)
headers:
Location:
schema:
type: string
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Invalid authorize request (pre-redirect failure — unknown client, redirect mismatch, malformed params)
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: OAuth disabled
security: []
summary: Begin or resume an OAuth 2.1 authorization request
tags:
- oauth
post:
description: |
JSON-only consent submission. The handler verifies the per-row CSRF token, atomically marks the authorization request consumed (single-use covers both allow and deny paths), then returns the redirect URL the browser must navigate to. The URL contains either `code` + original `state` for allow, or the RFC 6749 §5.2 error and `state` for deny.
Workspace membership is re-checked at submission time. Consent is persisted keyed by `(comfy_user_id, client_id, resource_id, workspace_id)`; broadening the previously approved scope set requires a fresh consent flow.
operationId: postOAuthAuthorize
requestBody:
content:
application/json:
schema:
properties:
csrf_token:
type: string
decision:
enum:
- allow
- deny
type: string
oauth_request_id:
format: uuid
type: string
workspace_id:
type: string
required:
- oauth_request_id
- csrf_token
- decision
- workspace_id
type: object
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthAuthorizeRedirectResponse'
description: Redirect URL for the frontend to navigate to (allow → with code+state; deny → with error+state)
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Bad request (CSRF mismatch, expired/consumed request, inaccessible workspace)
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: Scope broadening on consent re-grant — fresh consent flow required
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: OAuth disabled
security: []
summary: Submit OAuth consent decision
tags:
- oauth
/oauth/register:
post:
description: |
Public, unauthenticated, insert-only RFC 7591 §3.1 client registration. Used by MCP-spec-compliant clients (Claude Desktop, Claude Code, Cursor, Windsurf) to self-register a public OAuth client without ops involvement.
Policy:
- Public clients only — `token_endpoint_auth_method` is forced to `none`. Confidential-client registration is out of scope this phase.
- Server-owned `resource_grants`. Caller-supplied `scope` or `resource_grants` is rejected as `invalid_client_metadata` (would be a privilege-escalation surface). Dynamic clients receive the same scopes the active MCP resource publishes.
- Application-type-aware redirect URI policy. `application_type=native` accepts loopback (`127.0.0.1`, `::1`, `localhost`) and reverse-DNS-shaped custom schemes; `application_type=web` accepts HTTPS to hosts in `OAUTH_DCR_HTTPS_HOSTS` only. `application_type` is OPTIONAL on the request — omit it to default to `native` (the MCP SDK omits it); a present value must be `native` or `web`, and any other value rejects with `invalid_client_metadata`.
- Anti-impersonation: reserved client names (Claude/Cursor/etc.) are rejected from third parties via NFKC-folded compare.
- Generated `client_id` carries the `comfy-dyn-` prefix to distinguish dynamic from seeded clients in audit logs.
- Cache-Control: `no-store` on every 201 and 400 response (the response carries fresh credentials and rejection reasons).
operationId: postOAuthRegister
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthRegisterRequest'
required: true
responses:
"201":
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthRegisterResponse'
description: Registered. Body echoes the metadata RFC 7591 §3.2.1 requires.
headers:
Cache-Control:
description: Always "no-store" per RFC 6749 §5.1 instinct (response carries fresh client_id)
schema:
type: string
Pragma:
description: Always "no-cache"
schema:
type: string
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthRegisterBadRequestResponse'
description: |
Bad request. Two shapes possible: `OAuthRegisterError` (RFC 7591 §3.2.2, emitted by the handler for invalid client metadata, missing application_type, reserved client_name, etc.) OR `BindingErrorResponse` (emitted by the strict-server binding layer when the request body fails OpenAPI-schema validation — malformed JSON, missing required fields, `additionalProperties: false` violations).
headers:
Cache-Control:
description: Always "no-store"
schema:
type: string
Pragma:
description: Always "no-cache"
schema:
type: string
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: OAuth disabled
"503":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: No active MCP resource is configured — DCR cannot mint a usable client until ops seeds an active oauth_resources row.
security: []
summary: Dynamic Client Registration (RFC 7591)
tags:
- oauth
/oauth/token:
post:
description: |
OAuth 2.1 token endpoint (RFC 6749 §3.2). Public clients only — `client_secret` is rejected.
Two grant types are supported:
- `authorization_code` — exchanges the code minted by `/oauth/authorize` (with PKCE verifier) for an access token + first refresh token. Single-use; reuse fails closed.
- `refresh_token` — rotates the refresh token. Old token immediately invalid; presenting an already-rotated token revokes the entire token family and emits a security metric.
Both grant types re-validate canonical user state, current workspace membership, and the resource's `active` flag at every mint. A code or refresh token bound to a deactivated resource fails closed.
Errors follow RFC 6749 §5.2. Logs never contain raw codes, refresh tokens, or minted JWTs.
Per RFC 6749 §5.1, every 200 and 400 response carries `Cache-Control: no-store` and `Pragma: no-cache` so intermediaries cannot cache token-bearing or state-change-reason responses.
operationId: postOAuthToken
requestBody:
content:
application/x-www-form-urlencoded:
schema:
properties:
client_id:
type: string
client_secret:
type: string
code:
type: string
code_verifier:
type: string
grant_type:
enum:
- authorization_code
- refresh_token
type: string
redirect_uri:
type: string
refresh_token:
type: string
scope:
type: string
required:
- grant_type
- client_id
type: object
required: true
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthTokenResponse'
description: New token pair
headers:
Cache-Control:
description: Always "no-store" per RFC 6749 §5.1
schema:
type: string
Pragma:
description: Always "no-cache" per RFC 6749 §5.1
schema:
type: string
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthTokenError'
description: RFC 6749 §5.2 error
headers:
Cache-Control:
description: Always "no-store" per RFC 6749 §5.1
schema:
type: string
Pragma:
description: Always "no-cache" per RFC 6749 §5.1
schema:
type: string
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: OAuth disabled
security: []
summary: Exchange authorization code or refresh token for a resource-bound Cloud JWT
tags:
- oauth
security:
- ApiKeyAuth: []
- BearerAuth: []
servers:
- description: Default ComfyUI server
url: /
tags:
- description: Workflow execution and management
name: workflow
- description: Node information
name: node
- description: File operations
name: file
- description: User secret management (API keys, tokens)
name: secrets
- description: User settings management
name: settings
- description: User feedback management
name: feedback
- description: System operations and monitoring
name: system
- description: Administrative operations
name: admin
- description: Authentication and session management
name: auth
- description: User information and management
name: user
- description: Background task management
name: task
- description: Workspace management
name: workspaces
- description: ComfyHub - workflow publishing and profile management
name: hub
- description: Workspace billing and subscription management
name: billing
- description: Workflow storage and version management
name: workflows
- description: Job queue state and control
name: queue
- description: Job lifecycle queries
name: job
- description: Workflow template assets proxied from versioned GCS storage
name: templates
- description: OAuth 2.1 authorization-server endpoints for public PKCE clients
name: oauth
- description: |
Routes served by raw Echo handlers that bypass the generated
ServerInterface. Documented here purely as a URL inventory for
drift detection (BE-123); excluded from Go codegen. See the comment
above this tag declaration for per-route migration status.
name: runtime-only
- description: |
Routes served ONLY by local ComfyUI (x-runtime: [local]); the cloud
runtime does not route them — single-user / local-filesystem / dev-mode
concerns with no cloud analogue. Documented here so this spec is the
complete cross-runtime contract: the cloud→core projection (BE-1157)
includes them and core stays a subset of this spec (BE-752 / BE-1155).
Excluded from Go codegen and exempt from the route-drift "documented ⟹
registered in server.go" check — they are contract documentation, not
cloud routes. Distinct from `runtime-only` (which cloud DOES serve via
raw Echo and must register).
name: local-only