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

# Comfy Router API reference

> Every Comfy Router endpoint, parameter, response body and error bucket, generated from the Comfy API contract.

<div className="router-api-reference-marker" />

Comfy Router's canonical, model-ID-addressed routes.

Base URL: `https://api.comfy.org`

Every endpoint below is authenticated. Send `X-API-Key: <api-key>` or `Authorization: Bearer <jwt>`.

Comfy API keys can also be sent as Bearer tokens. `X-API-Key` takes precedence when both credential headers are supplied. See [authentication headers](/development/comfy-router/headers#request-headers) for the key/JWT distinction and [the Quickstart](/development/comfy-router/quickstart) for access requirements.

## Endpoints

### `GET /v2/models`

**List the models Comfy Router can run.**

List available model IDs and billing facts. Use `next_cursor` while `has_more` is true.

**Parameters**

| Name     | In    | Required | Type                                    | Constraints                                               | Description                             |
| -------- | ----- | -------- | --------------------------------------- | --------------------------------------------------------- | --------------------------------------- |
| `cursor` | query | no       | [`RouterPageCursor`](#routerpagecursor) | Opaque cursor returned as `next_cursor`, 1–512 characters | Opaque pagination cursor.               |
| `limit`  | query | no       | integer                                 | Up to 100, Default: 20                                    | Number of models to return in one page. |

**Responses**

| Status | Body                                                  | Headers                                    | Description                                             |
| ------ | ----------------------------------------------------- | ------------------------------------------ | ------------------------------------------------------- |
| `200`  | [`RouterModelListResponse`](#routermodellistresponse) | `X-Comfy-Request-Id`                       | OK - one page of the model catalog.                     |
| `400`  | [`RouterErrorResponse`](#routererrorresponse)         | `X-Comfy-Error-Type`, `X-Comfy-Request-Id` | Invalid request. Check the error type and request body. |
| `401`  | [`RouterErrorResponse`](#routererrorresponse)         | `X-Comfy-Error-Type`, `X-Comfy-Request-Id` | Missing or invalid credentials.                         |
| `403`  | [`RouterErrorResponse`](#routererrorresponse)         | `X-Comfy-Error-Type`, `X-Comfy-Request-Id` | The request is not allowed for this caller or model.    |
| `503`  | [`RouterErrorResponse`](#routererrorresponse)         | `X-Comfy-Error-Type`, `X-Comfy-Request-Id` | Router is temporarily unavailable. Retry with backoff.  |

### `GET /v2/models/{provider}/{model}`

**Read one partner model's catalog entry by canonical model ID.**

Read details for one model without listing the full catalog.

**Parameters**

| Name       | In   | Required | Type                                              | Constraints                                                     | Description                                                      |
| ---------- | ---- | -------- | ------------------------------------------------- | --------------------------------------------------------------- | ---------------------------------------------------------------- |
| `provider` | path | yes      | [`RouterProviderSegment`](#routerprovidersegment) | Alphanumeric slug, e.g. `anthropic`, Up to 64 characters        | Provider portion of the canonical `{provider}/{model}` model ID. |
| `model`    | path | yes      | [`RouterModelSegment`](#routermodelsegment)       | Alphanumeric slug, e.g. `claude-opus-4-6`, Up to 128 characters | Model portion of the canonical `{provider}/{model}` model ID.    |

**Responses**

| Status | Body                                          | Headers                                    | Description                                            |
| ------ | --------------------------------------------- | ------------------------------------------ | ------------------------------------------------------ |
| `200`  | [`RouterModelDetail`](#routermodeldetail)     | `X-Comfy-Request-Id`                       | OK - the model's catalog entry.                        |
| `401`  | [`RouterErrorResponse`](#routererrorresponse) | `X-Comfy-Error-Type`, `X-Comfy-Request-Id` | Missing or invalid credentials.                        |
| `403`  | [`RouterErrorResponse`](#routererrorresponse) | `X-Comfy-Error-Type`, `X-Comfy-Request-Id` | The request is not allowed for this caller or model.   |
| `404`  | [`RouterErrorResponse`](#routererrorresponse) | `X-Comfy-Error-Type`, `X-Comfy-Request-Id` | The model ID was not found.                            |
| `503`  | [`RouterErrorResponse`](#routererrorresponse) | `X-Comfy-Error-Type`, `X-Comfy-Request-Id` | Router is temporarily unavailable. Retry with backoff. |

### `POST /v2/models/{provider}/{model}`

**Run a partner model synchronously by canonical model ID.**

Run a model and receive its finished result in the same response.

**Parameters**

| Name              | In     | Required | Type                                              | Constraints                                                     | Description                                                      |
| ----------------- | ------ | -------- | ------------------------------------------------- | --------------------------------------------------------------- | ---------------------------------------------------------------- |
| `provider`        | path   | yes      | [`RouterProviderSegment`](#routerprovidersegment) | Alphanumeric slug, e.g. `anthropic`, Up to 64 characters        | Provider portion of the canonical `{provider}/{model}` model ID. |
| `model`           | path   | yes      | [`RouterModelSegment`](#routermodelsegment)       | Alphanumeric slug, e.g. `claude-opus-4-6`, Up to 128 characters | Model portion of the canonical `{provider}/{model}` model ID.    |
| `Idempotency-Key` | header | no       | string                                            | 1–255 characters                                                | Caller-generated key that makes retrying ONE logical call safe.  |

**Request body**

`application/json` -- [`RouterModelInput`](#routermodelinput) (required)

The partner model's native JSON input, forwarded to the provider unchanged.

**Responses**

| Status | Body                                                              | Headers                                                                                                                                                      | Description                                                                                                                                                                                |
| ------ | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `200`  | [`RouterModelOutput`](#routermodeloutput)                         | `X-Comfy-Request-Id`, `X-Content-Type-Options`, `Idempotent-Replayed`, `X-Committed-Spend-Limit`, `X-Committed-Spend-Current`, `X-Committed-Spend-Remaining` | OK - the partner model's native output, returned unchanged, under the partner's OWN media type.                                                                                            |
| `400`  | [`RouterErrorResponse`](#routererrorresponse)                     | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`, `X-Comfy-Upstream-Status`, `Idempotent-Replayed`                                                                 | Invalid request. Check the error type and request body.                                                                                                                                    |
| `401`  | [`RouterErrorResponse`](#routererrorresponse)                     | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`                                                                                                                   | Missing or invalid credentials.                                                                                                                                                            |
| `403`  | [`RouterErrorResponse`](#routererrorresponse)                     | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`                                                                                                                   | The request is not allowed for this caller or model.                                                                                                                                       |
| `404`  | [`RouterErrorResponse`](#routererrorresponse)                     | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`                                                                                                                   | The model ID was not found.                                                                                                                                                                |
| `409`  | [`RouterErrorResponse`](#routererrorresponse)                     | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`, `Retry-After` (when `concurrency_limit_exceeded`)                                                                | Inspect `X-Comfy-Error-Type`: `concurrency_limit_exceeded` means the original call is still running, so wait for `Retry-After` and reuse the same key; `invalid_input` requires a new key. |
| `413`  | [`RouterErrorResponse`](#routererrorresponse)                     | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`                                                                                                                   | The request body is too large.                                                                                                                                                             |
| `422`  | [`RouterValidationErrorResponse`](#routervalidationerrorresponse) | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`, `Idempotent-Replayed`                                                                                            | The request's contents were rejected against the model's schema.                                                                                                                           |
| `429`  | [`RouterErrorResponse`](#routererrorresponse)                     | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`, `X-Committed-Spend-Limit`, `X-Committed-Spend-Current`, `X-Committed-Spend-Remaining`                            | Inspect `X-Comfy-Error-Type`: `concurrency_limit_exceeded` means reduce in-flight calls; `rate_limited` means wait for the allowance window.                                               |
| `502`  | [`RouterErrorResponse`](#routererrorresponse)                     | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`, `X-Comfy-Upstream-Status`                                                                                        | The provider's own response could not be turned into a result (`provider_error`).                                                                                                          |
| `503`  | [`RouterErrorResponse`](#routererrorresponse)                     | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`                                                                                                                   | Router is temporarily unavailable. Retry with backoff.                                                                                                                                     |
| `504`  | [`RouterErrorResponse`](#routererrorresponse)                     | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`, `X-Comfy-Upstream-Status`, `Retry-After`                                                                         | The request exceeded a deadline. Check the error type before retrying.                                                                                                                     |

### `GET /v2/models/{provider}/{model}/openapi.json`

**Read one partner model's input and output schemas as an OpenAPI document.**

Read one model's input and output schemas as a standalone OpenAPI document.

**Parameters**

| Name            | In     | Required | Type                                              | Constraints                                                     | Description                                                      |
| --------------- | ------ | -------- | ------------------------------------------------- | --------------------------------------------------------------- | ---------------------------------------------------------------- |
| `provider`      | path   | yes      | [`RouterProviderSegment`](#routerprovidersegment) | Alphanumeric slug, e.g. `anthropic`, Up to 64 characters        | Provider portion of the canonical `{provider}/{model}` model ID. |
| `model`         | path   | yes      | [`RouterModelSegment`](#routermodelsegment)       | Alphanumeric slug, e.g. `claude-opus-4-6`, Up to 128 characters | Model portion of the canonical `{provider}/{model}` model ID.    |
| `If-None-Match` | header | no       | string                                            | -                                                               | The `ETag` a caller holds from an earlier `200`.                 |

**Responses**

| Status | Body                                                                | Headers                                       | Description                                                                                   |
| ------ | ------------------------------------------------------------------- | --------------------------------------------- | --------------------------------------------------------------------------------------------- |
| `200`  | [`RouterModelInputSchemaDocument`](#routermodelinputschemadocument) | `X-Comfy-Request-Id`, `ETag`, `Cache-Control` | OK - the model's input AND output schemas, as a standalone OpenAPI document.                  |
| `304`  | -                                                                   | `X-Comfy-Request-Id`, `ETag`, `Cache-Control` | Not Modified - the document is unchanged since the `ETag` the caller sent in `If-None-Match`. |
| `401`  | [`RouterErrorResponse`](#routererrorresponse)                       | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`    | Missing or invalid credentials.                                                               |
| `403`  | [`RouterErrorResponse`](#routererrorresponse)                       | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`    | The request is not allowed for this caller or model.                                          |
| `404`  | [`RouterErrorResponse`](#routererrorresponse)                       | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`    | The model ID was not found.                                                                   |
| `500`  | [`RouterErrorResponse`](#routererrorresponse)                       | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`    | Router could not complete the request.                                                        |
| `503`  | [`RouterErrorResponse`](#routererrorresponse)                       | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`    | Router is temporarily unavailable. Retry with backoff.                                        |

### `POST /v2/models/{provider}/{model}/requests`

**Submit a partner model run to the queue and return immediately.**

Comfy Router's QUEUED delivery mode. The request body is the same partner-native JSON input `POST /v2/models/{provider}/{model}` accepts for this model - one body shape, one per-model schema, two delivery modes - but this route does NOT hold the connection for the result. It admits the run, answers `201` with a handle, and the caller collects the result later through the three reads below.

**Parameters**

| Name              | In     | Required | Type                                              | Constraints                                                     | Description                                                                                                       |
| ----------------- | ------ | -------- | ------------------------------------------------- | --------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `provider`        | path   | yes      | [`RouterProviderSegment`](#routerprovidersegment) | Alphanumeric slug, e.g. `anthropic`, Up to 64 characters        | Lowercase provider segment of the canonical `{provider}/{model}` model ID - the partner whose model is being run. |
| `model`           | path   | yes      | [`RouterModelSegment`](#routermodelsegment)       | Alphanumeric slug, e.g. `claude-opus-4-6`, Up to 128 characters | Lowercase model segment of the canonical `{provider}/{model}` model ID - the model to run within that provider.   |
| `Idempotency-Key` | header | no       | string                                            | 1–255 characters                                                | Caller-generated key that makes retrying ONE logical call safe.                                                   |

**Request body**

`application/json` -- [`RouterModelInput`](#routermodelinput) (required)

The partner model's native JSON input, identical to the body the synchronous route accepts for this model. Validated against the model's own input schema BEFORE the run is admitted, so a body the model would reject is a `422` here rather than a queued request that fails minutes later.

**Responses**

| Status | Body                                                              | Headers                                                                                       | Description                                                                                                                                                                                |
| ------ | ----------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `201`  | [`RouterQueueSubmitResponse`](#routerqueuesubmitresponse)         | `X-Comfy-Request-Id`, `Idempotent-Replayed`                                                   | Created - the run was admitted to the queue.                                                                                                                                               |
| `401`  | [`RouterErrorResponse`](#routererrorresponse)                     | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`                                                    | Missing or invalid credentials.                                                                                                                                                            |
| `400`  | [`RouterErrorResponse`](#routererrorresponse)                     | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`                                                    | Invalid request. Check the error type and request body.                                                                                                                                    |
| `413`  | [`RouterErrorResponse`](#routererrorresponse)                     | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`                                                    | The request body is too large.                                                                                                                                                             |
| `402`  | [`RouterErrorResponse`](#routererrorresponse)                     | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`                                                    | A Router request-level failure - the request never reached the model, or failed for a reason the model itself did not report.                                                              |
| `403`  | [`RouterErrorResponse`](#routererrorresponse)                     | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`                                                    | The request is not allowed for this caller or model.                                                                                                                                       |
| `404`  | [`RouterErrorResponse`](#routererrorresponse)                     | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`                                                    | The model ID was not found.                                                                                                                                                                |
| `409`  | [`RouterErrorResponse`](#routererrorresponse)                     | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`, `Retry-After` (when `concurrency_limit_exceeded`) | Inspect `X-Comfy-Error-Type`: `concurrency_limit_exceeded` means the original call is still running, so wait for `Retry-After` and reuse the same key; `invalid_input` requires a new key. |
| `422`  | [`RouterValidationErrorResponse`](#routervalidationerrorresponse) | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`, `Idempotent-Replayed`                             | The request's contents were rejected against the model's schema.                                                                                                                           |
| `503`  | [`RouterErrorResponse`](#routererrorresponse)                     | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`                                                    | Router is temporarily unavailable. Retry with backoff.                                                                                                                                     |

### `GET /v2/models/{provider}/{model}/requests/{request_id}`

**Collect the result of one submitted request.**

The collect endpoint. On a request that has finished successfully it returns the partner model's OWN native output, byte for byte what the synchronous route's `200` carries for the same model and the same input - so the two delivery modes produce one result shape and a caller can move between them without a second parser.

**Parameters**

| Name         | In   | Required | Type                                              | Constraints                                                                                          | Description                                                                                                                                              |
| ------------ | ---- | -------- | ------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `provider`   | path | yes      | [`RouterProviderSegment`](#routerprovidersegment) | Alphanumeric slug, e.g. `anthropic`, Up to 64 characters                                             | Lowercase provider segment of the canonical `{provider}/{model}` model ID - the partner whose model is being run.                                        |
| `model`      | path | yes      | [`RouterModelSegment`](#routermodelsegment)       | Alphanumeric slug, e.g. `claude-opus-4-6`, Up to 128 characters                                      | Lowercase model segment of the canonical `{provider}/{model}` model ID - the model to run within that provider.                                          |
| `request_id` | path | yes      | [`RouterQueueRequestId`](#routerqueuerequestid)   | `pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`, uuid, Up to 36 characters | The queued request to address - the `request_id` the submission returned, which is also the value that submission's `X-Comfy-Request-Id` header carried. |

**Responses**

| Status    | Body                                                              | Headers                                                           | Description                                                                                                                                                                                                                                                                                             |
| --------- | ----------------------------------------------------------------- | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `200`     | [`RouterModelOutput`](#routermodeloutput)                         | `X-Comfy-Request-Id`, `X-Content-Type-Options`                    | OK - the partner model's native output for a request that produced one - a request that completed successfully, or a terminal one that carries both a recorded charge and a stored result - returned unchanged under the partner's OWN media type, exactly as the synchronous route's `200` returns it. |
| `202`     | [`RouterQueueStatusResponse`](#routerqueuestatusresponse)         | `X-Comfy-Request-Id`, `Retry-After`                               | Accepted - the request has not finished.                                                                                                                                                                                                                                                                |
| `401`     | [`RouterErrorResponse`](#routererrorresponse)                     | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`                        | Missing or invalid credentials.                                                                                                                                                                                                                                                                         |
| `403`     | [`RouterErrorResponse`](#routererrorresponse)                     | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`                        | The request is not allowed for this caller or model.                                                                                                                                                                                                                                                    |
| `404`     | [`RouterErrorResponse`](#routererrorresponse)                     | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`                        | The model ID was not found.                                                                                                                                                                                                                                                                             |
| `410`     | [`RouterErrorResponse`](#routererrorresponse)                     | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`                        | A Router request-level failure - the request never reached the model, or failed for a reason the model itself did not report.                                                                                                                                                                           |
| `503`     | [`RouterErrorResponse`](#routererrorresponse)                     | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`                        | Router is temporarily unavailable. Retry with backoff.                                                                                                                                                                                                                                                  |
| `409`     | [`RouterErrorResponse`](#routererrorresponse)                     | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`                        | The request is in a state that conflicts with the operation. Check the error type.                                                                                                                                                                                                                      |
| `504`     | [`RouterErrorResponse`](#routererrorresponse)                     | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`                        | The request exceeded a deadline. Check the error type before retrying.                                                                                                                                                                                                                                  |
| `422`     | [`RouterValidationErrorResponse`](#routervalidationerrorresponse) | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`, `Idempotent-Replayed` | The request's contents were rejected against the model's schema.                                                                                                                                                                                                                                        |
| `default` | [`RouterErrorResponse`](#routererrorresponse)                     | `X-Comfy-Error-Type`, `X-Comfy-Request-Id`                        | A Router request-level failure - the request never reached the model, or failed for a reason the model itself did not report.                                                                                                                                                                           |

### `PUT /v2/models/{provider}/{model}/requests/{request_id}/cancel`

**Ask for one submitted request to be cancelled.**

Asks Comfy to stop a request that has not finished. It is a REQUEST, not a guarantee, and the `202` says exactly that: `CANCELLATION_REQUESTED` means the ask was accepted, not that the run has stopped. A run already on the wire at a partner may complete anyway - and a partner generation that completes is charged, whether or not anyone collected it - so a caller who needs to know what actually happened reads the status endpoint afterwards, where a cancellation that took effect is `COMPLETED` carrying an `error_type` like every other terminal outcome.

**Parameters**

| Name         | In   | Required | Type                                              | Constraints                                                                                          | Description                                                                                                                                              |
| ------------ | ---- | -------- | ------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `provider`   | path | yes      | [`RouterProviderSegment`](#routerprovidersegment) | Alphanumeric slug, e.g. `anthropic`, Up to 64 characters                                             | Lowercase provider segment of the canonical `{provider}/{model}` model ID - the partner whose model is being run.                                        |
| `model`      | path | yes      | [`RouterModelSegment`](#routermodelsegment)       | Alphanumeric slug, e.g. `claude-opus-4-6`, Up to 128 characters                                      | Lowercase model segment of the canonical `{provider}/{model}` model ID - the model to run within that provider.                                          |
| `request_id` | path | yes      | [`RouterQueueRequestId`](#routerqueuerequestid)   | `pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`, uuid, Up to 36 characters | The queued request to address - the `request_id` the submission returned, which is also the value that submission's `X-Comfy-Request-Id` header carried. |

**Responses**

| Status    | Body                                                      | Headers                                    | Description                                                                                                                   |
| --------- | --------------------------------------------------------- | ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------- |
| `202`     | [`RouterQueueCancelResponse`](#routerqueuecancelresponse) | `X-Comfy-Request-Id`                       | Accepted - `CANCELLATION_REQUESTED`.                                                                                          |
| `409`     | [`RouterQueueCancelResponse`](#routerqueuecancelresponse) | `X-Comfy-Request-Id`                       | Conflict - `ALREADY_COMPLETED`.                                                                                               |
| `400`     | [`RouterErrorResponse`](#routererrorresponse)             | `X-Comfy-Error-Type`, `X-Comfy-Request-Id` | Invalid request. Check the error type and request body.                                                                       |
| `401`     | [`RouterErrorResponse`](#routererrorresponse)             | `X-Comfy-Error-Type`, `X-Comfy-Request-Id` | Missing or invalid credentials.                                                                                               |
| `403`     | [`RouterErrorResponse`](#routererrorresponse)             | `X-Comfy-Error-Type`, `X-Comfy-Request-Id` | The request is not allowed for this caller or model.                                                                          |
| `404`     | [`RouterErrorResponse`](#routererrorresponse)             | `X-Comfy-Error-Type`, `X-Comfy-Request-Id` | The model ID was not found.                                                                                                   |
| `503`     | [`RouterErrorResponse`](#routererrorresponse)             | `X-Comfy-Error-Type`, `X-Comfy-Request-Id` | Router is temporarily unavailable. Retry with backoff.                                                                        |
| `default` | [`RouterErrorResponse`](#routererrorresponse)             | `X-Comfy-Error-Type`, `X-Comfy-Request-Id` | A Router request-level failure - the request never reached the model, or failed for a reason the model itself did not report. |

### `GET /v2/models/{provider}/{model}/requests/{request_id}/status`

**Read the queue state of one submitted request.**

The poll endpoint. It answers with the request's current state and never with the result, so a client can watch a long generation without transferring its output on every poll - the result is collected once, from the read below, when this says `COMPLETED`.

**Parameters**

| Name         | In   | Required | Type                                              | Constraints                                                                                          | Description                                                                                                                                              |
| ------------ | ---- | -------- | ------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `provider`   | path | yes      | [`RouterProviderSegment`](#routerprovidersegment) | Alphanumeric slug, e.g. `anthropic`, Up to 64 characters                                             | Lowercase provider segment of the canonical `{provider}/{model}` model ID - the partner whose model is being run.                                        |
| `model`      | path | yes      | [`RouterModelSegment`](#routermodelsegment)       | Alphanumeric slug, e.g. `claude-opus-4-6`, Up to 128 characters                                      | Lowercase model segment of the canonical `{provider}/{model}` model ID - the model to run within that provider.                                          |
| `request_id` | path | yes      | [`RouterQueueRequestId`](#routerqueuerequestid)   | `pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`, uuid, Up to 36 characters | The queued request to address - the `request_id` the submission returned, which is also the value that submission's `X-Comfy-Request-Id` header carried. |

**Responses**

| Status    | Body                                                      | Headers                                    | Description                                                                                                                   |
| --------- | --------------------------------------------------------- | ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------- |
| `200`     | [`RouterQueueStatusResponse`](#routerqueuestatusresponse) | `X-Comfy-Request-Id`, `Retry-After`        | OK - the request's current queue state.                                                                                       |
| `401`     | [`RouterErrorResponse`](#routererrorresponse)             | `X-Comfy-Error-Type`, `X-Comfy-Request-Id` | Missing or invalid credentials.                                                                                               |
| `403`     | [`RouterErrorResponse`](#routererrorresponse)             | `X-Comfy-Error-Type`, `X-Comfy-Request-Id` | The request is not allowed for this caller or model.                                                                          |
| `404`     | [`RouterErrorResponse`](#routererrorresponse)             | `X-Comfy-Error-Type`, `X-Comfy-Request-Id` | The model ID was not found.                                                                                                   |
| `410`     | [`RouterErrorResponse`](#routererrorresponse)             | `X-Comfy-Error-Type`, `X-Comfy-Request-Id` | A Router request-level failure - the request never reached the model, or failed for a reason the model itself did not report. |
| `503`     | [`RouterErrorResponse`](#routererrorresponse)             | `X-Comfy-Error-Type`, `X-Comfy-Request-Id` | Router is temporarily unavailable. Retry with backoff.                                                                        |
| `default` | [`RouterErrorResponse`](#routererrorresponse)             | `X-Comfy-Error-Type`, `X-Comfy-Request-Id` | A Router request-level failure - the request never reached the model, or failed for a reason the model itself did not report. |

Table descriptions are brief. Use [Using the Comfy Router API](/development/comfy-router/api) for model selection, validation, retries, and billing, and [Headers](/development/comfy-router/headers) for header behavior.

## Error buckets

Machine-readable Router error category, also sent in the `X-Comfy-Error-Type` header.

### Request-level buckets

Raised for a request Router accepted and then could not complete.

| `error_type`               | Meaning                                                                                                                                                                                                                                                                                                                                                                                   |
| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `invalid_input`            | The request was rejected before it reached the model - a malformed body, a malformed or expired pagination cursor, an input the model's own schema does not accept, or an `Idempotency-Key` that cannot serve this request (already used for a different request - the method, the path and query, or the body differ - or already consumed by a call whose response cannot be replayed). |
| `content_policy_violation` | The provider refused the request on content-policy grounds.                                                                                                                                                                                                                                                                                                                               |
| `provider_error`           | The partner provider reported a failure of its own, or returned a response Router could not interpret as a result.                                                                                                                                                                                                                                                                        |
| `provider_timeout`         | The partner provider did not answer within its deadline.                                                                                                                                                                                                                                                                                                                                  |
| `insufficient_credits`     | The calling workspace does not have enough credits to run the model.                                                                                                                                                                                                                                                                                                                      |
| `model_not_found`          | The `{provider}/{model}` ID names no model Router can run; an unknown provider lands here too.                                                                                                                                                                                                                                                                                            |

### Transport-level buckets

Raised by Router itself, before or around the call to the model.

| `error_type`                 | Meaning                                                                                                                                                                           |
| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `unauthorized`               | The request carried no usable credential.                                                                                                                                         |
| `forbidden`                  | The credential is valid but is not entitled to this model or this operation.                                                                                                      |
| `concurrency_limit_exceeded` | The workspace already has as many calls in flight as it is allowed; retry once one of them finishes.                                                                              |
| `client_disconnected`        | The caller closed the connection before Router could return a result.                                                                                                             |
| `internal_error`             | Router itself failed.                                                                                                                                                             |
| `deadline_exceeded`          | Comfy stopped holding the connection at its own configured bound before an answer arrived.                                                                                        |
| `not_enabled`                | Comfy Router is not switched on for this caller yet.                                                                                                                              |
| `service_unavailable`        | A service Comfy Router depends on is temporarily unavailable and the caller did nothing wrong.                                                                                    |
| `rate_limited`               | The caller has spent an allowance measured over a WINDOW and must wait for that window to roll.                                                                                   |
| `cancelled`                  | A queued request was withdrawn — through the cancel route, or by an operator — before it produced a result; it is TERMINAL, and it is not by itself a statement about the charge. |
| `queue_timeout`              | A queued request waited past its queue timeout without ever being admitted.                                                                                                       |
| `request_not_found`          | The `request_id` names no request of the caller's under this model.                                                                                                               |

## Response headers

| Header                        | Type                                  | Description                                                                                                                                                                                           |
| ----------------------------- | ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Cache-Control`               | string                                | Freshness directives for the served schema document.                                                                                                                                                  |
| `ETag`                        | string                                | Strong entity tag over the served document's bytes, for `GET /v2/models/{provider}/{model}/openapi.json`.                                                                                             |
| `Idempotent-Replayed`         | boolean                               | Present and `true` when this response was served from an `Idempotency-Key`'s record rather than by running the model again.                                                                           |
| `Retry-After`                 | integer                               | Seconds to wait before retrying the SAME request with the SAME `Idempotency-Key`.                                                                                                                     |
| `X-Comfy-Error-Type`          | [`RouterErrorType`](#routererrortype) | Coarse, machine-readable bucket for the failure, set by Router on every error response.                                                                                                               |
| `X-Comfy-Request-Id`          | string                                | Server-generated identifier for this call, present on EVERY Router response - success, 4xx and 5xx alike, because an error response is exactly when a user needs an id to quote in a support request. |
| `X-Comfy-Upstream-Status`     | integer                               | The model provider's OWN HTTP status for this call.                                                                                                                                                   |
| `X-Committed-Spend-Current`   | integer                               | The USD cents the caller currently has committed to calls still in flight.                                                                                                                            |
| `X-Committed-Spend-Limit`     | integer                               | The ceiling, in USD cents, on the partner spend the caller may have committed to calls still in flight - money held from the moment a call is admitted and released when that call finishes.          |
| `X-Committed-Spend-Remaining` | integer                               | The USD cents of headroom left under the ceiling, floored at zero.                                                                                                                                    |
| `X-Content-Type-Options`      | string                                | Always `nosniff`, on every successful run of a Router model.                                                                                                                                          |

## Result assets

A model can return asset URLs, inline bytes, or both. The providers below copy selected assets onto Comfy storage and replace their URLs. This behavior depends on the model; there is no request header that selects it.

| Models                                                      | What is copied onto Comfy storage                                         | Maximum Comfy-hosted URL lifetime |
| ----------------------------------------------------------- | ------------------------------------------------------------------------- | --------------------------------- |
| `bfl/*`                                                     | the finished asset, and the draft-cache asset when the result carries one | 24 hours                          |
| `byteplus/*` video models (`seedance`, `dreamina-seedance`) | the finished video, and the last-frame image when the result carries one  | 24 hours                          |
| `minimax/*`                                                 | the finished video                                                        | 12 hours                          |
| `xai/*`                                                     | every generated image, and the finished video                             | 24 hours                          |

These lifetimes start when the URL is signed, not when you open it. Cached or replayed URLs can have less time remaining; replay does not renew them. Download the asset promptly. Only the assets named in each row are copied: `byteplus/seedream-*` and `byteplus/seededit-*` images are not covered by the BytePlus video row.

**Veo (`veo/*`) has a separate storage path.** In `response.videos[]`, read whichever member is present: `bytesBase64Encoded` contains the clip inline, while `gcsUri` contains a Comfy-signed HTTPS link when the environment is configured for direct provider writes to Comfy storage. That link is valid for 24 hours from the response. The latter case writes the asset directly rather than copying it, so Veo is not in the rehosting table.

Other models return provider asset references or inline bytes. Provider URLs follow the provider's expiry, which can be much shorter than the lifetimes above and is not specified by the Router contract.

Copying is best effort per asset. If one copy fails, that entry keeps its provider reference; the response can contain both Comfy and provider URLs, with no explicit per-asset copy-status field. The generation still succeeds and is charged. Do not infer every URL's lifetime from one successfully rehosted asset.

Whether a result is Comfy-hosted also decides whether a completed call can still be replayed from its `Idempotency-Key` record later; the `Idempotency-Key` parameter above says what a retry is answered with when it cannot be.

<span id="per-model-input-schemas" />

## Per-model input and output schemas

Read each model's fields from `GET /v2/models/{provider}/{model}/openapi.json`. The operation's `requestBody` describes input validation; its `200` response describes the output shape and media type when authored. When `x-comfy-input-schema-authored` is false, Router accepts any JSON object without model-specific prevalidation. Provider requirements still apply. The output schemas describe results; Router does not validate returned provider payloads against them. An unauthored output may use `*/*` rather than `application/json`; inspect the response content type before decoding it.

## Schemas

### RouterChargesOnPolicyRejection

Whether a content-policy refusal is charged for this model. Treat an unknown value as potentially charged.

Type: `string`

### RouterErrorResponse

Error body for authentication, access, model lookup, quota, and provider transport failures.

| Field        | Type                                  | Required | Constraints | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| ------------ | ------------------------------------- | -------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `detail`     | string                                | yes      | -           | Human-readable description of the failure, safe to surface to an end user. Not machine-parsed - branch on `error_type` instead.                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `error_type` | [`RouterErrorType`](#routererrortype) | yes      | -           | Coarse, machine-readable bucket for a Router failure, mirrored on the `X-Comfy-Error-Type` response header so a caller can branch without parsing the body. The set is closed at fifteen values: the six request-level buckets `invalid_input`, `content_policy_violation`, `provider_error`, `provider_timeout`, `insufficient_credits` and `model_not_found`, plus the transport-level `unauthorized`, `forbidden`, `concurrency_limit_exceeded`, `client_disconnected`, `internal_error`, `deadline_exceeded`, `not_enabled`, `service_unavailable` and `rate_limited`. |

### RouterErrorType

Machine-readable Router error category, also sent in the `X-Comfy-Error-Type` header.

Type: `string`

### RouterModelBilling

Billing behavior to check before invoking a model. It does not include prices or usage.

| Field                         | Type                                                                | Required | Constraints | Description                                                                                                                                                                                                                                                                                                                                  |
| ----------------------------- | ------------------------------------------------------------------- | -------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `charges_on_policy_rejection` | [`RouterChargesOnPolicyRejection`](#routerchargesonpolicyrejection) | yes      | -           | Whether a call this model REFUSES on content-policy grounds is nevertheless charged to the caller. Providers differ, the difference is invisible at call time, and a user who sees an error and a charge for the same call has no way to have known - so it is stated per model, before the call, rather than left to per-provider folklore. |

### RouterModelDetail

Per-model detail for one Comfy Router model: everything the catalog listing reports for it, plus the per-model fields that only the single-model route carries.

Composes [`RouterModelListEntry`](#routermodellistentry), [`RouterModelDetailFields`](#routermodeldetailfields).

Type: `object`

### RouterModelDetailFields

Optional fields returned by the model-details endpoint.

| Field              | Type   | Required | Constraints                                                                                          | Description                                                                   |
| ------------------ | ------ | -------- | ---------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| `input_schema_url` | string | no       | HTTPS URL, e.g. `https://api.comfy.org/v2/models/bfl/flux-2-pro/openapi.json`, Up to 2048 characters | URL of this model's OpenAPI document, including its input and output schemas. |

### RouterModelId

The model ID used in `POST /v2/models/{provider}/{model}`.

Type: `string` -- Model ID, e.g. `anthropic/claude-opus-4-6`, Up to 193 characters

### RouterModelInput

The model input object. Read the selected model's OpenAPI document for fields and validation.

Type: `object`

### RouterModelInputSchemaDocument

A standalone OpenAPI document for one model's input and output.

Type: `object`

### RouterModelListEntry

A model's ID and billing facts.

| Field      | Type                                              | Required | Constraints                                                      | Description                                                                                                                                                                                                                                                                                                                                                                   |
| ---------- | ------------------------------------------------- | -------- | ---------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`       | [`RouterModelId`](#routermodelid)                 | yes      | Model ID, e.g. `anthropic/claude-opus-4-6`, Up to 193 characters | A canonical Comfy Router model ID, `{provider}/{model}` - exactly the value that addresses the model on `POST /v2/models/{provider}/{model}`, so a caller can interpolate it into that path without re-deriving it from anything. Its `pattern` is `RouterProviderSegment` and `RouterModelSegment` joined by a single `/`, and `maxLength` is their sum plus that separator. |
| `provider` | [`RouterProviderSegment`](#routerprovidersegment) | yes      | Alphanumeric slug, e.g. `anthropic`, Up to 64 characters         | Lowercase `provider` segment of the canonical `{provider}/{model}` model ID - the partner whose model is being addressed. The invocation route's `provider` path parameter and a catalog entry's `provider` field both reference this one schema, which is what keeps the listed IDs and the accepted IDs from drifting apart.                                                |
| `model`    | [`RouterModelSegment`](#routermodelsegment)       | yes      | Alphanumeric slug, e.g. `claude-opus-4-6`, Up to 128 characters  | Lowercase `model` segment of the canonical `{provider}/{model}` model ID - the model to run within that provider. Shared by the invocation route's `model` path parameter and a catalog entry's `model` field, for the same no-drift reason as `RouterProviderSegment`.                                                                                                       |
| `billing`  | [`RouterModelBilling`](#routermodelbilling)       | yes      | -                                                                | Per-model billing FACTS a caller needs before invoking - not prices. Usage and cost figures never appear here.                                                                                                                                                                                                                                                                |

### RouterModelListResponse

One page of the Router model catalog.

| Field         | Type                                                     | Required | Constraints                                               | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| ------------- | -------------------------------------------------------- | -------- | --------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `data`        | array of [`RouterModelListEntry`](#routermodellistentry) | yes      | -                                                         | The models on this page, at most `limit` of them.                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `has_more`    | boolean                                                  | yes      | -                                                         | Whether another page exists beyond this one. Keep walking while this is true; do not infer the end of the catalog from a short or empty `data`.                                                                                                                                                                                                                                                                                                                                                                  |
| `next_cursor` | [`RouterPageCursor`](#routerpagecursor)                  | no       | Opaque cursor returned as `next_cursor`, 1–512 characters | An OPAQUE cursor into a Router list. It is produced by the server and only ever round-tripped: it is not an offset, not a model ID, not ordered, and not stable across catalog rebuilds, so parsing one, incrementing one, or persisting one beyond the walk it came from are all outside the contract. Cursor rather than offset because the catalog is a moving list - an offset walk silently skips or repeats entries when entries are added or removed mid-walk, and a caller cannot tell that it happened. |
| `limit`       | integer                                                  | yes      | 1–100                                                     | The page size actually served. A requested `limit` above the maximum is CLAMPED down to the maximum rather than rejected, so this can be smaller than the value asked for - paginate with this number, not with the one you sent, or you will assume rows you never received.                                                                                                                                                                                                                                    |

### RouterModelOutput

The model result object. Read the selected model's output schema for its exact shape.

Type: `object`

### RouterModelSegment

The model portion of a `{provider}/{model}` model ID.

Type: `string` -- Alphanumeric slug, e.g. `claude-opus-4-6`, Up to 128 characters

### RouterPageCursor

An opaque catalog cursor. Pass it back unchanged as `cursor`.

Type: `string` -- Opaque cursor returned as `next_cursor`, 1–512 characters

### RouterProviderSegment

The provider portion of a `{provider}/{model}` model ID.

Type: `string` -- Alphanumeric slug, e.g. `anthropic`, Up to 64 characters

### RouterQueueCancelResponse

The answer to a cancellation ask on the two statuses that describe a request this route resolved - the `202` and the `400`. One body shape across both rather than a success envelope plus an error envelope, because both are the same statement - what cancelling found - and a client that has to parse a different type per status code gains nothing from the split.

| Field        | Type                                                  | Required | Constraints                                                                                          | Description                                                                                                                                                                       |
| ------------ | ----------------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `request_id` | [`RouterQueueRequestId`](#routerqueuerequestid)       | yes      | `pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`, uuid, Up to 36 characters | Identifier of one queued Router request - the handle a caller polls, cancels and collects a result by.                                                                            |
| `status`     | [`RouterQueueCancelStatus`](#routerqueuecancelstatus) | yes      | -                                                                                                    | What a cancellation ask found, for the two outcomes that describe a request this route actually resolved. Both are mirrored by the HTTP status, so a client may branch on either. |

### RouterQueueCancelStatus

What a cancellation ask found, for the two outcomes that describe a request this route actually resolved. Both are mirrored by the HTTP status, so a client may branch on either.

Type: `string`

### RouterQueuePosition

How many requests are ahead of this one in the queue, at the instant the response was composed. Zero means this request is at the front.

Type: `integer` -- At least 0

### RouterQueueRequestId

Identifier of one queued Router request - the handle a caller polls, cancels and collects a result by.

Type: `string` -- `pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`, uuid, Up to 36 characters

### RouterQueueStatus

The state of a queued Router request. EXACTLY THREE VALUES, and unlike `RouterErrorType` this one IS a closed `enum`, because the two schemas are closed in opposite directions on purpose. `RouterErrorType` classifies failures and its set is expected to grow, so a generated client that hard-rejected an unrecognised bucket would fail hardest exactly when something had already gone wrong. This one is a lifecycle, and a lifecycle with a fourth state added later is a breaking change to every polling loop written against it whether it is declared as an enum or not - so it is declared as one, and the constraint is stated where a client can see it.

Type: `string`

### RouterQueueStatusFields

The half of `RouterQueueStatusResponse` that is not the URL block: one queued request's identity, its current state, and - when that state is terminal and the run did not succeed - the coarse bucket saying why.

| Field            | Type                                            | Required | Constraints                                                                                          | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| ---------------- | ----------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `request_id`     | [`RouterQueueRequestId`](#routerqueuerequestid) | yes      | `pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`, uuid, Up to 36 characters | Identifier of one queued Router request - the handle a caller polls, cancels and collects a result by.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `status`         | [`RouterQueueStatus`](#routerqueuestatus)       | yes      | -                                                                                                    | The state of a queued Router request. EXACTLY THREE VALUES, and unlike `RouterErrorType` this one IS a closed `enum`, because the two schemas are closed in opposite directions on purpose. `RouterErrorType` classifies failures and its set is expected to grow, so a generated client that hard-rejected an unrecognised bucket would fail hardest exactly when something had already gone wrong. This one is a lifecycle, and a lifecycle with a fourth state added later is a breaking change to every polling loop written against it whether it is declared as an enum or not - so it is declared as one, and the constraint is stated where a client can see it. |
| `queue_position` | [`RouterQueuePosition`](#routerqueueposition)   | no       | At least 0                                                                                           | How many requests are ahead of this one in the queue, at the instant the response was composed. Zero means this request is at the front.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `error_type`     | [`RouterErrorType`](#routererrortype)           | no       | -                                                                                                    | Present ONLY on a `COMPLETED` request that did not succeed, carrying the same coarse bucket the result read puts on `X-Comfy-Error-Type` when it returns that failure. It is what distinguishes a terminal request that succeeded from one that failed or was cancelled - there is no separate terminal status for either - and it is ABSENT on success rather than null, so branch on its presence.                                                                                                                                                                                                                                                                     |

### RouterQueueStatusResponse

One queued request's current state, composed with the same three URLs the submission returned.

Composes [`RouterQueueUrls`](#routerqueueurls), [`RouterQueueStatusFields`](#routerqueuestatusfields).

Type: `object`

### RouterQueueSubmitFields

The half of `RouterQueueSubmitResponse` that is not the URL block: the new request's identity and its state at the instant it was admitted.

| Field            | Type                                            | Required | Constraints                                                                                          | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| ---------------- | ----------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `request_id`     | [`RouterQueueRequestId`](#routerqueuerequestid) | yes      | `pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`, uuid, Up to 36 characters | Identifier of one queued Router request - the handle a caller polls, cancels and collects a result by.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `status`         | [`RouterQueueStatus`](#routerqueuestatus)       | yes      | -                                                                                                    | The state of a queued Router request. EXACTLY THREE VALUES, and unlike `RouterErrorType` this one IS a closed `enum`, because the two schemas are closed in opposite directions on purpose. `RouterErrorType` classifies failures and its set is expected to grow, so a generated client that hard-rejected an unrecognised bucket would fail hardest exactly when something had already gone wrong. This one is a lifecycle, and a lifecycle with a fourth state added later is a breaking change to every polling loop written against it whether it is declared as an enum or not - so it is declared as one, and the constraint is stated where a client can see it. |
| `queue_position` | [`RouterQueuePosition`](#routerqueueposition)   | no       | At least 0                                                                                           | How many requests are ahead of this one in the queue, at the instant the response was composed. Zero means this request is at the front.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |

### RouterQueueSubmitResponse

The handle returned when a run is admitted to the queue: the request's identity and state, composed with the three URLs that address the rest of its lifetime.

Composes [`RouterQueueUrls`](#routerqueueurls), [`RouterQueueSubmitFields`](#routerqueuesubmitfields).

Type: `object`

### RouterQueueUrls

The three URLs that address the rest of one queued request's lifetime, returned on every response that carries a live handle so a client never composes a queue URL itself.

| Field          | Type   | Required | Constraints | Description                                           |
| -------------- | ------ | -------- | ----------- | ----------------------------------------------------- |
| `status_url`   | string | yes      | URI         | Absolute URL of this request's status read.           |
| `response_url` | string | yes      | URI         | Absolute URL this request's result is collected from. |
| `cancel_url`   | string | yes      | URI         | Absolute URL a cancellation is asked for at.          |

### RouterValidationErrorContext

Provider-supplied details about the validation rule that failed.

Type: `object`

### RouterValidationErrorDetail

One field-level validation failure.

| Field   | Type                                                            | Required | Constraints | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| ------- | --------------------------------------------------------------- | -------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `loc`   | array of any                                                    | yes      | -           | Path to the offending field, outermost segment first - for example `["body", "image_url"]`, or `["body", "images", 0]` where an integer indexes into an array.                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `msg`   | string                                                          | yes      | -           | Human-readable description of this single failure.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `type`  | string                                                          | yes      | -           | Specific, machine-readable reason for this failure, passed through from the provider unchanged. This is the value a typed SDK exception hierarchy branches on; `error_type` on the response header is only its coarse bucket.                                                                                                                                                                                                                                                                                                                                                                              |
| `ctx`   | [`RouterValidationErrorContext`](#routervalidationerrorcontext) | no       | -           | The violated bound for one `RouterValidationErrorDetail`, carried from the provider verbatim - for example `{"limit_value": 8}` alongside `greater_than`, `{"min_width": 512}` alongside `image_too_small`, or `{"max_size_bytes": 10485760}` alongside `file_too_large`. The key set is specific to the provider and the error type, so this is deliberately an open object: narrowing it to a fixed field list, or folding it into the `msg` string, is precisely how a ported integration compiles and then silently loses the branch that read the bound. Absent when the error type carries no bound. |
| `input` | [`RouterValidationErrorInput`](#routervalidationerrorinput)     | no       | -           | The offending input value, echoed back verbatim so a caller can see what was rejected without re-deriving it from `loc`. Any JSON type - string, number, boolean, array, object or null - so this schema is deliberately left untyped rather than narrowed to an object. Absent when the provider does not echo the input back.                                                                                                                                                                                                                                                                            |

### RouterValidationErrorInput

The rejected input value, when the provider includes it.

### RouterValidationErrorResponse

The `422` validation error body. Read `X-Comfy-Error-Type` for its category.

| Field    | Type                                                                   | Required | Constraints | Description                                                                   |
| -------- | ---------------------------------------------------------------------- | -------- | ----------- | ----------------------------------------------------------------------------- |
| `detail` | array of [`RouterValidationErrorDetail`](#routervalidationerrordetail) | yes      | -           | Every validation failure found on the request, one entry per offending field. |
