> ## Documentation Index
> Fetch the complete documentation index at: https://dripart-chore-sync-comfy-api-v2-spec.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# List jobs, newest first

> Lists jobs newest first. At a deployment's address, the jobs sent to
that deployment; at the workspace address, every job in the
caller's workspace. A caller never sees another workspace's jobs.

Filter by your own labels with `metadata[<key>]=<value>`, up to 3
times; a job is listed only when every pair matches exactly. A 4th
filter, a repeated key, a key outside the key rule, or a value with a
character no label may hold (a control character or a bidirectional
embedding, override or isolate, as on submit) is refused `400`
`invalid_metadata_filter`. A filter value must be URL-encoded; a raw
`;` or a bad `%` escape answers `400` `invalid_metadata_filter`.

Pages: pass the response's `next_cursor` back as `cursor`, with the
same filters, to read the next page. `next_cursor` is absent on the
last page. Each job appears once across the pages.

List items are a job's stored record, not the `Job` object: they
carry no `outputs` and no `urls`. Read a job with
`GET /api/v2/jobs/{id}` for its outputs.

Only the serverless platform lists jobs today. Comfy Cloud answers
`501` `not_implemented`.




## OpenAPI

````yaml /openapi-v2.yaml get /api/v2/jobs
openapi: 3.0.3
info:
  title: Comfy API v2
  version: 2.0.0
  description: |
    The official, versioned HTTP API for running ComfyUI workflows from
    external applications: upload inputs, submit a workflow, observe
    execution, retrieve results.

    Design principles:
    - **Poll-first.** Every capability is reachable via plain GET polling;
      the SSE stream is a live enhancement, never the source of truth.
    - **Everything is resumable.** Submission is idempotent; job state and
      outputs are retrievable by ID until `expires_at`.
    - **UUID identity, content-addressed dedup.** Assets are UUID-identified
      records over blobs keyed by a server-computed blake3 hash. The hash is
      nullable and may be computed lazily.
    - **Follow links, don't build URLs.** Responses embed follow-up URLs.

    Additive changes only within v2; breaking changes require v3.
servers:
  - url: http://127.0.0.1:8189
    description: Self-hosted (comfy-api-proxy)
  - url: https://cloud.comfy.org
    description: Comfy Cloud
  - url: https://{deployment}.run.comfy.app
    description: Serverless deployment
    variables:
      deployment:
        description: >-
          DNS-safe deployment id (subdomain label). Staging uses
          {deployment}.stg.run.comfy.app.
        default: dep-1234abcd-56ef-7890-abcd-ef1234567890
security:
  - bearerAuth: []
  - {}
tags:
  - name: assets
    description: UUID-identified records over content-addressed blobs.
  - name: jobs
    description: One execution of a workflow — durable, pollable, cancelable.
paths:
  /api/v2/jobs:
    get:
      tags:
        - jobs
      summary: List jobs, newest first
      description: |
        Lists jobs newest first. At a deployment's address, the jobs sent to
        that deployment; at the workspace address, every job in the
        caller's workspace. A caller never sees another workspace's jobs.

        Filter by your own labels with `metadata[<key>]=<value>`, up to 3
        times; a job is listed only when every pair matches exactly. A 4th
        filter, a repeated key, a key outside the key rule, or a value with a
        character no label may hold (a control character or a bidirectional
        embedding, override or isolate, as on submit) is refused `400`
        `invalid_metadata_filter`. A filter value must be URL-encoded; a raw
        `;` or a bad `%` escape answers `400` `invalid_metadata_filter`.

        Pages: pass the response's `next_cursor` back as `cursor`, with the
        same filters, to read the next page. `next_cursor` is absent on the
        last page. Each job appears once across the pages.

        List items are a job's stored record, not the `Job` object: they
        carry no `outputs` and no `urls`. Read a job with
        `GET /api/v2/jobs/{id}` for its outputs.

        Only the serverless platform lists jobs today. Comfy Cloud answers
        `501` `not_implemented`.
      operationId: listJobs
      parameters:
        - name: limit
          in: query
          required: false
          description: >-
            Most jobs per page. Above 500 is read as 500; absent means 500. Not
            a positive integer: `422` `invalid_request`.
          schema:
            type: integer
            minimum: 1
        - name: cursor
          in: query
          required: false
          description: >-
            The previous page's `next_cursor`, unchanged. Opaque: do not build
            or edit one. A cursor that is not well-formed is refused `400`
            `invalid_cursor`. Cursors are not signed, so a well-formed one is
            read as a position whether or not this list issued it.
          schema:
            type: string
        - name: metadata
          in: query
          required: false
          style: deepObject
          explode: true
          description: >-
            Exact-match label filters, written `metadata[client]=acme`. Up to 3;
            all must match.
          schema:
            type: object
            maxProperties: 3
            additionalProperties:
              type: string
          example:
            client: acme
      responses:
        '200':
          description: One page of jobs, newest first.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JobList'
        '400':
          description: '`invalid_metadata_filter` or `invalid_cursor`.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          description: >-
            `not_found`: on a deployment's address, no deployment there that the
            caller's workspace owns.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '422':
          description: '`invalid_request`: `limit` is not a positive integer.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/UpstreamError'
        '501':
          description: '`not_implemented`: this surface does not list jobs yet.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
