> ## 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.

# Referencia de la API de Comfy Router

> Todos los endpoints, parámetros, respuestas y errores de Comfy Router, según el contrato de la API de Comfy.

Rutas canónicas de Comfy Router, direccionadas por ID de modelo.

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

Todos los endpoints siguientes requieren autenticación. Envía `X-API-Key: <api-key>` o `Authorization: Bearer <jwt>`.

Las claves de API de Comfy también se pueden enviar como tokens Bearer. `X-API-Key` tiene prioridad cuando se proporcionan ambos encabezados de credenciales. Consulta [encabezados de autenticación](https://docs.comfy.org/es/development/comfy-router/headers.md#encabezados-de-la-solicitud) para ver la distinción entre clave y JWT y [la guía de inicio rápido](https://docs.comfy.org/es/development/comfy-router/quickstart.md) para conocer los requisitos de acceso.

## Endpoints

### `GET /v2/models`

**Enumera los modelos que Comfy Router puede ejecutar.**

Consulta los IDs de modelo disponibles y los datos de facturación. Usa `next_cursor` mientras `has_more` sea verdadero.

**Parámetros**

**cursor** `RouterPageCursor`

Cursor de paginación opaco.

Tipo: [`RouterPageCursor`](#routerpagecursor) -- Cursor opaco devuelto como `next_cursor`, de 1 a 512 caracteres

**limit** `integer`

Cantidad de modelos que se devuelven en una página.

Hasta 100, Predeterminado: 20

**If-None-Match** `string`

El `ETag` que el solicitante conserva de un `200` anterior.

**Respuestas**

**200** `RouterModelListResponse`

OK: una página del catálogo de modelos.

Cuerpo: [`RouterModelListResponse`](#routermodellistresponse) -- Encabezados: `X-Comfy-Request-Id`, `ETag`, `Cache-Control`

**304** `no body`

Not Modified: la página no cambió desde el `ETag` que el solicitante envió en `If-None-Match`.

Encabezados: `X-Comfy-Request-Id`, `ETag`, `Cache-Control`

**400** `RouterErrorResponse`

Solicitud no válida. Revisa el tipo de error y el cuerpo de la solicitud.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**401** `RouterErrorResponse`

Credenciales faltantes o no válidas.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**403** `RouterErrorResponse`

La solicitud no está permitida para este solicitante o modelo.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**503** `RouterErrorResponse`

El router no está disponible temporalmente. Reintenta con retroceso exponencial.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

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

**Lee la entrada del catálogo de un modelo socio por su ID de modelo canónico.**

Lee los detalles de un modelo sin listar el catálogo completo.

**Parámetros**

**provider** `RouterProviderSegment` *required*

Parte del proveedor en el ID de modelo canónico `{provider}/{model}`.

Tipo: [`RouterProviderSegment`](#routerprovidersegment). Slug alfanumérico, p. ej. `anthropic`. Hasta 64 caracteres

**model** `RouterModelSegment` *required*

Parte del modelo en el ID de modelo canónico `{provider}/{model}`.

Tipo: [`RouterModelSegment`](#routermodelsegment). Slug alfanumérico, p. ej. `claude-opus-4-6`. Hasta 128 caracteres

**If-None-Match** `string`

El `ETag` que un llamador conserva de un `200` anterior.

**Respuestas**

**200** `RouterModelDetail`

OK: la entrada del catálogo del modelo.

Cuerpo: [`RouterModelDetail`](#routermodeldetail). Encabezados: `X-Comfy-Request-Id`, `ETag`, `Cache-Control`

**304** `no body`

No modificado: la entrada no ha cambiado desde el `ETag` que el llamador envió en `If-None-Match`.

Encabezados: `X-Comfy-Request-Id`, `ETag`, `Cache-Control`

**401** `RouterErrorResponse`

Credenciales faltantes o inválidas.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse). Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**403** `RouterErrorResponse`

La solicitud no está permitida para este llamador ni para este modelo.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse). Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**404** `RouterErrorResponse`

No se encontró el ID de modelo.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse). Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**503** `RouterErrorResponse`

Router no está disponible temporalmente. Reintenta con retroceso exponencial.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse). Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

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

**Ejecuta un modelo socio de forma sincrónica mediante el ID canónico del modelo.**

Ejecuta un modelo y recibe su resultado finalizado en la misma respuesta.

**Parámetros**

**provider** `RouterProviderSegment` *required*

Parte del proveedor en el ID canónico `{provider}/{model}` del modelo.

Tipo: [`RouterProviderSegment`](#routerprovidersegment) -- Slug alfanumérico, por ejemplo `anthropic`, de hasta 64 caracteres

**model** `RouterModelSegment` *required*

Parte del modelo en el ID canónico `{provider}/{model}` del modelo.

Tipo: [`RouterModelSegment`](#routermodelsegment) -- Slug alfanumérico, por ejemplo `claude-opus-4-6`, de hasta 128 caracteres

**Idempotency-Key** `string`

Clave generada por quien llama que hace seguro reintentar una misma llamada lógica.

De 1 a 255 caracteres

**model\_provider** `string`

Selecciona un proveedor alternativo para servir este modelo, en lugar de su valor predeterminado actual; `fal`, `wavespeed`, `runware` y `higgsfield` son los alternativos, y `GET /v2/models/{provider}/{model}` informa cuáles de ellos admite un modelo dado. Sus rechazos se comprueban en un orden fijo, y los anteriores responden tanto si los posteriores lo harían como si no: un valor no reconocido, que no es un proveedor registrado en absoluto, se rechaza con `400`; después, un proveedor alternativo en una solicitud cuyo cuerpo selecciona una operación multipart (una edición) se rechaza con `409` y un `detail` que comienza con "this request's `image` selects the edit operation", pero solo cuando el traductor de ese proveedor para este modelo no puede servir la operación: una opción cuyo traductor sí admite el medio continúa con normalidad; después, cualquier proveedor alternativo en una solicitud que resolvió una credencial de tipo bring-your-own-key se rechaza con `409` y un `detail` que comienza con `this request resolved a BYOK credential` (consulta esa respuesta), sirva o no ese proveedor a este modelo; después, la compuerta propia del proveedor indicado, que rechaza con `403` y `error_type: not_enabled` cuando ese proveedor no está activado para ti y con `503` y `error_type: service_unavailable` cuando la compuerta no se puede evaluar; y solo después de las cuatro se rechaza con `400` y `error_type: invalid_input` un proveedor real sin opción para este modelo, la misma respuesta que la de un valor no reconocido. `fallback_provider` queda inerte en lugar de rechazarse en una solicitud bring-your-own-key, en una solicitud cuyo cuerpo selecciona una operación multipart y con `strict_mode=true`.

**strict\_mode** `boolean`

Solo tiene sentido junto con `model_provider`.

Predeterminado: False

**fallback\_provider** `string`

Controla si Router reintenta esta llamada contra el otro proveedor registrado del modelo cuando el primer intento falla por un motivo atribuible a Router o al proveedor probado. Si se omite, o con cualquier valor distinto de `false`, el fallback queda activo; `false` lo desactiva. Una respuesta de fallback exitosa incluye `X-Comfy-Router-Fallback-Provider`. En una solicitud que resolvió una credencial de tipo bring-your-own-key el fallback no está disponible diga lo que diga este parámetro: el intento simplemente no se hace y el primer fallo te llega sin cambios, lo cual es inerte, no un rechazo: aquí no se origina ningún `409`. Lo mismo ocurre, por la misma razón, en una solicitud cuyo cuerpo selecciona una operación multipart y con `strict_mode=true`: cada una vincula la llamada a un único proveedor que no se puede reproducir fielmente contra otro, así que el fallback simplemente se omite en lugar de rechazarse. Solo un `model_provider` explícito se rechaza con ese `409`, y a diferencia de esta omisión incondicional, su `409` por multipart se aplica únicamente a una opción cuyo traductor no puede servir la operación.

**reject\_unknown\_fields** `boolean`

Actívalo para rechazar un campo de nivel superior del cuerpo de la solicitud que el esquema de entrada de este modelo no declara, en lugar de aceptarlo; los campos anidados no se comprueban, y no se rechaza nada para un modelo cuyo esquema permite campos no declarados o que no tiene esquema creado, ni en un envío en cola enviado con `strict_mode=true`.

Predeterminado: False

**Cuerpo de la solicitud**

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

La entrada JSON nativa del modelo socio. Sin `model_provider`, la solicitud ejecuta el despacho nativo en el proveedor predeterminado del modelo y este cuerpo es el propio esquema nativo del modelo, reenviado sin cambios (`strict_mode` no tiene sentido ahí y no cambia nada). Con `model_provider` seleccionando un proveedor alternativo y `strict_mode=false` (el valor predeterminado), el cuerpo se traduce al esquema real de ese proveedor antes de enviarse: cualquier campo nativo que no se pueda expresar con exactitud se descarta y se divulga mediante el encabezado `X-Comfy-Router-Dropped-Params` de la respuesta, nunca en silencio. Con `model_provider` seleccionando un proveedor alternativo y `strict_mode=true` no se ejecuta ninguna traducción: el cuerpo ya debe ser el esquema real propio de ese proveedor alternativo, no el nativo de este modelo (consulta `strict_mode`), y se reenvía sin cambios. Los propios campos del cuerpo también seleccionan qué operación ejecuta Router en un modelo que admite más de una: para un modelo de imagen editable, incluir una imagen de entrada lo cambia de la operación texto a imagen a la operación imagen a imagen (edición), que puede facturarse con su propia tarifa; para un modelo de video Seedance, `content[].role` selecciona la operación (una imagen de primer fotograma selecciona imagen a video, y una imagen o un clip de referencia selecciona referencia a video). En el despacho nativo, la facturación de Seedance sigue los tipos de medio en `content`, no los roles: una solicitud con cualquier entrada de video se factura como video a video; si no, una con cualquier imagen se factura como imagen a video; si no, texto a video, salvo que un render final de un elemento `draft_task` se factura como la operación del Draft que renderiza; algunos modelos cobran la misma tarifa para texto a video e imagen a video. Con `model_provider` seleccionando un proveedor alternativo, cada operación condicionada puede facturarse con la tarifa propia de ese proveedor.

**Respuestas**

**200** `RouterModelOutput`

OK: sin `model_provider`, o con `model_provider` y `strict_mode=false` (el valor predeterminado; se traduce de vuelta al contrato nativo de este modelo cuando es posible, y si la traducción falla se recurre a la respuesta sin procesar del proveedor alternativo, registrada en el log y nunca silenciosa), la forma es la salida nativa de este modelo; con `strict_mode=true` es la respuesta del proveedor alternativo devuelta sin cambios. Para un modelo cuyo socio responde a una generación directamente como bytes, el cuerpo son esos bytes con el `Content-Type` propio del socio en lugar de `application/json`; ramifica según el `Content-Type` de la respuesta y no des por hecho que se trata de un documento JSON.

Cuerpo: [`RouterModelOutput`](#routermodeloutput) o bytes sin procesar (`*/*`) -- Encabezados: `X-Comfy-Request-Id`, `X-Content-Type-Options`, `X-Comfy-Router-Fallback-Provider`, `X-Comfy-Router-Provider`, `X-Comfy-Router-Dropped-Params`, `X-Comfy-Credits-Used`, `Idempotent-Replayed`, `X-Committed-Spend-Limit`, `X-Committed-Spend-Current`, `X-Committed-Spend-Remaining`

**400** `RouterErrorResponse`

Solicitud no válida. Revisa el tipo de error y el cuerpo de la solicitud.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`, `X-Comfy-Upstream-Status`, `X-Comfy-Upstream-Detail`, `X-Comfy-Refusal-Subject`, `Idempotent-Replayed`

**401** `RouterErrorResponse`

Credenciales faltantes o no válidas.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**402** `RouterErrorResponse`

Un fallo a nivel de solicitud del Router: la solicitud nunca llegó al modelo, o falló por un motivo que el propio modelo no reportó.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**403** `RouterErrorResponse`

La solicitud no está permitida para este solicitante o este modelo.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**404** `RouterErrorResponse`

No se encontró el ID del modelo.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**409** `RouterErrorResponse`

Revisa `X-Comfy-Error-Type`: `concurrency_limit_exceeded` significa que la llamada original sigue en ejecución, así que espera el `Retry-After` y reutiliza la misma clave; `invalid_input` requiere una clave nueva. Dos conflictos `invalid_input` en esta ruta no tienen nada que ver con la clave, y ninguna clave nueva resuelve ninguno de los dos: se rechaza un `model_provider` que nombra a un proveedor alternativo cuando el cuerpo de la solicitud selecciona una operación multipart (una edición) que el traductor de ese proveedor para este modelo no puede atender, y cuyo `detail` comienza con "this request's `image` selects the edit operation"; y, comprobado después de eso, cuando la solicitud ya resolvió una credencial de tipo bring-your-own-key para el proveedor de la ruta, cuyo `detail` comienza con `this request resolved a BYOK credential`. Quita `model_provider`, o envía la solicitud sin la credencial BYOK y (para el caso multipart) sin la edición.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`, `Retry-After` (cuando es `concurrency_limit_exceeded`)

**413** `RouterErrorResponse`

El cuerpo de la solicitud es demasiado grande.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**422** `RouterValidationErrorResponse`

El contenido de la solicitud fue rechazado contra el esquema del modelo.

Cuerpo: [`RouterValidationErrorResponse`](#routervalidationerrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`, `Idempotent-Replayed`

**429** `RouterErrorResponse`

Revisa `X-Comfy-Error-Type`: `concurrency_limit_exceeded` significa que debes reducir las llamadas en curso; `rate_limited` significa que debes esperar a que se abra la ventana de cupo.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`, `X-Committed-Spend-Limit`, `X-Committed-Spend-Current`, `X-Committed-Spend-Remaining`, `X-Model-Concurrency-Limit`, `X-Model-Concurrency-Current`, `X-Model-Concurrency-Remaining`

**502** `RouterErrorResponse`

La propia respuesta del proveedor no se pudo convertir en un resultado (`provider_error`).

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`, `X-Comfy-Upstream-Status`

**503** `RouterErrorResponse`

Router no está disponible temporalmente. Reintenta con retroceso exponencial.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`, `Retry-After` (solo rechazos por capacidad)

**504** `RouterErrorResponse`

La solicitud superó un plazo límite. Revisa el tipo de error antes de reintentar.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`, `X-Comfy-Upstream-Status`, `Retry-After`

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

**Calcula el precio de una llamada a un modelo antes de ejecutarla, sin ejecutarla.**

Devuelve una estimación previa, en dólares estadounidenses, de lo que costará ejecutar este cuerpo en este modelo, con precios tomados de la misma tarifa con la que se factura la ejecución. Es una estimación, no el cargo final: lo que pagas es el cargo liquidado en los registros de uso y facturación de tu espacio de trabajo. El cuerpo se valida primero contra el esquema de entrada del modelo, tal como lo valida una ejecución predeterminada (sin `strict_mode`, sin `reject_unknown_fields`), así que un cuerpo que no cumple el esquema del modelo produce aquí el mismo `422` que en la ejecución; no se despacha nada a un proveedor y no se cobra nada. La respuesta no es un bloqueo de precio: se calcula con las tarifas vigentes en `pricing_as_of`, y una ejecución se cobra con las tarifas vigentes cuando se tarifica. Mientras la función se está desplegando, la ruta responde `403` con `error_type: not_enabled`.

**Parámetros**

**provider** `RouterProviderSegment` *required*

Segmento de proveedor en minúsculas del ID de modelo canónico `{provider}/{model}`: el socio cuyo modelo se ejecuta.

Tipo: [`RouterProviderSegment`](#routerprovidersegment) -- Slug alfanumérico, p. ej. `anthropic`, hasta 64 caracteres

**model** `RouterModelSegment` *required*

Segmento de modelo en minúsculas del ID de modelo canónico `{provider}/{model}`: el modelo a ejecutar dentro de ese proveedor.

Tipo: [`RouterModelSegment`](#routermodelsegment) -- Slug alfanumérico, p. ej. `claude-opus-4-6`, hasta 128 caracteres

**model\_provider** `string`

Selecciona un proveedor alternativo para servir este modelo, en lugar de su valor predeterminado actual.

**Cuerpo de la solicitud**

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

La entrada JSON nativa del modelo del socio, idéntica al cuerpo que la ruta síncrona acepta para este modelo. Se valida contra el esquema de entrada propio del modelo tal como lo valida una ejecución predeterminada (esta ruta no acepta `strict_mode` ni `reject_unknown_fields`), y sus propios campos (el número de salidas, la operación que selecciona una imagen de entrada) deciden qué se tarifica.

**Respuestas**

**200** `RouterCostEstimate`

La cotización.

Cuerpo: [`RouterCostEstimate`](#routercostestimate) -- Encabezados: `X-Comfy-Request-Id`

**400** `RouterErrorResponse`

Solicitud no válida. Revisa el tipo de error y el cuerpo de la solicitud.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**401** `RouterErrorResponse`

Credenciales faltantes o no válidas.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**403** `RouterErrorResponse`

La solicitud no está permitida para este solicitante o modelo.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**404** `RouterErrorResponse`

No se encontró el ID de modelo.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**413** `RouterErrorResponse`

El cuerpo de la solicitud es demasiado grande.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**422** `RouterValidationErrorResponse`

El cuerpo de la estimación se rechazó contra el esquema del modelo, o nombraba un modelo distinto del de la ruta.

Cuerpo: [`RouterValidationErrorResponse`](#routervalidationerrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**503** `RouterErrorResponse`

Router no está disponible temporalmente. Reintenta aplicando backoff.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`, `Retry-After` (solo rechazos por capacidad)

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

**Lee los esquemas de entrada y salida de un modelo socio como documento OpenAPI.**

Lee los esquemas de entrada y salida de un modelo como un documento OpenAPI independiente.

**Parámetros**

**provider** `RouterProviderSegment` *required*

Parte del proveedor en el ID de modelo canónico `{provider}/{model}`.

Tipo: [`RouterProviderSegment`](#routerprovidersegment). Slug alfanumérico, p. ej. `anthropic`. Hasta 64 caracteres

**model** `RouterModelSegment` *required*

Parte del modelo en el ID de modelo canónico `{provider}/{model}`.

Tipo: [`RouterModelSegment`](#routermodelsegment). Slug alfanumérico, p. ej. `claude-opus-4-6`. Hasta 128 caracteres

**If-None-Match** `string`

El `ETag` que el solicitante conserva de una respuesta `200` anterior.

**Respuestas**

**200** `RouterModelInputSchemaDocument`

OK: los esquemas de entrada y salida del modelo, como un documento OpenAPI independiente.

Cuerpo: [`RouterModelInputSchemaDocument`](#routermodelinputschemadocument). Encabezados: `X-Comfy-Request-Id`, `ETag`, `Cache-Control`

**304** `no body`

Not Modified: el documento no ha cambiado desde el `ETag` que el solicitante envió en `If-None-Match`.

Encabezados: `X-Comfy-Request-Id`, `ETag`, `Cache-Control`

**401** `RouterErrorResponse`

Credenciales faltantes o no válidas.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse). Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**403** `RouterErrorResponse`

La solicitud no está permitida para este solicitante ni para este modelo.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse). Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**404** `RouterErrorResponse`

No se encontró el ID del modelo.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse). Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**500** `RouterErrorResponse`

Router no pudo completar la solicitud.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse). Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**503** `RouterErrorResponse`

Router no está disponible temporalmente. Reintenta con retroceso exponencial.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse). Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

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

**Envía una ejecución de modelo asociado a la cola y regresa de inmediato.**

El modo de entrega en cola de Comfy Router. El cuerpo de la solicitud es la misma entrada JSON nativa del socio que `POST /v2/models/{provider}/{model}` acepta para este modelo: una sola forma de cuerpo, un esquema por modelo, dos modos de entrega; pero esta ruta no mantiene la conexión para el resultado. Admite la ejecución, responde `201` con un identificador y quien llama recoge el resultado más tarde mediante las tres lecturas que aparecen a continuación.

**Parámetros**

**provider** `RouterProviderSegment` *required*

Segmento de proveedor en minúsculas del ID de modelo canónico `{provider}/{model}`, es decir, el socio cuyo modelo se está ejecutando.

Tipo: [`RouterProviderSegment`](#routerprovidersegment) -- Slug alfanumérico, por ejemplo `anthropic`, hasta 64 caracteres

**model** `RouterModelSegment` *required*

Segmento de modelo en minúsculas del ID de modelo canónico `{provider}/{model}`, es decir, el modelo que se ejecutará dentro de ese proveedor.

Tipo: [`RouterModelSegment`](#routermodelsegment) -- Slug alfanumérico, por ejemplo `claude-opus-4-6`, hasta 128 caracteres

**model\_provider** `string`

Selecciona un proveedor alternativo para atender este modelo en lugar de su proveedor predeterminado actual.

**strict\_mode** `boolean`

Solo tiene sentido junto con `model_provider`.

Predeterminado: False

**Idempotency-Key** `string`

Clave generada por quien llama que hace seguro reintentar una misma llamada lógica.

1–255 caracteres

**reject\_unknown\_fields** `boolean`

Actívalo para rechazar un campo de nivel superior del cuerpo de la solicitud que el esquema de entrada de este modelo no declare, en lugar de aceptarlo; los campos anidados no se revisan, y no se rechaza nada en un modelo cuyo esquema permita campos no declarados o que no tenga esquema definido, ni en un envío en cola enviado con `strict_mode=true`.

Predeterminado: False

**Cuerpo de la solicitud**

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

La entrada JSON nativa del modelo asociado, idéntica al cuerpo que la ruta síncrona acepta para este modelo, y que selecciona la operación y se factura de la misma manera: los campos del propio cuerpo eligen qué operación ejecuta Router en un modelo que admite más de una (una imagen de entrada cambia un modelo de imagen editable a imagen a imagen, lo que puede facturarse con su propia tarifa; una imagen de primer fotograma de Seedance selecciona imagen a video, y una imagen o clip de referencia selecciona referencia a video). En el despacho nativo, una solicitud de Seedance se factura según los tipos de medio en `content`, no según los roles: cualquier entrada de video se factura como video a video; de lo contrario, cualquier imagen se factura como imagen a video; de lo contrario, texto a video; salvo que un render final a partir de un elemento `draft_task` se factura como la operación del Draft que renderiza, con algunos modelos cobrando la misma tarifa para texto a video e imagen a video; y con `model_provider` seleccionando un proveedor alternativo, cada operación condicionada puede facturarse con la tarifa propia de ese proveedor. El mismo contrato de selección de proveedor se aplica en el despacho: sin `model_provider`, o con `model_provider` y `strict_mode=false` (el valor predeterminado), el cuerpo es el documento nativo del modelo y se valida contra el esquema de entrada propio del modelo antes de admitir la ejecución, por lo que un cuerpo que el modelo rechazaría es un `422` aquí en vez de una solicitud en cola que falla minutos después; además, un cuerpo no estricto de proveedor alternativo se traduce al esquema real de ese proveedor en el despacho. Con `strict_mode=true`, el cuerpo ya debe ser el esquema propio del proveedor alternativo y se reenvía sin cambios: la validación del esquema nativo se omite, exactamente como en la ruta síncrona (consulta `model_provider` y `strict_mode`).

**Respuestas**

**201** `RouterQueueSubmitResponse`

Created: la ejecución se admitió en la cola.

Cuerpo: [`RouterQueueSubmitResponse`](#routerqueuesubmitresponse) -- Encabezados: `X-Comfy-Request-Id`, `Idempotent-Replayed`

**401** `RouterErrorResponse`

Credenciales faltantes o no válidas.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**400** `RouterErrorResponse`

Solicitud no válida. Revisa el tipo de error y el cuerpo de la solicitud.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**413** `RouterErrorResponse`

El cuerpo de la solicitud es demasiado grande.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**402** `RouterErrorResponse`

Un fallo de nivel de solicitud de Router: la solicitud nunca llegó al modelo o falló por un motivo que el propio modelo no reportó.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**403** `RouterErrorResponse`

La solicitud no está permitida para quien llama ni para este modelo. Un modelo cuyo socio responde una generación directamente como bytes aún no se puede poner en cola y se rechaza con `not_enabled`; ejecútalo en la ruta síncrona en su lugar.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**404** `RouterErrorResponse`

No se encontró el ID de modelo.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**409** `RouterErrorResponse`

Revisa `X-Comfy-Error-Type`: `concurrency_limit_exceeded` significa que la llamada original sigue en ejecución, así que espera el `Retry-After` y reutiliza la misma clave; `invalid_input` requiere una clave nueva. Dos conflictos de `invalid_input` en esta ruta no tienen nada que ver con la clave y ninguna clave nueva resuelve ninguno de los dos: `model_provider` que nombra un proveedor alternativo se rechaza cuando el cuerpo de la solicitud selecciona una operación multipart (una edición) que el traductor de ese proveedor para este modelo no puede servir, cuyo `detail` comienza con "this request's `image` selects the edit operation"; y, comprobado después de eso, cuando la solicitud ya ha resuelto una credencial de tipo bring-your-own-key para el proveedor de la ruta, cuyo `detail` comienza con `this request resolved a BYOK credential`. Quita `model_provider`, o envía la solicitud sin la credencial BYOK y (para el caso multipart) sin la edición.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`, `Retry-After` (cuando es `concurrency_limit_exceeded`)

**422** `RouterValidationErrorResponse`

El contenido de la solicitud se rechazó contra el esquema del modelo.

Cuerpo: [`RouterValidationErrorResponse`](#routervalidationerrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`, `Idempotent-Replayed`

**429** `RouterErrorResponse`

Revisa `X-Comfy-Error-Type`: `queue_backlog_full` significa que ya tienes tantas solicitudes en cola sin terminar como se te permite, así que vuelve a enviar cuando una de ellas termine; `rate_limited` significa que debes esperar a la ventana de margen.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**503** `RouterErrorResponse`

El router no está disponible temporalmente. Reintenta con retroceso exponencial.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`, `Retry-After` (solo para rechazos por capacidad)

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

**Recupera el resultado de una solicitud enviada.**

El endpoint de recogida. Sobre una solicitud que ha finalizado correctamente, devuelve la salida nativa del modelo del socio, byte por byte lo que la ruta síncrona entrega en su `200` para el mismo modelo y la misma entrada, de modo que los dos modos de entrega producen una sola forma de resultado y un cliente puede pasar de uno a otro sin necesidad de un segundo analizador.

**Parámetros**

**provider** `RouterProviderSegment` *required*

Segmento de proveedor en minúsculas del ID de modelo canónico `{provider}/{model}`: el socio cuyo modelo se está ejecutando.

Tipo: [`RouterProviderSegment`](#routerprovidersegment) -- Slug alfanumérico, p. ej. `anthropic`, hasta 64 caracteres

**model** `RouterModelSegment` *required*

Segmento de modelo en minúsculas del ID de modelo canónico `{provider}/{model}`: el modelo que se ejecutará dentro de ese proveedor.

Tipo: [`RouterModelSegment`](#routermodelsegment) -- Slug alfanumérico, p. ej. `claude-opus-4-6`, hasta 128 caracteres

**request\_id** `RouterQueueRequestId` *required*

La solicitud en cola a la que se dirige: el `request_id` que el envío devolvió en su cuerpo.

Tipo: [`RouterQueueRequestId`](#routerqueuerequestid) -- `pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`, uuid, hasta 36 caracteres

**Respuestas**

**200** `RouterModelOutput`

OK: el resultado almacenado para una solicitud que produjo uno, una solicitud que se completó correctamente, o una terminal que lleva tanto un cargo registrado como un resultado almacenado, devuelto sin cambios bajo el tipo de medio propio del socio, exactamente como lo devuelve el `200` de la ruta síncrona, y bajo el mismo contrato de selección de proveedor que aceptó el envío: sin `model_provider`, o con `model_provider` y `strict_mode=false` (el valor predeterminado, traducido de vuelta al contrato nativo de este modelo cuando sea posible, recurriendo a la respuesta sin procesar del propio proveedor alternativo cuando falle la traducción, registrado en el log, nunca de forma silenciosa), la forma es la salida nativa de este modelo; con `strict_mode=true`, es la respuesta del proveedor alternativo devuelta sin cambios. Para un modelo cuyo socio responde a una generación directamente como bytes, el cuerpo son esos bytes bajo el `Content-Type` del propio socio en lugar de `application/json`; decide según el `Content-Type` de la respuesta y no asumas que hay un documento JSON.

Cuerpo: [`RouterModelOutput`](#routermodeloutput) o bytes sin procesar (`*/*`) -- Encabezados: `X-Comfy-Request-Id`, `X-Content-Type-Options`, `X-Comfy-Credits-Used`

**202** `RouterQueueStatusResponse`

Aceptado: la solicitud aún no ha finalizado.

Cuerpo: [`RouterQueueStatusResponse`](#routerqueuestatusresponse) -- Encabezados: `X-Comfy-Request-Id`, `Retry-After`

**401** `RouterErrorResponse`

Credenciales faltantes o no válidas.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**403** `RouterErrorResponse`

La solicitud no está permitida para este cliente ni para este modelo.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**404** `RouterErrorResponse`

No se encontró el ID del modelo.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**410** `RouterErrorResponse`

Un fallo a nivel de solicitud de Router: la solicitud nunca llegó al modelo o falló por un motivo que el propio modelo no reportó.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**503** `RouterErrorResponse`

Router no está disponible temporalmente. Reintenta con un retroceso progresivo.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**409** `RouterErrorResponse`

La solicitud está en un estado que entra en conflicto con la operación. Comprueba el tipo de error.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**504** `RouterErrorResponse`

La solicitud superó un plazo límite. Comprueba el tipo de error antes de reintentar.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**default** `RouterErrorResponse`

Un fallo a nivel de solicitud de Router: la solicitud nunca llegó al modelo o falló por un motivo que el propio modelo no reportó.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

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

**Solicitar la cancelación de una solicitud enviada.**

Le pide a Comfy que detenga una solicitud que no ha finalizado. Es una solicitud, no una garantía, y el `202` lo dice exactamente: `CANCELLATION_REQUESTED` significa que la petición fue aceptada, no que la ejecución se haya detenido. Una ejecución que ya está en curso en un socio puede completarse de todos modos, y una generación del socio que se completa se cobra, se haya recogido o no, así que quien llama y necesita saber qué pasó realmente consulta el endpoint de estado después, donde una cancelación que surtió efecto aparece como `COMPLETED` con un `error_type`, igual que cualquier otro resultado terminal.

**Parámetros**

**provider** `RouterProviderSegment` *required*

Segmento de proveedor en minúsculas del ID de modelo canónico `{provider}/{model}`: el socio cuyo modelo se está ejecutando.

Tipo: [`RouterProviderSegment`](#routerprovidersegment) -- Slug alfanumérico, p. ej. `anthropic`, Hasta 64 caracteres

**model** `RouterModelSegment` *required*

Segmento de modelo en minúsculas del ID de modelo canónico `{provider}/{model}`: el modelo a ejecutar dentro de ese proveedor.

Tipo: [`RouterModelSegment`](#routermodelsegment) -- Slug alfanumérico, p. ej. `claude-opus-4-6`, Hasta 128 caracteres

**request\_id** `RouterQueueRequestId` *required*

La solicitud en cola que se va a atender: el `request_id` que el envío devolvió en su cuerpo.

Tipo: [`RouterQueueRequestId`](#routerqueuerequestid) -- `pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`, uuid, Hasta 36 caracteres

**Respuestas**

**202** `RouterQueueCancelResponse`

Aceptado: `CANCELLATION_REQUESTED`.

Cuerpo: [`RouterQueueCancelResponse`](#routerqueuecancelresponse) -- Encabezados: `X-Comfy-Request-Id`

**409** `RouterQueueCancelResponse`

Conflicto: `ALREADY_COMPLETED`.

Cuerpo: [`RouterQueueCancelResponse`](#routerqueuecancelresponse) -- Encabezados: `X-Comfy-Request-Id`

**400** `RouterErrorResponse`

Solicitud no válida. Revisa el tipo de error y el cuerpo de la solicitud.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**401** `RouterErrorResponse`

Credenciales faltantes o no válidas.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**403** `RouterErrorResponse`

La solicitud no está permitida para quien llama ni para este modelo.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**404** `RouterErrorResponse`

No se encontró el ID de modelo.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**503** `RouterErrorResponse`

Router no está disponible temporalmente. Reintenta con retroceso exponencial.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**default** `RouterErrorResponse`

Un fallo a nivel de solicitud del Router: la solicitud nunca llegó al modelo, o falló por un motivo que el propio modelo no reportó.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse) -- Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

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

**Lee el estado en la cola de una solicitud enviada.**

El endpoint de sondeo. Responde con el estado actual de la solicitud y nunca con el resultado, así que un cliente puede seguir una generación larga sin transferir su salida en cada sondeo: el resultado se recoge una sola vez, desde la lectura de abajo, cuando este indica `COMPLETED`.

**Parámetros**

**provider** `RouterProviderSegment` *required*

Segmento de proveedor en minúsculas del ID de modelo canónico `{provider}/{model}`: el socio cuyo modelo se está ejecutando.

Tipo: [`RouterProviderSegment`](#routerprovidersegment). Slug alfanumérico, por ejemplo `anthropic`. Hasta 64 caracteres

**model** `RouterModelSegment` *required*

Segmento de modelo en minúsculas del ID de modelo canónico `{provider}/{model}`: el modelo que se ejecuta dentro de ese proveedor.

Tipo: [`RouterModelSegment`](#routermodelsegment). Slug alfanumérico, por ejemplo `claude-opus-4-6`. Hasta 128 caracteres

**request\_id** `RouterQueueRequestId` *required*

La solicitud en cola que se quiere consultar: el `request_id` que devolvió el envío en su cuerpo.

Tipo: [`RouterQueueRequestId`](#routerqueuerequestid). `pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`, uuid, Hasta 36 caracteres

**Respuestas**

**200** `RouterQueueStatusResponse`

OK: el estado actual de la solicitud en la cola.

Cuerpo: [`RouterQueueStatusResponse`](#routerqueuestatusresponse). Encabezados: `X-Comfy-Request-Id`, `Retry-After`, `X-Comfy-Estimated-Duration-Seconds`, `X-Comfy-Estimated-Duration-P90-Seconds`, `X-Comfy-Estimate-Source`

**401** `RouterErrorResponse`

Credenciales faltantes o no válidas.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse). Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**403** `RouterErrorResponse`

La solicitud no está permitida para este solicitante o modelo.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse). Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**404** `RouterErrorResponse`

No se encontró el ID del modelo.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse). Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**410** `RouterErrorResponse`

Un fallo a nivel de solicitud del Router: la solicitud nunca llegó al modelo o falló por un motivo que el propio modelo no reportó.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse). Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**503** `RouterErrorResponse`

Router no está disponible temporalmente. Reintenta con retroceso progresivo.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse). Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

**default** `RouterErrorResponse`

Un fallo a nivel de solicitud del Router: la solicitud nunca llegó al modelo o falló por un motivo que el propio modelo no reportó.

Cuerpo: [`RouterErrorResponse`](#routererrorresponse). Encabezados: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`

Las descripciones aquí son breves. Usa [Uso de la API de Comfy Router](https://docs.comfy.org/es/development/comfy-router/api.md) para la selección de modelos, la validación, los reintentos y la facturación, y [Encabezados](https://docs.comfy.org/es/development/comfy-router/headers.md) para el comportamiento de los encabezados.

## Categorías de error

Categoría de error del Router legible por máquina, que también se envía en el encabezado `X-Comfy-Error-Type`.

### Categorías a nivel de solicitud

Se generan para una solicitud que el Router aceptó y luego no pudo completar.

| `error_type` | Significado |
| - | - |
| `invalid_input` | La solicitud se rechazó antes de llegar al modelo: un cuerpo mal formado, un cursor de paginación mal formado o vencido, una entrada que el propio esquema del modelo no acepta, o un `Idempotency-Key` que no puede servir a esta solicitud (ya usado para una solicitud diferente, porque el método, la ruta y los parámetros de consulta, o el cuerpo difieren, o ya consumido por una llamada cuya respuesta no se puede reproducir). |
| `content_policy_violation` | El proveedor rechazó la solicitud por motivos de política de contenido. |
| `provider_error` | El proveedor socio informó un fallo propio, o devolvió una respuesta que Router no pudo interpretar como resultado. |
| `provider_timeout` | El proveedor socio no respondió dentro de su plazo. |
| `insufficient_credits` | El espacio de trabajo que llama no tiene créditos suficientes para ejecutar el modelo. |
| `model_not_found` | El ID `{provider}/{model}` no nombra ningún modelo que Router pueda ejecutar: un proveedor desconocido, un id no enrolado, uno que el catálogo ya retiró después de su fecha de retiro, o un ID catalogado que el proveedor no sirve actualmente para Comfy. |

### Categorías a nivel de transporte

Las genera el propio Router, antes de la llamada al modelo o en torno a ella.

| `error_type` | Significado |
| - | - |
| `unauthorized` | La solicitud no llevaba ninguna credencial utilizable. |
| `forbidden` | La credencial es válida, pero no tiene derecho a este modelo ni a esta operación. |
| `concurrency_limit_exceeded` | El espacio de trabajo ya tiene tantas llamadas en curso como se le permite; reintenta cuando termine una de ellas. |
| `client_disconnected` | Quien llama cerró la conexión antes de que Router pudiera devolver un resultado. |
| `internal_error` | El propio Router falló. |
| `deadline_exceeded` | Comfy dejó de mantener la conexión en su propio límite configurado antes de que llegara una respuesta. |
| `not_enabled` | Comfy Router aún no está habilitado para quien llama. |
| `service_unavailable` | Un servicio del que depende Comfy Router no está disponible temporalmente y quien llama no hizo nada mal. |
| `rate_limited` | Quien llama agotó un cupo medido sobre una ventana y debe esperar a que esa ventana avance. |
| `cancelled` | Una solicitud en cola se retiró (mediante la ruta de cancelación o por un operador) antes de producir un resultado; es terminal y no constituye por sí misma una declaración sobre el cobro. |
| `queue_timeout` | Una solicitud en cola esperó más allá de su tiempo de espera en cola sin llegar a ser admitida. |
| `request_not_found` | El `request_id` no identifica ninguna solicitud de quien llama con este modelo. |
| `queue_backlog_full` | Quien llama ya tiene demasiadas solicitudes en cola esperando ejecutarse, por lo que este envío se rechazó. |

## Encabezados de respuesta

**Cache-Control** `string`

Directivas de frescura para una página o entrada del catálogo.

Se envía en: `200`, `304`

**Cache-Control** `string`

Directivas de frescura para el documento de esquema servido.

Se envía en: `200`, `304`

**ETag** `string`

Etiqueta de entidad fuerte sobre los bytes del cuerpo servido, para `GET /v2/models` y `GET /v2/models/{provider}/{model}`.

Se envía en: `200`, `304`

**ETag** `string`

Etiqueta de entidad fuerte sobre los bytes del documento servido, para `GET /v2/models/{provider}/{model}/openapi.json`.

Se envía en: `200`, `304`

**Idempotent-Replayed** `boolean`

Presente y con valor `true` cuando esta respuesta se sirvió desde el registro de una `Idempotency-Key` en lugar de ejecutar el modelo de nuevo.

**Retry-After** `integer`

Segundos de espera antes de reenviar la misma solicitud, sin cambios.

Se envía en: `503`

**Retry-After** `integer`

Segundos de espera antes de volver a consultar esta solicitud en cola.

Se envía en: `200`, `202`

**Retry-After** `integer`

Segundos de espera antes de reintentar la misma solicitud con la misma `Idempotency-Key`.

Se envía en: `409`, `504`

**X-Comfy-Credits-Used** `string`

Cuánto costó esta ejecución, en créditos de Comfy, con el precio de la misma tarifa con la que se factura el cargo: así el llamador no necesita su propia tabla de precios, y en una ejecución que llegó al proveedor mediante más de una llamada facturada es la suma de todas ellas y no la de la última.

**X-Comfy-Error-Type** `RouterErrorType`

Categoría gruesa y legible por máquina del fallo, establecida por Router en cada respuesta de error.

Tipo: [`RouterErrorType`](#routererrortype)

**X-Comfy-Estimate-Source** `string`

Se envía solo en la lectura de estado mientras `status` es `IN_PROGRESS`, junto a `X-Comfy-Estimated-Duration-Seconds`: de dónde proviene esa estimación de duración de generación (no la `source` de la estimación de costo), `historical` (medida en ejecuciones recientes) o `default` (un valor de respaldo por tipo de medio, usado mientras hay muy pocas ejecuciones recientes registradas).

**X-Comfy-Estimated-Duration-P90-Seconds** `integer`

Se envía solo en la lectura de estado mientras `status` es `IN_PROGRESS`, junto a `X-Comfy-Estimated-Duration-Seconds`: el percentil 90, en segundos enteros, de esa estimación de duración de generación.

**X-Comfy-Estimated-Duration-Seconds** `integer`

Se envía solo en la lectura de estado mientras `status` es `IN_PROGRESS`: la estimación de Router, en segundos enteros, de la ejecución completa de la generación una vez que el proveedor la ha aceptado (no el tiempo restante y nunca el tiempo pasado en `IN_QUEUE`).

**X-Comfy-Refusal-Subject** `string`

Sobre qué entrada o salida trataba un rechazo por política de contenido, como vocabulario cerrado a nivel de Router: `input`, `output`, `input_text`, `input_image`, `input_video`, `input_audio`, `output_text`, `output_image`, `output_video`, `output_audio`.

**X-Comfy-Request-Id** `string`

Identificador generado por el servidor para esta llamada, presente en cada respuesta de Router, tanto de éxito como 4xx y 5xx, porque una respuesta de error es justo cuando un usuario necesita un id que citar en una solicitud de soporte.

**X-Comfy-Router-Dropped-Params** `string`

Una sola cadena codificada en JSON que contiene un arreglo de cadenas: decódificala con un analizador de JSON en lugar de dividirla por comas, porque es una única cadena en el cable, no un arreglo OpenAPI separado por comas, y cada entrada es una oración que lleva sus propias comas. Está presente siempre que una traducción produjo el cuerpo de la solicitud de esta llamada y no pudo expresar uno o más campos nativos exactamente en el proveedor que la sirvió, indicando cada campo descartado y el motivo, ya sea que el llamador haya pedido esa traducción con `model_provider` (`strict_mode=false`, el valor predeterminado) o que la haya ejecutado un reintento automático de `fallback_provider`.

**X-Comfy-Router-Fallback-Provider** `string`

Presente, con el nombre del proveedor, solo cuando `fallback_provider` reintentó realmente esta llamada contra un segundo proveedor y ese reintento tuvo éxito: el proveedor que finalmente sirvió la llamada, nunca uno que se intentó y también falló.

**X-Comfy-Router-Provider** `string`

El proveedor del tramo de Router que sirvió esta llamada, presente en cada respuesta de ejecución exitosa: el proveedor propio del modelo en una ejecución nativa, el proveedor alternativo que indicó `model_provider`, o el proveedor en el que aterrizó un reintento de `fallback_provider` (que `X-Comfy-Router-Fallback-Provider` también nombra, solo en ese caso). Es el tramo al que Router despachó y no necesariamente el proveedor que produjo la salida, ya que una cascada a nivel de proxy dentro de un tramo nativo (la cadena de imágenes Gemini de `vertexai`, por ejemplo) puede entregar la llamada a otro proveedor que ningún encabezado nombra.

**X-Comfy-Upstream-Detail** `string`

Un motivo acotado y saneado que dio el proveedor del modelo para rechazar la solicitud.

**X-Comfy-Upstream-Status** `integer`

El estado HTTP propio del proveedor del modelo para esta llamada.

**X-Committed-Spend-Current** `integer`

Los centavos de USD que el llamador tiene comprometidos actualmente en llamadas aún en curso.

**X-Committed-Spend-Limit** `integer`

El límite máximo, en centavos de USD, del gasto de socio que el llamador puede tener comprometido en llamadas aún en curso: dinero retenido desde el momento en que se admite una llamada y liberado cuando esa llamada termina.

**X-Committed-Spend-Remaining** `integer`

Los centavos de USD de margen disponible que quedan por debajo del límite máximo, con un mínimo de cero.

**X-Content-Type-Options** `string`

Siempre `nosniff`, en toda ejecución exitosa de un modelo de Router.

**X-Model-Concurrency-Current** `integer`

Las llamadas simultáneas del solicitante a modelos clasificados como costosos, tal como las cuenta la compuerta que rechazó esta llamada.

**X-Model-Concurrency-Limit** `integer`

La mayor cantidad de llamadas simultáneas a modelos clasificados como costosos que el solicitante puede mantener a la vez, una cuarta parte del límite de llamadas simultáneas, compartida con las llamadas de nodos asociados.

**X-Model-Concurrency-Remaining** `integer`

Las llamadas a modelos costosos que el solicitante aún puede iniciar; `0` en el `429`.

## Estimaciones de costos previas a la ejecución

`POST /v2/models/{provider}/{model}/estimate` tarifica un cuerpo sin ejecutarlo, y un envío en cola (`POST /v2/models/{provider}/{model}/requests`) devuelve el mismo [`RouterCostEstimate`](#routercostestimate) que `estimate` en su `201`. Ambos se calculan con la tarjeta de tarifas contra la que Comfy factura la ejecución. Cada cifra que devuelve cualquiera de los dos es una estimación, no el cargo final: el cargo liquidado en los registros de uso y facturación de tu espacio de trabajo es el definitivo. Comfy no factura una ejecución con tu propia clave de proveedor (ver abajo). Mientras la estimación se está implementando, la ruta responde `403` con `error_type: not_enabled` y la respuesta del envío omite `estimate`. El catálogo sigue sin mostrar precios.

Lee `source` antes de cualquier cantidad. Que falte una cifra nunca significa que sea gratis.

| `source` | Contiene | Cómo leerlo |
| - | - | - |
| `exact` | `amount`, `amount_cents`, `credits` | Una estimación igual al cargo de este cuerpo con las tarifas de `pricing_as_of`; el cargo liquidado en los registros de uso y facturación de tu espacio de trabajo es el definitivo. |
| `estimated` | `min_amount`, `max_amount` y sus formas `_cents`, sin `amount` | Una estimación cuyo cargo depende de una cantidad que el proveedor reporta de vuelta y que el cuerpo acota; se espera que el cargo esté entre los límites, y el cargo liquidado en los registros de uso y facturación de tu espacio de trabajo es el definitivo. |
| `unknown` | `reason`, sin cifra | No se pudo dar un precio antes de la ejecución. Trata cualquier otro valor de `source` como `unknown`. |

El `reason` de una estimación `unknown` es uno de los siguientes:

* `not_quotable`: Router no puede tarificar esta llamada antes de que se ejecute, porque se factura según una cantidad que el proveedor reporta de vuelta y que el cuerpo no acota, o porque no se puede tarificar el cuerpo tal como se envió. Trata cualquier `reason` no reconocido como `not_quotable`.
* `unpriced_model`: la tarjeta de tarifas no tarifica esta solicitud.
* `byok` (solo envío en cola): la ejecución usa tu propia clave de proveedor, por lo que Comfy no cobra nada por ella.
* `pricing_unavailable` (solo envío en cola): no se pudo leer la tarjeta de tarifas cuando se admitió la solicitud. El envío se acepta igualmente y la ejecución se cobra como de costumbre.

Los modelos para los que Router aún no puede calcular un precio antes de una ejecución se enumeran en [modelos sin una estimación previa a la ejecución](https://docs.comfy.org/es/development/comfy-router/limitations.md#modelos-sin-estimación-previa). Un modelo que no aparezca allí puede responder igualmente `unknown` para un cuerpo concreto, así que lee `source` en cada estimación.

Cuándo la estimación falla de forma segura:

* Cuando una cifra necesita la tarjeta de tarifas y la tarjeta no está cargada o está desactualizada, `/estimate` responde `503` en lugar de adivinar. Router nunca rechaza el envío en cola por su estimación; en su lugar, este lleva `source: unknown` con `reason: pricing_unavailable`. Router responde a una llamada que no se puede tarificar antes de ejecutarse en absoluto (`not_quotable`), o a un envío en cola con tu propia clave de proveedor (`byok`), sin leer la tarjeta, así que ese `200` no dice nada sobre si la tarjeta está actualizada.
* `/estimate` valida el cuerpo con el esquema de entrada propio del modelo igual que lo hace una ejecución predeterminada, así que un cuerpo que no cumple el esquema del modelo recibe el mismo `422`, con la misma forma de `detail[]`, que respondería la ejecución. No se calcula ningún precio ni se despacha nada.
* Una repetición idempotente de un envío en cola (`Idempotent-Replayed: true`) omite `estimate`, porque la cotización original no se almacena.

Límites de la estimación. Una cifra de `200` no garantiza que la ejecución se acepte ni que se cobre exactamente eso:

* `/estimate` no acepta `strict_mode` ni `reject_unknown_fields`, así que solo comprueba el contrato nativo del modelo: un cuerpo que una ejecución con `strict_mode=true` acepta en el esquema propio del proveedor alternativo puede recibir aquí un `422`, y aquí se calcula el precio de un campo de nivel superior no declarado que una ejecución con `reject_unknown_fields=true` rechazaría.
* `pricing_as_of` indica cuándo se obtuvo la tarjeta de tarifas (o, cuando no se leyó ninguna, cuándo se respondió la estimación). No es un bloqueo de precio: la ejecución se cobra con las tarifas vigentes cuando se tarifica.
* `/estimate` cotiza el tramo que indica `model_provider`, o el proveedor nativo. No acepta el parámetro `fallback_provider` ni `strict_mode`. Una ejecución síncrona cuyo reintento de respaldo recae en otro proveedor se cobra con la tarifa de ese proveedor, que la estimación no cotizó; `X-Comfy-Router-Fallback-Provider` en la respuesta de la ejecución indica que ocurrió. Un envío en cola no tiene respaldo, así que su `estimate` cotiza el tramo que se ejecuta.
* `/estimate` y el `estimate` de un envío en cola pueden calcular el precio de documentos ligeramente distintos para el mismo cuerpo en un tramo de `model_provider`, o para un cuerpo que se ejecuta en una operación hermana. El `estimate` del envío se calcula sobre el documento que envía la ejecución.
* `/estimate` siempre cotiza el cargo de la plataforma. Comfy no factura una ejecución con tu propia clave de proveedor, pero `/estimate` no lo detecta y aun así devuelve una cifra; solo un envío en cola responde `reason: byok`.
* Los dólares se calculan a partir de centavos sin redondear, con hasta 8 decimales, y una `amount` cobrable inferior a un centavo nunca se muestra como `0`. `credits` es `round(amount × 211, 2)`, la misma conversión que `X-Comfy-Credits-Used` aplica a un cargo, así que `credits` puede redondearse a `0` para un precio muy pequeño distinto de cero; presupuesta con `amount` o `amount_cents`, no con `credits`, cuando eso importe. Ese encabezado sigue siendo la cifra a posteriori de una ejecución; los saldos están en la plataforma de Comfy.

## Recursos del resultado

Un modelo puede devolver URL de recursos, bytes en línea o ambos. Los proveedores siguientes copian los recursos seleccionados en el almacenamiento de Comfy y sustituyen sus URL. Este comportamiento depende del modelo; no hay ningún encabezado de solicitud que lo seleccione.

| Modelos | Qué se copia en el almacenamiento de Comfy | Tiempo de vida máximo de la URL alojada en Comfy |
| - | - | - |
| `bfl/*` | el recurso finalizado, y el recurso de caché de borrador cuando el resultado lo incluye | 24 horas |
| modelos de video `byteplus/*` (`seedance`, `dreamina-seedance`) | el video finalizado, y la imagen del último fotograma cuando el resultado la incluye | 24 horas |
| `minimax/*` | el video finalizado | 12 horas |
| `xai/*` | cada imagen generada, y el video finalizado | 24 horas |

Estos tiempos de vida empiezan cuando se firma la URL, no cuando la abres. Las URL en caché o de una llamada repetida pueden tener menos tiempo restante; repetir la llamada no las renueva. Descarga el recurso cuanto antes. Solo se copian los recursos indicados en cada fila: las imágenes `byteplus/seedream-*` y `byteplus/seededit-*` no están cubiertas por la fila de video de BytePlus.

La copia la realiza únicamente el proveedor nativo del modelo. Una ejecución atendida por un proveedor alternativo (`model_provider` que nombre uno, o una ejecución nativa cuyo reintento de respaldo haya recaído en uno, indicado por `X-Comfy-Router-Fallback-Provider`) devuelve las URL propias de ese proveedor, que siguen la caducidad del proveedor y no se copian. Los valores `default`, `comfy` y `comfyui` de `model_provider` no nombran ningún proveedor alternativo, por lo que esas ejecuciones son nativas y se copian como se describe arriba, igual que una ejecución con `model_provider` cuyo reintento de respaldo haya vuelto a recaer en el proveedor nativo.

**Veo (`veo/*`) tiene una ruta de almacenamiento aparte.** En `response.videos[]`, lee el miembro que esté presente: `bytesBase64Encoded` contiene el clip en línea, mientras que `gcsUri` contiene un enlace HTTPS firmado por Comfy cuando el entorno está configurado para que el proveedor escriba directamente en el almacenamiento de Comfy. Ese enlace es válido durante 24 horas desde la respuesta. En este último caso el recurso se escribe directamente en lugar de copiarse, por lo que Veo no figura en la tabla de realojamiento.

Otros modelos devuelven referencias a recursos del proveedor o bytes en línea. Las URL del proveedor siguen la caducidad del proveedor, que puede ser mucho más corta que los tiempos de vida anteriores y no está especificada por el contrato del Router.

La copia se hace con el mejor esfuerzo en cada recurso. Si una copia falla, esa entrada conserva su referencia del proveedor; la respuesta puede contener tanto URL de Comfy como del proveedor, sin un campo explícito de estado de copia por recurso. La generación se completa igualmente y se cobra. No deduzcas el tiempo de vida de todas las URL a partir de un recurso realojado con éxito.

Que un resultado esté alojado en Comfy también determina si más tarde aún es posible repetir una llamada completada desde su registro de `Idempotency-Key`; el parámetro `Idempotency-Key` de arriba indica qué recibe un reintento cuando no es posible.

## Esquema de entrada y salida por modelo

Lee los campos de cada modelo desde `GET /v2/models/{provider}/{model}/openapi.json`. Esa llamada requiere una clave API. El mismo documento, para cada modelo con un esquema definido explícitamente, también se publica en este sitio sin clave, en `/router-schemas/{provider}/{model}.json`. Esa copia es una instantánea tomada en la última actualización de la documentación, así que el endpoint es la fuente autoritativa cuando hay diferencias. El `requestBody` de la operación describe la validación de la entrada; su respuesta `200` describe la forma de la salida y el tipo de medio cuando este está definido explícitamente. Cuando `x-comfy-input-schema-authored` es `false`, Router acepta cualquier objeto JSON sin prevalidación específica del modelo. Los requisitos del proveedor siguen aplicando. Los esquemas de salida describen resultados; Router no valida contra ellos las cargas útiles que devuelve el proveedor. Una salida sin esquema definido explícitamente puede usar `*/*` en lugar de `application/json`; revisa el tipo de contenido de la respuesta antes de decodificarla.

## Esquemas

### RouterChargesOnPolicyRejection

Indica si un rechazo por política de contenido se cobra en este modelo. Trata un valor desconocido como potencialmente cobrado.

Tipo: `string`

### RouterCostEstimate

Una estimación previa de cuánto costará esta llamada, en dólares estadounidenses, calculada antes del despacho a partir de la misma tabla de tarifas con la que se factura la ejecución. No es el cargo final: el cargo que pagas es el liquidado en los registros de uso y facturación de tu espacio de trabajo. `X-Comfy-Credits-Used`, que se informa después de la ejecución, es una cifra redondeada calculada a posteriori, no un recibo. `source` indica cuánto puedes confiar en el número: `exact` incluye `amount`; `estimated` incluye `min_amount` y `max_amount` y ningún `amount`; `unknown` no incluye ninguno de los dos y sí un `reason`. Nunca interpretes un `amount` ausente como gratis. No es un bloqueo de precio: consulta `pricing_as_of`.

**Campos**

**source** `string` *required*

`exact` | `estimated` | `unknown`; interpreta cualquier otro valor como `unknown`. Tanto `exact` como `estimated` etiquetan una estimación; ninguno es el cargo final. `unknown` no incluye ninguna cifra.

**currency** `string` *required*

Siempre `USD`.

**amount** `string`

El costo estimado en dólares como cadena decimal, por ejemplo "0.04", con hasta 8 decimales y sin exponente. Un precio inferior a un centavo que sí se cobra nunca se representa como "0". Presente solo cuando `source` es `exact`. No es el cargo final: lo es el cargo liquidado en los registros de uso y facturación de tu espacio de trabajo.

**min\_amount** `string`

El extremo inferior de la estimación en dólares como cadena decimal. Es una estimación, no un mínimo garantizado: una llamada puede facturarse menos, por ejemplo cuando el proveedor devuelve menos de lo que pedía la solicitud (como ninguna imagen), cuando la estimación es un precio típico aprendido de llamadas anteriores, o cuando el precio no sube de forma constante con la cantidad solicitada. Presente solo cuando `source` es `estimated`.

**max\_amount** `string`

El extremo superior de la estimación en dólares como cadena decimal. Es una estimación, no un máximo garantizado: una llamada puede facturarse más, por ejemplo cuando el proveedor devuelve más de lo pedido (como más imágenes de las solicitadas), cuando la estimación se aprende de llamadas anteriores, o cuando el precio no sube de forma constante con la cantidad solicitada. Presente solo cuando `source` es `estimated`.

**amount\_cents** `number`

La misma cifra en centavos de dólar, sin redondear, para operaciones aritméticas. Presente junto con `amount`.

double

**min\_amount\_cents** `number`

`min_amount` en centavos de dólar, sin redondear. Presente junto con `min_amount`.

double

**max\_amount\_cents** `number`

`max_amount` en centavos de dólar. Presente junto con `max_amount`.

double

**credits** `number`

`amount` en créditos de Comfy usando la conversión de la plataforma (\$1 = 211 créditos), redondeado a 2 decimales: la cifra que se espera que lleve `X-Comfy-Credits-Used` para una cotización `exact`. Ese encabezado es una cifra redondeada calculada a posteriori, no un recibo; el cargo liquidado en los registros de uso y facturación de tu espacio de trabajo es el definitivo.

double

**provider** `string` *required*

El tramo del proveedor al que corresponde esta cotización. En un envío en cola, es el tramo que se ejecutará.

**model** `RouterModelId` *required*

Un ID de modelo canónico de Comfy Router, `{provider}/{model}`, exactamente el valor que direcciona el modelo en `POST /v2/models/{provider}/{model}`, de modo que quien llama pueda interpolarlo en esa ruta sin volver a derivarlo de nada. Su `pattern` es `RouterProviderSegment` y `RouterModelSegment` unidos por un solo `/`, y `maxLength` es su suma más ese separador.

Tipo: [`RouterModelId`](#routermodelid) -- ID de modelo, por ejemplo `anthropic/claude-opus-4-6`, hasta 193 caracteres

**pricing\_as\_of** `string` *required*

Cuándo se obtuvo la tabla de tarifas con la que se calculó esta cotización. La estimación no es un bloqueo de precio: la ejecución se cobra a las tarifas vigentes cuando se tarifica, no en este instante. Siempre que no se leyó ninguna tabla de tarifas (`reason: pricing_unavailable`, `byok`, o una llamada `not_quotable` que no puede cotizarse con ninguna tabla), esto es el momento en que se respondió la cotización.

date-time

**reason** `string`

Presente solo cuando `source` es `unknown`: `not_quotable` (el Router no puede poner precio a esta llamada antes de que se ejecute: su precio depende de lo que el proveedor informe de vuelta, o el cuerpo no delimita una cantidad facturable), `unpriced_model` (la tabla de tarifas no da precio a esta solicitud), `byok` (solo envío en cola: la ejecución usa tu propia clave de proveedor, así que Comfy no cobra nada por ella), o `pricing_unavailable` (solo envío en cola: no se pudo leer la tabla de tarifas cuando se admitió la solicitud; esto es transitorio y la ejecución se cobra igual que siempre). Interpreta cualquier otro valor como `not_quotable`.

### RouterErrorResponse

Cuerpo de error para fallos de autenticación, acceso, búsqueda de modelos, cuota y transporte del proveedor.

**Campos**

**detail** `string` *required*

Descripción legible del fallo, apta para mostrarse a un usuario final. No se analiza automáticamente: en su lugar, ramifica según `error_type`. Para `model_not_found` en un modelo retirado, `detail` contiene `<id> was retired on <YYYY-MM-DD>; use <successor>` cuando hay un sucesor registrado y visible para quien llama, o solo `<id> was retired on <YYYY-MM-DD>` cuando no lo hay, en lugar de la lista de sugerencias habitual. Un sucesor nombrado aquí es siempre un ID de catálogo vigente al que se puede redirigir la llamada. Un modelo cuya fecha de retiro todavía está en el futuro no está retirado: sigue apareciendo en `GET /v2/models` y se puede ejecutar hasta esa fecha. Como el resto de `detail`, este texto de retiro es solo para mostrar y no conlleva ninguna garantía de compatibilidad. Dos excepciones documentadas a la regla de no analizar automáticamente: en `POST /v2/models/{provider}/{model}` el `409` responde a tres condiciones no relacionadas que comparten el grupo `invalid_input`, y solo `detail` las distingue: un `detail` que empieza por "this request's `image` selects the edit operation" es el rechazo multipart de `model_provider`, y un `detail` que empieza por `this request resolved a BYOK credential` es el rechazo BYOK de `model_provider`; ninguno se resuelve con una nueva `Idempotency-Key`. Cualquier otro `409` de `invalid_input` en esa ruta es el conflicto de clave. Ambos prefijos son términos de contrato estables y se pueden comparar. En ningún otro caso ramificar según `detail` conlleva una garantía de compatibilidad.

**error\_type** `RouterErrorType` *required*

Grupo amplio y legible por máquina para un fallo del Router, replicado en el encabezado de respuesta `X-Comfy-Error-Type` para que quien llama pueda ramificar sin analizar el cuerpo. El conjunto está cerrado en diecinueve valores: los seis grupos de nivel de solicitud `invalid_input`, `content_policy_violation`, `provider_error`, `provider_timeout`, `insufficient_credits` y `model_not_found`, más los de nivel de transporte `unauthorized`, `forbidden`, `concurrency_limit_exceeded`, `client_disconnected`, `internal_error`, `deadline_exceeded`, `not_enabled`, `service_unavailable`, `rate_limited`, `cancelled`, `queue_timeout`, `request_not_found` y `queue_backlog_full`. «Cerrado» describe el conjunto tal como se documenta hoy, no un límite que se mantenga para siempre: se espera que el conjunto crezca, y por eso esto es deliberadamente una cadena simple y no un `enum`, de modo que un cliente debe tratar cualquier valor no reconocido como `internal_error` en lugar de hacer un switch exhaustivo sobre la lista anterior y romperse con la próxima adición.

Tipo: [`RouterErrorType`](#routererrortype)

**upstream\_detail** `string`

Motivo acotado y saneado que dio el proveedor del modelo para rechazar la solicitud; solo está presente cuando `error_type` es `invalid_input` y `X-Comfy-Upstream-Status` es un `4xx` o `2xx` del proveedor, es decir, el proveedor rechazó la solicitud por malformada y explicó por qué. Normalmente ese estado es un `4xx`; es un `2xx` para un proveedor que informa de una generación rechazada dentro de una envoltura de éxito (una consulta de tarea fallida de BytePlus es HTTP `200` con el motivo en su cuerpo). Está ausente en cualquier otro fallo, incluidos los `5xx` del proveedor, los fallos de transporte, los rechazos por políticas de contenido y cualquier rechazo que el Router haya generado sobre sí mismo. Replica el encabezado `X-Comfy-Upstream-Detail`.

**refusal\_subject** `string`

Sobre qué entrada o salida se produjo un rechazo por políticas de contenido, como vocabulario cerrado a nivel del Router: `input`, `output`, `input_text`, `input_image`, `input_video`, `input_audio`, `output_text`, `output_image`, `output_video`, `output_audio`. Los valores simples `input` / `output` indican el lado cuando el proveedor no especificó una modalidad. Solo está presente cuando `error_type` es `content_policy_violation` y el proveedor indicó el sujeto rechazado con un código legible por máquina; en caso contrario, está ausente. Nunca es texto del proveedor. Hoy se rellena para rechazos de BytePlus, Runway, BFL, Gemini, Veo, Vertex, xAI y Wan, y para los rechazos de Gemini de las vertientes Nano Banana del Router de MiniMax; un proveedor cuyo rechazo no indica de qué lado se trataba lo deja ausente. Replica el encabezado `X-Comfy-Refusal-Subject`.

### RouterErrorType

Categoría de error del Router legible por máquina, que también se envía en el encabezado `X-Comfy-Error-Type`.

Tipo: `string`

### RouterModelBilling

Comportamiento de facturación que debes revisar antes de invocar un modelo. No incluye precios ni uso.

**Campos**

**charges\_on\_policy\_rejection** `RouterChargesOnPolicyRejection` *required*

Si una llamada que este modelo rechaza por motivos de política de contenido se cobra de todos modos a quien realiza la llamada. Los proveedores difieren, la diferencia es invisible en el momento de la llamada, y un usuario que ve un error y un cargo por la misma llamada no tendría forma de saberlo, así que se indica por modelo, antes de la llamada, en lugar de dejarlo a la tradición de cada proveedor.

Tipo: [`RouterChargesOnPolicyRejection`](#routerchargesonpolicyrejection)

### RouterModelDetail

Detalle por modelo de un modelo de Comfy Router: todo lo que el listado del catálogo reporta para ese modelo, más los campos por modelo que solo incluye la ruta de modelo único.

Combina [`RouterModelListEntry`](#routermodellistentry) y [`RouterModelDetailFields`](#routermodeldetailfields).

Tipo: `object`

### RouterModelDetailFields

Campos opcionales que devuelve el endpoint de detalles del modelo.

**Campos**

**input\_schema\_url** `string`

URL del documento OpenAPI de este modelo, incluidos sus esquemas de entrada y salida.

URL HTTPS, por ejemplo, `https://api.comfy.org/v2/models/bfl/flux-2-pro/openapi.json`, hasta 2048 caracteres

### RouterModelId

El ID del modelo que se usa en `POST /v2/models/{provider}/{model}`.

Tipo: `string`. ID del modelo, p. ej. `anthropic/claude-opus-4-6`. Hasta 193 caracteres.

### RouterModelInput

El objeto de entrada del modelo. Consulta el documento OpenAPI del modelo seleccionado para ver los campos y la validación.

Tipo: `object`

### RouterModelInputSchemaDocument

Un documento OpenAPI independiente para la entrada y la salida de un modelo.

Tipo: `object`

### RouterModelListEntry

El ID de un modelo y sus datos de facturación.

**Campos**

**id** `RouterModelId` *required*

Un ID de modelo canónico de Comfy Router, `{provider}/{model}`: exactamente el valor que direcciona el modelo en `POST /v2/models/{provider}/{model}`, así que quien llama puede interpolarlo en esa ruta sin volver a derivarlo de otra cosa. Su `pattern` es `RouterProviderSegment` y `RouterModelSegment` unidos por un solo `/`, y `maxLength` es su suma más ese separador.

Tipo: [`RouterModelId`](#routermodelid) -- ID de modelo, p. ej. `anthropic/claude-opus-4-6`, hasta 193 caracteres

**provider** `RouterProviderSegment` *required*

Segmento `provider` en minúsculas del ID de modelo canónico `{provider}/{model}`: el socio cuyo modelo se está direccionando. El parámetro de ruta `provider` de la ruta de invocación y el campo `provider` de una entrada de catálogo hacen referencia a este mismo esquema, y eso es lo que evita que los IDs listados y los IDs aceptados se separen con el tiempo.

Tipo: [`RouterProviderSegment`](#routerprovidersegment) -- Slug alfanumérico, p. ej. `anthropic`, hasta 64 caracteres

**model** `RouterModelSegment` *required*

Segmento `model` en minúsculas del ID de modelo canónico `{provider}/{model}`: el modelo a ejecutar dentro de ese proveedor. Lo comparten el parámetro de ruta `model` de la ruta de invocación y el campo `model` de una entrada de catálogo, por la misma razón de evitar divergencias que en `RouterProviderSegment`.

Tipo: [`RouterModelSegment`](#routermodelsegment) -- Slug alfanumérico, p. ej. `claude-opus-4-6`, hasta 128 caracteres

**billing** `RouterModelBilling` *required*

Datos de facturación por modelo que quien llama necesita antes de invocar, no precios. Las cifras de uso y de costo nunca aparecen aquí.

Tipo: [`RouterModelBilling`](#routermodelbilling)

**schema\_etag** `string`

El `ETag` fuerte actual del documento `GET /v2/models/{provider}/{model}/openapi.json` de este modelo. Envíalo como `If-None-Match` en esa lectura para obtener un `304` mientras el esquema no cambie, o compáralo con el valor visto la última vez para saber qué esquemas de modelos cambiaron sin descargar todos los documentos. Está ausente siempre que esa lectura no vaya a responder `200` para quien llama en este momento: el servicio de esquemas no está disponible, el documento del modelo no se puede renderizar, o el modelo dejó de estar disponible para quien llama mientras se construía la respuesta. Una etiqueta ausente no es un cambio de esquema; vuelve a leer el documento del modelo para conocer su etiqueta actual.

### RouterModelListResponse

Una página del catálogo de modelos del Router.

**Campos**

**data** `array of RouterModelListEntry` *required*

Los modelos de esta página, como máximo `limit` de ellos.

Tipo: array de [`RouterModelListEntry`](#routermodellistentry)

**has\_more** `boolean` *required*

Indica si existe otra página después de esta. Sigue avanzando mientras sea verdadero; no deduzcas el final del catálogo a partir de un `data` corto o vacío.

**next\_cursor** `RouterPageCursor`

Un cursor opaco hacia una lista del Router. Lo produce el servidor y solo se reenvía tal cual: no es un offset, no es un ID de modelo, no está ordenado y no es estable entre reconstrucciones del catálogo, así que analizarlo, incrementarlo o persistirlo más allá del recorrido del que proviene queda fuera del contrato. Se usa un cursor en lugar de un offset porque el catálogo es una lista cambiante: un recorrido por offset omite o repite entradas de forma silenciosa cuando se agregan o quitan entradas a mitad del recorrido, y quien llama no puede detectar que eso ocurrió.

Tipo: [`RouterPageCursor`](#routerpagecursor) -- Cursor opaco devuelto como `next_cursor`, de 1 a 512 caracteres

**limit** `integer` *required*

El tamaño de página que realmente se entregó. Un `limit` solicitado por encima del máximo se ajusta al máximo en lugar de rechazarse, así que puede ser menor que el valor pedido: pagina con este número, no con el que enviaste, o supondrás filas que nunca recibiste.

1–100

### RouterModelOutput

El objeto de resultado del modelo. Consulta el esquema de salida del modelo seleccionado para conocer su forma exacta.

Tipo: `object`

### RouterModelSegment

La parte del modelo de un ID de modelo `{provider}/{model}`.

Tipo: `string`. Slug alfanumérico, p. ej. `claude-opus-4-6`, de hasta 128 caracteres

### RouterPageCursor

Un cursor de catálogo opaco. Devuélvelo sin cambios como `cursor`.

Tipo: `string`. Cursor opaco devuelto como `next_cursor`, de 1 a 512 caracteres.

### RouterProviderSegment

La parte del proveedor de un ID de modelo `{provider}/{model}`.

Tipo: `string`: slug alfanumérico, p. ej. `anthropic`, hasta 64 caracteres

### RouterQueueCancelResponse

La respuesta a una solicitud de cancelación en los dos estados que describen una solicitud que esta ruta resolvió: el `202` y el `409`. Una sola forma de cuerpo para ambos en lugar de un envelope de éxito más un envelope de error, porque ambos son la misma afirmación (lo que encontró la cancelación) y un cliente que tiene que analizar un tipo distinto por código de estado no gana nada con la separación.

**Campos**

**request\_id** `RouterQueueRequestId` *required*

Identificador de una solicitud de Router en cola: el identificador por el que un cliente consulta, cancela y recoge un resultado.

Tipo: [`RouterQueueRequestId`](#routerqueuerequestid) -- `pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`, uuid, hasta 36 caracteres

**status** `RouterQueueCancelStatus` *required*

Lo que encontró una solicitud de cancelación, para los dos resultados que describen una solicitud que esta ruta efectivamente resolvió. Ambos se reflejan en el estado HTTP, así que un cliente puede ramificar según cualquiera de los dos.

Tipo: [`RouterQueueCancelStatus`](#routerqueuecancelstatus)

### RouterQueueCancelStatus

Qué encontró una solicitud de cancelación, para los dos resultados que describen una solicitud que esta ruta realmente resolvió. Ambos se reflejan en el estado HTTP, así que un cliente puede ramificar según cualquiera de los dos.

Tipo: `string`

### RouterQueuePosition

Cuántas solicitudes hay por delante de esta en la cola, en el instante en que se compuso la respuesta. Cero significa que esta solicitud está al frente.

Tipo: `integer` -- Al menos 0

### RouterQueueRequestId

Identificador de una solicitud de Router en cola: el identificador que usa quien llama para consultar, cancelar y recoger un resultado.

Tipo: `string` -- `pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`, uuid, hasta 36 caracteres

### RouterQueueStatus

El estado de una solicitud Router en cola. Tiene exactamente tres valores y, a diferencia de `RouterErrorType`, este es un `enum` cerrado, porque los dos esquemas están cerrados en direcciones opuestas a propósito. `RouterErrorType` clasifica los fallos y se espera que su conjunto crezca, por lo que un cliente generado que rechazara de forma estricta un bucket no reconocido fallaría más justo cuando algo ya hubiera salido mal. Este es un ciclo de vida, y un ciclo de vida al que se le añade más tarde un cuarto estado es un cambio incompatible para todos los bucles de sondeo escritos contra él, se declare como enum o no, así que se declara como uno y la restricción se indica donde un cliente pueda verla.

Tipo: `string`

### RouterQueueStatusFields

La mitad de `RouterQueueStatusResponse` que no es el bloque de URL: la identidad de una solicitud en cola, su estado actual y, cuando ese estado es terminal y la ejecución no tuvo éxito, el grupo genérico que indica por qué.

**Campos**

**request\_id** `RouterQueueRequestId` *required*

Identificador de una solicitud en cola del Router: el identificador que usa quien llama para consultar, cancelar y recoger un resultado.

Tipo: [`RouterQueueRequestId`](#routerqueuerequestid) -- `pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`, uuid, Hasta 36 caracteres

**status** `RouterQueueStatus` *required*

El estado de una solicitud en cola del Router. Tiene exactamente tres valores y, a diferencia de `RouterErrorType`, este es un `enum` cerrado, porque los dos esquemas son cerrados en direcciones opuestas a propósito. `RouterErrorType` clasifica fallos y se espera que su conjunto crezca, así que un cliente generado que rechazara de forma estricta un grupo no reconocido fallaría con más fuerza justo cuando algo ya había salido mal. Este es un ciclo de vida, y un ciclo de vida al que más tarde se le añade un cuarto estado es un cambio incompatible para todos los bucles de polling escritos contra él, se declare como enum o no; por eso se declara como uno y la restricción se indica donde un cliente puede verla.

Tipo: [`RouterQueueStatus`](#routerqueuestatus)

**queue\_position** `RouterQueuePosition`

Cuántas solicitudes hay delante de esta en la cola, en el instante en que se compuso la respuesta. Cero significa que esta solicitud está al frente.

Tipo: [`RouterQueuePosition`](#routerqueueposition) -- Al menos 0

**error\_type** `RouterErrorType`

Presente solo en una solicitud `COMPLETED` que no tuvo éxito, y lleva el mismo grupo genérico que la lectura del resultado pone en `X-Comfy-Error-Type` cuando devuelve ese fallo. Es lo que distingue una solicitud terminal que tuvo éxito de una que falló o se canceló (no hay un estado terminal separado para ninguna de las dos), y está ausente en caso de éxito en lugar de ser null, así que ramifica en función de su presencia.

Tipo: [`RouterErrorType`](#routererrortype)

### RouterQueueStatusResponse

Estado actual de una solicitud en cola, compuesto con las mismas tres URL que devolvió el envío.

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

Tipo: `object`

### RouterQueueSubmitFields

La mitad de `RouterQueueSubmitResponse` que no es el bloque de URL: la identidad de la nueva solicitud y su estado en el instante en que fue admitida.

**Campos**

**request\_id** `RouterQueueRequestId` *required*

Identificador de una solicitud de Router en cola: el identificador con el que un llamador consulta, cancela y recoge un resultado.

Tipo: [`RouterQueueRequestId`](#routerqueuerequestid) -- `pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`, uuid, Hasta 36 caracteres

**status** `RouterQueueStatus` *required*

El estado de una solicitud de Router en cola. Tiene exactamente tres valores y, a diferencia de `RouterErrorType`, este es un `enum` cerrado, porque los dos esquemas se cierran en direcciones opuestas a propósito. `RouterErrorType` clasifica fallos y se espera que su conjunto crezca, así que un cliente generado que rechazara de forma estricta una categoría no reconocida fallaría con más fuerza justo cuando algo ya había salido mal. Este otro es un ciclo de vida, y añadir más tarde un cuarto estado a un ciclo de vida es un cambio incompatible para todo bucle de consulta escrito contra él, se declare como enum o no; por eso se declara como uno, y la restricción se indica donde un cliente puede verla.

Tipo: [`RouterQueueStatus`](#routerqueuestatus)

**queue\_position** `RouterQueuePosition`

Cuántas solicitudes hay delante de esta en la cola, en el instante en que se compuso la respuesta. Cero significa que esta solicitud está al frente.

Tipo: [`RouterQueuePosition`](#routerqueueposition) -- Al menos 0

**estimate** `RouterCostEstimate`

La estimación de costo previa para esta solicitud, presente en una admisión nueva cuando la estimación de costo está habilitada para el llamador. Cotiza el tramo del proveedor al que se fijó esta solicitud (la cola no tiene bucle de respaldo, así que `fallback_provider` nunca cambia el tramo que se ejecuta). Cuando no se puede dar una cifra, sigue presente, con `source: unknown`; el envío nunca falla por la estimación. Se omite en una repetición idempotente (`Idempotent-Replayed: true`), porque la cotización original no se almacena. Es una estimación, no el cargo final, y no es un bloqueo de precio: la ejecución se cobra a las tarifas vigentes cuando se tarifica, y el cargo liquidado en los registros de uso y facturación de tu espacio de trabajo es definitivo.

Tipo: [`RouterCostEstimate`](#routercostestimate)

### RouterQueueSubmitResponse

El identificador que se devuelve cuando una ejecución se admite en la cola: la identidad y el estado de la solicitud, compuesto con las tres URL que direccionan el resto de su ciclo de vida.

Está compuesto por [`RouterQueueUrls`](#routerqueueurls) y [`RouterQueueSubmitFields`](#routerqueuesubmitfields).

Tipo: `object`

### RouterQueueUrls

Las tres URL que abarcan el resto del ciclo de vida de una solicitud en cola y que se devuelven en cada respuesta que incluye un handle activo, para que el cliente nunca tenga que componer por su cuenta una URL de cola.

**Campos**

**status\_url** `string` *required*

URL absoluta de la lectura de estado de esta solicitud.

URI

**response\_url** `string` *required*

URL absoluta desde la que se recopila el resultado de esta solicitud.

URI

**cancel\_url** `string` *required*

URL absoluta en la que se solicita una cancelación.

URI

### RouterValidationErrorContext

Detalles proporcionados por el proveedor sobre la regla de validación que falló.

Tipo: `object`

### RouterValidationErrorDetail

Un fallo de validación a nivel de campo.

**Campos**

**loc** `array of any` *required*

Ruta al campo que causó el error, con el segmento más externo primero; por ejemplo `["body", "image_url"]`, o `["body", "images", 0]` donde un entero indexa dentro de un arreglo.

**msg** `string` *required*

Descripción legible para humanos de este fallo individual.

**type** `string` *required*

Motivo específico y legible por máquina de este fallo, que el proveedor entrega sin cambios. Es el valor sobre el que se ramifica una jerarquía tipada de excepciones del SDK; `error_type` en el encabezado de la respuesta es solo su categoría general.

**ctx** `RouterValidationErrorContext`

El límite violado para un `RouterValidationErrorDetail`, tomado literalmente del proveedor; por ejemplo `{"limit_value": 8}` junto con `greater_than`, `{"min_width": 512}` junto con `image_too_small`, o `{"max_size_bytes": 10485760}` junto con `file_too_large`. El conjunto de claves es específico del proveedor y del tipo de error, así que este objeto es deliberadamente abierto: reducirlo a una lista fija de campos, o incorporarlo a la cadena `msg`, es justo la forma en que una integración portada compila y luego pierde en silencio la rama que leía el límite. No está presente cuando el tipo de error no lleva ningún límite.

Tipo: [`RouterValidationErrorContext`](#routervalidationerrorcontext)

**input** `RouterValidationErrorInput`

El valor de entrada que causó el error, devuelto literalmente para que quien llama pueda ver qué se rechazó sin volver a deducirlo a partir de `loc`. Puede ser cualquier tipo JSON (cadena, número, booleano, arreglo, objeto o null), por lo que este esquema se deja deliberadamente sin tipar en lugar de reducirlo a un objeto. No está presente cuando el proveedor no devuelve la entrada.

Tipo: [`RouterValidationErrorInput`](#routervalidationerrorinput)

### RouterValidationErrorInput

El valor de entrada rechazado, cuando el proveedor lo incluye.

### RouterValidationErrorResponse

El cuerpo del error de validación `422`. Lee `X-Comfy-Error-Type` para conocer su categoría.

**Campos**

**detail** `array of RouterValidationErrorDetail` *required*

Todos los fallos de validación encontrados en la solicitud, una entrada por cada campo no válido.

Tipo: array de [`RouterValidationErrorDetail`](#routervalidationerrordetail)


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