mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-10-24 02:49:04 +03:00
9446 lines
426 KiB
YAML
9446 lines
426 KiB
YAML
components:
|
||
responses:
|
||
SessionForbidden:
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ForbiddenError'
|
||
description: A refused request. For a web session, `code` is `workspace_access_denied` (the selected workspace is unknown, deleted, or the user is not a member; the three look the same), `no_workspace_access` (the account has no personal workspace and is a member of no live workspace), `origin_not_allowed` or `cross_site_request`; see the `WebSessionAuth` scheme. For any credential, `sso_required` means an SSO organization holds the account (its email is on the organization's verified domains) and the credential is not an SSO sign-in, or the workspace is an SSO organization's and the account is not on its domains or the credential is not an SSO sign-in; `organization_id`, when present, names the organization to sign in with. `account_outside_organization` means the workspace is an SSO organization's and the account is on none of its domains, so no sign-in admits it; `organization_id` names the workspace's organization. `FORBIDDEN` is the route's own authorization check failing, such as an unverified email. On `GET /api/billing/churnkey/auth`, `NOT_ORIGINAL_OWNER` means the caller is not the workspace's creator; it is returned only when the rollout mode is `creator`. A credential this route does not take gets AuthTypeNotAllowedError instead, and so does the session while `web_session_enabled` is off for the user, unless the operation says it takes the session whatever `web_session_enabled` says.
|
||
SessionUnauthorized:
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: No valid credential, or an `Authorization` header, `X-API-Key` header or `?token=` next to the session cookie that could not be read, which is refused rather than answered with the session. `code` is `UNAUTHORIZED`.
|
||
SessionWorkspaceAccessDenied:
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: '`code` is `workspace_access_denied`: the selected workspace is unknown, deleted, or the user is not a member; the three look the same. This route also serves anonymous callers, so the session''s other refusals fall back to an anonymous request. See the `WebSessionAuth` scheme.'
|
||
SessionWorkspaceIDInvalid:
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: '`code` is `workspace_id_invalid`: the `X-Comfy-Workspace-ID` header or `workspace_id` query value is malformed, or conflicts with another value or with the workspace the credential resolves to. Answered only while `web_session_enabled` is on for the user. See the `WebSessionAuth` scheme.'
|
||
SessionWriteForbidden:
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ForbiddenError'
|
||
description: A refused request that changes data. For a web session, `code` is `csrf_invalid` (no `X-CSRF-Token`, or not the session's), `workspace_access_denied` (the selected workspace is unknown, deleted, or the user is not a member; the three look the same), `no_workspace_access` (the account has no personal workspace and is a member of no live workspace), `origin_not_allowed` or `cross_site_request`; see the `WebSessionAuth` scheme. For any credential, `sso_required` means an SSO organization holds the account (its email is on the organization's verified domains) and the credential is not an SSO sign-in, or the workspace is an SSO organization's and the account is not on its domains or the credential is not an SSO sign-in; `organization_id`, when present, names the organization to sign in with. `account_outside_organization` means the workspace is an SSO organization's and the account is on none of its domains, so no sign-in admits it; `organization_id` names the workspace's organization. `FORBIDDEN` is the route's own authorization check failing, such as an unverified email, or, on `POST /api/workspaces`, an account an SSO organization holds (its organization manages its workspaces; signing in again does not change it). On the plan-lifecycle writes (`POST /api/billing/subscribe`, `POST /api/billing/subscription/cancel`, `POST /api/billing/subscription/resubscribe`, `POST /api/billing/subscription/revert-scheduled-change`, `POST /api/billing/ops/{id}/cancel` and the `/api/billing/retention/*` routes), `NOT_ORIGINAL_OWNER` means the caller is an owner but not the workspace's creator, and only the creator may change the plan; it is returned only when the rollout mode is `creator`. A credential this route does not take gets AuthTypeNotAllowedError instead, and so does the session while `web_session_enabled` is off for the user, unless the operation says it takes the session whatever the flag.
|
||
schemas:
|
||
Asset:
|
||
description: Represents a user-owned asset (image, video, or other generated output).
|
||
properties:
|
||
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
|
||
file_path:
|
||
description: Relative path in global-namespace-root form (e.g. "models/checkpoints/flux.safetensors")
|
||
nullable: true
|
||
type: string
|
||
hash:
|
||
description: Blake3 hash of the asset content.
|
||
pattern: ^blake3:[a-f0-9]{64}$
|
||
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
|
||
loader_path:
|
||
description: The bare value a loader widget consumes for this asset. For models it is the path inside the category folder (e.g. "flux.safetensors" for "models/checkpoints/flux.safetensors"), which is what the model resolver matches. For input/output/temp it is the content hash, because those assets are fetched by hash rather than staged by name — that is the value LoadImage-style widgets must carry. Clients add the "[output]"/"[temp]" annotation from the asset's own type, so it is never included here. Null when no such value can be derived.
|
||
nullable: true
|
||
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
|
||
short_url:
|
||
description: Durable, owner-gated short link to this asset's content (relative `/api/s/{id}` path). Stable across the underlying signed URL's expiry — resolving it re-mints a fresh signed URL on every request — so it is safe to persist or share into chat, unlike `preview_url`. Only the minting user can resolve it. Omitted when the short-link surface is disabled or the asset has no resolvable content hash.
|
||
nullable: true
|
||
type: string
|
||
x-runtime:
|
||
- cloud
|
||
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
|
||
- 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.
|
||
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
|
||
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:
|
||
display_name:
|
||
description: Display name of the asset. Mirrors name for backwards compatibility.
|
||
nullable: true
|
||
type: string
|
||
file_path:
|
||
description: Relative path in global-namespace-root form (e.g. "models/checkpoints/flux.safetensors")
|
||
nullable: true
|
||
type: string
|
||
hash:
|
||
description: Blake3 hash of the asset content.
|
||
pattern: ^blake3:[a-f0-9]{64}$
|
||
type: string
|
||
id:
|
||
description: Asset ID
|
||
format: uuid
|
||
type: string
|
||
job_id:
|
||
description: ID of the job that created this asset, if available
|
||
format: uuid
|
||
nullable: true
|
||
type: string
|
||
loader_path:
|
||
description: The bare value a loader widget consumes for this asset. For models it is the path inside the category folder (e.g. "flux.safetensors" for "models/checkpoints/flux.safetensors"), which is what the model resolver matches. For input/output/temp it is the content hash, because those assets are fetched by hash rather than staged by name — that is the value LoadImage-style widgets must carry. Clients add the "[output]"/"[temp]" annotation from the asset's own type, so it is never included here. Null when no such value can be derived.
|
||
nullable: true
|
||
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
|
||
AuthTypeNotAllowedError:
|
||
description: 403 for a credential the route does not take. `accepted` names the ones it does, as `WWW-Authenticate` does.
|
||
properties:
|
||
accepted:
|
||
items:
|
||
type: string
|
||
type: array
|
||
error:
|
||
properties:
|
||
message:
|
||
type: string
|
||
type:
|
||
enum:
|
||
- auth_type_not_allowed
|
||
type: string
|
||
required:
|
||
- message
|
||
- type
|
||
type: object
|
||
required:
|
||
- error
|
||
- accepted
|
||
type: object
|
||
CCCAuthoringContext:
|
||
additionalProperties: false
|
||
properties:
|
||
actor_uid:
|
||
minLength: 1
|
||
type: string
|
||
can_apply:
|
||
type: boolean
|
||
can_edit:
|
||
type: boolean
|
||
owner_uid:
|
||
minLength: 1
|
||
type: string
|
||
state:
|
||
$ref: '#/components/schemas/CCCCatalogState'
|
||
required:
|
||
- actor_uid
|
||
- owner_uid
|
||
- can_edit
|
||
- can_apply
|
||
- state
|
||
type: object
|
||
CCCCatalogState:
|
||
additionalProperties: false
|
||
properties:
|
||
draft_generation:
|
||
format: int64
|
||
minimum: 0
|
||
type: integer
|
||
draft_rev:
|
||
format: int64
|
||
minimum: 1
|
||
type: integer
|
||
live_rev:
|
||
format: int64
|
||
minimum: 1
|
||
type: integer
|
||
next_rev:
|
||
format: int64
|
||
minimum: 1
|
||
type: integer
|
||
previous_live_rev:
|
||
format: int64
|
||
minimum: 1
|
||
nullable: true
|
||
type: integer
|
||
required:
|
||
- live_rev
|
||
- draft_rev
|
||
- previous_live_rev
|
||
- draft_generation
|
||
- next_rev
|
||
type: object
|
||
CCCCheckedReviewReceipt:
|
||
additionalProperties: false
|
||
properties:
|
||
publish_enabled:
|
||
type: boolean
|
||
receipt_version:
|
||
enum:
|
||
- 1
|
||
type: integer
|
||
selected_count:
|
||
maximum: 5000
|
||
minimum: 1
|
||
type: integer
|
||
selected_versions_digest:
|
||
pattern: ^[0-9a-f]{64}$
|
||
type: string
|
||
selection_digest:
|
||
pattern: ^[0-9a-f]{64}$
|
||
type: string
|
||
state:
|
||
$ref: '#/components/schemas/CCCCatalogState'
|
||
unchecked_count:
|
||
maximum: 5000
|
||
minimum: 0
|
||
type: integer
|
||
required:
|
||
- receipt_version
|
||
- state
|
||
- selected_count
|
||
- unchecked_count
|
||
- selected_versions_digest
|
||
- selection_digest
|
||
- publish_enabled
|
||
type: object
|
||
CCCCreatorLink:
|
||
additionalProperties: false
|
||
properties:
|
||
label:
|
||
type: string
|
||
url:
|
||
description: An https URL
|
||
format: uri
|
||
type: string
|
||
required:
|
||
- label
|
||
- url
|
||
type: object
|
||
CCCCreatorProfile:
|
||
additionalProperties: false
|
||
properties:
|
||
avatar_url:
|
||
description: Empty when the creator has no safe https avatar
|
||
type: string
|
||
bio:
|
||
maxLength: 5000
|
||
type: string
|
||
display_name:
|
||
type: string
|
||
links:
|
||
items:
|
||
$ref: '#/components/schemas/CCCCreatorLink'
|
||
maxItems: 8
|
||
type: array
|
||
username:
|
||
type: string
|
||
required:
|
||
- username
|
||
- display_name
|
||
- bio
|
||
- avatar_url
|
||
- links
|
||
type: object
|
||
CCCCreatorSummary:
|
||
additionalProperties: false
|
||
properties:
|
||
avatar_url:
|
||
type: string
|
||
display_name:
|
||
type: string
|
||
username:
|
||
type: string
|
||
workflow_count:
|
||
minimum: 1
|
||
type: integer
|
||
required:
|
||
- username
|
||
- display_name
|
||
- avatar_url
|
||
- workflow_count
|
||
type: object
|
||
CCCCreatorsPage:
|
||
additionalProperties: false
|
||
properties:
|
||
items:
|
||
items:
|
||
$ref: '#/components/schemas/CCCCreatorSummary'
|
||
maxItems: 100
|
||
type: array
|
||
next_cursor:
|
||
maxLength: 200
|
||
type: string
|
||
required:
|
||
- items
|
||
type: object
|
||
CCCJSON:
|
||
additionalProperties: true
|
||
description: Flat type-versioned CCC JSON. Domain schemas (/api/v1/catalog/schemas/{type}/{version}) constrain authored fields. The readOnly properties are server metadata returned by reads; a save may send them back unchanged and they are ignored, never applied. expected_draft_rev and expected_revision_uid are the save concurrency tokens.
|
||
properties:
|
||
catalog_rev:
|
||
description: Catalog revision of this edit; may be older than the working Draft.
|
||
format: int64
|
||
readOnly: true
|
||
type: integer
|
||
creator_uid:
|
||
description: Immutable account that created the resource.
|
||
readOnly: true
|
||
type: string
|
||
digest:
|
||
description: SHA-256 of the canonical authored document.
|
||
readOnly: true
|
||
type: string
|
||
draft_generation:
|
||
format: int64
|
||
readOnly: true
|
||
type: integer
|
||
edit_sequence:
|
||
format: int64
|
||
readOnly: true
|
||
type: integer
|
||
is_deleted:
|
||
description: Tombstone flag. false may be sent back; true is refused (use restore).
|
||
readOnly: true
|
||
type: boolean
|
||
owner_uid:
|
||
description: Fixed organization owner; never transferred by a save.
|
||
readOnly: true
|
||
type: string
|
||
revision_uid:
|
||
description: This immutable edit; send it back as expected_revision_uid.
|
||
format: uuid
|
||
readOnly: true
|
||
type: string
|
||
saved_at:
|
||
description: RFC3339 UTC save time of this exact edit.
|
||
format: date-time
|
||
readOnly: true
|
||
type: string
|
||
saved_by_uid:
|
||
description: Account that saved this edit.
|
||
readOnly: true
|
||
type: string
|
||
uid:
|
||
description: Server-assigned logical resource UID.
|
||
format: uuid
|
||
readOnly: true
|
||
type: string
|
||
type: object
|
||
x-go-type: map[string]interface{}
|
||
CCCLegacyTarget:
|
||
description: Current Hub page that replaces an old public URL
|
||
properties:
|
||
path:
|
||
description: Website path of the Hub page, for example /hub/workflows/<slug>/
|
||
type: string
|
||
slug:
|
||
description: Current slug of the record
|
||
type: string
|
||
type:
|
||
enum:
|
||
- workflow
|
||
- app
|
||
- model
|
||
type: string
|
||
required:
|
||
- type
|
||
- slug
|
||
- path
|
||
type: object
|
||
CCCPublicItemsPage:
|
||
allOf:
|
||
- $ref: '#/components/schemas/ContentCatalogProjection'
|
||
- properties:
|
||
has_more:
|
||
type: boolean
|
||
next_cursor:
|
||
description: Opaque continuation bound to this query and publication identity; omitted on the last page.
|
||
type: string
|
||
page_size:
|
||
maximum: 100
|
||
minimum: 1
|
||
type: integer
|
||
required:
|
||
- page_size
|
||
- has_more
|
||
type: object
|
||
CCCWebsiteCardFacet:
|
||
additionalProperties: false
|
||
properties:
|
||
count:
|
||
description: Staff-only eligible facet count
|
||
minimum: 0
|
||
type: integer
|
||
label:
|
||
type: string
|
||
value:
|
||
type: string
|
||
required:
|
||
- value
|
||
- label
|
||
type: object
|
||
CCCWebsiteCardFacets:
|
||
additionalProperties: false
|
||
properties:
|
||
categories:
|
||
items:
|
||
$ref: '#/components/schemas/CCCWebsiteCardFacet'
|
||
maxItems: 100
|
||
type: array
|
||
models:
|
||
items:
|
||
$ref: '#/components/schemas/CCCWebsiteCardFacet'
|
||
maxItems: 100
|
||
type: array
|
||
use_cases:
|
||
items:
|
||
$ref: '#/components/schemas/CCCWebsiteCardFacet'
|
||
maxItems: 100
|
||
type: array
|
||
required:
|
||
- categories
|
||
- models
|
||
- use_cases
|
||
type: object
|
||
CCCWebsiteCardsPage:
|
||
additionalProperties: false
|
||
properties:
|
||
available_kinds:
|
||
items:
|
||
enum:
|
||
- MODEL
|
||
- WORKFLOW
|
||
- APP
|
||
type: string
|
||
maxItems: 3
|
||
type: array
|
||
facets:
|
||
$ref: '#/components/schemas/CCCWebsiteCardFacets'
|
||
generation:
|
||
description: Staff-only Draft generation
|
||
format: int64
|
||
type: integer
|
||
has_more:
|
||
type: boolean
|
||
items:
|
||
items:
|
||
$ref: '#/components/schemas/ContentCatalogRecord'
|
||
maxItems: 24
|
||
type: array
|
||
next_cursor:
|
||
maxLength: 4096
|
||
type: string
|
||
page_size:
|
||
maximum: 24
|
||
minimum: 1
|
||
type: integer
|
||
previous_cursor:
|
||
maxLength: 4096
|
||
type: string
|
||
revision_id:
|
||
format: int64
|
||
type: integer
|
||
sort_orders:
|
||
items:
|
||
enum:
|
||
- popular
|
||
- name
|
||
- priceAsc
|
||
- priceDesc
|
||
type: string
|
||
maxItems: 4
|
||
type: array
|
||
total:
|
||
description: Staff-only filtered count; omitted for anonymous callers
|
||
minimum: 0
|
||
type: integer
|
||
required:
|
||
- revision_id
|
||
- items
|
||
- page_size
|
||
- has_more
|
||
- facets
|
||
- available_kinds
|
||
- sort_orders
|
||
type: object
|
||
CCCWebsiteModelDirectory:
|
||
additionalProperties: false
|
||
properties:
|
||
generation:
|
||
description: Staff-only Draft generation
|
||
format: int64
|
||
type: integer
|
||
items:
|
||
items:
|
||
additionalProperties: false
|
||
properties:
|
||
provider:
|
||
description: Authored provider label; empty when not set
|
||
type: string
|
||
slug:
|
||
description: Canonical /hub/models path without a trailing slash
|
||
type: string
|
||
title:
|
||
description: Localized title when reviewed, otherwise source title
|
||
type: string
|
||
uid:
|
||
format: uuid
|
||
type: string
|
||
required:
|
||
- uid
|
||
- slug
|
||
- title
|
||
- provider
|
||
type: object
|
||
maxItems: 5000
|
||
type: array
|
||
revision_id:
|
||
format: int64
|
||
type: integer
|
||
required:
|
||
- revision_id
|
||
- items
|
||
type: object
|
||
CCCWebsiteRootPageInfo:
|
||
additionalProperties: false
|
||
properties:
|
||
has_more:
|
||
type: boolean
|
||
page_size:
|
||
enum:
|
||
- 24
|
||
type: integer
|
||
required:
|
||
- page_size
|
||
- has_more
|
||
type: object
|
||
CCCWebsiteRootPresentation:
|
||
additionalProperties: false
|
||
properties:
|
||
as_of:
|
||
description: Database observation clock for this complete presentation.
|
||
format: date-time
|
||
type: string
|
||
items:
|
||
items:
|
||
$ref: '#/components/schemas/ContentCatalogRecord'
|
||
maxItems: 5000
|
||
type: array
|
||
model_directory:
|
||
$ref: '#/components/schemas/CCCWebsiteModelDirectory'
|
||
next_visibility_at:
|
||
description: Never reuse the artifact at or after this scheduled visibility boundary. Null means no pending boundary.
|
||
format: date-time
|
||
nullable: true
|
||
type: string
|
||
revision_id:
|
||
format: int64
|
||
type: integer
|
||
tabs:
|
||
$ref: '#/components/schemas/CCCWebsiteRootTabs'
|
||
required:
|
||
- revision_id
|
||
- as_of
|
||
- next_visibility_at
|
||
- items
|
||
- model_directory
|
||
- tabs
|
||
type: object
|
||
CCCWebsiteRootTab:
|
||
additionalProperties: false
|
||
properties:
|
||
facets:
|
||
$ref: '#/components/schemas/CCCWebsiteCardFacets'
|
||
page:
|
||
$ref: '#/components/schemas/CCCWebsiteRootPageInfo'
|
||
sort_orders:
|
||
items:
|
||
enum:
|
||
- popular
|
||
- name
|
||
- priceAsc
|
||
- priceDesc
|
||
type: string
|
||
maxItems: 4
|
||
type: array
|
||
required:
|
||
- facets
|
||
- sort_orders
|
||
- page
|
||
type: object
|
||
CCCWebsiteRootTabs:
|
||
additionalProperties: false
|
||
properties:
|
||
apps:
|
||
$ref: '#/components/schemas/CCCWebsiteRootTab'
|
||
models:
|
||
$ref: '#/components/schemas/CCCWebsiteRootTab'
|
||
workflows:
|
||
$ref: '#/components/schemas/CCCWebsiteRootTab'
|
||
required:
|
||
- models
|
||
- workflows
|
||
- apps
|
||
type: object
|
||
ChurnkeyAuthResponse:
|
||
description: |
|
||
Credentials the Churnkey embed requires to launch the cancel flow.
|
||
`auth_hash` is hex-encoded HMAC-SHA256 of `customer_id` signed with the
|
||
server's CHURNKEY_HMAC_SECRET; it is bound to that single customer ID
|
||
and must not be reused for other customers.
|
||
properties:
|
||
auth_hash:
|
||
description: Hex-encoded HMAC-SHA256(customer_id, CHURNKEY_HMAC_SECRET)
|
||
type: string
|
||
customer_id:
|
||
description: Stripe customer ID for the workspace
|
||
type: string
|
||
mode:
|
||
description: Churnkey environment matching the configured app
|
||
enum:
|
||
- live
|
||
- test
|
||
- sandbox
|
||
type: string
|
||
offer_subscription_id:
|
||
description: |
|
||
Stripe subscription a native Churnkey retention offer may apply to.
|
||
Present only when the caller is in the native-offer rollout and owns
|
||
a Personal workspace on an active paid monthly plan with no billing
|
||
change in flight; absent otherwise, and the client then keeps offers
|
||
disabled. Present in any mode. Not a signed authorization: the HMAC
|
||
covers only the customer ID.
|
||
minLength: 1
|
||
type: string
|
||
required:
|
||
- customer_id
|
||
- auth_hash
|
||
- mode
|
||
type: object
|
||
ContentCatalogProjection:
|
||
properties:
|
||
generation:
|
||
format: int64
|
||
type: integer
|
||
items:
|
||
items:
|
||
$ref: '#/components/schemas/ContentCatalogRecord'
|
||
type: array
|
||
revision_id:
|
||
format: int64
|
||
minimum: 1
|
||
type: integer
|
||
required:
|
||
- revision_id
|
||
- generation
|
||
- items
|
||
type: object
|
||
ContentCatalogRecord:
|
||
properties:
|
||
data:
|
||
additionalProperties: true
|
||
type: object
|
||
deleted:
|
||
type: boolean
|
||
edit_version:
|
||
type: string
|
||
enabled:
|
||
type: boolean
|
||
kind:
|
||
enum:
|
||
- MODEL
|
||
- WORKFLOW
|
||
- APP
|
||
- TEMPLATE_SET
|
||
type: string
|
||
revision:
|
||
description: Integer revision supplying this entity; may precede the requested catalog revision.
|
||
format: int64
|
||
minimum: 1
|
||
type: integer
|
||
slug:
|
||
description: Canonical website pathname for page content; native slug for template sets. Identity is always UID.
|
||
type: string
|
||
uid:
|
||
type: string
|
||
visibility:
|
||
enum:
|
||
- PUBLIC
|
||
- STAFF
|
||
type: string
|
||
visible_from:
|
||
format: date-time
|
||
type: string
|
||
required:
|
||
- uid
|
||
- revision
|
||
- edit_version
|
||
- kind
|
||
- slug
|
||
- enabled
|
||
- visibility
|
||
- deleted
|
||
- data
|
||
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
|
||
DeployToCloudError:
|
||
description: Error body of local ComfyUI's /api/deploy/* routes. Branch on `error`, never on `message`.
|
||
properties:
|
||
error:
|
||
enum:
|
||
- offline
|
||
- multiple_credentials
|
||
- invalid_api_key_format
|
||
- invalid_body
|
||
- missing_credentials
|
||
- unauthorized
|
||
- too_large
|
||
- too_many_bundles
|
||
- builder_rejected
|
||
- builder_unavailable
|
||
- builder_busy
|
||
type: string
|
||
message:
|
||
description: Human-readable detail, present for invalid_body and builder_rejected.
|
||
type: string
|
||
required:
|
||
- error
|
||
type: object
|
||
ErrorResponse:
|
||
description: Standard error response with a machine-readable code and human-readable message.
|
||
properties:
|
||
code:
|
||
type: string
|
||
details:
|
||
additionalProperties: true
|
||
description: Optional open object carrying structured, machine-readable context about the error (e.g. offending field names, validation specifics). Absent for most errors; consumers must not assume any particular shape.
|
||
type: object
|
||
message:
|
||
type: string
|
||
organization_id:
|
||
description: 'On `sso_required`: the SSO organization the caller must sign in with (its WorkOS id, `org_...`), the value `GET /api/auth/sso/start?organization=` takes: the organization that owns the account''s email domain, else the workspace''s. Absent when no sign-in would admit the caller (an account another organization holds, in an SSO organization''s workspace), when unknown, and on every other code but `account_outside_organization`, where it is the workspace''s organization, which no sign-in of the account joins.'
|
||
type: string
|
||
required:
|
||
- code
|
||
- message
|
||
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
|
||
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
|
||
ForbiddenError:
|
||
description: 'A 403 body: ErrorResponse, or AuthTypeNotAllowedError for a credential the route does not take.'
|
||
oneOf:
|
||
- $ref: '#/components/schemas/ErrorResponse'
|
||
- $ref: '#/components/schemas/AuthTypeNotAllowedError'
|
||
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. The workflow graph (extra_data.extra_pnginfo) is omitted from records persisted after it stopped being stored; older records may still contain it.
|
||
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. extra_pnginfo (the workflow graph) is omitted from records persisted after it stopped being stored; older records may still contain it.
|
||
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
|
||
JobAssetsResponse:
|
||
description: Paginated list of the assets produced by a single job.
|
||
properties:
|
||
assets:
|
||
description: The job's output assets for the requested page (empty when the job produced none)
|
||
items:
|
||
$ref: '#/components/schemas/JobOutputAsset'
|
||
type: array
|
||
job_id:
|
||
description: ID of the job these assets belong to
|
||
format: uuid
|
||
type: string
|
||
pagination:
|
||
$ref: '#/components/schemas/PaginationInfo'
|
||
required:
|
||
- job_id
|
||
- assets
|
||
- pagination
|
||
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
|
||
JobDeployment:
|
||
description: 'The deployment a job ran on and the Release it ran, as they were when the job was sent: deployment_id and release_id stay the same after the deployment is updated to another Release or deleted. build_name and release_version are read from comfy-builder when the job is read, so a renamed Build shows its new name within a few minutes.'
|
||
properties:
|
||
build_name:
|
||
description: 'The name of the Build the Release was cut from, as comfy-builder names it now. Absent when it is not named for this caller: an API-key caller, a caller reading a job outside their active workspace (an admin reading another workspace''s job), comfy-builder not configured on this server, minting the token to ask comfy-builder failing, comfy-builder failing or not answering in time, or a Release or Build since deleted.'
|
||
type: string
|
||
deployment_id:
|
||
description: Developer-platform deployment id.
|
||
type: string
|
||
name:
|
||
description: The deployment's own name from comfy-deploy, including for a deleted deployment. Read when the job is read and cached for five minutes, so a rename appears after the cache expires; not a job-time snapshot. Absent for unnamed or unavailable deployments, API-key callers, jobs outside the caller's active workspace, or when the service or token mint is unavailable. Does not replace build_name or the stable IDs.
|
||
type: string
|
||
release_id:
|
||
description: The Release the job ran.
|
||
type: string
|
||
release_version:
|
||
description: The Release's version number within its Build. Absent whenever build_name is.
|
||
type: integer
|
||
required:
|
||
- deployment_id
|
||
- release_id
|
||
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
|
||
deployment:
|
||
allOf:
|
||
- $ref: '#/components/schemas/JobDeployment'
|
||
description: 'Where a platform_gateway job ran. Absent for cloud_inference jobs. Also absent when the platform has not taken the job, refused it, failed before dispatch, or removed its platform record; when the record names no deployment; or when that record could not be read. Absence does not mean the job is pending: use status for its state. A failed job can retain executor=platform_gateway without a known deployment. No deployment is inferred from the caller''s current pick.'
|
||
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_meta:
|
||
additionalProperties: true
|
||
description: Node-level execution metadata (only for terminal states)
|
||
type: object
|
||
execution_start_time:
|
||
description: Workflow execution start timestamp (Unix milliseconds, only present once execution has started)
|
||
format: int64
|
||
type: integer
|
||
execution_status:
|
||
additionalProperties: true
|
||
description: ComfyUI execution status and timeline (only for terminal states)
|
||
type: object
|
||
executor:
|
||
description: 'What ran the job: cloud_inference is Comfy Cloud''s own GPUs; platform_gateway is a deployment of the workspace''s own Build, which deployment names.'
|
||
enum:
|
||
- cloud_inference
|
||
- platform_gateway
|
||
type: string
|
||
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
|
||
previewable_outputs_count:
|
||
description: Count of outputs classified as previewable media types (images, video, audio, 3D, text) — a subset of outputs_count (omitted for non-terminal states)
|
||
type: integer
|
||
queue_position:
|
||
description: |
|
||
1-based position of this job among the caller's OWN jobs held
|
||
behind the same concurrency cap (same user, workspace and auth
|
||
method), in the dispatcher's admission order — i.e. the number of
|
||
the caller's own capped jobs that will be admitted before this
|
||
one, plus one. It is NOT a fleet-wide queue position and says
|
||
nothing about other users' jobs. (For an admin reading someone
|
||
else's job, the set is that job owner's, not the admin's — the
|
||
same scoping `workspace_id`/`user_id` already describe.)
|
||
|
||
Null unless `queue_reason` is `concurrency_limit`. May also be
|
||
null in that state on the rare rows whose admission ordering
|
||
cannot be determined (no recorded state-change timestamp), or if
|
||
the count query fails — a missing position never fails the
|
||
request.
|
||
minimum: 1
|
||
nullable: true
|
||
type: integer
|
||
queue_reason:
|
||
description: |
|
||
Why a still-queued job has not started yet. Present only while
|
||
`status` is `pending`; null for every other status.
|
||
|
||
`status` deliberately folds every waiting state into `pending`
|
||
(the frontend's filter categories depend on that), so this field
|
||
is the one that tells the two kinds of waiting apart:
|
||
|
||
- `concurrency_limit` — the job is awaiting admission under the
|
||
per-user/per-auth-method or aggregate workspace concurrent-job
|
||
cap. Other members' running jobs can fill the workspace cap
|
||
even when this job's owner has no running jobs. This field
|
||
does not distinguish which cap is full.
|
||
- `capacity` — the job has passed concurrency admission and is
|
||
waiting for an inference worker to become free.
|
||
|
||
Detail-only: this field is NOT present on the list view's
|
||
`JobEntry`, because deriving `queue_position` for a page of jobs
|
||
would cost one extra query per row.
|
||
enum:
|
||
- concurrency_limit
|
||
- capacity
|
||
nullable: true
|
||
type: string
|
||
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
|
||
user_id:
|
||
description: |
|
||
ID of the user that owns this job (see the `workspace_id`
|
||
description above for why this is always the caller's own id
|
||
on a successful response).
|
||
type: string
|
||
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
|
||
workflow_version_id:
|
||
description: |
|
||
UUID of the cloud workflow version this job is pinned to, if the
|
||
submission carried one (see PromptRequest's workflow_version_id).
|
||
Absent for jobs submitted without that association, including
|
||
every job submitted through the public API v2 today.
|
||
type: string
|
||
workspace_id:
|
||
description: |
|
||
ID of the workspace that owns this job. A successful (200)
|
||
response from this operation is only ever returned for the
|
||
caller's own job (see this operation's ownership-scoped
|
||
query), so this is always the caller's own workspace —
|
||
consumers that also need to correlate this job to its
|
||
live-progress broadcast channel (workspace+user scoped; see
|
||
the internal common/gateways/broadcast package) can use this
|
||
value directly rather than resolving their own identity a
|
||
second way.
|
||
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
|
||
deployment:
|
||
allOf:
|
||
- $ref: '#/components/schemas/JobDeployment'
|
||
description: 'Where a platform_gateway job ran. Absent for cloud_inference jobs. Also absent when the platform has not taken the job, refused it, failed before dispatch, or removed its platform record; when the record names no deployment; or when that record could not be read. Absence does not mean the job is pending: use status for its state. A failed job can retain executor=platform_gateway without a known deployment. No deployment is inferred from the caller''s current pick.'
|
||
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
|
||
executor:
|
||
description: 'What ran the job: cloud_inference is Comfy Cloud''s own GPUs; platform_gateway is a deployment of the workspace''s own Build, which deployment names.'
|
||
enum:
|
||
- cloud_inference
|
||
- platform_gateway
|
||
type: string
|
||
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
|
||
previewable_outputs_count:
|
||
description: Count of outputs classified as previewable media types (images, video, audio, 3D, text) — a subset of outputs_count (omitted for non-terminal states)
|
||
type: integer
|
||
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
|
||
JobOutputAsset:
|
||
description: |
|
||
An asset produced by a job, enriched with the per-output node context
|
||
(`node_id`, `output_key`, `output_index`) correlated from the job's
|
||
execution outputs by content hash. The node-context fields are null
|
||
when the asset cannot be matched to an output entry.
|
||
properties:
|
||
created_at:
|
||
description: Timestamp when the asset was created
|
||
format: date-time
|
||
type: string
|
||
hash:
|
||
description: Blake3 hash of the asset content.
|
||
pattern: ^blake3:[a-f0-9]{64}$
|
||
type: string
|
||
id:
|
||
description: Unique identifier for the asset
|
||
format: uuid
|
||
type: string
|
||
mime_type:
|
||
description: MIME type of the asset
|
||
type: string
|
||
name:
|
||
description: Name of the asset file
|
||
type: string
|
||
node_id:
|
||
description: ID of the workflow node that produced this asset, if known
|
||
nullable: true
|
||
type: string
|
||
output_index:
|
||
description: Zero-based index of this asset within the node's output slot, if known
|
||
nullable: true
|
||
type: integer
|
||
output_key:
|
||
description: Output slot key under the producing node (e.g. "images"), if known
|
||
nullable: true
|
||
type: string
|
||
preview_url:
|
||
description: Relative URL for asset preview/thumbnail
|
||
format: uri-reference
|
||
type: string
|
||
size:
|
||
description: Size of the asset in bytes
|
||
format: int64
|
||
type: integer
|
||
required:
|
||
- id
|
||
- name
|
||
- created_at
|
||
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
|
||
JobsCancelRequest:
|
||
additionalProperties: false
|
||
description: Request to cancel multiple jobs by ID.
|
||
properties:
|
||
job_ids:
|
||
description: Job identifiers (UUIDs) to cancel.
|
||
items:
|
||
format: uuid
|
||
type: string
|
||
maxItems: 100
|
||
minItems: 1
|
||
type: array
|
||
required:
|
||
- job_ids
|
||
type: object
|
||
JobsCancelResponse:
|
||
description: Response for POST /api/jobs/cancel.
|
||
properties:
|
||
cancelled:
|
||
description: |
|
||
Job IDs for which a cancel event was successfully dispatched by this
|
||
call. Jobs already in a terminal or cancelling state are idempotently
|
||
skipped and will not appear here.
|
||
items:
|
||
type: string
|
||
type: array
|
||
required:
|
||
- cancelled
|
||
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
|
||
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
|
||
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
|
||
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
|
||
PaginationInfo:
|
||
description: |
|
||
Pagination metadata included in list responses. Supports both legacy
|
||
offset/limit pagination and cursor-based pagination. When cursor-based
|
||
pagination is used, `next_cursor` is the primary pagination token and
|
||
`offset`/`total` may be zero.
|
||
properties:
|
||
has_more:
|
||
description: Whether more items are available beyond this page
|
||
type: boolean
|
||
limit:
|
||
description: Items per page
|
||
minimum: 1
|
||
type: integer
|
||
next_cursor:
|
||
description: |
|
||
Opaque cursor for the next page. Pass this value as the `after`
|
||
query parameter on the next request. Empty or absent when there
|
||
are no more results.
|
||
type: string
|
||
offset:
|
||
deprecated: true
|
||
description: 'Current offset (0-based). Deprecated: use cursor-based pagination.'
|
||
minimum: 0
|
||
type: integer
|
||
total:
|
||
description: Total number of items matching filters (may be 0 when using cursor pagination)
|
||
minimum: 0
|
||
type: integer
|
||
required:
|
||
- offset
|
||
- limit
|
||
- total
|
||
- has_more
|
||
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
|
||
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 job IDs to cancel; pending and running jobs transition to cancelled
|
||
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
|
||
RetentionAcceptRequest:
|
||
additionalProperties: false
|
||
properties:
|
||
session_id:
|
||
description: Server-issued session; carries no client-selected coupon or variant.
|
||
format: uuid
|
||
type: string
|
||
required:
|
||
- session_id
|
||
type: object
|
||
RetentionAcceptance:
|
||
properties:
|
||
billing_op_id:
|
||
type: string
|
||
status:
|
||
description: Show success only once this is succeeded; otherwise poll the billing operation.
|
||
enum:
|
||
- pending
|
||
- succeeded
|
||
type: string
|
||
required:
|
||
- billing_op_id
|
||
- status
|
||
type: object
|
||
RetentionFlowEventRequest:
|
||
additionalProperties: false
|
||
properties:
|
||
event:
|
||
description: flow_opened is reported at the same point for every arm.
|
||
enum:
|
||
- flow_opened
|
||
- offer_shown
|
||
type: string
|
||
session_id:
|
||
format: uuid
|
||
type: string
|
||
required:
|
||
- session_id
|
||
- event
|
||
type: object
|
||
RetentionFlowResponse:
|
||
properties:
|
||
experiment_variant:
|
||
description: |
|
||
The PostHog arm: control or a retention offer ID. Absent when the
|
||
subscription is ineligible or the owner is outside the experiment.
|
||
type: string
|
||
expires_at:
|
||
description: Unix seconds; reopen cancellation to refresh the offer after expiry.
|
||
maximum: 9007199254740991
|
||
type: integer
|
||
x-go-type: int64
|
||
offer:
|
||
$ref: '#/components/schemas/RetentionOffer'
|
||
session_id:
|
||
format: uuid
|
||
type: string
|
||
subscription:
|
||
$ref: '#/components/schemas/RetentionFlowSubscription'
|
||
required:
|
||
- session_id
|
||
- expires_at
|
||
- subscription
|
||
type: object
|
||
RetentionFlowSubscription:
|
||
properties:
|
||
currency:
|
||
type: string
|
||
period_end:
|
||
description: Unix seconds of the next renewal.
|
||
maximum: 9007199254740991
|
||
type: integer
|
||
x-go-type: int64
|
||
quantity:
|
||
maximum: 9007199254740991
|
||
type: integer
|
||
x-go-type: int64
|
||
unit_amount:
|
||
description: Recurring unit price in the currency's smallest unit.
|
||
maximum: 9007199254740991
|
||
type: integer
|
||
x-go-type: int64
|
||
required:
|
||
- currency
|
||
- unit_amount
|
||
- quantity
|
||
- period_end
|
||
type: object
|
||
RetentionOffer:
|
||
description: Present only when the session's arm is an offer. Terms come from the server catalog.
|
||
properties:
|
||
duration_in_months:
|
||
maximum: 9007199254740991
|
||
type: integer
|
||
x-go-type: int64
|
||
id:
|
||
type: string
|
||
percent_off:
|
||
maximum: 9007199254740991
|
||
type: integer
|
||
x-go-type: int64
|
||
required:
|
||
- id
|
||
- percent_off
|
||
- duration_in_months
|
||
type: object
|
||
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
|
||
deploy_environment:
|
||
description: How this ComfyUI instance is deployed (e.g. cloud, local-git, local-portable, local-desktop)
|
||
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, failed, or was cancelled (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
|
||
- cancelled
|
||
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
|
||
- cancelled
|
||
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
|
||
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
|
||
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
|
||
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
|
||
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: |
|
||
A token in the `Authorization: Bearer` header: a Firebase ID token, a
|
||
Cloud JWT from `POST /api/auth/token`, or an access token that
|
||
`POST /oauth/token` minted for a resource served here. A `comfyui-` key sent
|
||
here counts as `ApiKeyAuth`.
|
||
scheme: bearer
|
||
type: http
|
||
CookieAuth:
|
||
description: |
|
||
Session cookie authentication. Set automatically after successful
|
||
login via the /api/auth/session endpoint.
|
||
|
||
A POST, PUT, PATCH or DELETE with it is refused with 403 before the
|
||
handler runs unless the browser labels it same-origin, its `Origin`
|
||
is on the trusted-origins list, or, with no `Sec-Fetch-Site`, its
|
||
`Origin` is this host's own: `cross_site_request` for a cross-site
|
||
label, `origin_not_allowed` otherwise. The OAuth consent POST takes
|
||
it only with an `Origin` that is this host's own, never a trusted
|
||
one. This is not behind `web_session_enabled`.
|
||
in: cookie
|
||
name: session
|
||
type: apiKey
|
||
WebSessionAuth:
|
||
description: |
|
||
Server-side web session, set by `POST /api/auth/session`. The media
|
||
routes, the short-link redirect, OAuth consent, the custom-node proxy
|
||
and the admins' asynqmon UI accept it whatever `web_session_enabled`
|
||
says. The user-facing API groups accept it too, for users with the
|
||
flag on; machine, admin API and service-token routes never do. A credential in a header always wins and never falls back to
|
||
the cookie.
|
||
|
||
Wherever the cookie is accepted, the request is checked before the
|
||
handler runs (403 with the `code` shown):
|
||
- `cross_site_request`: the browser labels it `Sec-Fetch-Site:
|
||
cross-site`, other than a top-level GET navigation to the short-link
|
||
redirect or OAuth consent.
|
||
- `origin_not_allowed`: an `Origin` that is not on the trusted-origins
|
||
list, unless the call is labelled same-origin; a POST, PUT, PATCH or
|
||
DELETE with no `Origin`; or, on API routes, a request without
|
||
`X-Comfy-Client`, which SDK clients send with their name and version.
|
||
The OAuth consent POST takes the session only from this host's own
|
||
origin, so a trusted `Origin` is refused there too.
|
||
- `csrf_invalid`: a POST, PUT, PATCH or DELETE without the session's
|
||
CSRF token in `X-CSRF-Token`, except on OAuth consent, which checks
|
||
its own token, and the asynqmon UI, which cannot send one and is
|
||
not checked for it today.
|
||
|
||
With the flag on, `X-Comfy-Workspace-ID` (or `?workspace_id=` where a
|
||
header cannot go) selects the workspace; absent means the personal
|
||
workspace. A malformed or conflicting id is 400 `workspace_id_invalid`.
|
||
An unknown or deleted workspace, or one the user is not a member of, is
|
||
403 `workspace_access_denied`. An account with no personal workspace
|
||
(one SSO created) that is no longer a member of any live workspace,
|
||
for example after its directory removed its last membership, is 403
|
||
`no_workspace_access` on every route that reads the session. All
|
||
three are answered on routes that also
|
||
serve anonymous callers; there, the other refusals fall back to an
|
||
anonymous request, except on the OAuth consent POST, which answers
|
||
`origin_not_allowed` and `cross_site_request` too. Today the
|
||
short-link redirect and the OAuth consent GET, which a link may
|
||
open, do not select a workspace for the session.
|
||
|
||
A token or API key whose workspace selector names another workspace
|
||
than the one it resolves to is 400 `workspace_id_invalid` on these
|
||
routes, while the flag is on for its user. A service token, which has
|
||
no workspace, ignores the selector.
|
||
in: cookie
|
||
name: __Host-comfy_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:
|
||
/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:
|
||
- deprecated: true
|
||
description: |
|
||
Deprecated alias for `tags_all`, kept permanently for existing
|
||
callers. Filter assets that have ALL of these tags. Combining it
|
||
with `tags_all`, or exceeding 100 tags (counted after removing
|
||
empty values and duplicates), returns 400 `INVALID_TAG_FILTER`.
|
||
explode: false
|
||
in: query
|
||
name: include_tags
|
||
schema:
|
||
items:
|
||
type: string
|
||
type: array
|
||
style: form
|
||
- deprecated: true
|
||
description: |
|
||
Deprecated alias for `tags_none`, kept permanently for existing
|
||
callers. Exclude assets that have ANY of these tags. Combining it
|
||
with `tags_none`, or exceeding 100 tags (counted after removing
|
||
empty values and duplicates), returns 400 `INVALID_TAG_FILTER`.
|
||
explode: false
|
||
in: query
|
||
name: exclude_tags
|
||
schema:
|
||
items:
|
||
type: string
|
||
type: array
|
||
style: form
|
||
- description: |
|
||
Filter assets that have ALL of these tags. Tag values are opaque
|
||
byte-strings compared exactly and case-sensitively; unknown tags
|
||
are not an error — they simply match nothing. Replaces the
|
||
deprecated `include_tags`. Sending both spellings, listing the
|
||
same tag here and in `tags_none`, or exceeding 100 tags per list
|
||
(counted after removing empty values and duplicates) returns 400
|
||
`INVALID_TAG_FILTER`.
|
||
explode: false
|
||
in: query
|
||
name: tags_all
|
||
schema:
|
||
items:
|
||
type: string
|
||
type: array
|
||
style: form
|
||
- description: |
|
||
Filter assets that have AT LEAST ONE of these tags. Combines with
|
||
`tags_all`/`tags_none` by intersection (`tags_none` always wins;
|
||
overlap with `tags_none` is allowed and leaves a dead term).
|
||
Supplying a positive tag filter (`tags_any`, `tags_all`, or
|
||
`include_tags`) replaces the default category filter that is
|
||
otherwise applied. Lists over 100 tags (counted after removing
|
||
empty values and duplicates) return 400 `INVALID_TAG_FILTER`.
|
||
explode: false
|
||
in: query
|
||
name: tags_any
|
||
schema:
|
||
items:
|
||
type: string
|
||
type: array
|
||
style: form
|
||
- description: |
|
||
Exclude assets that have ANY of these tags. Replaces the
|
||
deprecated `exclude_tags`. Sending both spellings, or exceeding
|
||
100 tags per list (counted after removing empty values and
|
||
duplicates), returns 400 `INVALID_TAG_FILTER`.
|
||
explode: false
|
||
in: query
|
||
name: tags_none
|
||
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 content hash, in the canonical `blake3:<hex>`
|
||
form. Matches regardless of which of this asset store's two
|
||
internal hash storage formats the matching row was written
|
||
under (the canonical form used by from-hash-created references,
|
||
or the raw `<hex>.<ext>`/bare `<hex>` storage key used by direct
|
||
uploads) — both represent the same content hash.
|
||
in: query
|
||
name: 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
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
"500":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Internal server error
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: List user assets
|
||
tags:
|
||
- file
|
||
post:
|
||
description: |
|
||
Creates a new asset from a direct file upload (multipart/form-data) with associated metadata.
|
||
|
||
If an asset with the same hash already exists, returns the existing asset.
|
||
|
||
Location metadata is removed, best effort, from JPEG, PNG, WebP and
|
||
TIFF files (detected from the file's bytes, not its name) before they
|
||
are stored: the EXIF GPS block and whole XMP packets from all four, the
|
||
Photoshop/IPTC block from JPEG and TIFF, and PNG "Raw profile" text
|
||
chunks. Only a JPEG's first image is kept: everything after its end,
|
||
including MPO secondary images (whose MPF index is dropped) and a
|
||
motion-photo video, is dropped, as are bytes after a PNG's IEND or
|
||
past a WebP's RIFF end.
|
||
Dropping a whole XMP or Photoshop block also drops the non-location
|
||
fields in it (for example creator, copyright, an AI-generation label or
|
||
an XMP-only orientation) and breaks a C2PA signature. Pixels, the EXIF
|
||
orientation tag and ComfyUI workflow metadata are kept. A file whose
|
||
structure cannot be parsed is stored unchanged, as are other formats (for example HEIC,
|
||
AVIF, GIF, BMP and BigTIFF). The returned hash is the hash of the stored
|
||
bytes. A JPEG, PNG, WebP or TIFF file over 50 MiB is rejected with 413.
|
||
operationId: createAsset
|
||
requestBody:
|
||
content:
|
||
multipart/form-data:
|
||
schema:
|
||
properties:
|
||
file:
|
||
description: The asset file to upload
|
||
format: binary
|
||
type: string
|
||
hash:
|
||
description: Content hash of the file.
|
||
pattern: ^(blake3|sha256):[a-f0-9]{64}$
|
||
type: string
|
||
id:
|
||
description: Optional caller-chosen asset ID. If the upload's content matches an asset you already own in this workspace, that asset is returned and its `id` may differ from the one requested. Otherwise, an ID already taken by any asset is refused with 400 `ASSET_ID_UNAVAILABLE`.
|
||
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. Must be your own asset in this workspace; anything else (including a catalog asset, another user's published asset, or an ID that does not exist) is refused with 400 `INVALID_PREVIEW_ID`. If not provided, images use their own ID as preview, except OpenEXR and Radiance HDR, which get no preview; a preview_id equal to the asset's own id is ignored for those.
|
||
format: uuid
|
||
type: string
|
||
tags:
|
||
description: JSON-encoded array of freeform tag strings, e.g. '["models","checkpoint"]'. Common types include "models", "input", "output", and "temp", but any tag can be used in any order. At most 64 tags, each a non-empty UTF-8 string of at most 256 bytes (surrounding whitespace included) with no NUL; a request breaking either rule is refused with 400 `INVALID_BODY`. JSON decoding replaces invalid UTF-8 and lone surrogate escapes (e.g. `\ud800`) with U+FFFD (3 bytes each) instead of refusing them, and the 256-byte limit applies to the replaced value.
|
||
type: string
|
||
user_metadata:
|
||
description: Custom JSON metadata as a string
|
||
type: string
|
||
required:
|
||
- file
|
||
type: object
|
||
required: true
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/AssetCreated'
|
||
description: |
|
||
Asset already existed for this user (deduplicated by content hash); the
|
||
existing asset is returned with created_new=false.
|
||
"201":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/AssetCreated'
|
||
description: Asset created successfully (created_new=true)
|
||
"400":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Invalid request (bad file, invalid content type, etc.), `INVALID_PREVIEW_ID` when `preview_id` is not your own asset in this workspace, or `ASSET_ID_UNAVAILABLE` when a caller-chosen `id` is already taken
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unauthorized
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"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: Validation error (e.g., disallowed model_type tag)
|
||
"500":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Internal server error
|
||
"503":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Upload buffer budget exhausted on this pod while buffering an image part; retry after the Retry-After seconds. `code` is `UPLOAD_BUDGET_EXHAUSTED`.
|
||
headers:
|
||
Retry-After:
|
||
description: Seconds to wait before retrying
|
||
schema:
|
||
type: integer
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Create a new asset
|
||
tags:
|
||
- file
|
||
/api/assets/{id}:
|
||
delete:
|
||
description: Deletes the asset record.
|
||
operationId: deleteAsset
|
||
parameters:
|
||
- description: Asset ID
|
||
in: path
|
||
name: id
|
||
required: true
|
||
schema:
|
||
format: uuid
|
||
type: string
|
||
responses:
|
||
"204":
|
||
description: Asset record deleted successfully
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unauthorized
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"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. a workflow version, or because content moderation still holds it (error code: ASSET_IN_USE for both; a moderation hold is deliberately not distinguishable)'
|
||
"500":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Internal server error
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unauthorized
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
"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
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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 POST (add) and DELETE (remove) /api/assets/{id}/tags.
|
||
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. Must be your own asset in this workspace.
|
||
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, or `preview_id` is the zero UUID
|
||
(`INVALID_PREVIEW_ID`).
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unauthorized
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"404":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: |
|
||
Asset not found — returned both when the asset being updated does
|
||
not exist and when `preview_id` is not your own asset in this
|
||
workspace (a catalog asset or another user's published asset
|
||
does not qualify).
|
||
"500":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Internal server error
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Update asset metadata
|
||
tags:
|
||
- file
|
||
/api/assets/{id}/content:
|
||
get:
|
||
description: |
|
||
Returns the binary content of an asset by ID.
|
||
|
||
The contract is the same across runtimes — "GET this path and you
|
||
receive the asset's bytes" — but the mechanism differs:
|
||
- **Local ComfyUI** streams the bytes directly (`200`,
|
||
`application/octet-stream`).
|
||
- **Cloud** does not proxy large files; it responds `302` with a
|
||
`Location` redirect to a short-lived signed storage URL. Clients that
|
||
follow redirects (browsers, `fetch`/XHR, `<img>`/`<video>`) receive
|
||
the bytes transparently.
|
||
|
||
Prefer this over the filename-addressed `/api/view` when you have an
|
||
asset ID.
|
||
|
||
An `<img>`, `<video>` or `<audio>` tag loads this with the
|
||
`WebSessionAuth` or `CookieAuth` cookie, both accepted whatever
|
||
`web_session_enabled` says; neither needs `X-CSRF-Token` or
|
||
`X-Comfy-Client`, which a media tag cannot send. A 403
|
||
AuthTypeNotAllowedError here is a credential the route never takes,
|
||
such as `X-ComfyAPI-Secret`, never the session.
|
||
operationId: getAssetContent
|
||
parameters:
|
||
- description: Asset ID
|
||
in: path
|
||
name: id
|
||
required: true
|
||
schema:
|
||
type: string
|
||
- description: |
|
||
Content-Disposition for the response: `attachment` (download) or
|
||
`inline` (render in browser). Defaults to `attachment`.
|
||
in: query
|
||
name: disposition
|
||
schema:
|
||
default: attachment
|
||
enum:
|
||
- inline
|
||
- attachment
|
||
type: string
|
||
- content:
|
||
text/plain:
|
||
schema:
|
||
type: string
|
||
description: The workspace a media request reads from, where a media tag cannot send `X-Comfy-Workspace-ID`; see the `MediaWorkspaceID` parameter.
|
||
in: query
|
||
name: workspace_id
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/octet-stream:
|
||
schema:
|
||
format: binary
|
||
type: string
|
||
description: Asset content stream (local runtime streams the bytes directly)
|
||
"302":
|
||
description: Redirect to a signed storage URL (cloud runtime)
|
||
headers:
|
||
Cache-Control:
|
||
description: Private caching directive scoped to the signed URL lifetime
|
||
schema:
|
||
type: string
|
||
Location:
|
||
description: Short-lived signed URL to the asset content in storage
|
||
schema:
|
||
type: string
|
||
Vary:
|
||
description: Partitions any cached redirect by auth credentials so a private redirect is not reused across users
|
||
schema:
|
||
type: string
|
||
"400":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: '`code` `workspace_id_invalid`: the `workspace_id` or `X-Comfy-Workspace-ID` value is malformed, the two disagree, or, with the flag on, a token or API key names another workspace than its own. Or `BAD_REQUEST` from the generated wrapper when a parameter does not bind, such as a repeated `disposition`.'
|
||
"401":
|
||
$ref: '#/components/responses/SessionUnauthorized'
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
"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
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- CookieAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Get asset content
|
||
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
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"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
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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. At most 64 tags, each a non-empty UTF-8 string of at most 256 bytes (surrounding whitespace included) with no NUL; a request breaking either rule is refused with 400 `INVALID_BODY`. An add that would grow the asset's stored set (server-added tags included) past 64 is refused the same way; an asset already over 64 is not trimmed and can still re-apply its stored non-category tags that add no new server-derived tag (`input`, `output`, `temp` and `models` are refused with 422 `RESERVED_TAG` before any count check; re-applying a legacy bare model-directory tag whose `model_type:` twin is not stored adds that twin, so it counts as growth). The counted set is the stored one, which the response's `total_tags` need not equal, as it hides stored `model_type:` tags or shows synthesized ones, depending on the deployment. JSON decoding replaces invalid UTF-8 and lone surrogate escapes (e.g. `\ud800`) with U+FFFD (3 bytes each) instead of refusing them, and the 256-byte limit applies to the replaced value.
|
||
items:
|
||
type: string
|
||
maxItems: 64
|
||
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
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"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
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Add tags to asset
|
||
tags:
|
||
- file
|
||
/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: 'Blake3 content hash of the existing asset (blake3: prefix)'
|
||
pattern: ^blake3:[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. At most 64 tags, each a non-empty UTF-8 string of at most 256 bytes (surrounding whitespace included) with no NUL; a request breaking either rule is refused with 400 `INVALID_BODY`. JSON decoding replaces invalid UTF-8 and lone surrogate escapes (e.g. `\ud800`) with U+FFFD (3 bytes each) instead of refusing them, and the 256-byte limit applies to the replaced value.
|
||
items:
|
||
type: string
|
||
maxItems: 64
|
||
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:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/AssetCreated'
|
||
description: |
|
||
Asset reference already existed for this user (deduplicated by content
|
||
hash); the existing asset is returned with created_new=false.
|
||
"201":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/AssetCreated'
|
||
description: Asset reference created successfully (created_new=true)
|
||
"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
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"404":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Source asset with given hash not found
|
||
"422":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Validation error (e.g., disallowed model_type tag)
|
||
"500":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Internal server error
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Create asset reference from existing hash
|
||
tags:
|
||
- file
|
||
/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":
|
||
description: No valid credential (see SessionUnauthorized). No body.
|
||
"403":
|
||
description: A refused web session request, or the route's own authorization check failing (see SessionForbidden). A HEAD response has no body, so the code is not sent.
|
||
"404":
|
||
description: Asset not found
|
||
"500":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Internal server error
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Check if asset exists by hash
|
||
tags:
|
||
- file
|
||
/api/assets/prune:
|
||
post:
|
||
description: Starts a background job that removes asset entries whose underlying content no longer exists on disk.
|
||
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
|
||
/api/assets/seed:
|
||
post:
|
||
description: Starts a background job that scans configured directories and registers assets not yet in the asset database.
|
||
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
|
||
/api/assets/seed/cancel:
|
||
post:
|
||
description: Requests cancellation of the currently-running asset seed job.
|
||
operationId: cancelAssetSeed
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
properties:
|
||
status:
|
||
type: string
|
||
type: object
|
||
description: Scan cancelled
|
||
summary: Cancel an in-progress asset scan
|
||
/api/assets/seed/status:
|
||
get:
|
||
description: Returns progress/status of the most recent asset seed job.
|
||
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
|
||
/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:
|
||
- deprecated: true
|
||
description: |
|
||
Deprecated alias for `tags_all`, kept permanently for existing
|
||
callers. Filter assets that have ALL of these tags. The same
|
||
combination and list-size rules as on `/api/assets` apply
|
||
(400 `INVALID_TAG_FILTER`).
|
||
explode: false
|
||
in: query
|
||
name: include_tags
|
||
schema:
|
||
items:
|
||
type: string
|
||
type: array
|
||
style: form
|
||
- deprecated: true
|
||
description: |
|
||
Deprecated alias for `tags_none`, kept permanently for existing
|
||
callers. Exclude assets that have ANY of these tags. The same
|
||
combination and list-size rules as on `/api/assets` apply
|
||
(400 `INVALID_TAG_FILTER`).
|
||
explode: false
|
||
in: query
|
||
name: exclude_tags
|
||
schema:
|
||
items:
|
||
type: string
|
||
type: array
|
||
style: form
|
||
- description: |
|
||
Filter assets that have ALL of these tags. Replaces the deprecated
|
||
`include_tags`. The same combination and list-size rules as on
|
||
`/api/assets` apply (400 `INVALID_TAG_FILTER`).
|
||
explode: false
|
||
in: query
|
||
name: tags_all
|
||
schema:
|
||
items:
|
||
type: string
|
||
type: array
|
||
style: form
|
||
- description: |
|
||
Filter assets that have AT LEAST ONE of these tags. Combines with
|
||
`tags_all`/`tags_none` by intersection (`tags_none` always wins).
|
||
The same combination and list-size rules as on `/api/assets` apply
|
||
(400 `INVALID_TAG_FILTER`).
|
||
explode: false
|
||
in: query
|
||
name: tags_any
|
||
schema:
|
||
items:
|
||
type: string
|
||
type: array
|
||
style: form
|
||
- description: |
|
||
Exclude assets that have ANY of these tags. Replaces the deprecated
|
||
`exclude_tags`. The same combination and list-size rules as on
|
||
`/api/assets` apply (400 `INVALID_TAG_FILTER`).
|
||
explode: false
|
||
in: query
|
||
name: tags_none
|
||
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
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
"500":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Internal server error
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Get tag histogram for filtered assets
|
||
tags:
|
||
- file
|
||
/api/billing/churnkey/auth:
|
||
get:
|
||
description: |
|
||
Returns the Stripe customer identifier and a server-signed
|
||
HMAC-SHA256 of the customer ID, used to launch the Churnkey-hosted
|
||
cancellation flow embed.
|
||
operationId: getChurnkeyAuth
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ChurnkeyAuthResponse'
|
||
description: Success
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unauthorized
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
"404":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Workspace has no Stripe customer (never subscribed)
|
||
"500":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Internal server error
|
||
"503":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Churnkey is not configured on the server
|
||
security:
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Get Churnkey HMAC auth credentials
|
||
tags:
|
||
- billing
|
||
/api/billing/retention/accept:
|
||
post:
|
||
description: |
|
||
Owner-only, workspace-scoped cancellation flow. Cloud decides eligibility,
|
||
PostHog assigns the experiment arm, and billing-api binds any offer to a
|
||
server-issued session. The browser never sends coupon terms. A
|
||
non-owner gets `FORBIDDEN`, an owner who is not the creator gets
|
||
`NOT_ORIGINAL_OWNER` when the rollout mode is `creator`, and accepting a
|
||
session without an offer gets `RETENTION_NOT_ALLOWED`.
|
||
Poll the returned billing operation until it settles.
|
||
operationId: acceptRetentionOffer
|
||
requestBody:
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/RetentionAcceptRequest'
|
||
required: true
|
||
responses:
|
||
"202":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/RetentionAcceptance'
|
||
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
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"409":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Session stale or a billing operation conflicts
|
||
"500":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Internal server error
|
||
"503":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Cancellation offers unavailable
|
||
security:
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Accept the retention offer for this cancellation session
|
||
tags:
|
||
- billing
|
||
/api/billing/retention/events:
|
||
post:
|
||
description: |
|
||
Owner-only, workspace-scoped cancellation flow. Cloud decides eligibility,
|
||
PostHog assigns the experiment arm, and billing-api binds any offer to a
|
||
server-issued session. The browser never sends coupon terms. A
|
||
non-owner gets `FORBIDDEN`, an owner who is not the creator gets
|
||
`NOT_ORIGINAL_OWNER` when the rollout mode is `creator`, and accepting a
|
||
session without an offer gets `RETENTION_NOT_ALLOWED`.
|
||
Events are recorded only for sessions assigned an experiment arm.
|
||
operationId: recordRetentionFlowEvent
|
||
requestBody:
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/RetentionFlowEventRequest'
|
||
required: true
|
||
responses:
|
||
"204":
|
||
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
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"409":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Session stale or a billing operation conflicts
|
||
"500":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Internal server error
|
||
"503":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Cancellation offers unavailable
|
||
security:
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Record cancellation participation or an actual offer display
|
||
tags:
|
||
- billing
|
||
/api/billing/retention/prepare:
|
||
post:
|
||
description: |
|
||
Owner-only, workspace-scoped cancellation flow. Cloud decides eligibility,
|
||
PostHog assigns the experiment arm, and billing-api binds any offer to a
|
||
server-issued session. The browser never sends coupon terms. A
|
||
non-owner gets `FORBIDDEN`, an owner who is not the creator gets
|
||
`NOT_ORIGINAL_OWNER` when the rollout mode is `creator`, and accepting a
|
||
session without an offer gets `RETENTION_NOT_ALLOWED`.
|
||
Preparing a session does not cancel the subscription.
|
||
operationId: prepareRetentionFlow
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/RetentionFlowResponse'
|
||
description: Success
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unauthorized
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"422":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Subscription does not support this flow, or cancellation offers are switched off
|
||
"500":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Internal server error
|
||
"503":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Cancellation offers unavailable
|
||
security:
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Prepare a cancellation session and any retention offer
|
||
tags:
|
||
- billing
|
||
/api/default_workflow:
|
||
get:
|
||
description: Returns the workflow the frontend loads when no other workflow is open.
|
||
operationId: getDefaultWorkflow
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
additionalProperties: true
|
||
type: object
|
||
description: Default workflow JSON
|
||
security: []
|
||
summary: Get the default workflow
|
||
tags:
|
||
- workflow
|
||
/api/deploy/bundle:
|
||
post:
|
||
description: On explicit user action, collects this installation's snapshot (comfyui-desktop-2-snapshot) and installed model list, sends them with the optional workflow and name to comfy-builder's POST /v1/import-bundles, and returns the Create a Build wizard link that opens it. The caller's credential is forwarded verbatim and never stored; exactly one of a Bearer Authorization header or an X-API-Key header must be sent. Never available under --offline.
|
||
operationId: createDeployBundle
|
||
requestBody:
|
||
content:
|
||
application/json:
|
||
schema:
|
||
description: A JSON object; `{}` is valid. Null members count as absent.
|
||
properties:
|
||
name:
|
||
description: Optional label for the bundle.
|
||
maxLength: 200
|
||
nullable: true
|
||
type: string
|
||
workflow:
|
||
additionalProperties: true
|
||
description: The workflow open in ComfyUI, sent as is.
|
||
nullable: true
|
||
type: object
|
||
type: object
|
||
required: true
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
properties:
|
||
bundle_id:
|
||
format: uuid
|
||
type: string
|
||
expires_at:
|
||
description: When the bundle stops being readable (24 hours after creation).
|
||
format: date-time
|
||
type: string
|
||
url:
|
||
description: The Create a Build wizard link that opens the bundle (/profile/builds/new?step=import&bundle=&workspace=&bundle_workspace=).
|
||
format: uri
|
||
type: string
|
||
workspace_id:
|
||
description: The workspace the bundle belongs to (the credential's).
|
||
type: string
|
||
required:
|
||
- url
|
||
- bundle_id
|
||
- workspace_id
|
||
- expires_at
|
||
type: object
|
||
description: Bundle stored on comfy-builder
|
||
"400":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/DeployToCloudError'
|
||
description: 'Rejected before upload: `multiple_credentials` (both headers sent), `invalid_api_key_format` (X-API-Key is not comfyui- followed by 64 hex characters) or `invalid_body` (not a JSON object, or a bad workflow or name).'
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/DeployToCloudError'
|
||
description: '`missing_credentials` (no credential sent) or `unauthorized` (the builder refused the credential).'
|
||
"403":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/DeployToCloudError'
|
||
description: '`offline` (the server runs with --offline) or `unauthorized` (the builder refused the credential).'
|
||
"413":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/DeployToCloudError'
|
||
description: The bundle exceeds the builder's size cap (`too_large`).
|
||
"429":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/DeployToCloudError'
|
||
description: The user already holds the builder's limit of unexpired bundles in this workspace (`too_many_bundles`); clears as older bundles expire.
|
||
"502":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/DeployToCloudError'
|
||
description: '`builder_rejected` (the builder refused the bundle as invalid; `message` carries its reason, at most 500 characters) or `builder_unavailable` (the builder could not be reached or answered unexpectedly).'
|
||
"503":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/DeployToCloudError'
|
||
description: The builder is busy (`builder_busy`); retry after Retry-After seconds when present.
|
||
headers:
|
||
Retry-After:
|
||
description: Seconds to wait, when the builder sent one.
|
||
schema:
|
||
type: integer
|
||
security:
|
||
- BearerAuth: []
|
||
- ApiKeyAuth: []
|
||
summary: Upload this installation to Cloud as an import bundle
|
||
/api/deploy/summary:
|
||
get:
|
||
description: Counts the custom nodes and model files this local installation would send in an import bundle, so the UI can describe the upload before the user confirms it. Local reads only; makes no network request.
|
||
operationId: getDeploySummary
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
properties:
|
||
custom_nodes:
|
||
description: Custom node packages found in the custom_nodes folders
|
||
type: integer
|
||
models:
|
||
description: Model files found across the model folders
|
||
type: integer
|
||
required:
|
||
- custom_nodes
|
||
- models
|
||
type: object
|
||
description: Counts of what the bundle would include
|
||
"403":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/DeployToCloudError'
|
||
description: The server runs with --offline (error `offline`)
|
||
security: []
|
||
summary: Count what a Deploy to Cloud bundle would carry
|
||
/api/embeddings:
|
||
get:
|
||
description: Returns the list of text-encoder embeddings available on disk.
|
||
operationId: getEmbeddings
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
items:
|
||
type: string
|
||
type: array
|
||
description: Embedding names
|
||
summary: List available embedding names
|
||
/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.
|
||
Each folder's name is the identifier to pass to /api/experiment/models/{folder}.
|
||
The folder vocabulary is resolved per request from the caller's identity: where the
|
||
model_type migration is active for that caller the names are model_type folder_names
|
||
(e.g. `ultralytics_bbox`), and a folder with no folder_name mapping is returned by its
|
||
directory path. An authenticated response can therefore differ from an anonymous one.
|
||
operationId: getModelFolders
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
items:
|
||
$ref: '#/components/schemas/ModelFolder'
|
||
type: array
|
||
description: Success - List of model folders
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"403":
|
||
$ref: '#/components/responses/SessionWorkspaceAccessDenied'
|
||
"500":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Internal server error
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
- {}
|
||
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.
|
||
Accepted folder identifiers are those returned by /api/experiment/models for the same
|
||
caller. That vocabulary is request-scoped, so list folders and fetch a folder's models
|
||
with the same credentials — a name obtained anonymously may not resolve when
|
||
authenticated, and vice versa.
|
||
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
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"403":
|
||
$ref: '#/components/responses/SessionWorkspaceAccessDenied'
|
||
"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:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
- {}
|
||
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`). For a browser that picked a
|
||
developer-platform deployment (the cookie PUT
|
||
/api/workspaces/{id}/deployment sets) the list is the files of the
|
||
Release that deployment runs now, each at a release-scoped path,
|
||
`/extensions/<pack>@<workspace id>@<release id>/<rel>`; otherwise, and
|
||
for anonymous callers, it is the static list.
|
||
|
||
The `/extensions/*` files the browser then imports carry no
|
||
Authorization header, and cookie authentication resolves only a
|
||
personal workspace, so the scoped path itself names the workspace and
|
||
the Release. A scoped path is served the Release's file, with
|
||
`Cache-Control: private, max-age=31536000, immutable` and
|
||
`Vary: Sec-Fetch-Site`, to a member of the workspace it names when the
|
||
Release is that workspace's, and is a 404 otherwise. A path with no scope is always the static file, whatever
|
||
the browser picked.
|
||
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
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"403":
|
||
$ref: '#/components/responses/SessionWorkspaceAccessDenied'
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
- {}
|
||
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:
|
||
agent:
|
||
description: 'Present when the caller passes the agent-in-app-experience rollout gate that /api/agent/* also enforces; the frontend mounts the agent panel only when it is. Absent when the gate is off and for unauthenticated requests. It answers the rollout question only: it does not reflect a scoped OAuth token''s agent scope or whether the agent service is currently reachable.'
|
||
properties:
|
||
state:
|
||
enum:
|
||
- ready
|
||
type: string
|
||
required:
|
||
- state
|
||
type: object
|
||
agent-free-use-message-placement:
|
||
default: control
|
||
description: Authenticated assignment for the Agent free-use notice placement experiment. Current Cloud responses include it and default to control when the caller is unauthenticated, evaluation is unavailable, or no treatment is assigned. It remains optional in the client contract, as agent-starter-prompt-set does, so older environments mid-rolling-deploy and partial feature fixtures fail closed rather than decoding an absent field as the empty string, which is not a member of this enum.
|
||
enum:
|
||
- control
|
||
- top-banner
|
||
- near-composer
|
||
- above-input
|
||
- inside-input
|
||
type: string
|
||
agent-starter-prompt-set:
|
||
default: control
|
||
description: Authenticated assignment for the Agent starter-prompt experiment. Current Cloud responses include it and default to control when the caller is unauthenticated, evaluation is unavailable, or no treatment is assigned. It remains optional in the client contract so older environments and partial feature fixtures fail closed. Reading this field does not constitute experiment exposure; the frontend emits the custom exposure event only after rendering the starter prompt surface.
|
||
enum:
|
||
- control
|
||
- test
|
||
type: string
|
||
billing_web_url:
|
||
description: Origin of the billing-web deployment paired with this Cloud environment (e.g. https://billing.comfy.org). Absent when BILLING_WEB_URL is not configured on the server, so a client can tell "not configured" from "configured as empty".
|
||
type: string
|
||
can_run_partner_nodes:
|
||
description: |-
|
||
Whether a partner/API-node workflow from THIS authenticated caller could run. It is ingest's own submit-time account-level decision published as a capability, resolved from the same authority ExecutePrompt uses, so a consumer never re-derives it from a tier table.
|
||
The two values are NOT symmetric, and a consumer that treats them as symmetric will be wrong.
|
||
false is sound: a partner-node submission from this caller would be refused. Usually that refusal is PARTNER_NODE_PAYMENT_REQUIRED, but a caller who is FREE for a further reason (an API key, a non-Google session under FreeTierRequireGoogleSignIn, or no job allowance on the legacy rail) is refused earlier and by a different code. Either way the workflow does not run, which is what the field answers.
|
||
true is narrower than it reads: the partner-node paywall is not what refuses this caller. Another gate still might — an inactive subscription, a blocked workspace and a BlockedSubscriptionTiers entry all report true, because their refusal is account-wide rather than about partner nodes, and so do the exemptions and the fail-open outcomes that make ExecutePrompt admit a submission at all (a partner-execution workspace, a disabled subscription check, a failed subscription lookup). Two per-prompt refusals are not modelled here at all, because this field is per-account and they are not: FreeTierBlockedModels (MODEL_PAYMENT_REQUIRED, named open-weights models) and the workspace partner-provider governance gate, which keys on which providers a prompt names and answers 403 for an enforcing workspace or 503 when its policy cannot be verified. A paid caller in a governance-restricted workspace therefore reads true here and is still refused at submit.
|
||
So: read false as "do not build with partner nodes" and true as "the partner gate will not stop you". Do not read true as "this caller can submit".
|
||
Absent for an unauthenticated caller (the decision is per-identity and there is none) and absent while AgentPartnerCapabilityEnabled is off, which is its default — resolving it costs an account-level authority read that this endpoint does not otherwise make. A consumer must treat absence as "unknown" and fail open, never as false.
|
||
Because absence carries that meaning, the field is only ever the authority's answer: unlike the flags beside it, it cannot be set from dynamic configuration, and it is removed from the response rather than left at a configured value when it is unresolvable. It is likewise absent from the WebSocket feature_flags push, which resolves no capability, so a client refreshing from the socket reads "unknown" and fails open rather than inheriting a stale answer.
|
||
type: boolean
|
||
deploy_to_cloud:
|
||
description: 'Local ComfyUI only: whether the UI should offer Deploy to Cloud. True when the server is not --offline and this installation has ever had a prompt queued by a non-browser client (a persistent marker in the user directory). A discovery hint only: it grants nothing, and the /api/deploy/* routes do not check it. Not settable with --feature-flag.'
|
||
type: boolean
|
||
x-runtime:
|
||
- local
|
||
free_tier_balance:
|
||
description: Free-tier job allowance for an authenticated non-paid (FREE-tier) user in the rollout. Absent for paid users and unauthenticated requests. Synthesized from config before a grant row exists so a brand-new user still sees their full allowance.
|
||
properties:
|
||
allowance:
|
||
description: Total free jobs granted for the current period
|
||
type: integer
|
||
remaining:
|
||
description: Free jobs remaining (allowance - used, floored at 0)
|
||
type: integer
|
||
used:
|
||
description: Free jobs consumed so far
|
||
type: integer
|
||
required:
|
||
- allowance
|
||
- used
|
||
- remaining
|
||
type: object
|
||
free_tier_offer:
|
||
description: The free-tier job allowance offered to new users, so a signed-out visitor sees the real offer before signing up. Same value for authenticated and unauthenticated requests. Absent when the free-tier allowance is disabled or zero.
|
||
properties:
|
||
job_allowance:
|
||
description: Number of free jobs granted to a new FREE-tier user
|
||
type: integer
|
||
requires_google_sign_in:
|
||
description: True when only Google-authenticated sessions receive the allowance; email/password signups get none.
|
||
type: boolean
|
||
required:
|
||
- job_allowance
|
||
- requires_google_sign_in
|
||
type: object
|
||
max_upload_size:
|
||
description: Maximum upload size in bytes
|
||
type: integer
|
||
new_free_tier_subscriptions:
|
||
description: Whether new free-tier subscriptions are enabled for this caller. Current servers always emit a boolean; clients should tolerate absence when talking to older servers that predate this declared field.
|
||
type: boolean
|
||
sso_enabled:
|
||
description: Global switch, the same for every caller and readable without credentials. When true, the frontend shows enterprise single sign-on (the SSO sign-in entry and SSO workspace states); when false it shows today's app. It gates no backend behaviour. Defaults to false.
|
||
type: boolean
|
||
stripe_publishable_key:
|
||
description: Stripe publishable key (pk_...) for the environment's Stripe account. Public by design (the secret key is never exposed here). Absent when STRIPE_PUBLISHABLE_KEY is not configured on the server, so a client can tell "not configured" from "configured as empty".
|
||
type: string
|
||
supports_preview_metadata:
|
||
description: Whether the server supports preview metadata
|
||
type: boolean
|
||
web_session_probe:
|
||
description: Global switch, the same for every caller and readable without credentials. When true, first-party sites send the credentialed /api/features read and take behaviour from its per-user unified_web_session. It grants nothing itself. Defaults to false.
|
||
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
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"403":
|
||
$ref: '#/components/responses/SessionWorkspaceAccessDenied'
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- {}
|
||
- WebSessionAuth: []
|
||
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
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"500":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Internal server error
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"401":
|
||
$ref: '#/components/responses/SessionUnauthorized'
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
"404":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: File not found or not a mask file
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Get related mask layer files
|
||
tags:
|
||
- file
|
||
/api/free:
|
||
post:
|
||
description: Frees GPU memory by unloading models and/or freeing the resident model cache.
|
||
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
|
||
/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
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"500":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Internal server error
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unauthorized - Authentication required
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
"500":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Internal server error
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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 for the recorded prompt, except the
|
||
canvas-format workflow graph: `extra_data.extra_pnginfo` is no longer
|
||
persisted, so it is not included in history records persisted after
|
||
that change (older records may still carry it). Callers that need the
|
||
workflow graph should use `GET /api/jobs/{job_id}`, which serves it
|
||
from the job's own stored workflow — `prompt_id` is the job ID, so it
|
||
can be passed straight through as `job_id`.
|
||
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
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unauthorized - Authentication required
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
"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
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Get history for specific prompt
|
||
tags:
|
||
- workflow
|
||
/api/i18n:
|
||
get:
|
||
description: Returns translation file URLs contributed by custom nodes, keyed by locale.
|
||
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
|
||
/api/interrupt:
|
||
post:
|
||
deprecated: true
|
||
description: |
|
||
Deprecated. Prefer the jobs-namespace cancel endpoints:
|
||
POST /api/jobs/{job_id}/cancel for a single job, or
|
||
POST /api/jobs/cancel to cancel jobs by ID.
|
||
|
||
Cancels one job of the authenticated user's. The body is optional, as
|
||
on ComfyUI's own /interrupt, and is never refused: it is read whatever
|
||
its Content-Type (a browser fetch with a string body sends text/plain),
|
||
up to 64 KiB, and never answers 400 or 415.
|
||
|
||
When the body is a JSON object whose `prompt_id` is a non-empty string
|
||
(the ComfyUI frontend sends `{"prompt_id": "<job id>"}` naming the job
|
||
it shows running), that job and no other, exactly as
|
||
POST /api/jobs/{job_id}/cancel acts on it: a pending or running job is
|
||
cancelled; one already finished or cancelling is left as it is (200,
|
||
nothing done); an ID that is not one of the
|
||
caller's jobs in this workspace, or is not a job ID (a 36-character
|
||
UUID) at all, returns 404 and cancels nothing.
|
||
|
||
In every other case the job is picked by queue order: no body, an
|
||
empty body, `{}`, a `prompt_id` that is absent, null, empty or not a
|
||
string, a body that is not a JSON object (malformed JSON, an array, a
|
||
non-JSON body), or a body longer than 64 KiB. The job, in order:
|
||
|
||
1. If a job is running on Cloud: the oldest such job.
|
||
2. Otherwise, if a job that runs on a Build's deployment (the platform
|
||
gateway) is running: the oldest one.
|
||
3. Otherwise (nothing running) the oldest pending job on Cloud, even
|
||
when an older pending job runs on a Build's deployment.
|
||
4. Otherwise the oldest pending job that runs on a Build's deployment.
|
||
|
||
The job is cancelled; for a job that runs on a Build's deployment, the
|
||
deployment is then asked to stop its run, best effort and after this
|
||
answers: not when the platform cannot be reached, or does not yet know
|
||
the API key the request was made with (the run then continues until it
|
||
ends on its own, and the job still ends cancelled).
|
||
operationId: interruptJob
|
||
responses:
|
||
"200":
|
||
description: |
|
||
Success - the job was cancelled, was already finished or
|
||
cancelling, or (without `prompt_id`) no active job was found
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unauthorized - Authentication required
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"404":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: |
|
||
`prompt_id` is not one of the caller's jobs in this workspace, or
|
||
is not a job ID (a 36-character UUID) at all. Code NOT_FOUND;
|
||
nothing was cancelled.
|
||
"500":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Internal server error
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Interrupt a job, the named one or the first active one
|
||
tags:
|
||
- queue
|
||
/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
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"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
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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.
|
||
Each job says what ran it (`executor`) and, for a job that ran on a
|
||
deployment, which deployment and Release (`deployment`). The `deployment`
|
||
field and the `JobDeployment` schema say when each is absent.
|
||
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: |
|
||
Opaque cursor for keyset pagination. Pass the `next_cursor` value
|
||
from a previous response to fetch the next page.
|
||
Cursor pagination is supported only when `sort_by=create_time`
|
||
(default). If `sort_by=execution_time`, `after` is ignored and
|
||
offset/limit pagination is used.
|
||
Cursors are opaque base64url payloads — clients should treat them
|
||
as strings and not parse the contents.
|
||
example: eyJzIjoiY3JlYXRlX3RpbWUiLCJ2IjoiMTcxNjIwMDAwMDAwMDAwMCIsImlkIjoiYTFiMmMzZDQtZTVmNi03YTg5LWIwYzEtZDJlM2Y0YTViNmM3In0
|
||
in: query
|
||
name: after
|
||
schema:
|
||
type: string
|
||
- deprecated: true
|
||
description: 'Pagination offset (0-based). Deprecated: prefer cursor-based pagination via `after`.'
|
||
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
|
||
"400":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Bad request (e.g. malformed pagination cursor).
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unauthorized - Authentication required
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
"500":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Internal server error
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: List jobs with pagination and filtering
|
||
tags:
|
||
- workflow
|
||
/api/jobs/{job_id}:
|
||
delete:
|
||
description: |
|
||
Delete a single job and every asset linked to it in one call. The client
|
||
sends a job delete and the backend fans out to the job's assets — the
|
||
client must not enumerate and delete the assets itself.
|
||
|
||
The deletion is directional, not symmetric: deleting a job deletes both
|
||
the job and its assets, but deleting an asset directly (via
|
||
`DELETE /api/assets/{id}`) leaves the job and its history record intact.
|
||
Asset visibility is never derived from the job's deletion state.
|
||
|
||
The job soft-delete is scoped to user-deletable jobs — the finished,
|
||
failed and cancelled states the Job Queue trash icon acts on (this includes
|
||
still-settling failed and mid-cancellation states, not only strictly
|
||
terminal ones), mirroring the legacy `POST /api/history` delete path this
|
||
endpoint replaces. A pending, in-progress or already-deleted job is left in
|
||
place and returns `204` as a no-op. Idempotent: a job already deleted, or
|
||
an asset already gone, is treated as a successful no-op.
|
||
|
||
Asset deletion is a best-effort fan-out of independent hard deletes and is
|
||
NOT atomic: if it aborts partway — a `409` for an in-use asset, or a `500`
|
||
— the assets deleted before the failure stay deleted while the job remains
|
||
in place. A retry re-runs the fan-out and is a no-op for the assets already
|
||
gone.
|
||
|
||
If a linked asset cannot be deleted because it is still referenced by
|
||
another resource (e.g. a workflow version), the endpoint surfaces
|
||
`409 ASSET_IN_USE` and leaves the job in place rather than silently
|
||
skipping the asset.
|
||
operationId: deleteJob
|
||
parameters:
|
||
- description: Job identifier (UUID)
|
||
in: path
|
||
name: job_id
|
||
required: true
|
||
schema:
|
||
format: uuid
|
||
type: string
|
||
responses:
|
||
"204":
|
||
description: Job and its assets deleted successfully, or the job was not in a deletable state (pending/in-progress/already-deleted) and no change was made (no-op)
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unauthorized - Authentication required
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"404":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Job not found or does not belong to the user
|
||
"409":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: 'A linked asset cannot be deleted because it is referenced by another resource, e.g. a workflow version (error code: ASSET_IN_USE); the job is left in place'
|
||
"500":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Internal server error
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Delete a job and its assets
|
||
tags:
|
||
- workflow
|
||
get:
|
||
description: |
|
||
Retrieve complete details for a specific job including workflow and outputs.
|
||
Used for detail views, workflow re-execution, and debugging.
|
||
The job says what ran it (`executor`) and, for a job that ran on a
|
||
deployment, which deployment and Release (`deployment`). The `deployment`
|
||
field and the `JobDeployment` schema say when each is absent.
|
||
operationId: getJobDetail
|
||
parameters:
|
||
- description: Job identifier (UUID)
|
||
in: path
|
||
name: job_id
|
||
required: true
|
||
schema:
|
||
format: uuid
|
||
type: string
|
||
- description: |
|
||
When present, each output item in the response receives a `short_url` field containing a short link for that asset. Omit this parameter (the default) to receive a response identical to the no-param baseline. The value selects the link's lifetime and auth model: use `ephemeral_tool_chain` for short-lived (≤5 minute) machine-to-machine handoffs — these are public bearer links where the link ID itself is the credential, so anyone holding the link can resolve it (intended for pasting into an agent/MCP tool chain); use `default` for durable (30 day) human-revisitable links, which are owner-gated and resolvable only by the authenticated owner. Links are always minted under the authenticated request owner's identity; the auth model is selected by the server and is never settable by the caller.
|
||
in: query
|
||
name: short_link
|
||
schema:
|
||
enum:
|
||
- ephemeral_tool_chain
|
||
- default
|
||
type: string
|
||
x-runtime:
|
||
- cloud
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/JobDetailResponse'
|
||
description: Success - Job details retrieved
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"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
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Get full job details
|
||
tags:
|
||
- workflow
|
||
/api/jobs/{job_id}/assets:
|
||
get:
|
||
description: |
|
||
Retrieve a paginated list of the assets produced by a specific job,
|
||
enriched with the per-output node context (`node_id`, `output_key`,
|
||
`output_index`) correlated from the job's execution outputs by content
|
||
hash. Unlike `GET /api/assets?job_ids={id}`, this endpoint is scoped to a
|
||
single job and carries node-level placement, making it suited to job
|
||
output views rather than the general asset browser. Returns an empty
|
||
`assets` array for jobs that produced no assets.
|
||
operationId: getJobAssets
|
||
parameters:
|
||
- description: Job identifier (UUID)
|
||
in: path
|
||
name: job_id
|
||
required: true
|
||
schema:
|
||
format: uuid
|
||
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
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/JobAssetsResponse'
|
||
description: Success - Job 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 - Authentication required
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
"404":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Job not found or does not belong to the user
|
||
"500":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Internal server error
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: List a job's output assets
|
||
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.
|
||
|
||
A job that runs on a Build's deployment (the platform gateway) is
|
||
cancelled the same way, and the deployment is then asked to stop its
|
||
run, best effort and after this answers: not when the platform cannot
|
||
be reached, or does not yet know the API key the request was made
|
||
with. The run then continues until it ends on its own, and the job
|
||
still ends cancelled.
|
||
A job whose run has finished and whose result is being saved is left
|
||
to finish, as a finished job is.
|
||
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/ErrorResponse'
|
||
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
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"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
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Cancel a job
|
||
tags:
|
||
- workflow
|
||
/api/jobs/cancel:
|
||
post:
|
||
description: |
|
||
Cancel one or more jobs for the authenticated user in a single request.
|
||
|
||
State-agnostic: cancels both pending and running jobs (both transition to
|
||
the cancelled state via the same mechanism as the single-job endpoint).
|
||
|
||
Idempotent per job: a job already in a terminal or cancelling state is a
|
||
no-op and simply will not appear in the returned `cancelled` list.
|
||
|
||
Fail-fast on unknown IDs: if any provided job ID does not exist for this
|
||
user, the request returns 404 and no jobs are cancelled. This surfaces
|
||
bad IDs to the caller rather than silently dropping them.
|
||
|
||
A job that runs on a Build's deployment (the platform gateway) is
|
||
cancelled the same way, and the deployment is then asked to stop its
|
||
run, best effort and after this answers: not when the platform cannot
|
||
be reached, or does not yet know the API key the request was made
|
||
with. The run then continues until it ends on its own, and the job
|
||
still ends cancelled.
|
||
A job whose run has finished and whose result is being saved is left
|
||
to finish, as a finished job is.
|
||
|
||
This is the canonical batch-cancel endpoint. The delete operation on
|
||
POST /api/queue is deprecated in favour of this.
|
||
operationId: cancelJobs
|
||
requestBody:
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/JobsCancelRequest'
|
||
required: true
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/JobsCancelResponse'
|
||
description: Success - cancel requests dispatched (or jobs were already terminal)
|
||
"400":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Bad Request - job_ids is missing, empty, exceeds the maximum count, or contains an invalid UUID
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unauthorized - Authentication required
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"404":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: One or more job IDs not found for this user (no jobs cancelled)
|
||
"500":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Internal server error - cancellation failed
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Cancel multiple jobs
|
||
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. For a browser that
|
||
picked a developer-platform deployment (the cookie PUT
|
||
/api/workspaces/{id}/deployment sets) the catalog is that of the
|
||
Release the deployment runs now, fetched from comfy-builder; otherwise
|
||
it is Cloud's own.
|
||
operationId: getNodeInfo
|
||
parameters:
|
||
- description: |
|
||
Also list the models the caller can run that the models config
|
||
does not: their own imported models and the public model assets the
|
||
asset library shows them (assets tagged `models`), each in the model
|
||
dropdown of the directory it installs under, so a client that
|
||
validates widget values against this catalog accepts a model that
|
||
would run. Off by default: the frontend reads these models through
|
||
the asset browser instead.
|
||
in: query
|
||
name: include_user_models
|
||
schema:
|
||
default: false
|
||
type: boolean
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
additionalProperties:
|
||
$ref: '#/components/schemas/NodeInfo'
|
||
type: object
|
||
description: Success
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"401":
|
||
$ref: '#/components/responses/SessionUnauthorized'
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unauthorized
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
"500":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Internal server error
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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, or `code` `workspace_id_invalid` (see SessionWorkspaceIDInvalid).
|
||
"401":
|
||
$ref: '#/components/responses/SessionUnauthorized'
|
||
"402":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/PromptErrorResponse'
|
||
description: 'The account''s plan does not allow this submission; nothing was queued and retrying without changing the plan never succeeds. Disambiguated by the body''s `error.type`, NOT by parsing `error.message`: `PAYMENT_REQUIRED` (no active subscription, no funds, blocked tier), `CLOUD_SUBSCRIPTION_REQUIRED`, `FREE_TIER_EXHAUSTED`, `PARTNER_NODE_PAYMENT_REQUIRED`, or `MODEL_PAYMENT_REQUIRED`.'
|
||
"403":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/PromptErrorResponse'
|
||
description: Workspace governance policy blocks one or more partner providers (error.type PARTNER_NODE_DISABLED; error.class_types lists the offending nodes, error.providers the disabled providers), or a refused request with `code` and `message` (see SessionWriteForbidden).
|
||
"413":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/PromptErrorResponse'
|
||
description: Workflow JSON too large
|
||
"429":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/PromptErrorResponse'
|
||
description: 'Retryable backpressure, disambiguated by the body''s `error.type`: `QUEUE_LIMIT` (this workspace''s bounded job queue is full - retrying after some queued jobs complete will succeed) or `FREE_TIER_UNAVAILABLE` (the free tier is switched off for now - retrying once it is back will succeed), or `BILLING_UNAVAILABLE` with `error.reason` `funds_unavailable` (ingest got no billing verdict for the workspace because the billing service was unreachable or rejected the check, or the billing-status read behind a no-funds verdict failed - nothing was queued, and retrying the same submission after `Retry-After` seconds will succeed once billing answers). Of the billing outcomes, a plan or billing policy refusal is a 402; only billing being unavailable is a 429. For a browser that picked a developer-platform deployment, also `PLATFORM_REFUSED` with `error.details` `deployment_not_ready` (the deployment is on its way to ready - nothing was queued, and retrying after `Retry-After` seconds will succeed once it is ready) or another platform 429 passed through.'
|
||
headers:
|
||
Retry-After:
|
||
description: Seconds to wait before retrying. Sent with `BILLING_UNAVAILABLE` and with a `deployment_not_ready` that ingest answers before any job is written.
|
||
schema:
|
||
type: integer
|
||
"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
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unauthorized - Authentication required
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
"500":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Invalid request parameters
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Get queue information
|
||
tags:
|
||
- queue
|
||
post:
|
||
deprecated: true
|
||
description: |
|
||
Deprecated. Prefer the jobs-namespace cancel endpoints:
|
||
POST /api/jobs/cancel for cancelling jobs by ID, and
|
||
POST /api/jobs/{job_id}/cancel for a single job.
|
||
|
||
Cancel specific jobs by ID (the `delete` field) or clear all pending
|
||
jobs in the queue (the `clear` field). Despite the `delete` naming, this
|
||
does not delete anything — listed jobs transition to the cancelled state,
|
||
and `delete` cancels both pending and running jobs (not pending-only as
|
||
previously documented). Job-by-ID cancellation is superseded by
|
||
POST /api/jobs/cancel; `clear` has no jobs-namespace replacement yet.
|
||
|
||
Jobs that run on a Build's deployment (the platform gateway) are
|
||
cancelled the same way, by `delete` and by `clear`, and the deployment
|
||
is then asked to stop their runs, best effort and after this answers:
|
||
not when the platform cannot be reached, or does not yet know the API
|
||
key the request was made with. A run then continues until it ends on
|
||
its own, and its job still ends cancelled.
|
||
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
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"500":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Internal server error
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Manage queue operations
|
||
tags:
|
||
- queue
|
||
/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
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unauthorized
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unauthorized
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
"404":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Setting not found
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
"500":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Internal server error
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unauthorized - Authentication required
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
"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
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: List background tasks
|
||
tags:
|
||
- task
|
||
/api/tasks/{task_id}:
|
||
delete:
|
||
description: Cancels an authenticated user's queued or running asset download.
|
||
operationId: cancelTask
|
||
parameters:
|
||
- in: path
|
||
name: task_id
|
||
required: true
|
||
schema:
|
||
format: uuid
|
||
type: string
|
||
responses:
|
||
"204":
|
||
description: Cancellation accepted
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unauthorized
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"404":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Task not found
|
||
"409":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Task cannot be cancelled
|
||
"500":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Cancellation failed
|
||
"503":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Task queue unavailable
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Cancel an asset download task
|
||
tags:
|
||
- task
|
||
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
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unauthorized - Authentication required
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
"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
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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.
|
||
So is an upload too large to ever fit the pod's upload memory budget
|
||
("upload exceeds the maximum buffered size").
|
||
When the pod is already buffering its whole upload memory budget the
|
||
upload is shed with HTTP 503 and a Retry-After header; retry it.
|
||
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
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"500":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Internal server error
|
||
"503":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Upload buffer budget exhausted on this pod; retry after the Retry-After seconds. `code` is `UPLOAD_BUDGET_EXHAUSTED`.
|
||
headers:
|
||
Retry-After:
|
||
description: Seconds to wait before retrying
|
||
schema:
|
||
type: integer
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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.
|
||
So is an upload too large to ever fit the pod's upload memory budget
|
||
("upload exceeds the maximum buffered size").
|
||
When the pod is already buffering its whole upload memory budget the
|
||
upload is shed with HTTP 503 and a Retry-After header; retry it.
|
||
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
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"500":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Internal server error
|
||
"503":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Upload buffer budget exhausted on this pod; retry after the Retry-After seconds. `code` is `UPLOAD_BUDGET_EXHAUSTED`.
|
||
headers:
|
||
Retry-After:
|
||
description: Seconds to wait before retrying
|
||
schema:
|
||
type: integer
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unauthorized
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
text/plain:
|
||
schema:
|
||
type: string
|
||
description: Bad request (e.g., invalid filename).
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
text/plain:
|
||
schema:
|
||
type: string
|
||
description: Unauthorized.
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
"404":
|
||
content:
|
||
text/plain:
|
||
schema:
|
||
type: string
|
||
description: File not found or invalid path.
|
||
"500":
|
||
content:
|
||
text/plain:
|
||
schema:
|
||
type: string
|
||
description: General error
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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).
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
text/plain:
|
||
schema:
|
||
type: string
|
||
description: Unauthorized.
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"404":
|
||
content:
|
||
text/plain:
|
||
schema:
|
||
type: string
|
||
description: File not found.
|
||
"500":
|
||
content:
|
||
text/plain:
|
||
schema:
|
||
type: string
|
||
description: Internal server error.
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
text/plain:
|
||
schema:
|
||
type: string
|
||
description: Bad request (e.g., invalid filename).
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
text/plain:
|
||
schema:
|
||
type: string
|
||
description: Unauthorized.
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
"404":
|
||
content:
|
||
text/plain:
|
||
schema:
|
||
type: string
|
||
description: File not found or invalid path.
|
||
"500":
|
||
content:
|
||
text/plain:
|
||
schema:
|
||
type: string
|
||
description: General error
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
text/plain:
|
||
schema:
|
||
type: string
|
||
description: Missing or invalid 'file' parameter.
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
text/plain:
|
||
schema:
|
||
type: string
|
||
description: Unauthorized.
|
||
"403":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
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
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
text/plain:
|
||
schema:
|
||
type: string
|
||
description: Missing or invalid parameters.
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
text/plain:
|
||
schema:
|
||
type: string
|
||
description: Unauthorized.
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"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
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Move or rename a user data file
|
||
tags:
|
||
- user
|
||
/api/userdata/{file}/publish:
|
||
delete:
|
||
description: |-
|
||
Deletes the personal (URL) share for a workflow identified by its userdata path, retiring its `?share=<id>` link and the published snapshots behind it. Hub publishes are unaffected — those are revoked via `DELETE /api/hub/workflows/{share_id}`.
|
||
|
||
Note the asymmetry with `GET /api/userdata/{file}/publish` on this same path: that handler resolves the hub publish in preference to the URL one, so the `share_id` it reports is not necessarily the share this endpoint revokes. A hub-only publish reports a `share_id` there but gets a 404 here, and a workflow published on both channels gets a 204 here while the hub link it was showing keeps resolving.
|
||
operationId: deleteUserdataFilePublish
|
||
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:
|
||
"204":
|
||
description: Share revoked
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unauthorized
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"404":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Workflow or share not found
|
||
"500":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Internal server error
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Revoke the personal share link for a workflow file
|
||
tags:
|
||
- workflows
|
||
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)
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unauthorized
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
"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
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"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
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unauthorized
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: ComfyUI userdata storage info
|
||
tags:
|
||
- user
|
||
/api/v1/catalog/agents:
|
||
get:
|
||
operationId: getCatalogAgentInstructions
|
||
responses:
|
||
"200":
|
||
content:
|
||
text/plain:
|
||
schema:
|
||
type: string
|
||
description: Editing instructions from this deployed catalog API build
|
||
"503":
|
||
description: Catalog disabled or unavailable
|
||
security: []
|
||
summary: Agent instructions for editing Comfy Content Catalog JSON
|
||
tags:
|
||
- site-catalog
|
||
x-required-permissions: []
|
||
/api/v1/catalog/authoring-context:
|
||
get:
|
||
description: Read-only private staff verification for authoring clients. Returns the verified actor, canonical owner scope, independent edit/apply grants and current catalog tokens. Creates or refreshes no session, cookie, credential, content or approval. Does not return a legacy review projection. Every mutation must still reauthorize and check exact CAS. No query parameters.
|
||
operationId: getCCCAuthoringContext
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCAuthoringContext'
|
||
description: Current verified authoring context; private no-store
|
||
"400":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unsupported query parameters; or `code` `workspace_id_invalid` (see SessionWorkspaceIDInvalid).
|
||
"401":
|
||
$ref: '#/components/responses/SessionUnauthorized'
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
"503":
|
||
description: Dedicated catalog unavailable
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Verify current staff authoring permissions and catalog state
|
||
tags:
|
||
- site-catalog
|
||
x-permission-match: any
|
||
x-required-permissions:
|
||
- comfy_site.edit
|
||
- comfy_site.apply
|
||
/api/v1/catalog/cards:
|
||
get:
|
||
operationId: listCCCWebsiteCards
|
||
parameters:
|
||
- description: Optional exact public cache version from public-authority for an initial page. Cursor continuations are not cache fills. Invalid, superseded or cursor-bearing pins fail with 409. A guarded response is returned only when the version is unchanged before and after complete presentation.
|
||
in: header
|
||
name: X-Comfy-Catalog-Authority
|
||
schema:
|
||
type: string
|
||
- in: query
|
||
name: kind
|
||
required: true
|
||
schema:
|
||
enum:
|
||
- MODEL
|
||
- WORKFLOW
|
||
- APP
|
||
type: string
|
||
- in: query
|
||
name: limit
|
||
schema:
|
||
default: 24
|
||
maximum: 24
|
||
minimum: 1
|
||
type: integer
|
||
- in: query
|
||
name: cursor
|
||
schema:
|
||
maxLength: 4096
|
||
type: string
|
||
- in: query
|
||
name: locale
|
||
schema:
|
||
default: en
|
||
enum:
|
||
- en
|
||
- zh-CN
|
||
type: string
|
||
- in: query
|
||
name: q
|
||
schema:
|
||
maxLength: 300
|
||
type: string
|
||
- in: query
|
||
name: sort
|
||
schema:
|
||
default: popular
|
||
enum:
|
||
- popular
|
||
- name
|
||
- priceAsc
|
||
- priceDesc
|
||
type: string
|
||
- explode: true
|
||
in: query
|
||
name: category
|
||
schema:
|
||
items:
|
||
maxLength: 200
|
||
type: string
|
||
maxItems: 30
|
||
type: array
|
||
style: form
|
||
- explode: true
|
||
in: query
|
||
name: model
|
||
schema:
|
||
items:
|
||
maxLength: 200
|
||
type: string
|
||
maxItems: 30
|
||
type: array
|
||
style: form
|
||
- explode: true
|
||
in: query
|
||
name: use
|
||
schema:
|
||
items:
|
||
maxLength: 200
|
||
type: string
|
||
maxItems: 30
|
||
type: array
|
||
style: form
|
||
- explode: true
|
||
in: query
|
||
name: modality
|
||
schema:
|
||
items:
|
||
maxLength: 200
|
||
type: string
|
||
maxItems: 30
|
||
type: array
|
||
style: form
|
||
- explode: true
|
||
in: query
|
||
name: provider
|
||
schema:
|
||
items:
|
||
maxLength: 200
|
||
type: string
|
||
maxItems: 30
|
||
type: array
|
||
style: form
|
||
- explode: true
|
||
in: query
|
||
name: capability
|
||
schema:
|
||
items:
|
||
maxLength: 200
|
||
type: string
|
||
maxItems: 30
|
||
type: array
|
||
style: form
|
||
- description: Only Live public cards credited to this creator username (case-insensitive)
|
||
in: query
|
||
name: author
|
||
schema:
|
||
maxLength: 30
|
||
minLength: 1
|
||
type: string
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCWebsiteCardsPage'
|
||
description: At most 24 card summaries; no graphs, inputs, examples or long bodies. Anonymous responses omit total, generation and facet counts. Cursors are audience, filter, clock and state bound and expire after five minutes.
|
||
"400":
|
||
description: Invalid or unsupported query or cursor
|
||
"403":
|
||
description: Verified staff permission required for Preview
|
||
"409":
|
||
description: Public authority or cursor selection changed or expired; restart from current authority
|
||
"503":
|
||
description: Catalog unavailable or card budget exceeded
|
||
security: []
|
||
summary: Read bounded website card summaries
|
||
tags:
|
||
- site-catalog
|
||
x-required-permissions: []
|
||
/api/v1/catalog/creators:
|
||
get:
|
||
description: Creators that have at least one Live public Hub workflow, ordered by username. Public display fields only.
|
||
operationId: listCCCCreators
|
||
parameters:
|
||
- in: query
|
||
name: limit
|
||
schema:
|
||
default: 24
|
||
maximum: 100
|
||
minimum: 1
|
||
type: integer
|
||
- in: query
|
||
name: cursor
|
||
schema:
|
||
maxLength: 200
|
||
type: string
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCCreatorsPage'
|
||
description: One page of creators
|
||
"400":
|
||
description: Invalid or unsupported query or cursor
|
||
"503":
|
||
description: Catalog unavailable
|
||
security: []
|
||
summary: List creators with Live public workflows
|
||
tags:
|
||
- site-catalog
|
||
x-required-permissions: []
|
||
/api/v1/catalog/creators/{username}:
|
||
get:
|
||
description: The username match is case-insensitive. A creator without a Live public Hub workflow is not found.
|
||
operationId: getCCCCreator
|
||
parameters:
|
||
- in: path
|
||
name: username
|
||
required: true
|
||
schema:
|
||
maxLength: 30
|
||
minLength: 1
|
||
type: string
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCCreatorProfile'
|
||
description: Public creator profile
|
||
"400":
|
||
description: Unsupported query parameter
|
||
"404":
|
||
description: No creator with a Live public workflow has this username
|
||
"503":
|
||
description: Catalog unavailable
|
||
security: []
|
||
summary: Read one creator's public profile
|
||
tags:
|
||
- site-catalog
|
||
x-required-permissions: []
|
||
/api/v1/catalog/docs:
|
||
get:
|
||
description: Read-only HTML rendered from the deployed catalog contract. No credential collection or execution console.
|
||
operationId: getCatalogDocs
|
||
responses:
|
||
"200":
|
||
content:
|
||
text/html:
|
||
schema:
|
||
type: string
|
||
description: Build-coupled catalog instructions, permissions and endpoint contracts
|
||
"503":
|
||
description: Catalog disabled or unavailable
|
||
security: []
|
||
summary: Readable catalog-only API documentation
|
||
tags:
|
||
- site-catalog
|
||
x-required-permissions: []
|
||
/api/v1/catalog/draft/batch:
|
||
post:
|
||
description: One expected Draft and 1–100 flat documents. Omit uid for creates; existing items require uid and expected_revision_uid. Duplicate targets and per-item Draft overrides are rejected. Any failure rolls back every item, generation, audit and idempotency result. Media upload remains separate.
|
||
operationId: batchCCCItems
|
||
parameters:
|
||
- in: header
|
||
name: Idempotency-Key
|
||
required: true
|
||
schema:
|
||
maxLength: 200
|
||
minLength: 1
|
||
type: string
|
||
requestBody:
|
||
content:
|
||
application/json:
|
||
schema:
|
||
additionalProperties: false
|
||
properties:
|
||
expected_draft_rev:
|
||
format: int64
|
||
minimum: 1
|
||
type: integer
|
||
items:
|
||
items:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
maxItems: 100
|
||
minItems: 1
|
||
type: array
|
||
required:
|
||
- expected_draft_rev
|
||
- items
|
||
type: object
|
||
x-go-type: CCCJSON
|
||
required: true
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
items:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
type: array
|
||
description: Flat immutable edits in request order; retry returns identical UIDs/tokens
|
||
"400":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: Structured validation failure with item field paths
|
||
"401":
|
||
$ref: '#/components/responses/SessionUnauthorized'
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"404":
|
||
description: Existing target absent from owner-scoped Draft
|
||
"409":
|
||
description: Stale Draft/edit token or idempotency mismatch
|
||
"503":
|
||
description: Dedicated catalog unavailable
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Save bounded Content edits atomically
|
||
tags:
|
||
- site-catalog
|
||
x-required-permissions:
|
||
- comfy_site.edit
|
||
/api/v1/catalog/draft/discard-changes:
|
||
post:
|
||
description: Requires comfy_site.edit, an explicit confirmed selection of at most 100 unique UID/exact-version pairs, reviewed Live/Draft/generation, full matching filter/count/digest and Idempotency-Key. Restores selected Live JSON and exact media reference metadata through new immutable Draft saves; never-published additions become retained tombstones. No hard deletion, blob deletion, publication, inherited approval or change to Live/projection/unselected saves. Remaining Draft dependencies and pins are validated in the same state-locked transaction; conflicts fail all changes with field errors. Effective cancellations/restores leave the pending queue. No query parameters. Request maximum256KiB. Private/no-store.
|
||
operationId: discardCCCChanges
|
||
parameters:
|
||
- in: header
|
||
name: Idempotency-Key
|
||
required: true
|
||
schema:
|
||
maxLength: 200
|
||
minLength: 1
|
||
type: string
|
||
- in: header
|
||
name: Prefer
|
||
schema:
|
||
enum:
|
||
- return=minimal
|
||
type: string
|
||
requestBody:
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
required: true
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: Updated complete unfiltered private staging snapshot and global unresolved_count
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"401":
|
||
$ref: '#/components/responses/SessionUnauthorized'
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"409":
|
||
description: Stale state/selection/exact version or idempotency mismatch; no partial discard
|
||
"422":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: Invalid confirmed selection or remaining Draft dependency/pin conflict; no partial discard
|
||
"503":
|
||
description: Catalog unavailable
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Atomically discard selected Draft changes without deleting Live content
|
||
tags:
|
||
- site-catalog
|
||
x-required-permissions:
|
||
- comfy_site.edit
|
||
/api/v1/catalog/draft/final-review:
|
||
get:
|
||
description: Read-only publisher review of the complete selective candidate. Deferred changes are listed separately and restored to Live values for structural/reference checks. Returns state and selection_digest binding every exact save and decision. Any unfinished review or invalid dependency rejects the candidate. Does not publish, certify external delivery or functional evidence, or start paid execution. No query parameters are supported. Change items carry saved_at, the RFC3339 UTC save time of their exact revision (display only, not in the digest).
|
||
operationId: getCCCFinalReview
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: Private exact approved changes, deferred work, state and selection digest
|
||
"400":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unsupported query parameters; or `code` `workspace_id_invalid` (see SessionWorkspaceIDInvalid).
|
||
"401":
|
||
$ref: '#/components/responses/SessionUnauthorized'
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
"422":
|
||
description: Unreviewed work, no approved changes, or invalid selective candidate
|
||
"503":
|
||
description: Dedicated catalog unavailable
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Review the exact approved additions, modifications and deletions
|
||
tags:
|
||
- site-catalog
|
||
x-required-permissions:
|
||
- comfy_site.apply
|
||
post:
|
||
description: Body contains exact review state and a nonempty unique selected_uids set bounded to 5000. Stored editorial decisions are ignored. Changes contains only checked pending saves; deferred contains all unchecked work. The digest binds the canonical checked set and exact selected versions at this state. Invalid selected dependencies reject the whole candidate. No authoring, approval, audit, retry or publication writes. Private/no-store. Change items carry saved_at, the RFC3339 UTC save time of their exact revision (display only, not in the digest).
|
||
operationId: reviewCCCCheckedPublication
|
||
requestBody:
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
required: true
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: Exact checked changes and unchecked private work with state and selection digest
|
||
"400":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unsupported query parameters; or `code` `workspace_id_invalid` (see SessionWorkspaceIDInvalid).
|
||
"401":
|
||
$ref: '#/components/responses/SessionUnauthorized'
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"409":
|
||
description: Stale reviewed state or selected item no longer pending
|
||
"422":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: Invalid explicit selection or candidate dependencies; bounded field_errors include the affected resource_uid when known
|
||
"503":
|
||
description: Dedicated catalog unavailable
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Read-only review of an explicit checked publication candidate
|
||
tags:
|
||
- site-catalog
|
||
x-required-permissions:
|
||
- comfy_site.apply
|
||
/api/v1/catalog/draft/final-review/receipt:
|
||
post:
|
||
description: Same strict review state and selected_uids input and complete candidate validation as POST final-review. Returns no documents, presentation or unchecked IDs. selected_versions_digest is lowercase SHA256 of compact JSON ["ccc-checked-review-receipt-v1",[live_rev,draft_rev,draft_generation],[[uid,revision_uid],...]] with canonical UUID pairs sorted by ASCII UID. Clients must compare state, count and this digest against their frozen checked snapshot before displaying confirmation. selection_digest binds the existing publish request; publication revalidates state and candidate. Read-only, private/no-store; no approval, audit, retry or publication writes. Maximum request256KiB; response below16KiB.
|
||
operationId: reviewCCCCheckedReceipt
|
||
requestBody:
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
required: true
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCCheckedReviewReceipt'
|
||
description: Exact checked-version receipt after complete candidate validation
|
||
"400":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unsupported query parameters; or `code` `workspace_id_invalid` (see SessionWorkspaceIDInvalid).
|
||
"401":
|
||
$ref: '#/components/responses/SessionUnauthorized'
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"409":
|
||
description: Stale reviewed state or selected item no longer pending
|
||
"422":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: Invalid explicit selection or candidate dependencies; bounded field_errors include affected resource_uid
|
||
"503":
|
||
description: Dedicated catalog unavailable
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Validate checked publication and return a compact exact-version receipt
|
||
tags:
|
||
- site-catalog
|
||
x-required-permissions:
|
||
- comfy_site.apply
|
||
/api/v1/catalog/draft/items:
|
||
post:
|
||
description: Flat typed document with expected_draft_rev, type and schema_version. Server assigns UID and fixed organization owner; author_uid is editable versioned account attribution, defaulting to the creator. CONTENT v2 adds a short title/description, long_description, FAQ, runs/downloads and workflow facts. Exact type schemas and field values are validated before saving; historical v1 remains readable. Media requires verified upload instead. Private; no implicit paid validation.
|
||
operationId: createCCCItem
|
||
parameters:
|
||
- in: header
|
||
name: Idempotency-Key
|
||
required: true
|
||
schema:
|
||
maxLength: 200
|
||
minLength: 1
|
||
type: string
|
||
requestBody:
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
required: true
|
||
responses:
|
||
"201":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: Flat immutable Content edit with exact concurrency tokens
|
||
"400":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: Structured document or token validation errors
|
||
"401":
|
||
$ref: '#/components/responses/SessionUnauthorized'
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"409":
|
||
description: Stale Draft/edit token or idempotency payload mismatch
|
||
"503":
|
||
description: Dedicated catalog unavailable
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Create a Content identity and immutable Draft edit
|
||
tags:
|
||
- site-catalog
|
||
x-required-permissions:
|
||
- comfy_site.edit
|
||
/api/v1/catalog/draft/items/{uid}:
|
||
delete:
|
||
operationId: deleteCCCItem
|
||
parameters:
|
||
- in: path
|
||
name: uid
|
||
required: true
|
||
schema:
|
||
format: uuid
|
||
type: string
|
||
- in: header
|
||
name: Idempotency-Key
|
||
required: true
|
||
schema:
|
||
maxLength: 200
|
||
minLength: 1
|
||
type: string
|
||
requestBody:
|
||
content:
|
||
application/json:
|
||
schema:
|
||
additionalProperties: false
|
||
properties:
|
||
expected_draft_rev:
|
||
format: int64
|
||
minimum: 1
|
||
type: integer
|
||
expected_revision_uid:
|
||
format: uuid
|
||
type: string
|
||
required:
|
||
- expected_draft_rev
|
||
- expected_revision_uid
|
||
type: object
|
||
x-go-type: CCCJSON
|
||
required: true
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: Flat retained Content with is_deleted=true and new exact edit token
|
||
"400":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: Invalid tokens; generic Media mutation refused
|
||
"401":
|
||
$ref: '#/components/responses/SessionUnauthorized'
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"404":
|
||
description: Resource absent from owner-scoped Draft
|
||
"409":
|
||
description: Stale Draft/edit token or idempotency mismatch
|
||
"503":
|
||
description: Dedicated catalog unavailable
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Append a Draft tombstone without erasing history
|
||
tags:
|
||
- site-catalog
|
||
x-required-permissions:
|
||
- comfy_site.edit
|
||
get:
|
||
description: Owner-scoped private read, including retained tombstones. Returns flat authored JSON plus read-only metadata and expected_draft_rev/expected_revision_uid from a single snapshot. The record catalog_rev may be older than Draft; use expected_draft_rev for saves. The response saves back unchanged, since PUT accepts this exact body, and its read-only metadata (uid, owner_uid, creator_uid, revision_uid, catalog_rev, edit_sequence, digest, saved_by_uid, draft_generation, saved_at, is_deleted false) is ignored, never applied; author_uid is the authored credited author. saved_at is this exact edit's save time (RFC3339 UTC). Reading does not invalidate approval or create history. No query parameters.
|
||
operationId: getCCCDraftItem
|
||
parameters:
|
||
- in: path
|
||
name: uid
|
||
required: true
|
||
schema:
|
||
format: uuid
|
||
type: string
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: Current complete authored JSON with exact working-save tokens and read-only metadata
|
||
"400":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Invalid UID or unsupported query parameters; or `code` `workspace_id_invalid` (see SessionWorkspaceIDInvalid).
|
||
"401":
|
||
$ref: '#/components/responses/SessionUnauthorized'
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
"404":
|
||
description: Resource missing or outside canonical owner scope
|
||
"503":
|
||
description: Dedicated catalog unavailable
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Fetch current Draft JSON and exact save tokens without making a copy
|
||
tags:
|
||
- site-catalog
|
||
x-permission-match: any
|
||
x-required-permissions:
|
||
- comfy_site.edit
|
||
- comfy_site.apply
|
||
put:
|
||
description: Complete authored JSON plus expected_draft_rev, expected_revision_uid, type and schema_version. The exact getCCCDraftItem body is a valid request (GET then PUT). Read-only metadata keys from that read are accepted and ignored, never applied; owner, creator, editor and identity stay server-assigned. is_deleted true is refused (use restore). Unknown authored fields are rejected.
|
||
operationId: replaceCCCItem
|
||
parameters:
|
||
- in: path
|
||
name: uid
|
||
required: true
|
||
schema:
|
||
format: uuid
|
||
type: string
|
||
- in: header
|
||
name: Idempotency-Key
|
||
required: true
|
||
schema:
|
||
maxLength: 200
|
||
minLength: 1
|
||
type: string
|
||
requestBody:
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
required: true
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: New immutable edit; owner stays fixed, author attribution is versioned and saved_by_uid records the actual editor
|
||
"400":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: Structured document or token validation errors
|
||
"401":
|
||
$ref: '#/components/responses/SessionUnauthorized'
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"404":
|
||
description: Resource not found in the selected Draft/owner scope
|
||
"409":
|
||
description: Stale Draft/edit token or idempotency payload mismatch
|
||
"503":
|
||
description: Dedicated catalog unavailable
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Append a complete flat JSON replacement to Draft
|
||
tags:
|
||
- site-catalog
|
||
x-required-permissions:
|
||
- comfy_site.edit
|
||
/api/v1/catalog/draft/items/{uid}/restore:
|
||
post:
|
||
description: Source edit must belong to the same UID and organization. Append and revalidate a new immutable Draft save; never edit history or publish. Generic Media restore remains unavailable until verified media authoring is connected.
|
||
operationId: restoreCCCItemVersion
|
||
parameters:
|
||
- in: path
|
||
name: uid
|
||
required: true
|
||
schema:
|
||
format: uuid
|
||
type: string
|
||
- in: header
|
||
name: Idempotency-Key
|
||
required: true
|
||
schema:
|
||
maxLength: 200
|
||
minLength: 1
|
||
type: string
|
||
requestBody:
|
||
content:
|
||
application/json:
|
||
schema:
|
||
additionalProperties: false
|
||
properties:
|
||
expected_draft_rev:
|
||
format: int64
|
||
minimum: 1
|
||
type: integer
|
||
expected_revision_uid:
|
||
format: uuid
|
||
type: string
|
||
source_revision_uid:
|
||
format: uuid
|
||
type: string
|
||
required:
|
||
- expected_draft_rev
|
||
- expected_revision_uid
|
||
- source_revision_uid
|
||
type: object
|
||
x-go-type: CCCJSON
|
||
required: true
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: New immutable forward Draft save and exact concurrency tokens
|
||
"400":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: Invalid tokens or unsupported historical schema
|
||
"401":
|
||
$ref: '#/components/responses/SessionUnauthorized'
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"404":
|
||
description: Current or source edit not found in the target UID/owner scope
|
||
"409":
|
||
description: Stale Draft/edit token or idempotency mismatch
|
||
"503":
|
||
description: Dedicated catalog unavailable
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Restore an exact retained Content save into Draft
|
||
tags:
|
||
- site-catalog
|
||
x-required-permissions:
|
||
- comfy_site.edit
|
||
/api/v1/catalog/draft/media:
|
||
post:
|
||
description: Staff edit permission required. Multipart with exactly one file or upload_token; server verifies SHA-256, MIME, size and dimensions. upload_token finalizes bytes sent through upload-url directly to private storage, up to the configured 300 MiB limit. Inline multipart bytes retain the 65 MiB HTTP envelope. New UID per intentional upload even for identical bytes; idempotent retry returns original result. Private storage required. Videos include verified duration and dimensions. No public URL or paid execution.
|
||
operationId: uploadCCCMedia
|
||
parameters:
|
||
- in: header
|
||
name: Idempotency-Key
|
||
required: true
|
||
schema:
|
||
maxLength: 200
|
||
minLength: 1
|
||
type: string
|
||
requestBody:
|
||
content:
|
||
multipart/form-data:
|
||
schema:
|
||
additionalProperties: false
|
||
oneOf:
|
||
- required:
|
||
- file
|
||
- required:
|
||
- upload_token
|
||
properties:
|
||
change_id:
|
||
description: Optional case-sensitive editorial batch label; not identity or approval.
|
||
maxLength: 128
|
||
minLength: 1
|
||
pattern: ^[A-Za-z0-9][A-Za-z0-9._-]*$
|
||
type: string
|
||
expected_draft_rev:
|
||
minimum: 1
|
||
type: integer
|
||
file:
|
||
format: binary
|
||
type: string
|
||
name:
|
||
description: Safe contextual filename/path; normally entity-slug/filename.
|
||
maxLength: 500
|
||
minLength: 1
|
||
type: string
|
||
originating_entity_uid:
|
||
format: uuid
|
||
type: string
|
||
role:
|
||
maxLength: 500
|
||
minLength: 1
|
||
type: string
|
||
upload_token:
|
||
maxLength: 8192
|
||
minLength: 1
|
||
type: string
|
||
required:
|
||
- expected_draft_rev
|
||
- originating_entity_uid
|
||
- role
|
||
- name
|
||
type: object
|
||
required: true
|
||
responses:
|
||
"201":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: Private verified media metadata and exact Draft/edit tokens; bytes remain unreleased
|
||
"400":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Malformed multipart request; or `code` `workspace_id_invalid` (see SessionWorkspaceIDInvalid).
|
||
"401":
|
||
$ref: '#/components/responses/SessionUnauthorized'
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"404":
|
||
description: Origin is absent or outside owner scope
|
||
"409":
|
||
description: Stale Draft or reused retry key with different input
|
||
"413":
|
||
description: Request body exceeds bounded upload envelope
|
||
"422":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: Invalid fields or unsupported/unsafe bytes
|
||
"503":
|
||
description: Private storage or dedicated catalog unavailable
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Upload verified bytes as an independent Draft media use
|
||
tags:
|
||
- site-catalog
|
||
x-required-permissions:
|
||
- comfy_site.edit
|
||
/api/v1/catalog/draft/media/{uid}:
|
||
delete:
|
||
operationId: deleteCCCMedia
|
||
parameters:
|
||
- in: path
|
||
name: uid
|
||
required: true
|
||
schema:
|
||
format: uuid
|
||
type: string
|
||
- in: header
|
||
name: Idempotency-Key
|
||
required: true
|
||
schema:
|
||
maxLength: 200
|
||
minLength: 1
|
||
type: string
|
||
requestBody:
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
required: true
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: New tombstone version and Draft generation; history bytes retained
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"401":
|
||
$ref: '#/components/responses/SessionUnauthorized'
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"404":
|
||
description: Logical media is absent or outside owner scope
|
||
"409":
|
||
description: Stale Draft/edit token or retry mismatch
|
||
"422":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: Invalid exact edit tokens or non-Media target
|
||
"503":
|
||
description: Dedicated catalog unavailable
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Append a Draft Media tombstone without deleting bytes
|
||
tags:
|
||
- site-catalog
|
||
x-required-permissions:
|
||
- comfy_site.edit
|
||
/api/v1/catalog/draft/media/{uid}/file:
|
||
put:
|
||
description: Multipart with exactly one file or upload_token from upload-url; independent uses and old Live bytes are unchanged. Safe name is explicit to keep retries deterministic. Server verifies staged bytes before finalization; no caller-supplied storage key, verified MIME or owner metadata accepted.
|
||
operationId: replaceCCCMediaFile
|
||
parameters:
|
||
- in: path
|
||
name: uid
|
||
required: true
|
||
schema:
|
||
format: uuid
|
||
type: string
|
||
- in: header
|
||
name: Idempotency-Key
|
||
required: true
|
||
schema:
|
||
maxLength: 200
|
||
minLength: 1
|
||
type: string
|
||
requestBody:
|
||
content:
|
||
multipart/form-data:
|
||
schema:
|
||
additionalProperties: false
|
||
oneOf:
|
||
- required:
|
||
- file
|
||
- required:
|
||
- upload_token
|
||
properties:
|
||
change_id:
|
||
description: Optional case-sensitive editorial batch label; not identity or approval.
|
||
maxLength: 128
|
||
minLength: 1
|
||
pattern: ^[A-Za-z0-9][A-Za-z0-9._-]*$
|
||
type: string
|
||
expected_draft_rev:
|
||
minimum: 1
|
||
type: integer
|
||
expected_revision_uid:
|
||
format: uuid
|
||
type: string
|
||
file:
|
||
format: binary
|
||
type: string
|
||
name:
|
||
maxLength: 500
|
||
minLength: 1
|
||
type: string
|
||
upload_token:
|
||
maxLength: 8192
|
||
minLength: 1
|
||
type: string
|
||
required:
|
||
- expected_draft_rev
|
||
- expected_revision_uid
|
||
- name
|
||
type: object
|
||
required: true
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: New immutable Draft file-version metadata under the same media UID
|
||
"400":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Malformed multipart request; or `code` `workspace_id_invalid` (see SessionWorkspaceIDInvalid).
|
||
"401":
|
||
$ref: '#/components/responses/SessionUnauthorized'
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"404":
|
||
description: Logical media is absent or outside owner scope
|
||
"409":
|
||
description: Stale Draft/edit token or retry mismatch
|
||
"413":
|
||
description: Request body exceeds bounded upload envelope
|
||
"422":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: Invalid fields or unsupported/unsafe bytes
|
||
"503":
|
||
description: Private storage or dedicated catalog unavailable
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Replace one logical media use in Draft with verified bytes
|
||
tags:
|
||
- site-catalog
|
||
x-required-permissions:
|
||
- comfy_site.edit
|
||
/api/v1/catalog/draft/media/upload-url:
|
||
post:
|
||
description: Staff edit permission required. Supply filename, byte_size and optionally sha256. Returns an expiring PUT upload_url, required headers and an upload_token bound to this account, exact size and filename. Upload directly to private storage, then pass upload_token instead of file to the media create or replacement operation. No content becomes public. Finalization streams and verifies the exact uploaded bytes and recomputes SHA-256 before storing an immutable content-addressed blob. Direct uploads support up to the configured limit, at most 300 MiB.
|
||
operationId: requestCCCUploadURL
|
||
requestBody:
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
required: true
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: Expiring private upload URL, token and required request headers
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"401":
|
||
$ref: '#/components/responses/SessionUnauthorized'
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"422":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: Unsupported filename, invalid hash or empty/oversized file
|
||
"503":
|
||
description: Direct-upload storage or catalog unavailable
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Request a private direct-upload URL
|
||
tags:
|
||
- site-catalog
|
||
x-required-permissions:
|
||
- comfy_site.edit
|
||
/api/v1/catalog/draft/publish:
|
||
post:
|
||
description: Requires catalog publish permission. Body contains review.expected_live_rev, review.expected_draft_rev, review.expected_draft_generation, expected_selection_digest from POST Final review, and selected_uids (nonempty unique set, at most 5000, matching that review). Publishes exactly the checked changes; unchecked changes are carried into the next Draft unchanged (same version IDs). Stored approvals are ignored. Invalid references roll back everything. Dormant unless the catalog is enabled; never active in production. No query parameters, no paid validation. Idempotency-Key retries do not publish twice. Private/no-store. An API key gets 403 FORBIDDEN; publishing needs a signed-in session.
|
||
operationId: publishCCCDraft
|
||
parameters:
|
||
- in: header
|
||
name: Idempotency-Key
|
||
required: true
|
||
schema:
|
||
maxLength: 200
|
||
minLength: 1
|
||
type: string
|
||
requestBody:
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
required: true
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: New Live, previous Live and fresh Draft state after atomic commit
|
||
"400":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unsupported query parameters; or `code` `workspace_id_invalid` (see SessionWorkspaceIDInvalid).
|
||
"401":
|
||
$ref: '#/components/responses/SessionUnauthorized'
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"409":
|
||
description: Stale reviewed state or decisions or conflicting retry; nothing published
|
||
"422":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: Invalid review, unfinished decisions or reference/dependency validation failed; nothing published. Bounded field_errors include the affected resource_uid when known.
|
||
"503":
|
||
description: Catalog unavailable
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Publish the checked Draft changes and open the next Draft
|
||
tags:
|
||
- site-catalog
|
||
x-required-permissions:
|
||
- comfy_site.apply
|
||
/api/v1/catalog/draft/staging:
|
||
get:
|
||
description: Without representation, returns the legacy complete matching review. representation=page returns at most limit sparse rows. Cursors bind the complete Live/Draft/generation snapshot, filters, sort, and limit; stale snapshots return 409. representation=selection requires a snapshot cursor and returns sparse exact-version pins for all matching rows (at most 5000), only for explicit select-all. representation=detail requires that cursor and a matching uid and returns one complete change. Staff-only constrained search/filter. Credited author at the selected version is not the latest editor. unresolved_count counts every pending Draft entry whose exact-save decision is neither APPROVED nor DEFERRED, independently of display filters, including undecided deletions. It binds the same repeatable snapshot as the returned generation. Bulk operations cover explicit selected versions across all pages. Each item's saved_at is the RFC3339 UTC save time of its exact change; it is not part of selection_digest.
|
||
operationId: getCCCStaging
|
||
parameters:
|
||
- in: query
|
||
name: representation
|
||
schema:
|
||
enum:
|
||
- page
|
||
- selection
|
||
- detail
|
||
type: string
|
||
- in: query
|
||
name: limit
|
||
schema:
|
||
default: 50
|
||
maximum: 100
|
||
minimum: 1
|
||
type: integer
|
||
- in: query
|
||
name: cursor
|
||
schema:
|
||
maxLength: 2048
|
||
type: string
|
||
- in: query
|
||
name: sort
|
||
schema:
|
||
default: name
|
||
enum:
|
||
- name
|
||
- latest
|
||
type: string
|
||
- in: query
|
||
name: change
|
||
schema:
|
||
enum:
|
||
- new
|
||
- updates
|
||
type: string
|
||
- in: query
|
||
name: uid
|
||
schema:
|
||
format: uuid
|
||
type: string
|
||
- in: query
|
||
name: search
|
||
schema:
|
||
maxLength: 300
|
||
type: string
|
||
- in: query
|
||
name: author_uid
|
||
schema:
|
||
minLength: 1
|
||
type: string
|
||
- in: query
|
||
name: change_id
|
||
schema:
|
||
maxLength: 128
|
||
minLength: 1
|
||
pattern: ^[A-Za-z0-9][A-Za-z0-9._-]*$
|
||
type: string
|
||
- explode: true
|
||
in: query
|
||
name: tags
|
||
schema:
|
||
items:
|
||
maxLength: 200
|
||
minLength: 1
|
||
type: string
|
||
maxItems: 30
|
||
type: array
|
||
style: form
|
||
- explode: true
|
||
in: query
|
||
name: types
|
||
schema:
|
||
items:
|
||
enum:
|
||
- model
|
||
- workflow
|
||
- app
|
||
- media
|
||
- template_set
|
||
type: string
|
||
maxItems: 5
|
||
type: array
|
||
style: form
|
||
- explode: true
|
||
in: query
|
||
name: statuses
|
||
schema:
|
||
items:
|
||
enum:
|
||
- NEW
|
||
- APPROVED
|
||
- DEFERRED
|
||
- DELETED
|
||
type: string
|
||
maxItems: 4
|
||
type: array
|
||
style: form
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: Private review with exact Draft generation and optional sparse page metadata
|
||
"400":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unknown, repeated scalar or invalid filter; bounded result exceeded; or `code` `workspace_id_invalid` (see SessionWorkspaceIDInvalid).
|
||
"401":
|
||
$ref: '#/components/responses/SessionUnauthorized'
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
"409":
|
||
description: The frozen page, selection or detail belongs to a stale Draft generation
|
||
"503":
|
||
description: Dedicated catalog unavailable
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Read Draft changes for editorial staging
|
||
tags:
|
||
- site-catalog
|
||
x-permission-match: any
|
||
x-required-permissions:
|
||
- comfy_site.edit
|
||
- comfy_site.apply
|
||
post:
|
||
description: Requires review with expected_live_rev, expected_draft_rev and expected_draft_generation, the exact returned filter and expected_selection_digest, status NEW/APPROVED/DEFERRED and expected_count of the complete frozen matching set. Optional selected_uids is a nonempty list of at most 5000 distinct UUIDs from that set; omitted means all matching records. The operation is atomic, never a loop of separately committed decisions. The digest binds the full filter and exact matching versions; the selected UIDs are bound to the idempotent mutation request. An unfiltered action affecting every matching record additionally requires confirm_all, including when all are checked explicitly. Approval applies only to the exact immutable saves; later edits become NEW. Deleted changes remain explicit and require approval. No publication, functional validation or paid execution. Maximum request body 256 KiB. An API key gets 403 FORBIDDEN; staging needs a signed-in session.
|
||
operationId: stageCCCChanges
|
||
parameters:
|
||
- in: header
|
||
name: Idempotency-Key
|
||
required: true
|
||
schema:
|
||
maxLength: 200
|
||
minLength: 1
|
||
type: string
|
||
requestBody:
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
required: true
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: Atomic matching-set decisions and updated private staging state
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"401":
|
||
$ref: '#/components/responses/SessionUnauthorized'
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"409":
|
||
description: Stale review, changed matching count or conflicting retry
|
||
"422":
|
||
description: Invalid status/filter/tokens/count or missing unfiltered confirmation
|
||
"503":
|
||
description: Dedicated catalog unavailable
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Approve or defer reviewed changes, optionally a checked subset
|
||
tags:
|
||
- site-catalog
|
||
x-required-permissions:
|
||
- comfy_site.apply
|
||
/api/v1/catalog/items:
|
||
get:
|
||
description: Public bounded LIVE page (default 20, maximum 100). Filters run before keyset pagination. Unknown or repeated parameters and invalid cursors return 400; publication or revert invalidates prior cursors (409). Every request, including conditional GET, rechecks real UTC eligibility; browser caching requires revalidation and shared CDN caching is disabled. Never returns DRAFT, disabled, deleted, staff-only, or future content.
|
||
operationId: listContentCatalogItems
|
||
parameters:
|
||
- description: Optional exact public-authority token for a workflow_slug detail fill only. Collections and cursors with this header return 409. The token is checked before and after all presentation and file reads, including misses and conditional responses. Guarded responses are no-store; unavailable author or selected API-file reads return 503.
|
||
in: header
|
||
name: X-Comfy-Catalog-Authority
|
||
schema:
|
||
type: string
|
||
- in: query
|
||
name: q
|
||
schema:
|
||
maxLength: 300
|
||
type: string
|
||
- in: query
|
||
name: slug
|
||
schema:
|
||
type: string
|
||
- in: query
|
||
name: kind
|
||
schema:
|
||
enum:
|
||
- MODEL
|
||
- WORKFLOW
|
||
- APP
|
||
type: string
|
||
- in: query
|
||
name: type
|
||
schema:
|
||
enum:
|
||
- model
|
||
- workflow
|
||
- app
|
||
- template_set
|
||
type: string
|
||
- in: query
|
||
name: surface
|
||
schema:
|
||
enum:
|
||
- hub
|
||
- cloud_templates
|
||
- local_templates
|
||
- desktop_starters
|
||
- nvidia_performance_tests
|
||
type: string
|
||
- in: query
|
||
name: tag
|
||
schema:
|
||
maxLength: 200
|
||
type: string
|
||
- in: query
|
||
name: use_case
|
||
schema:
|
||
maxLength: 200
|
||
type: string
|
||
- in: query
|
||
name: sort
|
||
schema:
|
||
default: sort_order
|
||
enum:
|
||
- sort_order
|
||
- title
|
||
type: string
|
||
- in: query
|
||
name: limit
|
||
schema:
|
||
default: 20
|
||
maximum: 100
|
||
minimum: 1
|
||
type: integer
|
||
- in: query
|
||
name: cursor
|
||
schema:
|
||
maxLength: 4096
|
||
type: string
|
||
- description: Compatibility detail lookup, exclusive with all other query parameters. Select at most one eligible record by canonical path, UID or website detail slug, expanding the verified primary API file for that workflow only. A miss returns an empty page, never the collection. Collection reads never open API blobs. kind is a legacy alias for type and cannot be combined with type; slug accepts a canonical Hub pathname or native slug.
|
||
in: query
|
||
name: workflow_slug
|
||
schema:
|
||
maxLength: 300
|
||
minLength: 1
|
||
type: string
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCPublicItemsPage'
|
||
description: Bounded LIVE page with continuation metadata
|
||
"304":
|
||
description: Current eligible representation matches If-None-Match after fresh validation
|
||
"400":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Invalid, repeated, unsupported or conflicting query parameters or malformed cursor
|
||
"409":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Cursor publication identity or public authority changed, or a guarded request was not a single detail lookup
|
||
"503":
|
||
description: Catalog disabled or unavailable
|
||
security: []
|
||
summary: Read eligible LIVE website content
|
||
tags:
|
||
- site-catalog
|
||
x-required-permissions: []
|
||
/api/v1/catalog/items/{uid}:
|
||
get:
|
||
operationId: getContentCatalogItem
|
||
parameters:
|
||
- description: Optional exact public-authority token checked before and after complete detail presentation, including a not-found result. Malformed or superseded tokens return 409; unavailable author or selected API-file reads return 503. Responses are no-store and grant no private access.
|
||
in: header
|
||
name: X-Comfy-Catalog-Authority
|
||
schema:
|
||
type: string
|
||
- in: path
|
||
name: uid
|
||
required: true
|
||
schema:
|
||
type: string
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ContentCatalogRecord'
|
||
description: Website content record
|
||
"404":
|
||
description: Not found or not publicly eligible
|
||
"409":
|
||
description: Public authority changed; select the current version before filling
|
||
"503":
|
||
description: Catalog disabled or unavailable
|
||
security: []
|
||
summary: Read an eligible LIVE record by UID
|
||
tags:
|
||
- site-catalog
|
||
x-required-permissions: []
|
||
/api/v1/catalog/items/{uid}/history:
|
||
get:
|
||
description: Keyset pagination by descending per-resource edit_sequence, including intermediate and archived saves. This is not the public workflow-file version list. No total count or arbitrary query fields. Private no-store.
|
||
operationId: getCCCItemHistory
|
||
parameters:
|
||
- in: path
|
||
name: uid
|
||
required: true
|
||
schema:
|
||
format: uuid
|
||
type: string
|
||
- in: query
|
||
name: limit
|
||
schema:
|
||
default: 20
|
||
maximum: 100
|
||
minimum: 1
|
||
type: integer
|
||
- in: query
|
||
name: cursor
|
||
schema:
|
||
maxLength: 256
|
||
type: string
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: Flat immutable items with catalog_status and saved_at, has_more and optional opaque next_cursor; no total
|
||
"400":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Invalid limit, cursor or unsupported query parameter; or `code` `workspace_id_invalid` (see SessionWorkspaceIDInvalid).
|
||
"401":
|
||
$ref: '#/components/responses/SessionUnauthorized'
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
"404":
|
||
description: Resource outside organization scope or absent
|
||
"503":
|
||
description: Dedicated catalog unavailable
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Read bounded staff-only immutable save history
|
||
tags:
|
||
- site-catalog
|
||
x-permission-match: any
|
||
x-required-permissions:
|
||
- comfy_site.edit
|
||
- comfy_site.apply
|
||
/api/v1/catalog/legacy/{source}/{id}:
|
||
get:
|
||
description: Maps an id from an old public URL to the current Hub page of the record that replaced it. Source `template` takes a workflow_templates name; source `hub` takes an old Hub share id. Only an eligible LIVE workflow, app or model resolves. An unknown source, an unknown id, or a target that is not publicly eligible returns 404, so a caller has one miss path. Browser caching requires revalidation and shared CDN caching is disabled, as for the other public reads.
|
||
operationId: getCCCLegacyTarget
|
||
parameters:
|
||
- description: '`template` or `hub`'
|
||
in: path
|
||
name: source
|
||
required: true
|
||
schema:
|
||
maxLength: 20
|
||
type: string
|
||
- description: Template name or Hub share id
|
||
in: path
|
||
name: id
|
||
required: true
|
||
schema:
|
||
maxLength: 500
|
||
type: string
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCLegacyTarget'
|
||
description: Current Hub page of the mapped record
|
||
"404":
|
||
description: Unknown source or id, or the target is not publicly eligible
|
||
"503":
|
||
description: Catalog disabled or unavailable
|
||
security: []
|
||
summary: Resolve an old public id to its current Hub page
|
||
tags:
|
||
- site-catalog
|
||
x-required-permissions: []
|
||
/api/v1/catalog/model-directory:
|
||
get:
|
||
description: One compact typed read of eligible LIVE model UIDs, canonical paths, localized titles and providers, without cards, media or profiles. Only locale is accepted; unknown or repeated parameters return 400. More than 5000 models or 2 MiB returns 503, never partial data. Every request rechecks current Live and scheduled visibility. Responses are private, no-store. The existing cards contract is unchanged.
|
||
operationId: listCCCWebsiteModelDirectory
|
||
parameters:
|
||
- description: Optional exact public cache version; unchanged before and after the complete directory fill. Invalid, repeated or superseded tokens fail with 409 and no response body.
|
||
in: header
|
||
name: X-Comfy-Catalog-Authority
|
||
schema:
|
||
type: string
|
||
- in: query
|
||
name: locale
|
||
schema:
|
||
default: en
|
||
enum:
|
||
- en
|
||
- zh-CN
|
||
type: string
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCWebsiteModelDirectory'
|
||
description: Complete eligible model directory, without Draft generation
|
||
"400":
|
||
description: Invalid, repeated or unsupported query parameter
|
||
"409":
|
||
description: Public cache version changed; restart from current authority
|
||
"503":
|
||
description: Catalog unavailable or directory budget exceeded
|
||
security: []
|
||
summary: Read the complete eligible public model-name directory
|
||
tags:
|
||
- site-catalog
|
||
x-required-permissions: []
|
||
/api/v1/catalog/openapi.json:
|
||
get:
|
||
description: Public discovery grants no editing authority and does not replace the Cloud API specification.
|
||
operationId: getCatalogOpenAPI
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: Catalog OpenAPI with contract fingerprint and environment
|
||
"503":
|
||
description: Catalog disabled or unavailable
|
||
security: []
|
||
summary: Catalog-only deployed OpenAPI contract
|
||
tags:
|
||
- site-catalog
|
||
x-required-permissions: []
|
||
/api/v1/catalog/public-authority:
|
||
get:
|
||
description: A fresh metadata-only database snapshot. Never cache this response. The token binds environment, owner, public content generation, schedule visibility. Unchanged content keeps the same token across clock windows; valid_until bounds this observation rather than an artifact selected by a later fresh read. It grants no private access. Public artifact fills send the token in X-Comfy-Catalog-Authority; a changed version fails with 409 instead of returning content under a superseded key.
|
||
operationId: getCCCPublicCacheAuthority
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
additionalProperties: false
|
||
properties:
|
||
as_of:
|
||
format: date-time
|
||
type: string
|
||
next_visibility_at:
|
||
description: Exact next scheduled public visibility boundary; null when none is pending. Not the one-minute observation validity.
|
||
format: date-time
|
||
nullable: true
|
||
type: string
|
||
revision_id:
|
||
description: Current numeric Live revision, matching card revision_id. A URL-plus-revision cache key must also validate the token stored with its value because rollback, profile edits and eligibility changes can invalidate the same revision number.
|
||
format: int64
|
||
minimum: 1
|
||
type: integer
|
||
token:
|
||
pattern: ^[0-9a-f]{64}$
|
||
type: string
|
||
valid_until:
|
||
format: date-time
|
||
type: string
|
||
required:
|
||
- revision_id
|
||
- token
|
||
- as_of
|
||
- valid_until
|
||
- next_visibility_at
|
||
type: object
|
||
description: Current public authority and its next time boundary; no private identifiers
|
||
"503":
|
||
description: Current authority unavailable; do not reuse an earlier artifact
|
||
security: []
|
||
summary: Select the current opaque public website cache version
|
||
tags:
|
||
- site-catalog
|
||
x-required-permissions: []
|
||
/api/v1/catalog/revisions/{rev}/items/{uid}:
|
||
get:
|
||
description: Resolve heads before filtering. Explicit archived candidate review never makes it eligible in Live. Private no-store.
|
||
operationId: getCCCRevisionItem
|
||
parameters:
|
||
- in: path
|
||
name: rev
|
||
required: true
|
||
schema:
|
||
format: int64
|
||
minimum: 1
|
||
type: integer
|
||
- in: path
|
||
name: uid
|
||
required: true
|
||
schema:
|
||
format: uuid
|
||
type: string
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: Flat Content and exact edit/revision context
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"401":
|
||
$ref: '#/components/responses/SessionUnauthorized'
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
"404":
|
||
description: Resource/revision not found in organization scope
|
||
"503":
|
||
description: Dedicated catalog unavailable
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Read an exact retained staff Content view
|
||
tags:
|
||
- site-catalog
|
||
x-permission-match: any
|
||
x-required-permissions:
|
||
- comfy_site.edit
|
||
- comfy_site.apply
|
||
/api/v1/catalog/root-presentation:
|
||
get:
|
||
description: Complete eligible public card metadata for Models, Workflows and Apps in one snapshot-bound bundle, plus compact model labels and initial page metadata. No graphs, input contracts, private counts or continuation cursors. At most 5000 cards and 2 MiB serialized JSON; overflow fails rather than truncating. Search, filtering and paging continue through cards. Unknown or repeated query parameters are rejected. Select public authority once at page entry and send both revision_id and X-Comfy-Catalog-Authority to use the Ingest Redis artifact. Missing either bypasses Redis for a fresh guarded origin read. Cache hits match the authority stamp locally and check the absolute schedule deadline without current-state requests. A fresh selector pin after a same-revision public change rejects and refills the older cached artifact. Previously pinned metadata remains a selected snapshot, not an instant historical-revocation mechanism; protected media byte authorization is unchanged. Origin fills verify the revision and authority before and after complete presentation. Responses remain no-store to browser and CDN caches.
|
||
operationId: getCCCWebsiteRootPresentation
|
||
parameters:
|
||
- in: query
|
||
name: path
|
||
required: true
|
||
schema:
|
||
enum:
|
||
- /hub/models/
|
||
- /hub/workflows/
|
||
- /hub/apps/
|
||
type: string
|
||
- in: query
|
||
name: locale
|
||
schema:
|
||
default: en
|
||
enum:
|
||
- en
|
||
- zh-CN
|
||
type: string
|
||
- description: Live revision selected once at page entry. Redis requires both this revision and the selected authority pin. On an origin miss the revision must match current Live.
|
||
in: query
|
||
name: revision_id
|
||
schema:
|
||
format: int64
|
||
minimum: 1
|
||
type: integer
|
||
- description: Exact token from the fresh page-entry public-authority selection. Required with revision_id for Redis eligibility; absent pins bypass Redis. Invalid or repeated pins return 409.
|
||
in: header
|
||
name: X-Comfy-Catalog-Authority
|
||
schema:
|
||
type: string
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCWebsiteRootPresentation'
|
||
description: Complete root metadata; no personal data or executable bodies
|
||
headers:
|
||
X-Comfy-Catalog-Cache:
|
||
description: Ingest versioned root artifact source. Absent on direct catalog-api or bypassed requests.
|
||
schema:
|
||
enum:
|
||
- HIT
|
||
- MISS
|
||
type: string
|
||
"400":
|
||
description: Unsupported or repeated root path or locale
|
||
"409":
|
||
description: Public authority changed or the supplied pin is invalid
|
||
"503":
|
||
description: Current complete presentation unavailable or over budget
|
||
security: []
|
||
summary: Read complete bounded public Hub root presentation metadata
|
||
tags:
|
||
- site-catalog
|
||
x-required-permissions: []
|
||
/api/v1/catalog/schemas/{type}/{schema_version}:
|
||
get:
|
||
description: Author new Content as schema_version 2; v1 stays readable but skips input, binding and translation checks. Media is server-created (uploads are media/1, recorded Cloud-asset references media/2); generic JSON authoring cannot create or replace Media, and upload/finalization routes are separate. Media references use src "media" ("r2" is a legacy alias) and file_version_uid = the upload's revision_uid. static_thumb is recommended and must be verified image/webp Media, 1 byte to 160 KiB, at most 960 px per side; reviewed policy requires it at publish but the current runtime does not enforce that yet. Direct uploads support up to 300 MiB, subject to CATALOG_MAX_DIRECT_UPLOAD_BYTES; images remain capped at 50 MiB, JSON at 64 MiB and API workflow JSON at 1 MiB.
|
||
operationId: getCCCTypeSchema
|
||
parameters:
|
||
- in: path
|
||
name: type
|
||
required: true
|
||
schema:
|
||
enum:
|
||
- model
|
||
- workflow
|
||
- app
|
||
- template_set
|
||
- media
|
||
type: string
|
||
- in: path
|
||
name: schema_version
|
||
required: true
|
||
schema:
|
||
minimum: 1
|
||
type: integer
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: Build-coupled OpenAPI 3.0 schema object, type, version and API environment
|
||
"404":
|
||
description: Unsupported type or schema version
|
||
"503":
|
||
description: Catalog disabled or unavailable
|
||
security: []
|
||
summary: Type schema used by this deployed authoring validator
|
||
tags:
|
||
- site-catalog
|
||
x-required-permissions: []
|
||
/api/v1/catalog/state:
|
||
get:
|
||
operationId: getCCCState
|
||
responses:
|
||
"200":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CCCJSON'
|
||
description: Private state; never cacheable
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"401":
|
||
$ref: '#/components/responses/SessionUnauthorized'
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
"503":
|
||
description: Dedicated catalog unavailable; no legacy fallback
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Read dedicated CCC Live and Draft state
|
||
tags:
|
||
- site-catalog
|
||
x-permission-match: any
|
||
x-required-permissions:
|
||
- comfy_site.edit
|
||
- comfy_site.apply
|
||
/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.
|
||
|
||
An `<img>`, `<video>` or `<audio>` tag loads this with the
|
||
`WebSessionAuth` or `CookieAuth` cookie, both accepted whatever
|
||
`web_session_enabled` says; neither needs `X-CSRF-Token` or
|
||
`X-Comfy-Client`, which a media tag cannot send. A 403
|
||
AuthTypeNotAllowedError here is a credential the route never takes,
|
||
such as `X-ComfyAPI-Secret`, never the session.
|
||
operationId: getVhsQueryVideo
|
||
parameters:
|
||
- description: Name of the video file to query
|
||
in: query
|
||
name: filename
|
||
required: true
|
||
schema:
|
||
type: string
|
||
- content:
|
||
text/plain:
|
||
schema:
|
||
type: string
|
||
description: The workspace a media request reads from, where a media tag cannot send `X-Comfy-Workspace-ID`; see the `MediaWorkspaceID` parameter.
|
||
in: query
|
||
name: workspace_id
|
||
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/ErrorResponse'
|
||
description: |
|
||
Missing required query parameter. Produced by the oapi-codegen
|
||
wrapper via echo.NewHTTPError; the custom Echo HTTPErrorHandler
|
||
normalizes it to the standard ErrorResponse {code, message} shape
|
||
(BE-1178). Or `code` `workspace_id_invalid`: the `workspace_id` or
|
||
`X-Comfy-Workspace-ID` value is malformed, the two disagree, or,
|
||
with the flag on, a token or API key names another workspace than
|
||
its own.
|
||
"401":
|
||
$ref: '#/components/responses/SessionUnauthorized'
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
"500":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Internal server error, such as the auth policy failing to look up the workspace `workspace_id` names.
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- CookieAuth: []
|
||
- WebSessionAuth: []
|
||
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.
|
||
|
||
An `<img>`, `<video>` or `<audio>` tag loads this with the
|
||
`WebSessionAuth` or `CookieAuth` cookie, both accepted whatever
|
||
`web_session_enabled` says; neither needs `X-CSRF-Token` or
|
||
`X-Comfy-Client`, which a media tag cannot send. A 403
|
||
AuthTypeNotAllowedError here is a credential the route never takes,
|
||
such as `X-ComfyAPI-Secret`, never the session.
|
||
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
|
||
- content:
|
||
text/plain:
|
||
schema:
|
||
type: string
|
||
description: The workspace a media request reads from, where a media tag cannot send `X-Comfy-Workspace-ID`; see the `MediaWorkspaceID` parameter.
|
||
in: query
|
||
name: workspace_id
|
||
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, or `code` `workspace_id_invalid`: the `workspace_id` or `X-Comfy-Workspace-ID` value is malformed, the two disagree, or, with the flag on, a token or API key names another workspace than its own.'
|
||
"401":
|
||
$ref: '#/components/responses/SessionUnauthorized'
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
"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: []
|
||
- WebSessionAuth: []
|
||
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
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unauthorized
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
"500":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Internal server error
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unauthorized
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"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:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unauthorized
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"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
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"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
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unauthorized
|
||
"403":
|
||
$ref: '#/components/responses/SessionWriteForbidden'
|
||
"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
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"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
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"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
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"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
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
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
|
||
"400":
|
||
$ref: '#/components/responses/SessionWorkspaceIDInvalid'
|
||
"401":
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
description: Unauthorized
|
||
"403":
|
||
$ref: '#/components/responses/SessionForbidden'
|
||
"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
|
||
security:
|
||
- ApiKeyAuth: []
|
||
- BearerAuth: []
|
||
- WebSessionAuth: []
|
||
summary: Get a published workflow by share ID
|
||
tags:
|
||
- workflows
|
||
/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: Returns the filesystem paths ComfyUI loads models and assets from, keyed by folder type.
|
||
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
|
||
/internal/logs:
|
||
get:
|
||
description: Returns ComfyUI log entries from the in-memory log buffer.
|
||
operationId: getInternalLogs
|
||
responses:
|
||
"200":
|
||
content:
|
||
text/plain:
|
||
schema:
|
||
type: string
|
||
description: Log text
|
||
summary: Get server logs as text
|
||
/internal/logs/raw:
|
||
get:
|
||
description: Returns the raw ComfyUI log buffer plus size metadata.
|
||
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
|
||
/internal/logs/subscribe:
|
||
patch:
|
||
description: Subscribes or unsubscribes the current client from live log streaming over the WebSocket.
|
||
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
|
||
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 settings management
|
||
name: settings
|
||
- description: User feedback management
|
||
name: feedback
|
||
- description: System operations and monitoring
|
||
name: system
|
||
- description: User information and management
|
||
name: user
|
||
- description: Background task management
|
||
name: task
|
||
- description: Comfy Content Catalog discovery, reads and staff authoring
|
||
name: site-catalog
|
||
- 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
|