> ## 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">
  不透明分页游标。

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

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

  最多 100，默认值：20
</ParamField>

**响应**

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

  正文：[`RouterModelListResponse`](#routermodellistresponse) -- 响应头：`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="503" type="RouterErrorResponse">
  Router 暂时不可用。请使用退避策略重试。

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

### `GET /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>

**响应**

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

  响应体：[`RouterModelDetail`](#routermodeldetail)，响应头：`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>

### `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 操作（一次编辑）的请求，备用提供商会以 `detail` 开头为 "this request's `image` selects the edit operation" 的 `409` 被拒绝，但仅当该提供商针对此模型的翻译器无法服务该操作时才会如此，翻译器确实携带该媒体的支路则正常继续；接着，对于解析出自带密钥（bring-your-own-key）凭据的请求，任何备用提供商都会以 `detail` 开头为 `this request resolved a BYOK credential` 的 `409` 被拒绝（见该响应），无论该提供商是否服务此模型；接着是指定提供商自身的闸门，当该提供商未为你开启时它会以 `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 视频模型，首帧图像选择图生视频，参考图像或视频片段选择参考生视频。每个带条件的操作都按其自身的费率计费，而不是基础的文生图或文生视频费率。

**响应**

<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（BYOK）凭据时，也会被拒绝，其 `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>

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

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

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

**参数**

<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="If-None-Match" type="string">
  调用方从先前的 `200` 响应中保存的 `ETag`。
</ParamField>

**响应**

<ResponseField name="200" type="RouterModelInputSchemaDocument">
  成功 - 模型的输入和输出 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>
  规范模型 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 query="model_provider" type="string">
  选择服务此模型的替代提供商，而非其当前默认提供商。
</ParamField>

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

  默认值：False
</ParamField>

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

  1–255 个字符
</ParamField>

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

  默认值：False
</ParamField>

**请求体**

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

合作伙伴模型的原生 JSON 输入，与此模型在同步路由上接受的请求体完全相同，并且它以同样的方式选择操作与计费：对于支持多种操作的模型，由请求体自身的字段决定 Router 运行哪一种操作（输入图像会将可编辑图像模型切换为图生图；Seedance 首帧图像会选择图生视频，参考图像或视频片段会选择参考生视频），每个带条件的操作按其自身的费率计费，而不是基础的文生图或文生视频费率。相同的提供商选择约定在分发时同样适用：不使用 `model_provider`，或使用 `model_provider` 且 `strict_mode=false`（默认值）时，请求体就是该模型的原生文档，会在运行被接纳之前依据模型自身的输入 schema 进行验证，因此模型会拒绝的请求体在这里就是 `422`，而不是几分钟后才失败的排队请求；此外，在分发时，非严格的替代提供商请求体会被转换为该提供商的真实 schema。使用 `strict_mode=true` 时，请求体必须已经是替代提供商自己的 schema，并会被原样转发：跳过原生 schema 验证，与同步路由完全一致（参见 `model_provider` 和 `strict_mode`）。

**响应**

<ResponseField name="201" type="RouterQueueSubmitResponse">
  已创建：该次运行已被接纳入队列。

  请求体：[`RouterQueueSubmitResponse`](#routerqueuesubmitresponse)；响应头：`X-Comfy-Request-Id`、`Idempotent-Replayed`
</ResponseField>

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

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

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

  请求体：[`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="402" type="RouterErrorResponse">
  Router 请求级失败：请求从未到达模型，或因模型自身未反馈的原因而失败。

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

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

  请求体：[`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` 并复用同一个键；`invalid_input` 则需要换用新的键。此路由上的两种 `invalid_input` 冲突与键完全无关，换用新键也无法消除其中任何一种：其一，当 `model_provider` 指定了备用提供商，而请求体选择的 multipart 操作（即编辑）是该提供商针对此模型的转换器无法处理的时，请求会被拒绝，其 `detail` 以 "this request's `image` selects the edit operation" 开头；其二，在此之后检查，若请求已经为路径中的提供商解析出 BYOK 凭据，其 `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="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">
  OK：为产出了结果的请求所存储的结果（即成功完成的请求，或同时带有已记录计费和已存储结果的终端请求），按合作伙伴自身的媒体类型原样返回，与同步路由的 `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) -- 字母数字短标识，例如 `anthropic`，最多 64 个字符
</ParamField>

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

  类型：[`RouterModelSegment`](#routermodelsegment) -- 字母数字短标识，例如 `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) -- 字母数字短标识，例如 `anthropic`，最多 64 个字符
</ParamField>

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

  类型：[`RouterModelSegment`](#routermodelsegment) -- 字母数字短标识，例如 `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>

## 结果资产

模型可以返回资产 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`

### RouterErrorResponse

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

**字段**

<ResponseField name="detail" type="string" required>
  对失败的可读描述，可安全地展示给最终用户。不会被机器解析，请改为根据 `error_type` 进行分支判断。有两处已记录的例外：在 `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`，而不是对上面的列表做穷举分支，从而在下一次新增时出错。

  类型：[`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)。

类型：`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` 字段共享它，原因与 `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 状态码中，因此客户端可以依据其中任意一个进行分支判断。

类型：`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 请求的标识符：调用方据此轮询、取消并获取结果的句柄。

  类型：[`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>

### RouterQueueSubmitResponse

一次运行被准入队列时返回的句柄：包含该请求的身份与状态，并与指向其生命周期其余部分的三个 URL 组合在一起。

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

类型：`object`

### RouterQueueUrls

三个 URL，用于寻址某个已排队请求生命周期的其余阶段。每个携带活动句柄的响应都会返回这三个 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.