> ## Documentation Index
> Fetch the complete documentation index at: https://dripart-matt-router-pricing-pika-and-guard.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Comfy Router API 参考

> 每个 Comfy Router 端点、参数、响应体和错误分类，均由 Comfy API 契约生成。

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

Comfy Router 的规范路由，以模型 ID 寻址。

基础 URL：`https://api.comfy.org`

以下每个端点都需要身份验证。请发送 `X-API-Key: <api-key>` 或 `Authorization: Bearer <jwt>`。

Comfy API 密钥也可以作为 Bearer token 发送。当同时提供两个凭证请求头时，以 `X-API-Key` 为准。有关 API 密钥与 JWT 的区别，请参阅[身份验证请求头](/zh/development/comfy-router/headers#请求标头)；有关访问要求，请参阅[快速入门](/zh/development/comfy-router/quickstart)。

## 端点

### `GET /v2/models`

**列出 Comfy Router 可以运行的模型。**

列出可用的模型 ID 和计费信息。当 `has_more` 为 true 时，使用 `next_cursor`。

**参数**

<ParamField query="cursor" type="RouterPageCursor">
  不透明的分页游标。

  Type: [`RouterPageCursor`](#routerpagecursor) -- 作为 `next_cursor` 返回的不透明游标，1–512 个字符
</ParamField>

<ParamField query="limit" type="integer">
  单页返回的模型数量。

  最多 100，Default: 20
</ParamField>

**响应**

<ResponseField name="200" type="RouterModelListResponse">
  OK - 模型目录中的一页。

  Body: [`RouterModelListResponse`](#routermodellistresponse) -- Headers: `X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="400" type="RouterErrorResponse">
  请求无效。请检查错误类型和请求体。

  Body: [`RouterErrorResponse`](#routererrorresponse) -- Headers: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="401" type="RouterErrorResponse">
  凭据缺失或无效。

  Body: [`RouterErrorResponse`](#routererrorresponse) -- Headers: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="403" type="RouterErrorResponse">
  该调用方或模型不允许此请求。

  Body: [`RouterErrorResponse`](#routererrorresponse) -- Headers: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="503" type="RouterErrorResponse">
  Router 暂时不可用。请使用退避策略重试。

  Body: [`RouterErrorResponse`](#routererrorresponse) -- Headers: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`
</ResponseField>

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

**通过规范模型 ID 读取某个合作伙伴模型的目录条目。**

无需列出完整目录，即可读取单个模型的详情。

**参数**

<ParamField path="provider" type="RouterProviderSegment" required>
  规范模型 ID `{provider}/{model}` 中的提供商部分。

  Type: [`RouterProviderSegment`](#routerprovidersegment) -- 字母数字标识符，例如 `anthropic`，最多 64 个字符
</ParamField>

<ParamField path="model" type="RouterModelSegment" required>
  规范模型 ID `{provider}/{model}` 中的模型部分。

  Type: [`RouterModelSegment`](#routermodelsegment) -- 字母数字标识符，例如 `claude-opus-4-6`，最多 128 个字符
</ParamField>

**响应**

<ResponseField name="200" type="RouterModelDetail">
  OK - 该模型的目录条目。

  Body: [`RouterModelDetail`](#routermodeldetail) -- Headers: `X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="401" type="RouterErrorResponse">
  凭证缺失或无效。

  Body: [`RouterErrorResponse`](#routererrorresponse) -- Headers: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="403" type="RouterErrorResponse">
  该请求对此调用方或此模型不被允许。

  Body: [`RouterErrorResponse`](#routererrorresponse) -- Headers: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="404" type="RouterErrorResponse">
  未找到该模型 ID。

  Body: [`RouterErrorResponse`](#routererrorresponse) -- Headers: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="503" type="RouterErrorResponse">
  Router 暂时不可用。请使用退避策略重试。

  Body: [`RouterErrorResponse`](#routererrorresponse) -- Headers: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`
</ResponseField>

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

**按规范模型 ID 同步运行合作伙伴模型。**

运行模型，并在同一个响应中收到其已完成的结果。

**参数**

<ParamField path="provider" type="RouterProviderSegment" required>
  规范 `{provider}/{model}` 模型 ID 中的提供商部分。

  类型：[`RouterProviderSegment`](#routerprovidersegment) -- 字母数字 slug，例如 `anthropic`，最多 64 个字符
</ParamField>

<ParamField path="model" type="RouterModelSegment" required>
  规范 `{provider}/{model}` 模型 ID 中的模型部分。

  类型：[`RouterModelSegment`](#routermodelsegment) -- 字母数字 slug，例如 `claude-opus-4-6`，最多 128 个字符
</ParamField>

<ParamField header="Idempotency-Key" type="string">
  由调用方生成的键，使重试同一次逻辑调用保持安全。

  1–255 个字符
</ParamField>

<ParamField query="model_provider" type="string">
  选择其他提供商来为该模型提供服务，而不是其当前默认提供商；`fal`、`wavespeed`、`runware` 和 `higgsfield` 是可选的替代提供商，`GET /v2/models/{provider}/{model}` 会报告给定模型支持其中的哪些。其拒绝按固定顺序检查，无论后面的拒绝是否会触发，前面的拒绝都会作答：无法识别的值（根本不是一个已注册的提供商）会被拒绝并返回 `400`；然后，请求体选择了 multipart 操作（编辑）时，其他提供商会遭到拒绝并返回 `409`，`detail` 以 "this request's `image` selects the edit operation" 开头，但仅当该提供商针对此模型的转换器无法服务于该操作时才如此：转换器确实能处理该媒体的分支会正常继续；然后，在解析了自带密钥凭据的请求上，任何其他提供商都会被拒绝并返回 `409`，`detail` 以 `this request resolved a BYOK credential` 开头（参见该响应），无论该提供商是否为此模型提供服务；然后是所命名提供商自身的门控：当该提供商未为你开启时，它会以 `error_type: not_enabled` 拒绝并返回 `403`，当无法评估该门控时，以 `error_type: service_unavailable` 拒绝并返回 `503`；只有在越过这全部四道检查之后，一个对该模型没有可用分支的真实提供商才会以 `error_type: invalid_input` 被拒绝并返回 `400`，与无法识别的值得到相同的答复。在自带密钥请求上、在请求体选择了 multipart 操作的请求上，以及在 `strict_mode=true` 下，`fallback_provider` 都是不生效而不是被拒绝。
</ParamField>

<ParamField query="strict_mode" type="boolean">
  仅在与 `model_provider` 一起使用时才有意义。

  默认值：False
</ParamField>

<ParamField query="fallback_provider" type="string">
  控制当首次尝试因可归因于 Router 或所尝试提供商的原因而失败时，Router 是否针对该模型的其他已注册提供商重试此调用。省略该参数，或使用除 `false` 之外的任何值，都会保持回退开启；`false` 会将其关闭。成功的回退响应会带有 `X-Comfy-Router-Fallback-Provider`。在解析了自带密钥凭据的请求上，无论此参数怎么说，回退都不可用：该尝试根本不会进行，首次失败会原样到达你这里，这是不生效，而不是被拒绝：不会从这里产生 `409`。出于同样的原因，在请求体选择了 multipart 操作的请求上，以及在 `strict_mode=true` 下也是如此：这两者都把该调用绑定到某一个提供商，而该调用无法被如实地对另一个提供商重放，因此回退只是被跳过，而不是被拒绝。只有显式指定 `model_provider` 时才会以该 `409` 被拒绝，并且与这种无条件的跳过不同，其 multipart `409` 只适用于转换器无法服务于该操作的分支。
</ParamField>

<ParamField query="reject_unknown_fields" type="boolean">
  选择拒绝该模型输入 schema 未声明的顶层请求体字段，而不是接受它；嵌套字段不会被检查，对于 schema 允许未声明字段或没有编写 schema 的模型，或者对于使用 `strict_mode=true` 发送的排队提交，都不会拒绝任何内容。

  默认值：False
</ParamField>

**请求体**

`application/json` -- [`RouterModelInput`](#routermodelinput)（必填）

合作伙伴模型的原生 JSON 输入。不使用 `model_provider` 时，请求会在模型的默认提供商上运行原生调度，而此请求体就是模型自身的原生 schema，会被原样转发（此时 `strict_mode` 没有意义，也不会改变任何东西）。当 `model_provider` 选择替代提供商且 `strict_mode=false`（默认值）时，请求体在发送之前会被转换为该提供商的实际 schema：任何无法精确表达的原生字段都会被丢弃，并通过响应的 `X-Comfy-Router-Dropped-Params` 头披露，绝不会悄无声息地丢弃。当 `model_provider` 选择替代提供商且 `strict_mode=true` 时，不会运行任何转换：请求体必须已经是该替代提供商自身的实际 schema，而不是此模型的原生 schema（参见 `strict_mode`），并会被原样转发。请求体自身的字段还会选择 Router 在支持多种操作的模型上运行哪种操作：对于可编辑的图像模型，包含输入图像会将其从文生图切换为图生图（编辑）操作，该操作可能按其自身的费率计费；对于 Seedance 视频模型，`content[].role` 选择操作（首帧图像选择图生视频，参考图像或视频片段选择参考生视频）。在原生调度下，Seedance 计费遵循 `content` 中的媒体种类，而不是角色：任何带视频输入的请求都按视频转视频计费，否则任何带图像的请求按图生视频计费，再否则按文生视频计费，例外情况是，由 `draft_task` 项产生的最终渲染按其渲染的 Draft 所属操作计费；有些模型对文生视频和图生视频收取相同的费率。当 `model_provider` 选择替代提供商时，每种带条件的操作都可能按该提供商自身的费率计费。

**响应**

<ResponseField name="200" type="RouterModelOutput">
  OK：未提供 `model_provider`，或者提供了 `model_provider` 且 `strict_mode=false`（默认值，在可能时转换回该模型的原生契约，转换失败时回退到备选提供商自身的原始响应，会记录日志，绝不静默处理）时，形状为该模型自身的原生输出；当 `strict_mode=true` 时，返回的是备选提供商的响应，且原样不变。对于由合作伙伴直接以字节形式返回生成结果的模型，响应体就是这些字节，使用合作伙伴自己的 `Content-Type`，而不是 `application/json`；请根据响应的 `Content-Type` 进行分支判断，不要假定它一定是 JSON 文档。

  响应体：[`RouterModelOutput`](#routermodeloutput) 或原始字节（`*/*`） 请求头：`X-Comfy-Request-Id`、`X-Content-Type-Options`、`X-Comfy-Router-Fallback-Provider`、`X-Comfy-Router-Dropped-Params`、`X-Comfy-Credits-Used`、`Idempotent-Replayed`、`X-Committed-Spend-Limit`、`X-Committed-Spend-Current`、`X-Committed-Spend-Remaining`
</ResponseField>

<ResponseField name="400" type="RouterErrorResponse">
  请求无效。请检查错误类型和请求体。

  响应体：[`RouterErrorResponse`](#routererrorresponse) 请求头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`、`X-Comfy-Upstream-Status`、`X-Comfy-Upstream-Detail`、`X-Comfy-Refusal-Subject`、`Idempotent-Replayed`
</ResponseField>

<ResponseField name="401" type="RouterErrorResponse">
  凭据缺失或无效。

  响应体：[`RouterErrorResponse`](#routererrorresponse) 请求头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="402" type="RouterErrorResponse">
  Router 层面的请求失败：请求从未到达模型，或由于模型自身未反馈的原因而失败。

  响应体：[`RouterErrorResponse`](#routererrorresponse) 请求头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="403" type="RouterErrorResponse">
  该请求对于此调用方或此模型不被允许。

  响应体：[`RouterErrorResponse`](#routererrorresponse) 请求头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="404" type="RouterErrorResponse">
  未找到该模型 ID。

  响应体：[`RouterErrorResponse`](#routererrorresponse) 请求头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="409" type="RouterErrorResponse">
  检查 `X-Comfy-Error-Type`：`concurrency_limit_exceeded` 表示原始调用仍在运行，因此请等待 `Retry-After` 并复用同一个 key；`invalid_input` 则需要一个新的 key。此路由上的两种 `invalid_input` 冲突与 key 完全无关，换任何新 key 都无法解决：当请求体选择了某提供商针对该模型的翻译器无法提供的 multipart 操作（一次编辑）时，指定备选提供商的 `model_provider` 会被拒绝，其 `detail` 以 "this request's `image` selects the edit operation" 开头；之后还会检查另一种情况，即请求已为该路径中的提供商解析出 bring-your-own-key 凭据，其 `detail` 以 `this request resolved a BYOK credential` 开头。请去掉 `model_provider`，或不带该 BYOK 凭据发送请求（对于 multipart 的情况还要去掉该编辑）。

  响应体：[`RouterErrorResponse`](#routererrorresponse) 请求头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`、`Retry-After`（仅在 `concurrency_limit_exceeded` 时）
</ResponseField>

<ResponseField name="413" type="RouterErrorResponse">
  请求体过大。

  响应体：[`RouterErrorResponse`](#routererrorresponse) 请求头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="422" type="RouterValidationErrorResponse">
  请求的内容未通过模型 schema 的校验而被拒绝。

  响应体：[`RouterValidationErrorResponse`](#routervalidationerrorresponse) 请求头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`、`Idempotent-Replayed`
</ResponseField>

<ResponseField name="429" type="RouterErrorResponse">
  检查 `X-Comfy-Error-Type`：`concurrency_limit_exceeded` 表示需要减少进行中的调用；`rate_limited` 表示需要等待配额窗口。

  响应体：[`RouterErrorResponse`](#routererrorresponse) 请求头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`、`X-Committed-Spend-Limit`、`X-Committed-Spend-Current`、`X-Committed-Spend-Remaining`
</ResponseField>

<ResponseField name="502" type="RouterErrorResponse">
  提供商自身的响应无法被转换为结果（`provider_error`）。

  响应体：[`RouterErrorResponse`](#routererrorresponse) 请求头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`、`X-Comfy-Upstream-Status`
</ResponseField>

<ResponseField name="503" type="RouterErrorResponse">
  Router 暂时不可用。请使用退避策略重试。

  响应体：[`RouterErrorResponse`](#routererrorresponse) 请求头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`、`Retry-After`（仅在容量拒绝时）
</ResponseField>

<ResponseField name="504" type="RouterErrorResponse">
  请求超过了截止时间。重试之前请检查错误类型。

  响应体：[`RouterErrorResponse`](#routererrorresponse) 请求头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`、`X-Comfy-Upstream-Status`、`Retry-After`
</ResponseField>

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

**在运行模型调用之前先为其定价，而无需实际运行。**

返回 Comfy 使用此模型运行该请求体将会收取的费用，以美元计，依据与实际扣费相同的费率卡定价。请求体会先按模型的输入 schema 进行校验，与默认运行（不带 `strict_mode`、不带 `reject_unknown_fields`）的校验方式相同，因此未通过模型 schema 的请求体在此处与在运行时一样会返回 `422`；不会向任何提供商派发请求，也不会产生任何费用。该结果并非价格锁定：它按 `pricing_as_of` 当时生效的费率计价，而一次运行则按其计费时生效的费率收取费用。在该功能逐步上线期间，此路由会返回 `403`，并带有 `error_type: not_enabled`。

**参数**

<ParamField path="provider" type="RouterProviderSegment" required>
  规范 `{provider}/{model}` 模型 ID 中的小写提供商段，即正在运行其模型的合作伙伴。

  类型：[`RouterProviderSegment`](#routerprovidersegment)，字母数字 slug，例如 `anthropic`，最多 64 个字符
</ParamField>

<ParamField path="model" type="RouterModelSegment" required>
  规范 `{provider}/{model}` 模型 ID 中的小写模型段，即在该提供商内要运行的模型。

  类型：[`RouterModelSegment`](#routermodelsegment)，字母数字 slug，例如 `claude-opus-4-6`，最多 128 个字符
</ParamField>

<ParamField query="model_provider" type="string">
  选择另一个提供商来提供此模型的服务，而非其当前的默认提供商。
</ParamField>

**请求体**

`application/json`，[`RouterModelInput`](#routermodelinput)（必填）

合作伙伴模型的原生 JSON 输入，与同步路由为此模型接受的请求体完全相同。它会按模型自身的输入 schema 进行校验，与默认运行的校验方式相同（此路由不接受 `strict_mode` 或 `reject_unknown_fields`），并由其自身的字段（输出数量、输入图像所选定的操作）决定计价内容。

**响应**

<ResponseField name="200" type="RouterCostEstimate">
  报价。

  响应体：[`RouterCostEstimate`](#routercostestimate)，响应头：`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="400" type="RouterErrorResponse">
  请求无效。请检查错误类型和请求体。

  响应体：[`RouterErrorResponse`](#routererrorresponse)，响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="401" type="RouterErrorResponse">
  凭据缺失或无效。

  响应体：[`RouterErrorResponse`](#routererrorresponse)，响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="403" type="RouterErrorResponse">
  该请求对此调用方或此模型不被允许。

  响应体：[`RouterErrorResponse`](#routererrorresponse)，响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="404" type="RouterErrorResponse">
  未找到该模型 ID。

  响应体：[`RouterErrorResponse`](#routererrorresponse)，响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="413" type="RouterErrorResponse">
  请求体过大。

  响应体：[`RouterErrorResponse`](#routererrorresponse)，响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="422" type="RouterValidationErrorResponse">
  估算的请求体未通过模型 schema 的校验，或者指定的模型与路径中的模型不一致。

  响应体：[`RouterValidationErrorResponse`](#routervalidationerrorresponse)，响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="503" type="RouterErrorResponse">
  Router 暂时不可用。请使用退避策略重试。

  响应体：[`RouterErrorResponse`](#routererrorresponse)，响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`、`Retry-After`（仅容量拒绝时）
</ResponseField>

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

**以 OpenAPI 文档形式读取某一个合作伙伴模型的输入和输出 schema。**

以独立的 OpenAPI 文档形式读取某一个模型的输入和输出 schema。

**参数**

<ParamField path="provider" type="RouterProviderSegment" required>
  规范模型 ID `{provider}/{model}` 中的提供商部分。

  类型：[`RouterProviderSegment`](#routerprovidersegment) -- 由字母和数字组成的 slug，例如 `anthropic`，最多 64 个字符
</ParamField>

<ParamField path="model" type="RouterModelSegment" required>
  规范模型 ID `{provider}/{model}` 中的模型部分。

  类型：[`RouterModelSegment`](#routermodelsegment) -- 由字母和数字组成的 slug，例如 `claude-opus-4-6`，最多 128 个字符
</ParamField>

<ParamField header="If-None-Match" type="string">
  调用方从先前的 `200` 响应中持有的 `ETag`。
</ParamField>

**响应**

<ResponseField name="200" type="RouterModelInputSchemaDocument">
  OK - 该模型的输入和输出 schema，以独立的 OpenAPI 文档形式呈现。

  响应体：[`RouterModelInputSchemaDocument`](#routermodelinputschemadocument) -- 响应头：`X-Comfy-Request-Id`、`ETag`、`Cache-Control`
</ResponseField>

<ResponseField name="304" type="no body">
  未修改 - 自调用方在 `If-None-Match` 中发送的 `ETag` 以来，文档未发生变化。

  响应头：`X-Comfy-Request-Id`、`ETag`、`Cache-Control`
</ResponseField>

<ResponseField name="401" type="RouterErrorResponse">
  凭据缺失或无效。

  响应体：[`RouterErrorResponse`](#routererrorresponse) -- 响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="403" type="RouterErrorResponse">
  不允许该调用方或模型发起此请求。

  响应体：[`RouterErrorResponse`](#routererrorresponse) -- 响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="404" type="RouterErrorResponse">
  未找到该模型 ID。

  响应体：[`RouterErrorResponse`](#routererrorresponse) -- 响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="500" type="RouterErrorResponse">
  Router 无法完成该请求。

  响应体：[`RouterErrorResponse`](#routererrorresponse) -- 响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="503" type="RouterErrorResponse">
  Router 暂时不可用。请以退避策略重试。

  响应体：[`RouterErrorResponse`](#routererrorresponse) -- 响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

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

**向队列提交一次合作伙伴模型运行，并立即返回。**

Comfy Router 的队列投递模式。请求体与 `POST /v2/models/{provider}/{model}` 为该模型接受的合作伙伴原生 JSON 输入相同：一种请求体形状、一份按模型划分的 schema、两种投递模式；但此路由不会为获取结果而保持连接。它接纳这次运行，用句柄返回 `201`，调用方随后通过下面三个读取操作获取结果。

**参数**

<ParamField path="provider" type="RouterProviderSegment" required>
  规范 `{provider}/{model}` 模型 ID 中的小写提供商段，即正在运行其模型的合作伙伴。

  Type: [`RouterProviderSegment`](#routerprovidersegment) -- 字母数字短标识，例如 `anthropic`，最多 64 个字符
</ParamField>

<ParamField path="model" type="RouterModelSegment" required>
  规范 `{provider}/{model}` 模型 ID 中的小写模型段，即要在该提供商内运行的模型。

  Type: [`RouterModelSegment`](#routermodelsegment) -- 字母数字短标识，例如 `claude-opus-4-6`，最多 128 个字符
</ParamField>

<ParamField query="model_provider" type="string">
  选择另一个提供商来服务此模型，而不是使用其当前默认提供商。
</ParamField>

<ParamField query="strict_mode" type="boolean">
  仅在配合 `model_provider` 时才有意义。

  Default: False
</ParamField>

<ParamField header="Idempotency-Key" type="string">
  由调用方生成的键，使重试同一次逻辑调用是安全的。

  1–255 个字符
</ParamField>

<ParamField query="reject_unknown_fields" type="boolean">
  选择拒绝该模型输入 schema 未声明的顶层请求体字段，而不是接受它；嵌套字段不会被检查，对于其 schema 允许未声明字段或没有编写 schema 的模型，或者对以 `strict_mode=true` 发送的队列提交，都不会拒绝任何内容。

  Default: False
</ParamField>

**请求体**

`application/json` -- [`RouterModelInput`](#routermodelinput)（必填）

合作伙伴模型的原生 JSON 输入，与同步路由为该模型接受的请求体相同，它选择操作并以相同方式计量：请求体自身的字段决定 Router 在支持多种操作的模型上运行哪种操作（输入图像会把可编辑图像模型切换为图生图，这可能按其自身的费率计量；Seedance 的首帧图像选择图生视频，而参考图像或视频片段选择参考生视频）。在原生派发时，Seedance 请求按 `content` 中的媒体种类计费，而不是按角色：任何视频输入都按视频转视频计费，否则任何图像按图生视频计费，否则按文生视频计费；例外情况是，来自 `draft_task` 条目的最终渲染按其渲染的 Draft 所属操作计费，有些模型对文生视频和图生视频收取相同费率；当 `model_provider` 选择备用提供商时，每个带条件的操作可能按该提供商自身的费率计量。相同的提供商选择契约在派发时同样适用：不使用 `model_provider` 时，或使用 `model_provider` 且 `strict_mode=false`（默认值）时，请求体是模型的原生文档，并在运行被接纳之前针对模型自身的输入 schema 进行验证，因此模型会拒绝的请求体在这里是 `422`，而不是几分钟后才失败的已排队请求；在派发时，非严格的备用提供商请求体还会额外被转换为该提供商真正的 schema。使用 `strict_mode=true` 时，请求体必须已经是备用提供商自身的 schema，并会被原样转发：跳过原生 schema 验证，与同步路由完全一致（参见 `model_provider` 和 `strict_mode`）。

**响应**

<ResponseField name="201" type="RouterQueueSubmitResponse">
  Created：运行已被接纳进入队列。

  Body: [`RouterQueueSubmitResponse`](#routerqueuesubmitresponse) -- Headers: `X-Comfy-Request-Id`, `Idempotent-Replayed`
</ResponseField>

<ResponseField name="401" type="RouterErrorResponse">
  凭据缺失或无效。

  Body: [`RouterErrorResponse`](#routererrorresponse) -- Headers: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="400" type="RouterErrorResponse">
  请求无效。请检查错误类型和请求体。

  Body: [`RouterErrorResponse`](#routererrorresponse) -- Headers: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="413" type="RouterErrorResponse">
  请求体过大。

  Body: [`RouterErrorResponse`](#routererrorresponse) -- Headers: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="402" type="RouterErrorResponse">
  Router 请求级失败：请求从未到达模型，或因模型自身未反馈的原因而失败。

  Body: [`RouterErrorResponse`](#routererrorresponse) -- Headers: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="403" type="RouterErrorResponse">
  该请求对此调用方或模型不被允许。如果某个模型的合作伙伴直接以字节形式返回生成结果，则该模型目前无法排队，并会以 `not_enabled` 被拒绝；请改为在同步路由上运行它。

  Body: [`RouterErrorResponse`](#routererrorresponse) -- Headers: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="404" type="RouterErrorResponse">
  未找到该模型 ID。

  Body: [`RouterErrorResponse`](#routererrorresponse) -- Headers: `X-Comfy-Error-Type`, `X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="409" type="RouterErrorResponse">
  检查 `X-Comfy-Error-Type`：`concurrency_limit_exceeded` 表示原始调用仍在运行，因此请等待 `Retry-After` 并复用同一个键；`invalid_input` 则要求使用新的键。此路由上的两种 `invalid_input` 冲突与键完全无关，换用新键也无法消除其中任何一种：当请求体选择了该提供商针对此模型的转换器无法服务的多部分操作（一次编辑）时，用 `model_provider` 指定备用提供商会被拒绝，其 `detail` 以 "this request's `image` selects the edit operation" 开头；以及在此之后检查的另一种情况：当请求已经为路径中的提供商解析出自带密钥（BYOK）凭据时，其 `detail` 以 `this request resolved a BYOK credential` 开头。请去掉 `model_provider`，或者发送请求时不带 BYOK 凭据，（对于多部分操作的情况）也不带该编辑操作。

  请求体：[`RouterErrorResponse`](#routererrorresponse)。请求头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`、`Retry-After`（出现 `concurrency_limit_exceeded` 时）
</ResponseField>

<ResponseField name="422" type="RouterValidationErrorResponse">
  请求的内容未通过模型的 schema 校验。

  请求体：[`RouterValidationErrorResponse`](#routervalidationerrorresponse)。请求头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`、`Idempotent-Replayed`
</ResponseField>

<ResponseField name="503" type="RouterErrorResponse">
  Router 暂时不可用。请以退避方式重试。

  请求体：[`RouterErrorResponse`](#routererrorresponse)。请求头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`、`Retry-After`（仅在容量拒绝时）
</ResponseField>

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

**收集一次已提交请求的结果。**

这是收集端点。对于已成功完成的请求，它返回合作伙伴模型自身的原生输出，与同步路由针对同一模型、同一输入在 `200` 中返回的内容逐字节一致，因此两种交付模式产生同一种结果形状，调用方无需第二个解析器即可在两者之间切换。

**参数**

<ParamField path="provider" type="RouterProviderSegment" required>
  规范 `{provider}/{model}` 模型 ID 中的小写提供商段，即正在运行其模型的合作伙伴。

  类型：[`RouterProviderSegment`](#routerprovidersegment) -- 字母数字 slug，例如 `anthropic`，最长 64 个字符
</ParamField>

<ParamField path="model" type="RouterModelSegment" required>
  规范 `{provider}/{model}` 模型 ID 中的小写模型段，即要在该提供商内运行的模型。

  类型：[`RouterModelSegment`](#routermodelsegment) -- 字母数字 slug，例如 `claude-opus-4-6`，最长 128 个字符
</ParamField>

<ParamField path="request_id" type="RouterQueueRequestId" required>
  要寻址的队列请求，即提交时在响应体中返回的 `request_id`。

  类型：[`RouterQueueRequestId`](#routerqueuerequestid) -- `pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`，uuid，最长 36 个字符
</ParamField>

**响应**

<ResponseField name="200" type="RouterModelOutput">
  正常，即为产生了结果的请求所存储的结果：一个成功完成的请求，或一个同时带有已记录扣费和已存储结果的终端请求。该结果以合作伙伴自身的媒体类型原样返回，与同步路由的 `200` 返回方式完全一致，并且遵循提交时所接受的同一套提供商选择约定：在没有 `model_provider` 时，或带有 `model_provider` 且 `strict_mode=false`（默认值，尽可能翻译回此模型的原生约定，若翻译失败则回退到备用提供商的原始响应，会记录日志，绝不静默）时，其形状为此模型自身的原生输出；当 `strict_mode=true` 时，则原样返回备用提供商的响应。对于合作伙伴直接以字节形式应答生成结果的模型，响应体是这些字节，并采用合作伙伴自身的 `Content-Type` 而不是 `application/json`；请根据响应 `Content-Type` 分支处理，不要假定它是 JSON 文档。

  响应体：[`RouterModelOutput`](#routermodeloutput) 或原始字节（`*/*`）-- 响应头：`X-Comfy-Request-Id`、`X-Content-Type-Options`
</ResponseField>

<ResponseField name="202" type="RouterQueueStatusResponse">
  已接受，请求尚未完成。

  响应体：[`RouterQueueStatusResponse`](#routerqueuestatusresponse) -- 响应头：`X-Comfy-Request-Id`、`Retry-After`
</ResponseField>

<ResponseField name="401" type="RouterErrorResponse">
  凭据缺失或无效。

  响应体：[`RouterErrorResponse`](#routererrorresponse) -- 响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="403" type="RouterErrorResponse">
  该请求对该调用方或该模型不被允许。

  响应体：[`RouterErrorResponse`](#routererrorresponse) -- 响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="404" type="RouterErrorResponse">
  未找到该模型 ID。

  响应体：[`RouterErrorResponse`](#routererrorresponse) -- 响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="410" type="RouterErrorResponse">
  Router 请求级失败：请求从未到达模型，或因模型自身未反馈的原因而失败。

  响应体：[`RouterErrorResponse`](#routererrorresponse) -- 响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="503" type="RouterErrorResponse">
  Router 暂时不可用。请采用退避策略重试。

  响应体：[`RouterErrorResponse`](#routererrorresponse) -- 响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="409" type="RouterErrorResponse">
  请求处于与该操作冲突的状态。请检查错误类型。

  响应体：[`RouterErrorResponse`](#routererrorresponse) -- 响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="504" type="RouterErrorResponse">
  请求超过了截止时间。重试前请检查错误类型。

  响应体：[`RouterErrorResponse`](#routererrorresponse) -- 响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="422" type="RouterValidationErrorResponse">
  请求的内容依据模型的 schema 被拒绝。

  响应体：[`RouterValidationErrorResponse`](#routervalidationerrorresponse) -- 响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`、`Idempotent-Replayed`
</ResponseField>

<ResponseField name="default" type="RouterErrorResponse">
  Router 请求级失败：请求从未到达模型，或因模型自身未反馈的原因而失败。

  响应体：[`RouterErrorResponse`](#routererrorresponse) -- 响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

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

**请求取消一个已提交的请求。**

请求 Comfy 停止一个尚未完成的请求。这只是一个请求，而非保证，`202` 传达的正是这一点：`CANCELLATION_REQUESTED` 表示该请求已被接受，并不表示运行已经停止。已经发往合作伙伴的运行仍可能照常完成，而合作伙伴的生成一旦完成就会被计费，无论是否有人取用结果。因此，需要确切了解实际发生了什么的调用方应在此之后读取状态端点，在那里，真正生效的取消会呈现为 `COMPLETED`，并像其他所有终端结果一样带有 `error_type`。

**参数**

<ParamField path="provider" type="RouterProviderSegment" required>
  规范 `{provider}/{model}` 模型 ID 中的小写提供商片段：即正在运行其模型的合作伙伴。

  类型：[`RouterProviderSegment`](#routerprovidersegment) -- 字母数字 slug，例如 `anthropic`，最多 64 个字符
</ParamField>

<ParamField path="model" type="RouterModelSegment" required>
  规范 `{provider}/{model}` 模型 ID 中的小写模型片段：即在该提供商内要运行的模型。

  类型：[`RouterModelSegment`](#routermodelsegment) -- 字母数字 slug，例如 `claude-opus-4-6`，最多 128 个字符
</ParamField>

<ParamField path="request_id" type="RouterQueueRequestId" required>
  要处理的已排队请求：即提交操作在其响应体中返回的 `request_id`。

  类型：[`RouterQueueRequestId`](#routerqueuerequestid) -- `pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`，uuid，最多 36 个字符
</ParamField>

**响应**

<ResponseField name="202" type="RouterQueueCancelResponse">
  已接受：`CANCELLATION_REQUESTED`。

  响应体：[`RouterQueueCancelResponse`](#routerqueuecancelresponse) -- 响应头：`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="409" type="RouterQueueCancelResponse">
  冲突：`ALREADY_COMPLETED`。

  响应体：[`RouterQueueCancelResponse`](#routerqueuecancelresponse) -- 响应头：`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="400" type="RouterErrorResponse">
  无效请求。请检查错误类型和请求体。

  响应体：[`RouterErrorResponse`](#routererrorresponse) -- 响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="401" type="RouterErrorResponse">
  凭据缺失或无效。

  响应体：[`RouterErrorResponse`](#routererrorresponse) -- 响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="403" type="RouterErrorResponse">
  该请求对当前调用方或模型不被允许。

  响应体：[`RouterErrorResponse`](#routererrorresponse) -- 响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="404" type="RouterErrorResponse">
  未找到该模型 ID。

  响应体：[`RouterErrorResponse`](#routererrorresponse) -- 响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="503" type="RouterErrorResponse">
  Router 暂时不可用。请使用退避策略重试。

  响应体：[`RouterErrorResponse`](#routererrorresponse) -- 响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="default" type="RouterErrorResponse">
  Router 请求级失败：请求从未到达模型，或因模型自身未反馈的原因而失败。

  响应体：[`RouterErrorResponse`](#routererrorresponse) -- 响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

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

**读取已提交请求的队列状态。**

这是轮询端点。它只返回请求的当前状态，从不返回结果，因此客户端可以在不把输出随每次轮询一起传输的情况下观察长时间生成：当此处显示 `COMPLETED` 时，再从下面的读取操作中一次性收集结果。

**参数**

<ParamField path="provider" type="RouterProviderSegment" required>
  规范 `{provider}/{model}` 模型 ID 中的小写提供商片段，即正在运行其模型的合作伙伴。

  类型：[`RouterProviderSegment`](#routerprovidersegment)，字母数字 slug，例如 `anthropic`，最多 64 个字符
</ParamField>

<ParamField path="model" type="RouterModelSegment" required>
  规范 `{provider}/{model}` 模型 ID 中的小写模型片段，即在该提供商内运行的模型。

  类型：[`RouterModelSegment`](#routermodelsegment)，字母数字 slug，例如 `claude-opus-4-6`，最多 128 个字符
</ParamField>

<ParamField path="request_id" type="RouterQueueRequestId" required>
  要定位的排队请求，即提交时在响应体中返回的 `request_id`。

  类型：[`RouterQueueRequestId`](#routerqueuerequestid)，`pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`，uuid，最多 36 个字符
</ParamField>

**响应**

<ResponseField name="200" type="RouterQueueStatusResponse">
  OK，请求当前的队列状态。

  响应体：[`RouterQueueStatusResponse`](#routerqueuestatusresponse)，响应头：`X-Comfy-Request-Id`、`Retry-After`
</ResponseField>

<ResponseField name="401" type="RouterErrorResponse">
  凭据缺失或无效。

  响应体：[`RouterErrorResponse`](#routererrorresponse)，响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="403" type="RouterErrorResponse">
  该调用方或模型不允许执行此请求。

  响应体：[`RouterErrorResponse`](#routererrorresponse)，响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="404" type="RouterErrorResponse">
  未找到该模型 ID。

  响应体：[`RouterErrorResponse`](#routererrorresponse)，响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="410" type="RouterErrorResponse">
  Router 请求级失败：请求从未到达模型，或因模型本身未反馈的原因而失败。

  响应体：[`RouterErrorResponse`](#routererrorresponse)，响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="503" type="RouterErrorResponse">
  Router 暂时不可用。请以退避策略重试。

  响应体：[`RouterErrorResponse`](#routererrorresponse)，响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

<ResponseField name="default" type="RouterErrorResponse">
  Router 请求级失败：请求从未到达模型，或因模型本身未反馈的原因而失败。

  响应体：[`RouterErrorResponse`](#routererrorresponse)，响应头：`X-Comfy-Error-Type`、`X-Comfy-Request-Id`
</ResponseField>

这里的描述较为简略。关于模型选择、验证、重试和计费，请参阅[使用 Comfy Router API](/zh/development/comfy-router/api)；关于响应头行为，请参阅[响应头](/zh/development/comfy-router/headers)。

## 错误分类桶

Router 错误的机器可读类别，同时也会在 `X-Comfy-Error-Type` 响应头中发送。

### 请求级分类桶

针对 Router 已接受但随后无法完成的请求抛出。

| `error_type` | 含义 |
| - | - |
| `invalid_input` | 请求在到达模型之前就被拒绝：请求体格式错误、分页游标格式错误或已过期、模型自身 schema 不接受的输入，或无法用于此请求的 `Idempotency-Key`（已用于其他请求，即方法、路径与查询或请求体不同；或已被某个其响应无法重放的调用消耗）。 |
| `content_policy_violation` | 提供商基于内容政策理由拒绝了请求。 |
| `provider_error` | 合作伙伴提供商报告了其自身的故障，或返回了 Router 无法解释为结果的响应。 |
| `provider_timeout` | 合作伙伴提供商未在其截止时间内应答。 |
| `insufficient_credits` | 发起调用的工作区没有足够的积分来运行该模型。 |
| `model_not_found` | `{provider}/{model}` ID 未指向任何 Router 可运行的模型：提供商未知、ID 未登记、该 ID 已被目录在其停用日期之后退役，或该已编目的 ID 当前未由其提供商为 Comfy 提供。 |

### 传输级分类桶

由 Router 自身抛出，发生在调用模型之前或调用过程之中。

| `error_type` | 含义 |
| - | - |
| `unauthorized` | 请求未携带可用的凭据。 |
| `forbidden` | 凭据有效，但无权访问此模型或执行此操作。 |
| `concurrency_limit_exceeded` | 工作区已在进行中的调用数量已达到允许的上限；等待其中一项调用完成后重试。 |
| `client_disconnected` | 在 Router 能够返回结果之前，调用方关闭了连接。 |
| `internal_error` | Router 自身失败。 |
| `deadline_exceeded` | 在应答到达之前，Comfy 已在自身配置的时限处停止保持连接。 |
| `not_enabled` | Comfy Router 尚未为该调用方启用。 |
| `service_unavailable` | Comfy Router 依赖的某个服务暂时不可用，调用方没有任何过错。 |
| `rate_limited` | 调用方已用尽按窗口计量的配额，必须等待该窗口滚动过去。 |
| `cancelled` | 已排队的请求在产生结果之前被撤回（通过取消路由，或由操作员撤回）；它处于终态，其本身并不代表关于计费的说法。 |
| `queue_timeout` | 已排队的请求等待超过了其队列超时时间，始终未被准入。 |
| `request_not_found` | `request_id` 未指向该调用方在此模型下的任何请求。 |
| `queue_backlog_full` | 调用方已有过多等待运行的排队请求，因此此次提交被拒绝。 |

## 响应头

<ResponseField name="Cache-Control" type="string">
  所提供架构文档的新鲜度指令。
</ResponseField>

<ResponseField name="ETag" type="string">
  针对所提供文档字节的强实体标签，用于 `GET /v2/models/{provider}/{model}/openapi.json`。
</ResponseField>

<ResponseField name="Idempotent-Replayed" type="boolean">
  当此响应来自某条 `Idempotency-Key` 的记录，而不是通过再次运行模型产生时，该响应头会出现并且值为 `true`。
</ResponseField>

<ResponseField name="Retry-After" type="integer">
  原样重新发送同一请求前需要等待的秒数。

  发送条件：`503`
</ResponseField>

<ResponseField name="Retry-After" type="integer">
  下一次轮询这个已入队的请求前需要等待的秒数。

  发送条件：`200`、`202`
</ResponseField>

<ResponseField name="Retry-After" type="integer">
  使用同一个 `Idempotency-Key` 重试同一请求之前需要等待的秒数。

  发送条件：`409`、`504`
</ResponseField>

<ResponseField name="X-Comfy-Credits-Used" type="string">
  本次运行的费用，以 Comfy 积分计，按扣费本身所依据的同一价目卡片定价。因此调用方无需自备价格表；当一次运行通过多个计费调用抵达提供商时，该值是这些调用的总和，而不是最后一次调用的值。
</ResponseField>

<ResponseField name="X-Comfy-Error-Type" type="RouterErrorType">
  失败的粗粒度、机器可读分类，由 Router 在每个错误响应上设置。

  类型：[`RouterErrorType`](#routererrortype)
</ResponseField>

<ResponseField name="X-Comfy-Refusal-Subject" type="string">
  内容策略拒绝所针对的是哪个输入或输出，采用 Router 层面的封闭值集合：`input`、`output`、`input_text`、`input_image`、`input_video`、`input_audio`、`output_text`、`output_image`、`output_video`、`output_audio`。
</ResponseField>

<ResponseField name="X-Comfy-Request-Id" type="string">
  服务器为此次调用生成的标识符，存在于每一个 Router 响应中：成功、4xx 和 5xx 响应均如此，因为错误响应恰恰是用户需要在支持请求中引用某个 ID 的时候。
</ResponseField>

<ResponseField name="X-Comfy-Router-Dropped-Params" type="string">
  一个 JSON 编码的字符串，内含一个字符串数组。请使用 JSON 解析器来解码，而不要按逗号对其分割，因为它在传输时是单个字符串，而不是逗号分隔的 OpenAPI 数组，并且每个条目本身就是一个带有逗号的句子。当一次转换生成了本次调用的请求体，却无法在所服务的提供商上精确表达一个或多个原生字段时，该响应头就会出现，并逐一列出每个被丢弃的字段及其原因；无论调用方是通过 `model_provider`（`strict_mode=false`，默认值）请求该转换，还是由自动的 `fallback_provider` 重试执行了该转换，都是如此。
</ResponseField>

<ResponseField name="X-Comfy-Router-Fallback-Provider" type="string">
  仅当 `fallback_provider` 确实针对第二个提供商重试了此调用，并且该重试成功时，该响应头才会出现并指明该提供商：即最终服务此调用的提供商，绝不是被尝试过但也失败了的那个。
</ResponseField>

<ResponseField name="X-Comfy-Upstream-Detail" type="string">
  模型提供商给出的、有长度限制且已脱敏的拒绝该请求的原因。
</ResponseField>

<ResponseField name="X-Comfy-Upstream-Status" type="integer">
  模型提供商在此次调用中自身的 HTTP 状态。
</ResponseField>

<ResponseField name="X-Committed-Spend-Current" type="integer">
  调用方当前已承诺给仍在途调用的美分数。
</ResponseField>

<ResponseField name="X-Committed-Spend-Limit" type="integer">
  调用方可承诺给仍在途调用的合作伙伴支出上限，单位为美分。这笔资金从调用被接纳的那一刻起即被保留，并在该调用结束时释放。
</ResponseField>

<ResponseField name="X-Committed-Spend-Remaining" type="integer">
  上限之下剩余的可用额度，单位为美分，最低为零。
</ResponseField>

<ResponseField name="X-Content-Type-Options" type="string">
  在 Router 模型的每次成功运行中都始终为 `nosniff`。
</ResponseField>

## 预检费用预估

`POST /v2/models/{provider}/{model}/estimate` 可以在不运行请求体的情况下为其定价；排队提交（`POST /v2/models/{provider}/{model}/requests`）会在其 `201` 响应中返回与 `estimate` 相同的 [`RouterCostEstimate`](#routercostestimate)。两者的定价都基于 Comfy 对该次运行计费所依据的费率卡片；使用你自己的提供商密钥运行时，Comfy 不会计费（见下文）。在预估功能逐步开放期间，该路由会返回 `403` 以及 `error_type: not_enabled`，并且提交响应会省略 `estimate`。目录中仍然不包含任何价格。

在读取任何金额之前，先读取 `source`。缺失的数值绝不意味着免费。

| `source` | 携带字段 | 如何解读 |
| - | - | - |
| `exact` | `amount`、`amount_cents`、`credits` | 按 `pricing_as_of` 中的费率，对该请求体收取的费用。 |
| `estimated` | `min_amount`、`max_amount` 及其 `_cents` 形式，不含 `amount` | 费用取决于提供商回传的某个数量，而请求体对该数量给出了界限；预期落在两个界限之间。 |
| `unknown` | `reason`，无数值 | 在运行之前无法给出价格。任何其他 `source` 值都按 `unknown` 处理。 |

`unknown` 预估的 `reason` 是以下之一：

* `not_quotable`：Router 无法在调用运行之前为其定价，因为它按提供商回传的、而请求体未给出界限的数量计费，或者请求体无法按其发送时的状态定价。任何无法识别的 `reason` 都按 `not_quotable` 处理。
* `unpriced_model`：费率卡片未为此请求定价。
* `byok`（仅排队提交）：该次运行使用你自己的提供商密钥，因此 Comfy 不收取任何费用。
* `pricing_unavailable`（仅排队提交）：请求被接收时无法读取费率卡片。提交仍会被接受，运行照常计费。

预估在以下情况下会采用保守失败策略：

* 当某个数值需要费率卡片，而该卡片未加载或已过期时，`/estimate` 会返回 `503`，而不是给出猜测。排队提交绝不会因为其预估而被拒绝；它改为携带 `source: unknown` 和 `reason: pricing_unavailable`。对于完全无法在运行前定价的调用（`not_quotable`），或使用你自己的提供商密钥的排队提交（`byok`），应答时不会读取费率卡片，因此该 `200` 并不说明卡片是否是最新的。
* `/estimate` 会像默认运行那样，依据模型自身的输入 schema 校验请求体，因此未通过模型 schema 的请求体会得到与该次运行相同的 `422`，以及相同的 `detail[]` 结构。此时不会进行任何定价或派发。
* 排队提交的幂等重放（`Idempotent-Replayed: true`）会省略 `estimate`，因为原始报价不会被存储。

预估的局限性。`200` 返回的数值并不承诺该次运行会被接受，也不承诺实际收费正好是这个数值：

* `/estimate` 不接受 `strict_mode` 或 `reject_unknown_fields`，因此它只检查模型的原生契约：在备用提供商自身的 schema 下、`strict_mode=true` 的运行会接受的请求体，在这里可能得到 `422`；而 `reject_unknown_fields=true` 的运行会拒绝的未声明顶层字段，在这里却会被定价。
* `pricing_as_of` 是费率卡片被获取的时间（若未读取任何卡片，则为预估被应答的时间）。它不是价格锁定：运行按其被计价时生效的费率收费。
* `/estimate` 报价的是 `model_provider` 指定的那一段，或原生提供商。它不接受 `fallback_provider` 或 `strict_mode` 参数。同步运行如果其 fallback 重试落到另一个提供商上，就按该提供商的费率收费，而预估并未对该费率报价；运行响应中的 `X-Comfy-Router-Fallback-Provider` 表明发生了这种情况。排队提交没有 fallback，因此其 `estimate` 报价的就是实际运行的那一段。
* 对于同一个请求体，在 `model_provider` 这一段上，或在会在同级操作上运行的请求体上，`/estimate` 与排队提交的 `estimate` 可能对略微不同的文档定价。提交的 `estimate` 是按运行实际发送的文档定价的。
* `/estimate` 始终报价平台费用。使用你自己的提供商密钥的运行不会被 Comfy 计费，但 `/estimate` 不会检测到这一点，仍会返回一个数值；只有排队提交会返回 `reason: byok`。
* 美元金额由未取整的分数金额换算而来，最多保留 8 位小数，可计费的不足一美分的 `amount` 绝不会显示为 `0`。`credits` 为 `round(amount × 211, 2)`，与 `X-Comfy-Credits-Used` 对收费所用的换算相同，因此对于极小的非零价格，`credits` 可能取整为 `0`；在这一点重要时，请以 `amount` 或 `amount_cents` 而非 `credits` 来做预算。该响应头仍是运行事后的数值；余额位于 Comfy 平台上。

## 结果资产

模型可以返回资产 URL、内联字节，或两者兼有。下面的提供商会将已选择的资产复制到 Comfy 存储上并替换其 URL。此行为取决于模型；没有任何请求头能选择它。

| 模型 | 复制到 Comfy 存储的内容 | Comfy 托管 URL 的最长有效期 |
| - | - | - |
| `bfl/*` | 已完成资产，以及结果中携带的草稿缓存资产（如有） | 24 小时 |
| `byteplus/*` 视频模型（`seedance`、`dreamina-seedance`） | 已完成视频，以及结果中携带的末帧图像（如有） | 24 小时 |
| `minimax/*` | 已完成视频 | 12 小时 |
| `xai/*` | 每一张已生成的图像，以及已完成视频 | 24 小时 |

这些有效期从 URL 签名时开始计算，而不是从你打开它时开始。缓存或重放的 URL 可能剩余时间更少；重放不会为其续期。请及时下载资产。只有每一行中列出的资产会被复制：`byteplus/seedream-*` 和 `byteplus/seededit-*` 图像不在 BytePlus 视频行的覆盖范围内。

复制只由模型的原生提供商执行。由替代提供商提供服务的运行（`model_provider` 指定了某个替代提供商，或原生运行的回退重试落到了替代提供商上，并通过 `X-Comfy-Router-Fallback-Provider` 披露）会返回该提供商自己的 URL，这些 URL 遵循提供商的过期时间，不会被复制。`model_provider` 取值 `default`、`comfy` 和 `comfyui` 时不指定替代提供商，因此这些运行属于原生运行并按上述方式复制；`model_provider` 运行的回退重试落回原生提供商时也同样如此。

**Veo（`veo/*`）有单独的存储路径。** 在 `response.videos[]` 中，读取其中存在的成员：`bytesBase64Encoded` 内联包含视频片段，而当环境配置为提供商直接写入 Comfy 存储时，`gcsUri` 包含一个 Comfy 签名的 HTTPS 链接。该链接自响应起 24 小时内有效。后一种情况是直接写入资产而非复制，因此 Veo 不在重新托管表中。

其他模型返回提供商资产引用或内联字节。提供商 URL 遵循提供商的过期时间，这可能比上述有效期短得多，且 Router 契约未对此作出规定。

复制是按资产尽力而为的。如果某个复制失败，该条目会保留其提供商引用；响应可以同时包含 Comfy 和提供商 URL，且没有明确的按资产复制状态字段。生成仍会成功并计费。不要根据一个成功重新托管的资产来推断每个 URL 的有效期。

结果是否由 Comfy 托管也决定了已完成的调用以后是否仍能从其 `Idempotency-Key` 记录中重放；上面的 `Idempotency-Key` 参数说明了无法重放时重试会得到怎样的回应。

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

## 各模型的输入和输出架构

每个模型的字段可通过 `GET /v2/models/{provider}/{model}/openapi.json` 读取。该调用需要 API 密钥。对于每个具有已编写架构的模型，同一文档也在本站点上公开发布，无需密钥，地址为 `/router-schemas/{provider}/{model}.json`。该副本是上次文档更新时生成的快照，因此当两者不一致时，以端点为准。该操作的 `requestBody` 描述输入验证；在已编写的情况下，其 `200` 响应描述输出形状和媒体类型。当 `x-comfy-input-schema-authored` 为 false 时，Router 接受任意 JSON 对象，而不进行特定于模型的预验证。提供商依赖项仍然适用。输出架构描述的是结果；Router 不会依据它们验证提供商返回的载荷。未编写的输出可能使用 `*/*` 而非 `application/json`；在解码之前，请检查响应的内容类型。

## Schemas

### RouterChargesOnPolicyRejection

内容政策拒绝是否会对该模型计费。请将未知值视为可能计费。

类型：`string`

### RouterCostEstimate

Comfy 将为此调用收取的费用，在派发之前依据该费用实际计费所用的同一费率卡片定价，以美元计。`source` 说明该数字的可信程度：`exact` 会带有 `amount`；`estimated` 带有 `min_amount` 和 `max_amount`，不带 `amount`；`unknown` 两者都没有，并带有一个 `reason`。绝不要把缺失的 `amount` 理解为免费。这不是价格锁定：请参见 `pricing_as_of`。

**字段**

<ResponseField name="source" type="string" required>
  `exact` | `estimated` | `unknown`；其他任何值都按 `unknown` 理解。
</ResponseField>

<ResponseField name="currency" type="string" required>
  始终为 `USD`。
</ResponseField>

<ResponseField name="amount" type="string">
  以十进制字符串表示的美元金额，例如 "0.04"，最多 8 位小数，且不使用指数形式。可计费的低于 1 美分的价格绝不会被渲染为 "0"。仅在 `source` 为 `exact` 时出现。
</ResponseField>

<ResponseField name="min_amount" type="string">
  以十进制字符串表示的美元下限金额。仅在 `source` 为 `estimated` 时出现。
</ResponseField>

<ResponseField name="max_amount" type="string">
  以十进制字符串表示的美元上限金额。仅在 `source` 为 `estimated` 时出现。
</ResponseField>

<ResponseField name="amount_cents" type="number">
  以美分表示的同一数值，不做四舍五入，用于算术运算。与 `amount` 一同出现。

  double
</ResponseField>

<ResponseField name="min_amount_cents" type="number">
  以美分表示的 `min_amount`，不做四舍五入。与 `min_amount` 一同出现。

  double
</ResponseField>

<ResponseField name="max_amount_cents" type="number">
  以美分表示的 `max_amount`。与 `max_amount` 一同出现。

  double
</ResponseField>

<ResponseField name="credits" type="number">
  使用平台换算率（\$1 = 211 积分）换算得到的 `amount` 积分数，四舍五入到 2 位小数，即 `X-Comfy-Credits-Used` 对 `exact` 报价将携带的数值。

  double
</ResponseField>

<ResponseField name="provider" type="string" required>
  该报价所对应的提供商线路。在排队提交中，它就是将要运行的那条线路。
</ResponseField>

<ResponseField name="model" type="RouterModelId" required>
  规范的 Comfy Router 模型 ID，即 `{provider}/{model}`，正是 `POST /v2/models/{provider}/{model}` 上用于寻址该模型的值，因此调用方可以直接将其插入该路径，而无需从其他任何地方重新推导。其 `pattern` 为用单个 `/` 连接的 `RouterProviderSegment` 和 `RouterModelSegment`，`maxLength` 为二者之和加上该分隔符。

  类型：[`RouterModelId`](#routermodelid)：模型 ID，例如 `anthropic/claude-opus-4-6`，最多 193 个字符
</ResponseField>

<ResponseField name="pricing_as_of" type="string" required>
  该报价定价所依据的费率卡片的获取时间。运行时按评级时生效的费率计费，而非此时间点的费率。只要未读取任何费率卡片（`reason: pricing_unavailable`、`byok`，或无法从任何卡片定价的 `not_quotable` 调用），这里就是该报价被应答的时间。

  date-time
</ResponseField>

<ResponseField name="reason" type="string">
  仅在 `source` 为 `unknown` 时出现：`not_quotable`（Router 无法在调用运行之前为其定价：其价格取决于提供商回报的内容，或者请求体未限定计费数量）、`unpriced_model`（费率卡片未对该请求定价）、`byok`（仅排队提交：运行时使用你自己的提供商密钥，因此 Comfy 不为此收取任何费用），或 `pricing_unavailable`（仅排队提交：请求被接受时无法读取费率卡片；这是暂时性的，运行仍会照常计费）。其他任何值都按 `not_quotable` 理解。
</ResponseField>

### RouterErrorResponse

用于认证、访问、模型查找、配额以及提供商传输失败的错误响应体。

**字段**

<ResponseField name="detail" type="string" required>
  人类可读的失败描述，可安全地展示给最终用户。该字段不用于机器解析，请改为根据 `error_type` 进行分支判断。对于已退役模型的 `model_not_found`，当已记录后继模型且调用方可见时，`detail` 会显示 `<id> was retired on <YYYY-MM-DD>; use <successor>`；若没有记录后继模型，则只显示 `<id> was retired on <YYYY-MM-DD>`，而不是通常的建议列表。此处指明的后继模型始终是一个有效的目录 ID，调用可以重新指向它。停用日期仍在未来的模型并未退役：它仍会被 `GET /v2/models` 列出，并在该日期之前一直可运行。与 `detail` 的其他部分一样，这段退役措辞仅用于展示，不附带任何兼容性保证。“不用于机器解析”这一规则有两个已记录的例外：在 `POST /v2/models/{provider}/{model}` 上，`409` 会针对三种互不相关但同属 `invalid_input` 分类的情况返回，只有 `detail` 能区分它们：以 "this request's `image` selects the edit operation" 开头的 `detail` 表示 multipart 的 `model_provider` 拒绝，以 `this request resolved a BYOK credential` 开头的 `detail` 表示 BYOK 的 `model_provider` 拒绝；这两者都不会因为换用新的 `Idempotency-Key` 而消除。该路由上任何其他 `invalid_input` `409` 都是密钥冲突。这两个前缀都是稳定的契约条款，可以被匹配。在其他任何地方，根据 `detail` 进行分支判断都不附带兼容性保证。
</ResponseField>

<ResponseField name="error_type" type="RouterErrorType" required>
  对 Router 失败的粗粒度、机器可读的分类，同时镜像到 `X-Comfy-Error-Type` 响应头，以便调用方无需解析响应体即可分支判断。该集合固定为十九个值：六个请求级分类 `invalid_input`、`content_policy_violation`、`provider_error`、`provider_timeout`、`insufficient_credits` 和 `model_not_found`，以及传输级的 `unauthorized`、`forbidden`、`concurrency_limit_exceeded`、`client_disconnected`、`internal_error`、`deadline_exceeded`、`not_enabled`、`service_unavailable`、`rate_limited`、`cancelled`、`queue_timeout`、`request_not_found` 和 `queue_backlog_full`。“封闭”描述的是当前文档所记录的集合，并不是一个永远成立的界限：该集合预计还会增长，因此这里刻意使用普通字符串而不是 `enum`，客户端必须将无法识别的值视为 `internal_error`，而不是对上面的列表做穷举 switch，并在下次新增取值时出错。

  Type: [`RouterErrorType`](#routererrortype)
</ResponseField>

<ResponseField name="upstream_detail" type="string">
  模型提供商给出的、有长度上限且经过净化的拒绝原因，仅当 `error_type` 为 `invalid_input` 且 `X-Comfy-Upstream-Status` 是提供商返回的 `4xx` 或 `2xx` 时才存在，也就是说提供商认为请求格式有误而拒绝，并说明了原因。该状态通常是 `4xx`；对于在成功信封内报告生成被拒绝的提供商，它会是 `2xx`（BytePlus 的失败任务轮询返回 HTTP `200`，原因位于响应体中）。在其他所有失败情形下都不存在，包括提供商 `5xx`、传输失败、内容策略拒绝以及 Router 针对自身提出的任何拒绝。它与 `X-Comfy-Upstream-Detail` 响应头对应。
</ResponseField>

<ResponseField name="refusal_subject" type="string">
  内容策略拒绝针对的是哪个输入或输出，采用 Router 层面的封闭词表：`input`、`output`、`input_text`、`input_image`、`input_video`、`input_audio`、`output_text`、`output_image`、`output_video`、`output_audio`。当提供商未指明具体模态时，仅用 `input` / `output` 这两个值来指明是哪一侧。仅当 `error_type` 为 `content_policy_violation` 且提供商以机器可读代码指明了被拒绝的对象时才存在；否则不存在。绝不会是提供商原文。目前已对 BytePlus、Runway、BFL、Gemini、Veo、Vertex、xAI 和 Wan（万相）的拒绝进行命名；如果提供商的拒绝未说明针对哪一侧，该字段就会缺失。它与 `X-Comfy-Refusal-Subject` 响应头对应。
</ResponseField>

### RouterErrorType

机器可读的 Router 错误类别，同时也会在 `X-Comfy-Error-Type` 标头中发送。

类型: `string`

### RouterModelBilling

调用模型之前需要检查的计费行为。它不包含价格或用量信息。

**字段**

<ResponseField name="charges_on_policy_rejection" type="RouterChargesOnPolicyRejection" required>
  模型因内容政策原因拒绝的调用，是否仍会向调用方收费。各提供商的做法不同，而这种差异在调用时无法察觉，因此用户即使同时看到同一次调用的错误和扣费，也无从事先得知。所以这里按模型在调用之前明确说明，而不是留作各提供商之间的传闻。

  类型：[`RouterChargesOnPolicyRejection`](#routerchargesonpolicyrejection)
</ResponseField>

### RouterModelDetail

单个 Comfy Router 模型的逐模型详细信息：目录列表为该模型报告的全部内容，外加只有单模型路由才会携带的逐模型字段。

组合了 [`RouterModelListEntry`](#routermodellistentry)、[`RouterModelDetailFields`](#routermodeldetailfields)。

Type: `object`

### RouterModelDetailFields

模型详情端点返回的可选字段。

**字段**

<ResponseField name="input_schema_url" type="string">
  该模型的 OpenAPI 文档 URL，包含其输入和输出 Schema。

  HTTPS URL，例如 `https://api.comfy.org/v2/models/bfl/flux-2-pro/openapi.json`，最多 2048 个字符
</ResponseField>

### RouterModelId

用于 `POST /v2/models/{provider}/{model}` 的模型 ID。

类型：`string`。模型 ID，例如 `anthropic/claude-opus-4-6`，最多 193 个字符。

### RouterModelInput

模型输入对象。请阅读所选模型的 OpenAPI 文档，了解其中的字段与验证规则。

类型：`object`

### RouterModelInputSchemaDocument

单个模型的输入和输出的独立 OpenAPI 文档。

类型：`object`

### RouterModelListEntry

模型的 ID 与计费信息。

**字段**

<ResponseField name="id" type="RouterModelId" required>
  规范化的 Comfy Router 模型 ID，格式为 `{provider}/{model}`：正是在 `POST /v2/models/{provider}/{model}` 上定位该模型所用的值，因此调用方可以直接把它插值进该路径，无需再从其他任何地方推导。它的 `pattern` 是 `RouterProviderSegment` 与 `RouterModelSegment` 以单个 `/` 连接而成，`maxLength` 则是两者长度之和再加上该分隔符。

  类型：[`RouterModelId`](#routermodelid)，模型 ID，例如 `anthropic/claude-opus-4-6`，最多 193 个字符
</ResponseField>

<ResponseField name="provider" type="RouterProviderSegment" required>
  规范化 `{provider}/{model}` 模型 ID 中的小写 `provider` 段，即所寻址模型所属的合作伙伴。调用路由的 `provider` 路径参数与目录条目的 `provider` 字段都引用这同一个 schema，正是这一点让列出的 ID 与可接受的 ID 不会彼此偏离。

  类型：[`RouterProviderSegment`](#routerprovidersegment)，字母数字 slug，例如 `anthropic`，最多 64 个字符
</ResponseField>

<ResponseField name="model" type="RouterModelSegment" required>
  规范化 `{provider}/{model}` 模型 ID 中的小写 `model` 段，即在该提供商下要运行的模型。调用路由的 `model` 路径参数与目录条目的 `model` 字段共用这一 schema，原因与 `RouterProviderSegment` 一样，同样是为了避免偏离。

  类型：[`RouterModelSegment`](#routermodelsegment)，字母数字 slug，例如 `claude-opus-4-6`，最多 128 个字符
</ResponseField>

<ResponseField name="billing" type="RouterModelBilling" required>
  调用方在调用之前需要了解的单模型计费信息，而不是价格。用量和费用数字绝不会出现在这里。

  类型：[`RouterModelBilling`](#routermodelbilling)
</ResponseField>

### RouterModelListResponse

Router 模型目录的一页。

**字段**

<ResponseField name="data" type="array of RouterModelListEntry" required>
  本页包含的模型，最多 `limit` 个。

  类型：由 [`RouterModelListEntry`](#routermodellistentry) 组成的数组
</ResponseField>

<ResponseField name="has_more" type="boolean" required>
  本页之后是否还有另一页。只要此值为 true 就继续向后翻页；不要因为 `data` 很短或为空就断定目录已到末尾。
</ResponseField>

<ResponseField name="next_cursor" type="RouterPageCursor">
  指向 Router 列表的一个不透明游标。它由服务器生成，且仅用于原样往返传递：它不是偏移量，不是模型 ID，没有顺序，也不能在目录重建后保持稳定，因此解析它、对它做自增，或在产生它的那次遍历之外持久化它，都不属于契约范围。之所以使用游标而非偏移量，是因为目录是一个不断变化的列表：当遍历过程中有条目被增删时，基于偏移量的遍历会静默地跳过或重复条目，而调用方无法察觉这种情况已经发生。

  类型：[`RouterPageCursor`](#routerpagecursor) -- 作为 `next_cursor` 返回的不透明游标，1–512 个字符
</ResponseField>

<ResponseField name="limit" type="integer" required>
  实际提供的分页大小。请求的 `limit` 超过上限时会被截断到上限，而不是被拒绝，因此该值可能小于你所请求的值。请用这个数字进行分页，而不是你发送的那个数字，否则你会以为收到了从未收到的行。

  1–100
</ResponseField>

### RouterModelOutput

模型结果对象。请阅读已选择模型的输出 Schema，以了解其确切的形状。

类型：`object`

### RouterModelSegment

`{provider}/{model}` 模型 ID 中的模型部分。

类型：`string` -- 字母数字组成的 slug，例如 `claude-opus-4-6`，最多 128 个字符

### RouterPageCursor

一个不透明的目录游标。请原样传回，作为 `cursor`。

类型：`string` —— 作为 `next_cursor` 返回的不透明游标，1–512 个字符

### RouterProviderSegment

`{provider}/{model}` 模型 ID 中表示提供商的部分。

类型：`string`。字母数字 slug，例如 `anthropic`，最多 64 个字符

### RouterQueueCancelResponse

针对本路由已处理的请求的两种状态（`202` 与 `400`）的取消询问回答。两种状态共用一种响应体形状，而不是一个成功信封加一个错误信封，因为两者陈述的是同一件事：取消操作发现了什么；而如果客户端不得不按状态码解析不同类型，这种拆分不会带来任何好处。

**字段**

<ResponseField name="request_id" type="RouterQueueRequestId" required>
  一个已排队 Router 请求的标识符，即调用方用来轮询、取消并收集结果的句柄。

  类型：[`RouterQueueRequestId`](#routerqueuerequestid) -- `pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`，uuid，最多 36 个字符
</ResponseField>

<ResponseField name="status" type="RouterQueueCancelStatus" required>
  取消询问所发现的内容，针对的是本路由实际已处理的两种结果。两者都与 HTTP 状态相呼应，因此客户端可以依据任一者进行分支。

  类型：[`RouterQueueCancelStatus`](#routerqueuecancelstatus)
</ResponseField>

### RouterQueueCancelStatus

取消请求所发现的结果，仅针对该路由实际已处理请求的两种结果进行说明。两者都由 HTTP 状态码映射呈现，因此客户端可以任选其一进行分支判断。

Type: `string`

### RouterQueuePosition

在响应生成的那一刻，此请求在队列中前面还有多少请求。零表示此请求位于队首。

类型：`integer` -- 至少为 0

### RouterQueueRequestId

排队中的一个 Router 请求的标识符：调用方通过该句柄进行轮询、取消并收集结果。

类型：`string` -- `pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`，uuid，最多 36 个字符

### RouterQueueStatus

已执行的 Router 请求的状态。它恰好有三个取值，并且与 `RouterErrorType` 不同，它是一个封闭的 `enum`，因为这两个 schema 是刻意朝相反方向封闭的。`RouterErrorType` 对失败进行分类，其集合预期会不断扩展，因此，如果一个已生成的客户端硬性拒绝某个无法识别的分类，那么它恰恰会在已经出问题的时候失败得最严重。而这一类型描述的是生命周期，而日后新增第四个状态的生命周期，无论它是否被声明为 enum，对每一个针对它编写的轮询循环而言都是破坏性变更，因此它被声明为 enum，并且这一约束被写在客户端能够看到的地方。

类型：`string`

### RouterQueueStatusFields

`RouterQueueStatusResponse` 中并非 URL 块的那一半：一个队列中请求的身份、它当前的状态，以及在该状态为终端状态且运行未成功时，说明原因所属的粗粒度分类桶。

**字段**

<ResponseField name="request_id" type="RouterQueueRequestId" required>
  一个队列中的 Router 请求的标识符：调用方用于轮询、取消并收集结果的句柄。

  类型：[`RouterQueueRequestId`](#routerqueuerequestid) -- `pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`，uuid，最多 36 个字符
</ResponseField>

<ResponseField name="status" type="RouterQueueStatus" required>
  队列中 Router 请求的状态。它恰好有三个值，并且与 `RouterErrorType` 不同，这是一个封闭的 `enum`，因为这两个 schema 是故意朝相反方向封闭的。`RouterErrorType` 对失败进行分类，其集合预期会增长，因此，一个硬性拒绝无法识别分类桶的已生成客户端，恰恰会在已经出错的时候失败得最严重。而这一个描述的是生命周期，而一个日后新增第四种状态的生命周期，无论是否声明为 enum，对每一个针对它编写的轮询循环来说都是破坏性变更。因此它被声明为 enum，并把这一约束写在客户端能看到的地方。

  类型：[`RouterQueueStatus`](#routerqueuestatus)
</ResponseField>

<ResponseField name="queue_position" type="RouterQueuePosition">
  在响应生成的那一刻，队列中有多少个请求排在这一个之前。零表示该请求位于队首。

  类型：[`RouterQueuePosition`](#routerqueueposition) -- 至少 0
</ResponseField>

<ResponseField name="error_type" type="RouterErrorType">
  仅出现在未成功的 `COMPLETED` 请求上，携带的正是结果读取在返回该失败时赋给 `X-Comfy-Error-Type` 的那个粗粒度分类桶。它把一个成功的终端请求与一个失败或被取消的终端请求区分开来（后两者都没有单独的终端状态），并且它在成功时是缺失的而不是 null，因此请依据它的存在与否来分支。

  类型：[`RouterErrorType`](#routererrortype)
</ResponseField>

### RouterQueueStatusResponse

一个已执行请求的当前状态，并与提交时返回的相同三个 URL 组合在一起。

组合了 [`RouterQueueUrls`](#routerqueueurls)、[`RouterQueueStatusFields`](#routerqueuestatusfields)。

类型：`object`

### RouterQueueSubmitFields

`RouterQueueSubmitResponse` 中除 URL 区块之外的另一半：新请求的身份，以及它被接纳那一刻的状态。

**字段**

<ResponseField name="request_id" type="RouterQueueRequestId" required>
  一个排队中的 Router 请求的标识符，即调用方用来轮询、取消并获取结果的句柄。

  Type: [`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
</ResponseField>

<ResponseField name="status" type="RouterQueueStatus" required>
  排队中的 Router 请求的状态。它恰好有三个取值，而且与 `RouterErrorType` 不同，这是一个封闭的 `enum`，因为这两个 schema 被有意设计成朝相反方向封闭。`RouterErrorType` 对失败进行分类，其取值集合预期会增长，因此一个会硬性拒绝无法识别分类的已生成客户端，恰恰会在已经出错的时候失败得最惨。而这一个是一个生命周期，日后新增第四种状态对每一个针对它编写的轮询循环来说都是破坏性变更，无论它是否被声明为 enum，所以这里就把它声明为 enum，并把该约束写在客户端能看到的地方。

  Type: [`RouterQueueStatus`](#routerqueuestatus)
</ResponseField>

<ResponseField name="queue_position" type="RouterQueuePosition">
  在响应生成的那一刻，队列中有多少个请求排在本请求之前。零表示本请求位于队首。

  Type: [`RouterQueuePosition`](#routerqueueposition) -- At least 0
</ResponseField>

<ResponseField name="estimate" type="RouterCostEstimate">
  本次请求的预检成本估算，在调用方启用了成本估算时，会出现在新的准入响应中。它给出的是本次请求被固定到的那条提供商链路（队列没有回退循环，因此 `fallback_provider` 永远不会改变实际运行的链路）。当无法给出任何数字时，该字段仍然存在，并带有 `source: unknown`；提交永远不会因为成本估算而失败。在幂等重放时会省略（`Idempotent-Replayed: true`），因为原始报价不会被存储。它不是价格锁定：运行时按计费当时生效的费率收费。

  Type: [`RouterCostEstimate`](#routercostestimate)
</ResponseField>

### RouterQueueSubmitResponse

运行被接纳进入队列时返回的句柄：请求的身份与状态，并与用于处理其生命周期其余部分的三个 URL 组合在一起。

组合了 [`RouterQueueUrls`](#routerqueueurls)、[`RouterQueueSubmitFields`](#routerqueuesubmitfields)。

类型：`object`

### RouterQueueUrls

这三条 URL 指向一个已入队请求剩余的生命周期，凡是携带有效句柄的响应都会返回它们，因此客户端无需自行拼接队列 URL。

**字段**

<ResponseField name="status_url" type="string" required>
  获取此请求状态的绝对 URL。

  URI
</ResponseField>

<ResponseField name="response_url" type="string" required>
  收集此请求结果的绝对 URL。

  URI
</ResponseField>

<ResponseField name="cancel_url" type="string" required>
  请求取消时使用的绝对 URL。

  URI
</ResponseField>

### RouterValidationErrorContext

由提供商提供的、关于验证失败的规则的详情。

类型：`object`

### RouterValidationErrorDetail

一个字段级验证失败。

**字段**

<ResponseField name="loc" type="array of any" required>
  指向出错字段的路径，最外层片段在前，例如 `["body", "image_url"]`，或 `["body", "images", 0]`，其中整数表示数组的索引。
</ResponseField>

<ResponseField name="msg" type="string" required>
  对这一次失败的人类可读描述。
</ResponseField>

<ResponseField name="type" type="string" required>
  该失败的具体、机器可读的原因，由提供商原样传递。这是类型化 SDK 异常层次结构用于分支判断的值；响应头中的 `error_type` 只是它的粗略分类。
</ResponseField>

<ResponseField name="ctx" type="RouterValidationErrorContext">
  单个 `RouterValidationErrorDetail` 被违反的界限，从提供商原样携带，例如 `{"limit_value": 8}` 与 `greater_than` 一起，`{"min_width": 512}` 与 `image_too_small` 一起，或 `{"max_size_bytes": 10485760}` 与 `file_too_large` 一起。键集合特定于提供商和错误类型，因此这刻意是一个开放对象：把它收窄为固定字段列表，或把它合并到 `msg` 字符串中，正是移植后的集成能够编译、却静默丢失读取该界限的分支的原因。当错误类型不携带界限时不存在。

  类型：[`RouterValidationErrorContext`](#routervalidationerrorcontext)
</ResponseField>

<ResponseField name="input" type="RouterValidationErrorInput">
  出错的输入值，原样回显，以便调用方无需从 `loc` 重新推导就能看到被拒绝的内容。任意 JSON 类型（字符串、数字、布尔、数组、对象或 null），因此该 schema 被有意保持为无类型，而不是收窄为对象。当提供商不回显输入时不存在。

  类型：[`RouterValidationErrorInput`](#routervalidationerrorinput)
</ResponseField>

### RouterValidationErrorInput

被拒绝的输入值，当提供商包含该值时。

### RouterValidationErrorResponse

`422` 验证错误的响应体。读取 `X-Comfy-Error-Type` 以获取其类别。

**字段**

<ResponseField name="detail" type="array of RouterValidationErrorDetail" required>
  请求中发现的每一个验证失败项，每个出错的字段对应一个条目。

  类型：[`RouterValidationErrorDetail`](#routervalidationerrordetail) 数组
</ResponseField>


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