> ## Documentation Index
> Fetch the complete documentation index at: https://docs.comfy.org/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':
          description: >-
            `public_deployment_no_list`: the public demo deployment's address
            serves no job list, whatever credential is sent; its owner lists its
            jobs at the workspace address. Also `sso_required`, as on every
            operation (see `Forbidden`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '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, or the public demo deployment,
        which takes no credential), `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.
              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
        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'
    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.