components:
  schemas:
    JobList:
      type: object
      description: One page of `GET /api/v2/jobs`.
      required:
        - jobs
      properties:
        jobs:
          type: array
          items:
            $ref: '#/components/schemas/JobListItem'
        next_cursor:
          type: string
          description: Pass as `cursor` to read the next page. Absent on the last page.
    ErrorEnvelope:
      type: object
      description: |
        Shared error envelope with machine-readable codes. Core codes (v1):
        `invalid_workflow` (422), `workflow_format_ui` (422),
        `missing_asset` (422), `hash_mismatch` (409), `blob_not_found`
        (404), `idempotency_key_reuse` (422),
        `queue_full` (429 + Retry-After), `rate_limited` (429 + Retry-After:
        the caller is past a request rate limit; retry), `insufficient_credits`
        (402), `not_found` (404), `unauthorized` (401), `forbidden` (403).
        Deployment-scoped surfaces add: `deployment_not_ready` (429 +
        Retry-After — the deployment can still reach ready; retry),
        `deployment_unavailable` (429 + Retry-After: the deployment is ready
        but its GPU provider is not taking work on it yet; retry),
        `deployment_stopped` (422 — terminal deployment state; a retry
        cannot succeed without operator action), `invalid_request` (422:
        a malformed asset upload or asset-from-hash field, or a jobs-list
        `limit` that is not a positive integer), `content_blocked` (451:
        content moderation flagged the asset's bytes) and `sso_required` (403:
        the key is valid, but the account must sign in through its
        organization's single sign-on, which does not accept this key). Job
        labels add: `metadata_invalid` (422: a submitted `metadata` breaks a
        limit; `details.key` names the key, except for too many pairs, which
        has no `details`), `metadata_not_supported` (422:
        this surface keeps no job labels yet), `invalid_metadata_filter` (400)
        and `invalid_cursor` (400). A surface that does not list jobs yet
        answers `not_implemented` (501). A 429 is disambiguated
        by `error.code` alone; clients should treat any 429 + Retry-After
        as "back off and retry".
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              example: invalid_workflow
            message:
              type: string
              example: 'Node 12 (KSampler): required input ''model'' is not connected'
            organization_id:
              type: string
              description: >-
                On `sso_required`: the organization whose single sign-on governs
                this key, the one that holds the account, else the one that
                holds the key's workspace. It is the `organization` query
                parameter of Comfy Cloud's single sign-on start; treat it as
                opaque. Absent when the organization is unknown, and on every
                other code.
              example: org_01HXYZEXAMPLE
            details:
              type: object
              nullable: true
              additionalProperties: true
              description: >-
                Machine-readable detail for the code. When it carries
                `node_errors`, that is keyed by node id and each value is a
                `JobNodeError`, the same shape as a job's `error.node_errors`,
                whether the refusal came at submit (for example
                `unknown_node_class`, a node class the deployment's build does
                not contain) or from ComfyUI after dispatch. With
                `unknown_node_class` errors it carries `unknown_node_classes`,
                the missing classes; with `waits_for_browser` errors,
                `browser_wait_node_classes`, the classes that wait for a
                browser. A submit refusal names at most fifty nodes. For
                `invalid_node`, `invalid_inputs` and `invalid_class_type`, when
                it found more than fifty, `node_errors_truncated` is true and
                `malformed_node_count` carries the full count; for
                `waits_for_browser`, `browser_wait_node_count` does. For
                `unknown_node_class` it names only nodes whose class is one of
                the at most ten listed in `unknown_node_classes`; when those
                nodes number more than fifty, `node_errors_truncated` is true
                and `unknown_node_count` is how many nodes have a listed class.
                Nodes whose class is past those ten are neither named nor
                counted.
              example:
                node_errors:
                  '12':
                    class_type: SomeCustomNode
                    errors:
                      - type: unknown_node_class
                        message: >-
                          this deployment's build does not contain the node
                          class SomeCustomNode.
                unknown_node_classes:
                  - SomeCustomNode
    JobListItem:
      type: object
      description: >-
        A job's stored record. The fields below are stable; an item may carry
        more, which a client should ignore rather than rely on.
      required:
        - id
        - status
        - create_time
        - update_time
      additionalProperties: true
      properties:
        id:
          type: string
          example: 7f3d2c1b-9a8e-4d6f-b012-3c4d5e6f7a8b
        status:
          $ref: '#/components/schemas/JobStatus'
        create_time:
          type: string
          format: date-time
        update_time:
          type: string
          format: date-time
        release_version:
          type: integer
          minimum: 1
          description: >-
            The version of the release that ran the job. Absent where the
            serving surface does not report it or could not look it up at the
            time of the answer.
          example: 3
        metadata:
          $ref: '#/components/schemas/JobMetadata'
    JobStatus:
      type: string
      enum:
        - queued
        - running
        - succeeded
        - canceling
        - canceled
        - failed
        - expired
      description: |
        Lifecycle: queued → running → succeeded | failed | expired;
        a cancel request, or the deletion of the deployment the job is running
        on, moves running → canceling → canceled.
        Terminal states: succeeded, canceled, failed, expired.
    JobMetadata:
      type: object
      description: >-
        The labels the job was submitted with, exactly as sent. Absent when it
        was sent with none.
      additionalProperties:
        type: string
      example:
        client: acme
  responses:
    Unauthorized:
      description: '`unauthorized` — missing or invalid credentials.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
    Forbidden:
      description: >-
        `forbidden` — authenticated but not allowed. On a serverless deployment,
        also `sso_required` — the key is valid, but the account must sign in
        through its organization's single sign-on, which does not accept this
        key; it can come back on any operation.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
    RateLimited:
      description: >-
        `rate_limited` — the caller has exceeded a request rate limit for this
        account. Account/rate-scoped, not resource-specific — this can be
        returned even for a job, asset or deployment the caller doesn't own or
        that doesn't exist.
      headers:
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
    UpstreamError:
      description: >-
        `upstream_error` — an unexpected failure reaching or processing the
        request in this implementation's backing services. The message is always
        a generic, safe-to-display string; implementation detail (the specific
        upstream, its error text, transport failures) is never included here —
        see each implementation's own error-mapping notes. Every operation in
        this contract can fail this way.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
  headers:
    RetryAfter:
      schema:
        type: integer
      description: Seconds to wait before retrying.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        `Authorization: Bearer <credential>`. The credential is one of: an
        account-scoped API key (`comfyui-…`), accepted on Cloud and serverless;
        a Comfy Cloud session JWT; or an OAuth access token issued for the Comfy
        Cloud resource. Which kinds a given deployment accepts is deployment
        configuration — an API key always works on Cloud and serverless, and a
        deployment that does not accept JWT bearers answers `401` with a message
        saying so. Self-hosted accepts unauthenticated requests by default and
        can be configured with a static bearer token.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.