--- title: "Comfy Router API 参考" description: "每个 Comfy Router 端点、参数、响应体和错误分类,均由 Comfy API 契约生成。" sidebarTitle: "API 参考" translationSourceHash: 7bdc66a2 translationFrom: development/comfy-router/reference.mdx translationBlockHashes: "_intro": 3f6e5d23 "Endpoints": 222fd740 "Error buckets": 02a09cb4 "Response headers": 403c8bf5 "Pre-flight cost estimates": 862a49f8 "Result assets": 65fc939b "Per-model input and output schemas": 61c6bde8 "Schemas": 0c65163b --- {/* 生成的文件:请勿手动编辑。 由 gen_router_reference.py 从 Comfy API 契约生成。请编辑契约并重新生成; 在此处所做的编辑会在下次运行时被覆盖,并在此期间被漂移门禁(drift gate)拒绝。 */}
Comfy Router 的规范路由,以模型 ID 寻址。 基础 URL:`https://api.comfy.org` 以下每个端点都需要身份验证。请发送 `X-API-Key: ` 或 `Authorization: Bearer `。 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`。 **参数** 不透明分页游标。 类型:[`RouterPageCursor`](#routerpagecursor)。作为 `next_cursor` 返回的不透明游标,长度为 1–512 个字符 每页返回的模型数量。 最多 100,默认值:20 调用方从先前的 `200` 响应中持有的 `ETag`。 **响应** 成功:模型目录中的一页。 响应体:[`RouterModelListResponse`](#routermodellistresponse);响应头:`X-Comfy-Request-Id`、`ETag`、`Cache-Control` 未修改:页面未发生变化,仍与调用方在 `If-None-Match` 中发送的 `ETag` 所对应的版本一致。 响应头:`X-Comfy-Request-Id`、`ETag`、`Cache-Control` 请求无效。请检查错误类型和请求体。 响应体:[`RouterErrorResponse`](#routererrorresponse);响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` 凭证缺失或无效。 响应体:[`RouterErrorResponse`](#routererrorresponse);响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` 该调用方或模型不允许此请求。 响应体:[`RouterErrorResponse`](#routererrorresponse);响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` Router 暂时不可用。请采用退避策略重试。 响应体:[`RouterErrorResponse`](#routererrorresponse);响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` ### `GET /v2/models/{provider}/{model}` **按规范模型 ID 读取单个合作伙伴模型的目录条目。** 无需列出完整目录即可读取单个模型的详情。 **参数** 规范模型 ID `{provider}/{model}` 中的提供商部分。 类型:[`RouterProviderSegment`](#routerprovidersegment)。字母数字 slug,例如 `anthropic`,最多 64 个字符 规范模型 ID `{provider}/{model}` 中的模型部分。 类型:[`RouterModelSegment`](#routermodelsegment)。字母数字 slug,例如 `claude-opus-4-6`,最多 128 个字符 调用方从先前的 `200` 响应中持有的 `ETag`。 **响应** OK:该模型的目录条目。 响应体:[`RouterModelDetail`](#routermodeldetail)。响应头:`X-Comfy-Request-Id`、`ETag`、`Cache-Control` 未修改:自调用方在 `If-None-Match` 中发送 `ETag` 以来,该条目没有变化。 响应头:`X-Comfy-Request-Id`、`ETag`、`Cache-Control` 凭证缺失或无效。 响应体:[`RouterErrorResponse`](#routererrorresponse)。响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` 该调用方或模型不允许发起此请求。 响应体:[`RouterErrorResponse`](#routererrorresponse)。响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` 未找到该模型 ID。 响应体:[`RouterErrorResponse`](#routererrorresponse)。响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` Router 暂时不可用。请使用退避策略重试。 响应体:[`RouterErrorResponse`](#routererrorresponse)。响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` ### `POST /v2/models/{provider}/{model}` **按规范模型 ID 同步运行合作伙伴模型。** 运行模型,并在同一个响应中收到已完成的结果。 **参数** 规范 `{provider}/{model}` 模型 ID 中的提供商部分。 类型:[`RouterProviderSegment`](#routerprovidersegment) —— 字母数字 slug,例如 `anthropic`,最长 64 个字符 规范 `{provider}/{model}` 模型 ID 中的模型部分。 类型:[`RouterModelSegment`](#routermodelsegment) —— 字母数字 slug,例如 `claude-opus-4-6`,最长 128 个字符 由调用方生成的键,用于安全地重试同一次逻辑调用。 1 至 255 个字符 选择一个替代提供商来提供该模型,而不是使用其当前默认提供商;`fal`、`wavespeed`、`runware` 和 `higgsfield` 是可选替代项,`GET /v2/models/{provider}/{model}` 会报告某个模型支持其中的哪些。其拒绝按固定顺序检查,靠前的拒绝无论靠后的拒绝是否成立都会直接作答:无法识别的值(根本不是已注册的提供商)会以 `400` 拒绝;然后,在请求体选择 multipart 操作(编辑)的请求上,替代提供商会以 `409` 拒绝,`detail` 以 "this request's `image` selects the edit operation" 开头,但仅当该提供商针对此模型的转换器无法提供该操作时才会如此(若该线路的转换器确实支持该媒体,则正常继续);然后,在已解析出自带密钥(BYOK)凭据的请求上,任何替代提供商都会以 `409` 拒绝,`detail` 以 `this request resolved a BYOK credential` 开头(参见该响应),无论该提供商是否提供此模型;然后是所指定提供商自身的准入校验,当该提供商未对你开启时以 `403` 及 `error_type: not_enabled` 拒绝,当无法评估该准入校验时以 `503` 及 `error_type: service_unavailable` 拒绝;只有越过以上四项后,一个真实但不具备此模型线路的提供商才会以 `400` 及 `error_type: invalid_input` 拒绝,与无法识别的值的答复相同。在自带密钥请求、请求体选择 multipart 操作的请求以及 `strict_mode=true` 下,`fallback_provider` 是惰性的,而不会被拒绝。 仅在配合 `model_provider` 时才有意义。 默认值:False 控制当首次尝试因可归因于 Router 或所尝试提供商的原因失败时,Router 是否对该模型的其他已注册提供商重试此调用。省略,或设为 `false` 以外的任何值,都会保持回退开启;`false` 将其关闭。成功的回退响应会带有 `X-Comfy-Router-Fallback-Provider`。在已解析出自带密钥凭据的请求上,无论此参数如何设置,回退都不可用:尝试根本不会发起,首次失败会原样返回给你,这属于惰性而非拒绝:不会由此产生 `409`。出于同样的原因,在请求体选择 multipart 操作的请求上以及 `strict_mode=true` 下也同样如此:这两种情况都会把调用绑定到某个无法在另一个提供商上忠实重放的提供商,因此回退只是被跳过,而不是被拒绝。只有显式指定 `model_provider` 才会以该 `409` 拒绝,而且与这种无条件的跳过不同,它的 multipart `409` 仅适用于转换器无法提供该操作的线路。 选择拒绝此模型输入 schema 未声明的顶层请求体字段,而不是接受它;嵌套字段不做检查,而对于 schema 允许未声明字段或没有已编写 schema 的模型,或者在以 `strict_mode=true` 发送的已执行提交上,都不会拒绝任何内容。 默认值:False **请求体** `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` 选择替代提供商时,每种带条件的操作可能会按该提供商自身的费率计费。 **响应** OK - 不带 `model_provider`,或带 `model_provider` 且 `strict_mode=false`(默认值;在可能时转换回该模型的原生契约,若转换失败则回退到备选提供商自身的原始响应,失败会被记录日志,绝不会静默处理)时,形状为该模型自身的原生输出;当 `strict_mode=true` 时,则原样返回备选提供商的响应。对于合作伙伴直接以字节形式应答生成的模型,响应体是这些字节,并采用合作伙伴自己的 `Content-Type` 而非 `application/json`;请根据响应的 `Content-Type` 分支处理,不要假定返回的是 JSON 文档。 Body: [`RouterModelOutput`](#routermodeloutput) 或原始字节(`*/*`) -- Headers: `X-Comfy-Request-Id`、`X-Content-Type-Options`、`X-Comfy-Router-Fallback-Provider`、`X-Comfy-Router-Provider`、`X-Comfy-Router-Dropped-Params`、`X-Comfy-Credits-Used`、`Idempotent-Replayed`、`X-Committed-Spend-Limit`、`X-Committed-Spend-Current`、`X-Committed-Spend-Remaining` 请求无效。请检查错误类型和请求体。 Body: [`RouterErrorResponse`](#routererrorresponse) -- Headers: `X-Comfy-Error-Type`、`X-Comfy-Request-Id`、`X-Comfy-Upstream-Status`、`X-Comfy-Upstream-Detail`、`X-Comfy-Refusal-Subject`、`X-Comfy-Credits-Used`、`Idempotent-Replayed` 凭证缺失或无效。 Body: [`RouterErrorResponse`](#routererrorresponse) -- Headers: `X-Comfy-Error-Type`、`X-Comfy-Request-Id` Router 请求层面的失败 - 请求从未到达模型,或因模型自身未反馈的原因而失败。 Body: [`RouterErrorResponse`](#routererrorresponse) -- Headers: `X-Comfy-Error-Type`、`X-Comfy-Request-Id` 该调用方或该模型不允许此请求。 Body: [`RouterErrorResponse`](#routererrorresponse) -- Headers: `X-Comfy-Error-Type`、`X-Comfy-Request-Id` 未找到该模型 ID。 Body: [`RouterErrorResponse`](#routererrorresponse) -- Headers: `X-Comfy-Error-Type`、`X-Comfy-Request-Id` 请检查 `X-Comfy-Error-Type`:`concurrency_limit_exceeded` 表示原始调用仍在运行,因此请等待 `Retry-After` 后复用同一个 key;`invalid_input` 则需要一个新的 key。此路由上的两种 `invalid_input` 冲突都完全与 key 无关,且任何新 key 都无法消除其中任何一种:当请求体选择的是某个多部分操作(编辑),而该提供商针对此模型的转换器无法处理时,指定备选提供商的 `model_provider` 会被拒绝,其 `detail` 以 "this request's `image` selects the edit operation" 开头;以及在此之后检查的,当请求已经为路径中的提供商解析出自备密钥(BYOK)凭证时会被拒绝,其 `detail` 以 `this request resolved a BYOK credential` 开头。请去掉 `model_provider`,或不带 BYOK 凭证发送请求,并且(对于多部分的情况)不带编辑操作。 Body: [`RouterErrorResponse`](#routererrorresponse) -- Headers: `X-Comfy-Error-Type`、`X-Comfy-Request-Id`、`Retry-After`(当 `concurrency_limit_exceeded` 时) 请求体过大。 Body: [`RouterErrorResponse`](#routererrorresponse) -- Headers: `X-Comfy-Error-Type`、`X-Comfy-Request-Id` 请求内容未通过模型 schema 的校验而被拒绝。 Body: [`RouterValidationErrorResponse`](#routervalidationerrorresponse) -- Headers: `X-Comfy-Error-Type`、`X-Comfy-Request-Id`、`Idempotent-Replayed` 请检查 `X-Comfy-Error-Type`:`concurrency_limit_exceeded` 表示应减少并发中的调用;`rate_limited` 表示应等待配额窗口。 Body: [`RouterErrorResponse`](#routererrorresponse) -- Headers: `X-Comfy-Error-Type`、`X-Comfy-Request-Id`、`X-Committed-Spend-Limit`、`X-Committed-Spend-Current`、`X-Committed-Spend-Remaining`、`X-Model-Concurrency-Limit`、`X-Model-Concurrency-Current`、`X-Model-Concurrency-Remaining` 提供商自身的响应无法被转换为结果(`provider_error`)。 Body: [`RouterErrorResponse`](#routererrorresponse) -- Headers: `X-Comfy-Error-Type`、`X-Comfy-Request-Id`、`X-Comfy-Upstream-Status` Router 暂时不可用。请退避重试。 Body: [`RouterErrorResponse`](#routererrorresponse) -- Headers: `X-Comfy-Error-Type`、`X-Comfy-Request-Id`、`Retry-After`(仅容量拒绝时) 请求超过了截止时间。重试之前请先检查错误类型。 Body: [`RouterErrorResponse`](#routererrorresponse) -- Headers: `X-Comfy-Error-Type`、`X-Comfy-Request-Id`、`X-Comfy-Upstream-Status`、`Retry-After` ### `POST /v2/models/{provider}/{model}/estimate` **在运行模型调用之前估算其价格,而无需实际运行。** 返回一份以美元计的预检估算,说明在此模型上运行该请求体会产生多少费用,其定价依据与实际运行计费所依据的同一份费率卡片。这是估算值,而非最终费用:你实际支付的是工作区用量与账单记录中的结算费用。请求体会先按模型的输入 schema 进行校验,与默认运行(不带 `strict_mode`、不带 `reject_unknown_fields`)的校验方式一致,因此不符合模型 schema 的请求体在这里与在运行时一样返回 `422`;不会向提供商派发任何请求,也不会产生任何费用。该结果并非价格锁定:它按 `pricing_as_of` 时点生效的费率计价,而实际运行按其计费定价时生效的费率收费。在该功能逐步推出期间,该路由会返回 `403`,并带有 `error_type: not_enabled`。 **参数** 规范的 `{provider}/{model}` 模型 ID 中的小写提供商标识段,即所运行模型所属的合作伙伴。 类型:[`RouterProviderSegment`](#routerprovidersegment):字母数字标识,例如 `anthropic`,最多 64 个字符 规范的 `{provider}/{model}` 模型 ID 中的小写模型标识段,即在该提供商下要运行的模型。 类型:[`RouterModelSegment`](#routermodelsegment):字母数字标识,例如 `claude-opus-4-6`,最多 128 个字符 选择用于提供此模型的替代提供商,而非其当前的默认提供商。 **请求体** `application/json`:[`RouterModelInput`](#routermodelinput)(必填) 合作伙伴模型的原生 JSON 输入,与此模型的同步路由所接受的请求体完全相同。它会按模型自身的输入 schema 进行校验,与默认运行的校验方式一致(此路由不接受 `strict_mode` 或 `reject_unknown_fields`),并由其自身字段(输出数量、输入图像所选的操作)决定计价内容。 **响应** 报价。 响应体:[`RouterCostEstimate`](#routercostestimate);响应头:`X-Comfy-Request-Id` 请求无效。请检查错误类型和请求体。 响应体:[`RouterErrorResponse`](#routererrorresponse);响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` 凭据缺失或无效。 响应体:[`RouterErrorResponse`](#routererrorresponse);响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` 此调用方或模型不允许该请求。 响应体:[`RouterErrorResponse`](#routererrorresponse);响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` 未找到该模型 ID。 响应体:[`RouterErrorResponse`](#routererrorresponse);响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` 请求体过大。 响应体:[`RouterErrorResponse`](#routererrorresponse);响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` 估算请求的请求体被模型 schema 拒绝,或其指定的模型与路径中的模型不一致。 响应体:[`RouterValidationErrorResponse`](#routervalidationerrorresponse);响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` Router 暂时不可用。请使用退避策略重试。 响应体:[`RouterErrorResponse`](#routererrorresponse);响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id`、`Retry-After`(仅在容量不足被拒时) ### `GET /v2/models/{provider}/{model}/openapi.json` **以 OpenAPI 文档的形式读取单个合作伙伴模型的输入和输出 Schema。** 以独立的 OpenAPI 文档形式读取单个模型的输入和输出 Schema。 **参数** 规范 `{provider}/{model}` 模型 ID 中的提供商部分。 类型:[`RouterProviderSegment`](#routerprovidersegment):字母数字 slug,例如 `anthropic`,最多 64 个字符 规范 `{provider}/{model}` 模型 ID 中的模型部分。 类型:[`RouterModelSegment`](#routermodelsegment):字母数字 slug,例如 `claude-opus-4-6`,最多 128 个字符 调用方从之前的 `200` 响应中持有的 `ETag`。 **响应** OK:该模型的输入和输出 Schema,作为独立的 OpenAPI 文档。 正文:[`RouterModelInputSchemaDocument`](#routermodelinputschemadocument);响应头:`X-Comfy-Request-Id`、`ETag`、`Cache-Control` 未修改:自调用方在 `If-None-Match` 中发送的 `ETag` 以来,文档未发生变化。 响应头:`X-Comfy-Request-Id`、`ETag`、`Cache-Control` 凭据缺失或无效。 正文:[`RouterErrorResponse`](#routererrorresponse);响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` 此调用方或模型不允许发起该请求。 正文:[`RouterErrorResponse`](#routererrorresponse);响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` 未找到该模型 ID。 正文:[`RouterErrorResponse`](#routererrorresponse);响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` Router 无法完成该请求。 正文:[`RouterErrorResponse`](#routererrorresponse);响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` Router 暂时不可用。请退避后重试。 正文:[`RouterErrorResponse`](#routererrorresponse);响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` ### `POST /v2/models/{provider}/{model}/requests` **将合作伙伴模型运行提交到队列并立即返回。** Comfy Router 的排队交付模式。请求体与 `POST /v2/models/{provider}/{model}` 为此模型接受的合作伙伴原生 JSON 输入相同:一个请求体形状、一个按模型定义的 schema、两种交付模式。但此路由不会为结果保持连接。它接纳运行,用句柄返回 `201`,调用方稍后通过下面三个读取操作收集结果。 **参数** 规范化 `{provider}/{model}` 模型 ID 中的小写提供商段,即正在运行其模型的合作伙伴。 类型:[`RouterProviderSegment`](#routerprovidersegment):字母数字 slug,例如 `anthropic`,最多 64 个字符 规范化 `{provider}/{model}` 模型 ID 中的小写模型段,即在该提供商内要运行的模型。 类型:[`RouterModelSegment`](#routermodelsegment):字母数字 slug,例如 `claude-opus-4-6`,最多 128 个字符 选择服务此模型的备用提供商,而不是其当前默认提供商。 仅与 `model_provider` 一起使用时才有意义。 默认值:False 调用方生成的键,使重试一个逻辑调用变得安全。 1–255 个字符 选择拒绝此模型的输入 schema 未声明的顶层请求体字段,而不是接受它;不检查嵌套字段;并且,对于其 schema 允许未声明字段或没有已编写 schema 的模型,或者对于使用 `strict_mode=true` 发送的排队提交,不会拒绝任何内容。 默认值:False **请求体** `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`)。 **响应** 已创建:运行已进入队列。 响应体:[`RouterQueueSubmitResponse`](#routerqueuesubmitresponse)。响应头:`X-Comfy-Request-Id`、`Idempotent-Replayed` 凭据缺失或无效。 响应体:[`RouterErrorResponse`](#routererrorresponse)。响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` 无效请求。请检查错误类型和请求体。 响应体:[`RouterErrorResponse`](#routererrorresponse)。响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` 请求体过大。 响应体:[`RouterErrorResponse`](#routererrorresponse)。响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` Router 请求级失败:请求从未到达模型,或因模型本身未报告的原因而失败。 响应体:[`RouterErrorResponse`](#routererrorresponse)。响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` 此调用方或模型不允许该请求。对于合作伙伴直接以字节形式返回生成结果的模型,目前无法排队,并会以 `not_enabled` 拒绝;请改为在同步路由上运行它。 响应体:[`RouterErrorResponse`](#routererrorresponse)。响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` 未找到模型 ID。 响应体:[`RouterErrorResponse`](#routererrorresponse)。响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` 检查 `X-Comfy-Error-Type`:`concurrency_limit_exceeded` 表示原始调用仍在运行,因此需要等待 `Retry-After` 指示的时间,并复用同一个键;`invalid_input` 则需要使用新的键。此路由上的两种 `invalid_input` 冲突与键完全无关,更换任何新键都无法消除:当请求体选择的是该提供商针对此模型无法处理的 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` 时) 请求内容未通过模型 schema 的校验。 响应体:[`RouterValidationErrorResponse`](#routervalidationerrorresponse)——响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id`、`Idempotent-Replayed` 检查 `X-Comfy-Error-Type`:`queue_backlog_full` 表示你已持有的未完成排队请求数量已达到上限,等其中一个完成后再提交;`rate_limited` 表示需等待限额窗口。 响应体:[`RouterErrorResponse`](#routererrorresponse)——响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` Router 暂时不可用。请以退避方式重试。 响应体:[`RouterErrorResponse`](#routererrorresponse)——响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id`、`Retry-After`(仅容量拒绝时) ### `GET /v2/models/{provider}/{model}/requests/{request_id}` **收集一次已提交请求的结果。** 收集端点。对于已成功完成的请求,它返回合作伙伴模型自身的原生输出,与同步路由针对同一模型、同一输入在 `200` 中返回的内容逐字节相同,因此两种交付方式产生同一种结果形状,调用方无需再写一套解析器即可在两者之间切换。 **参数** 规范 `{provider}/{model}` 模型 ID 中的小写提供商段,即正在运行其模型的合作伙伴。 类型:[`RouterProviderSegment`](#routerprovidersegment):字母数字 slug,例如 `anthropic`,最多 64 个字符 规范 `{provider}/{model}` 模型 ID 中的小写模型段,即在该提供商下要运行的模型。 类型:[`RouterModelSegment`](#routermodelsegment):字母数字 slug,例如 `claude-opus-4-6`,最多 128 个字符 要定位的排队请求,即提交时在响应体中返回的 `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 个字符 **响应** OK:为产生了结果的请求所存储的结果,该请求可以是已成功完成的请求,也可以是同时带有已记录扣费和已存储结果的终端请求,其结果按合作伙伴自身的媒体类型原样返回,与同步路由的 `200` 完全一致;并且遵循 submit 所接受的同一套提供商选择约定:不带 `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-Credits-Used` Accepted:请求尚未完成。 响应体:[`RouterQueueStatusResponse`](#routerqueuestatusresponse)。响应头:`X-Comfy-Request-Id`、`Retry-After` 凭证缺失或无效。 响应体:[`RouterErrorResponse`](#routererrorresponse)。响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` 该请求对此调用方或此模型不被允许。 响应体:[`RouterErrorResponse`](#routererrorresponse)。响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` 未找到该模型 ID。 响应体:[`RouterErrorResponse`](#routererrorresponse)。响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` Router 请求级失败:请求从未到达模型,或失败原因并非模型自身所报告。 响应体:[`RouterErrorResponse`](#routererrorresponse)。响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` Router 暂时不可用。请退避重试。 响应体:[`RouterErrorResponse`](#routererrorresponse)。响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` 请求处于与该操作冲突的状态。请检查错误类型。 响应体:[`RouterErrorResponse`](#routererrorresponse)。响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` 请求超过了截止时间。重试前请检查错误类型。 响应体:[`RouterErrorResponse`](#routererrorresponse)。响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` Router 请求级失败:请求从未到达模型,或失败原因并非模型自身所报告。 响应体:[`RouterErrorResponse`](#routererrorresponse)。响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` ### `PUT /v2/models/{provider}/{model}/requests/{request_id}/cancel` **请求取消某个已提交的请求。** 请求 Comfy 停止一个尚未完成的请求。这只是一次请求,并不构成保证,而 `202` 正是在表达这一点:`CANCELLATION_REQUESTED` 表示该请求已被接受,并不表示运行已经停止。已经发往合作伙伴处执行的运行仍可能照常完成;而合作伙伴侧完成的生成会被计费,无论是否有人取用其结果。因此,需要知道实际发生了什么情况的调用方,应在此之后读取状态端点。在那里,已生效的取消会表现为 `COMPLETED`,并和其他所有终态结果一样携带一个 `error_type`。 **参数** 规范 `{provider}/{model}` 模型 ID 中的小写提供商片段,即正在运行其模型的合作伙伴。 类型:[`RouterProviderSegment`](#routerprovidersegment) -- 字母数字短标识,例如 `anthropic`,最多 64 个字符 规范 `{provider}/{model}` 模型 ID 中的小写模型片段,即在该提供商下要运行的模型。 类型:[`RouterModelSegment`](#routermodelsegment) -- 字母数字短标识,例如 `claude-opus-4-6`,最多 128 个字符 要处理的已执行请求,即提交时在响应体中返回的 `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 个字符 **响应** 已接受 - `CANCELLATION_REQUESTED`。 响应体:[`RouterQueueCancelResponse`](#routerqueuecancelresponse) -- 响应头:`X-Comfy-Request-Id` 冲突 - `ALREADY_COMPLETED`。 响应体:[`RouterQueueCancelResponse`](#routerqueuecancelresponse) -- 响应头:`X-Comfy-Request-Id` 无效请求。请检查错误类型与请求体。 响应体:[`RouterErrorResponse`](#routererrorresponse) -- 响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` 凭证缺失或无效。 响应体:[`RouterErrorResponse`](#routererrorresponse) -- 响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` 该调用方或模型不允许执行此请求。 响应体:[`RouterErrorResponse`](#routererrorresponse) -- 响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` 未找到该模型 ID。 响应体:[`RouterErrorResponse`](#routererrorresponse) -- 响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` Router 暂时不可用。请以退避方式重试。 响应体:[`RouterErrorResponse`](#routererrorresponse) -- 响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` Router 请求级失败:请求从未到达模型,或因模型自身未反馈的原因而失败。 响应体:[`RouterErrorResponse`](#routererrorresponse) -- 响应头:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` ### `GET /v2/models/{provider}/{model}/requests/{request_id}/status` **读取单个已提交请求的队列状态。** 轮询端点。它只返回请求的当前状态,从不返回结果,因此客户端可以持续观察一次长时间生成,而不必在每次轮询时传输其输出:当该端点返回 `COMPLETED` 时,再从下面的读取中一次性获取结果。 **参数** 规范 `{provider}/{model}` 模型 ID 中的小写提供商片段,即正在运行其模型的合作伙伴。 类型:[`RouterProviderSegment`](#routerprovidersegment) -- 字母数字短标识,例如 `anthropic`,最长 64 个字符 规范 `{provider}/{model}` 模型 ID 中的小写模型片段,即在该提供商下要运行的模型。 类型:[`RouterModelSegment`](#routermodelsegment) -- 字母数字短标识,例如 `claude-opus-4-6`,最长 128 个字符 要查询的排队请求,即提交时在响应体中返回的 `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 个字符 **响应** OK - 请求当前的队列状态。 Body:[`RouterQueueStatusResponse`](#routerqueuestatusresponse) -- Headers:`X-Comfy-Request-Id`、`Retry-After`、`X-Comfy-Estimated-Duration-Seconds`、`X-Comfy-Estimated-Duration-P90-Seconds`、`X-Comfy-Estimate-Source` 凭证缺失或无效。 Body:[`RouterErrorResponse`](#routererrorresponse) -- Headers:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` 该调用方或模型不允许此请求。 Body:[`RouterErrorResponse`](#routererrorresponse) -- Headers:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` 未找到该模型 ID。 Body:[`RouterErrorResponse`](#routererrorresponse) -- Headers:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` Router 请求级失败:请求从未到达模型,或因模型本身未反馈的原因而失败。 Body:[`RouterErrorResponse`](#routererrorresponse) -- Headers:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` Router 暂时不可用。请退避重试。 Body:[`RouterErrorResponse`](#routererrorresponse) -- Headers:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` Router 请求级失败:请求从未到达模型,或因模型本身未反馈的原因而失败。 Body:[`RouterErrorResponse`](#routererrorresponse) -- Headers:`X-Comfy-Error-Type`、`X-Comfy-Request-Id` 此处描述较为简短。模型选择、验证、重试和计费请参阅[使用 Comfy Router API](/zh/development/comfy-router/api),Header 行为请参阅 [Headers](/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` | 调用方已有过多等待运行的排队请求,因此此次提交被拒绝。 | | `result_expired` | 请求存在且已完成,但其结果已不再存储,因此收集时没有可返回的内容。 | ## 响应头 用于目录页面或条目的新鲜度指令。 发送条件:`200`、`304` 用于所提供架构文档的新鲜度指令。 发送条件:`200`、`304` 针对所提供响应体字节的强实体标签,用于 `GET /v2/models` 和 `GET /v2/models/{provider}/{model}`。 发送条件:`200`、`304` 针对所提供文档字节的强实体标签,用于 `GET /v2/models/{provider}/{model}/openapi.json`。 发送条件:`200`、`304` 当此响应来自某条 `Idempotency-Key` 的记录,而不是通过再次运行模型产生时,该响应头会出现并且值为 `true`。 原样重新发送同一请求前需要等待的秒数。 发送条件:`503` 下一次轮询这个已排队的请求前需要等待的秒数。 发送条件:`200`、`202` 使用同一个 `Idempotency-Key` 重试同一请求之前需要等待的秒数。 发送条件:`409`、`504` 本次运行的费用,以 Comfy 积分计,按照扣费本身所依据的同一价目表定价。因此调用方无需自备价格表;当一次运行经由不止一个计费调用抵达提供商时,该值是这些调用的总和,而不是最后一次调用的值。 失败的粗粒度、机器可读分类,由 Router 在每个错误响应上设置。 类型:[`RouterErrorType`](#routererrortype) 仅在 `status` 为 `IN_PROGRESS` 的状态读取时发送,位于 `X-Comfy-Estimated-Duration-Seconds` 旁边:说明该生成时长估计来自哪里(不是费用估计中的 `source`),取值为 `historical`(依据近期运行实测)或 `default`(按媒体类型设置的兜底值,在记录的近期运行太少时使用)。 仅在 `status` 为 `IN_PROGRESS` 的状态读取时发送,位于 `X-Comfy-Estimated-Duration-Seconds` 旁边:该生成时长估计的第 90 百分位,以整秒为单位。 仅在 `status` 为 `IN_PROGRESS` 的状态读取时发送:Router 对这次生成在提供商接受之后整个运行耗时的估计,以整秒为单位(不是剩余时间,也从不包含 `IN_QUEUE` 中度过的时间)。 内容策略拒绝所针对的是哪个输入或输出,采用 Router 层面的封闭词表:`input`、`output`、`input_text`、`input_image`、`input_video`、`input_audio`、`output_text`、`output_image`、`output_video`、`output_audio`。 服务器为此次调用生成的标识符,存在于每一个 Router 响应中:成功、4xx 和 5xx 响应均如此,因为错误响应恰恰是用户需要在支持请求中引用某个 ID 的时候。 一个 JSON 编码的字符串,内含一个字符串数组。请使用 JSON 解析器来解码,而不要按逗号对其分割,因为它在传输时是单个字符串,而不是逗号分隔的 OpenAPI 数组,并且每个条目本身就是一个自带逗号的句子。当一次转换生成了本次调用的请求体,却无法在所服务的提供商上精确表达一个或多个原生字段时,该响应头就会出现,并逐一列出每个被丢弃的字段及其原因;无论调用方是通过 `model_provider`(`strict_mode=false`,默认值)请求该转换,还是由自动的 `fallback_provider` 重试执行了该转换,都是如此。 仅当 `fallback_provider` 确实针对第二个提供商重试了此调用,并且该重试成功时,该响应头才会出现并指明该提供商:即最终服务此调用的提供商,绝不是被尝试过但也失败了的那个。 服务此次调用的 Router 链路的提供商,出现在每个成功运行的响应中:原生运行时为模型自身的提供商,也可能是 `model_provider` 指定的备用提供商,或者是 `fallback_provider` 重试最终落在的提供商(仅在这种情况下 `X-Comfy-Router-Fallback-Provider` 也会指明它)。它代表的是 Router 派发到的链路,而不一定是产生输出的厂商,因为原生链路内部的代理级联(例如 `vertexai` 的 Gemini 图像链)可能把调用交给另一个厂商,而没有任何响应头会指明它。 模型提供商给出的、有长度限制且已脱敏的拒绝该请求的原因。 模型提供商在此次调用中自身的 HTTP 状态。 调用方当前已承诺给仍在途调用的美分数。 调用方可承诺给仍在途调用的合作伙伴支出上限,单位为美分。这笔资金从调用被接纳的那一刻起即被保留,并在该调用结束时释放。 上限之下剩余的可用额度,单位为美分,最低为零。 在 Router 模型的每次成功运行中都始终为 `nosniff`。 调用方对归为昂贵的模型的并发调用数,由拒绝此次调用的闸门统计得出。 调用方一次可持有的、对归为昂贵的模型的并发调用上限,为并发调用限额的四分之一,与合作伙伴节点调用共享。 调用方仍可启动的昂贵模型调用数;在 `429` 时为 `0`。 ## 预检费用预估 `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`(仅排队提交):请求被接收时无法读取费率卡片。提交仍会被接受,运行照常计费。 Router 在运行之前尚无法定价的模型列在[没有预检预估的模型](/zh/development/comfy-router/limitations#无法预先估算的模型)中。未列在该处的模型对于特定请求体仍可能返回 `unknown`,因此请对每个预估都读取 `source`。 预估在以下情况下会采用保守失败策略: - 当某个数值需要费率卡片,而该卡片未加载或已过期时,`/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` 参数说明了无法重放时重试会得到怎样的回应。 ## 各模型的输入和输出架构 每个模型的字段可通过 `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 ### RouterBilledWorkspace 被拒绝的调用本会扣费的电子钱包,位于 `RouterErrorResponse.billed_workspace`。它回答“哪个钱包余额不足?”,但未必是调用方界面当前所选的工作区:即使正在使用一个有余额的团队,团队成员的个人凭证在这里也会指向其个人钱包。仅在同时存在 `denied_reason` 时出现。 **字段** Cloud 工作区 id。在旧式计费通道上不存在。 `personal` 或 `team`。这是一个开放字符串:其他任何值都按 personal 处理。 当该调用向调用方在工作区出现之前的 Metronome 客户计费、而不是向 Cloud 工作区计费时为 `legacy`;该客户没有工作区 id。Cloud 工作区不出现此字段。 ### RouterChargesOnPolicyRejection 内容政策拒绝是否会对该模型计费。请将未知值视为可能计费。 类型:`string` ### RouterCostEstimate 对本次调用费用的预估值,以美元计,在派发之前依据该次运行实际计费所用的同一费率卡片定价。它不是最终收费:你实际支付的是工作区用量与账单记录中的结算费用。运行结束后返回的 `X-Comfy-Credits-Used` 是一个取整的事后数值,不是收据。`source` 说明该数字的可信程度:`exact` 带有 `amount`;`estimated` 带有 `min_amount` 和 `max_amount`,不带 `amount`;`unknown` 两者都不带,并带有一个 `reason`。绝不要把缺失的 `amount` 理解为免费。这不是价格锁定:请参见 `pricing_as_of`。 **字段** `exact` | `estimated` | `unknown`;其他任何值都按 `unknown` 理解。`exact` 和 `estimated` 都只是预估;两者都不是最终收费。`unknown` 不带任何数值。 始终为 `USD`。 预估费用,以十进制字符串表示的美元金额,例如 "0.04",最多 8 位小数,且不使用指数形式。可计费的低于 1 美分的价格绝不会被渲染为 "0"。仅在 `source` 为 `exact` 时出现。这不是最终收费:最终收费是工作区用量与账单记录中的结算费用。 预估值下限,以十进制字符串表示的美元金额。仅在 `source` 为 `estimated` 时出现。 预估值上限,以十进制字符串表示的美元金额。仅在 `source` 为 `estimated` 时出现。 同一数值以美分表示,不做四舍五入,用于算术运算。与 `amount` 一同出现。 double `min_amount` 以美分表示,不做四舍五入。与 `min_amount` 一同出现。 double `max_amount` 以美分表示。与 `max_amount` 一同出现。 double 使用平台换算率($1 = 211 积分)换算得到的 `amount` 积分数,四舍五入到 2 位小数,即 `X-Comfy-Credits-Used` 对 `exact` 报价预期携带的数值。该响应头是取整后的事后数值,不是收据;最终以你工作区用量与账单记录中的结算费用为准。 double 该报价所对应的提供商线路。在排队提交中,它就是将要运行的那条线路。 规范的 Comfy Router 模型 ID,即 `{provider}/{model}`,正是 `POST /v2/models/{provider}/{model}` 上用于寻址该模型的值,因此调用方可以直接将其插入该路径,而无需从其他任何地方重新推导。其 `pattern` 为用单个 `/` 连接的 `RouterProviderSegment` 和 `RouterModelSegment`,`maxLength` 为二者之和加上该分隔符。 类型:[`RouterModelId`](#routermodelid):模型 ID,例如 `anthropic/claude-opus-4-6`,最多 193 个字符 该报价定价所依据的费率卡片的获取时间。该预估不是价格锁定:运行按评级时生效的费率计费,而非此时间点的费率。从提供商公布的价格清单取得的 `estimated` 报价(按提供商上报成本计费的模型)会带有该清单的读取日期;而计费数量由该清单预测、再按费率卡片定价的报价(按提供商上报积分计费的模型)则取两个日期中较早的一个。每当未读取任何费率卡片时(`reason: pricing_unavailable`、`byok`,或无法从任何卡片定价的 `not_quotable` 调用),这里就是该报价被应答的时间。 date-time 仅在 `source` 为 `unknown` 时出现:`not_quotable`(Router 无法在调用运行之前为其定价:其价格取决于提供商回报的内容,或者请求体未限定计费数量)、`unpriced_model`(费率卡片未对该请求定价)、`byok`(仅排队提交:运行时使用你自己的提供商密钥,因此 Comfy 不为此收取任何费用),或 `pricing_unavailable`(仅排队提交:请求被接受时无法读取费率卡片;这是暂时性的,运行仍会照常计费)。其他任何值都按 `not_quotable` 理解。 ### RouterErrorResponse 用于认证、访问、模型查找、配额以及提供商传输失败的错误响应体。 **字段** 人类可读的失败描述,可安全地展示给最终用户。该字段不用于机器解析,请改为根据 `error_type` 进行分支判断。对于已退役模型的 `model_not_found`,当已记录后继模型且调用方可见时,`detail` 会显示 ` was retired on ; use `;若未记录后继模型或调用方不可见,则只显示 ` was retired on `,而不是通常的建议列表。此处指明的后继模型始终是一个有效的目录 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` 进行分支判断都不附带兼容性保证。 对 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` 和 `result_expired`。“封闭”描述的是当前文档所记录的集合,并不是一个永远成立的界限:该集合预计还会增长,因此这里刻意使用普通字符串而不是 `enum`,客户端必须将无法识别的值视为 `internal_error`,而不是对上面的列表做穷举 switch,并在下次新增取值时出错。 类型:[`RouterErrorType`](#routererrortype) 模型提供商给出的、有界且经过净化的拒绝原因,仅当 `error_type` 为 `invalid_input` 且 `X-Comfy-Upstream-Status` 是提供商返回的 `4xx` 或 `2xx` 时才存在,也就是说提供商认为请求格式有误而拒绝,并说明了原因。该状态通常是 `4xx`;对于在成功信封内报告生成被拒绝的提供商,它会是 `2xx`(BytePlus 的失败任务轮询返回 HTTP `200`,原因位于响应体中)。在其他所有失败情形下都不存在,包括提供商 `5xx`、传输失败、内容策略拒绝以及 Router 针对自身提出的任何拒绝。它与 `X-Comfy-Upstream-Detail` 响应头对应。 内容策略拒绝针对的是哪个输入或输出,采用 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(万相)的拒绝给出该字段,也为 MiniMax Router 的 Nano Banana 链路中的 Gemini 拒绝给出该字段;如果提供商的拒绝未说明针对哪一侧,该字段就会缺失。它与 `X-Comfy-Refusal-Subject` 响应头对应。 计费侧针对合作伙伴节点支出拒绝的策略分支:`no_funds` 表示计费钱包为空,`unspecified` 表示该调用在没有资金读数的情形下被拒绝。仅当 `error_type` 为 `insufficient_credits` 且部署会上报钱包事实时出现;否则不出现。这是机器可读的代码而非展示文本:展示 `detail`,按此字段分支。 被拒绝的调用本会扣费的电子钱包,位于 `RouterErrorResponse.billed_workspace`。它回答“哪个钱包余额不足?”,但未必是调用方界面当前所选的工作区:即使正在使用一个有余额的团队,团队成员的个人凭证在这里也会指向其个人钱包。仅在同时存在 `denied_reason` 时出现。 类型:[`RouterBilledWorkspace`](#routerbilledworkspace) 被拒绝的请求以何种方式完成认证:`personal_api_key`、`team_api_key`、`personal_session` 或 `team_session`。它回答“该换成哪份凭证来向另一个钱包计费?”。它不是权限,也不授予任何权限。仅在同时存在 `denied_reason` 时出现。 ### RouterErrorType 机器可读的 Router 错误类别,同时也会在 `X-Comfy-Error-Type` 标头中发送。 类型:`string` ### RouterModelBilling 调用模型之前需要检查的计费行为。它不包含价格或用量信息。 **字段** 模型以内容政策为由拒绝的调用,是否仍向调用方计费。各提供商的做法不尽相同,而这种差异在调用时无法察觉,因此用户即使同时看到同一次调用的错误与扣费,也无从事先得知。所以这里在调用之前按模型明确说明,而不是留待各提供商各自口口相传。当该值为 `yes` 时,同步路由上的 `content_policy_violation` 错误可能带有 `X-Comfy-Credits-Used`:当提供商拒绝了模型生成的输出,且 Comfy 记录了该次被拒生成的用量时会带上它,并携带该金额。输入侧的拒绝与同键重放(`Idempotent-Replayed: true`)不带此头;没有该头的拒绝不会上报,也不能证明是免费的。 类型:[`RouterChargesOnPolicyRejection`](#routerchargesonpolicyrejection) ### RouterModelDetail 单个 Comfy Router 模型的逐模型详细信息:目录列表为该模型报告的全部内容,外加只有单模型路由才会携带的逐模型字段。 组合了 [`RouterModelListEntry`](#routermodellistentry)、[`RouterModelDetailFields`](#routermodeldetailfields)。 类型:`object` ### RouterModelDetailFields 模型详情端点返回的可选字段。 **字段** 该模型 OpenAPI 文档的 URL,包含其输入和输出 Schema。 HTTPS URL,例如 `https://api.comfy.org/v2/models/bfl/flux-2-pro/openapi.json`,最多 2048 个字符 ### RouterModelId 用于 `POST /v2/models/{provider}/{model}` 的模型 ID。 类型:`string`。模型 ID,例如 `anthropic/claude-opus-4-6`,最多 193 个字符。 ### RouterModelInput 模型输入对象。请阅读已选择模型的 OpenAPI 文档,了解字段与验证规则。 类型:`object` ### RouterModelInputSchemaDocument 一份独立描述单个模型输入与输出的 OpenAPI 文档。 类型:`object` ### RouterModelListEntry 模型的 ID 与计费信息。 **字段** 规范化的 Comfy Router 模型 ID,格式为 `{provider}/{model}`:正是在 `POST /v2/models/{provider}/{model}` 上定位该模型所用的值,因此调用方可以直接把它插值进该路径,无需再从其他任何地方推导。它的 `pattern` 是 `RouterProviderSegment` 与 `RouterModelSegment` 以单个 `/` 连接而成,`maxLength` 则是两者长度之和再加上该分隔符。 类型:[`RouterModelId`](#routermodelid),模型 ID,例如 `anthropic/claude-opus-4-6`,最多 193 个字符 规范化 `{provider}/{model}` 模型 ID 中的小写 `provider` 段,即所寻址模型所属的合作伙伴。调用路由的 `provider` 路径参数与目录条目的 `provider` 字段都引用这同一个 schema,正是这一点让列出的 ID 与可接受的 ID 不会彼此偏离。 类型:[`RouterProviderSegment`](#routerprovidersegment),字母数字 slug,例如 `anthropic`,最多 64 个字符 规范化 `{provider}/{model}` 模型 ID 中的小写 `model` 段,即在该提供商下要运行的模型。调用路由的 `model` 路径参数与目录条目的 `model` 字段共用这一 schema,原因与 `RouterProviderSegment` 相同,同样是为了避免偏离。 类型:[`RouterModelSegment`](#routermodelsegment),字母数字 slug,例如 `claude-opus-4-6`,最多 128 个字符 调用方在调用之前需要了解的单模型计费信息,而不是价格。用量和费用数字绝不会出现在这里。 类型:[`RouterModelBilling`](#routermodelbilling) 该模型 `GET /v2/models/{provider}/{model}/openapi.json` 文档的当前强 `ETag`。在该读取请求中将其作为 `If-None-Match` 发送,当 schema 未发生变化时即可获得 `304`;也可以将其与上次看到的值比较,从而无需获取每个文档就能得知哪些模型的 schema 发生了变化。只要该读取请求此刻无法为此调用方返回 `200`,该字段就会缺失:schema 服务不可用、该模型的文档无法渲染,或者该模型在响应构建期间对此调用方变为不可用。标签缺失并不表示 schema 发生了变化;请重新读取该模型的文档以了解其当前标签。 ### RouterModelListResponse Router 模型目录的一页。 **字段** 本页包含的模型,最多 `limit` 个。 类型:由 [`RouterModelListEntry`](#routermodellistentry) 组成的数组 本页之后是否还有另一页。只要该值为 true,就继续向后翻页;不要因为 `data` 很短或为空就断定目录已到末尾。 指向 Router 列表的一个不透明游标。它由服务器生成,且仅用于原样往返传递:它不是偏移量,不是模型 ID,没有顺序,也不能在目录重建后保持稳定,因此解析它、对它做自增,或在产生它的那次遍历之外持久化它,都不属于契约范围。之所以使用游标而非偏移量,是因为目录是一个不断变化的列表:当遍历过程中有条目被增删时,基于偏移量的遍历会静默地跳过或重复条目,而调用方无法察觉这种情况已经发生。 类型:[`RouterPageCursor`](#routerpagecursor),作为 `next_cursor` 返回的不透明游标,1–512 个字符 实际提供的分页大小。请求的 `limit` 超过上限时会被截断到上限,而不是被拒绝,因此该值可能小于你所请求的值。请用这个数字进行分页,而不是你发送的那个数字,否则你会假定存在一些你从未收到的行。 1–100 ### 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` 和 `409`)的取消询问所作的应答。两者共用同一种响应体形状,而不是一个成功信封加一个错误信封,因为两者陈述的是同一件事:取消操作发现了什么;而且,如果客户端必须按状态码解析不同的类型,这种拆分并不能带来任何好处。 **字段** 一个已排队 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 个字符 取消询问所发现的内容,对应描述本路由实际已处理请求的两种结果。两者都会与 HTTP 状态相呼应,因此客户端可以依据任一者进行分支。 类型:[`RouterQueueCancelStatus`](#routerqueuecancelstatus) ### 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 块的那一半:一个排队中请求的身份、它当前的状态,以及在该状态为终端状态且运行未成功时,说明失败原因所属的粗粒度分类桶。 **字段** 一个排队中 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 个字符 排队中 Router 请求的状态。它恰好有三个值,并且与 `RouterErrorType` 不同,这是一个封闭的 `enum`,因为这两个 schema 是故意朝相反方向封闭的。`RouterErrorType` 对失败进行分类,其集合预期会增长,因此,一个硬性拒绝无法识别分类桶的已生成客户端,恰恰会在已经出错的时候失败得最严重。而这一个描述的是生命周期,一个日后新增第四种状态的生命周期,无论是否被声明为 enum,对每一个针对它编写的轮询循环来说都是破坏性变更。因此它被声明为 enum,并把这一约束写在客户端能看到的地方。 类型:[`RouterQueueStatus`](#routerqueuestatus) 在响应生成的那一刻,队列中有多少个请求排在该请求之前。零表示该请求位于队首。 类型:[`RouterQueuePosition`](#routerqueueposition) -- 至少 0 仅出现在未成功的 `COMPLETED` 请求上,携带的正是结果读取在返回该失败时赋给 `X-Comfy-Error-Type` 的那个粗粒度分类桶。它把一个成功的终端请求与一个失败或被取消的终端请求区分开来(后两者都没有单独的终端状态),并且它在成功时是缺失的而不是 null,因此请依据它是否存在来分支。 类型:[`RouterErrorType`](#routererrortype) ### RouterQueueStatusResponse 一个已执行请求的当前状态,由提交时返回的相同三个 URL 组合而成。 组合了 [`RouterQueueUrls`](#routerqueueurls)、[`RouterQueueStatusFields`](#routerqueuestatusfields)。 类型:`object` ### RouterQueueSubmitFields `RouterQueueSubmitResponse` 中除 URL 区块之外的另一半:新请求的身份,以及它被接纳那一刻的状态。 **字段** 一个排队中的 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 个字符 排队中的 Router 请求的状态。它恰好有三个取值,而且与 `RouterErrorType` 不同,这是一个封闭的 `enum`,因为这两个 schema 被有意设计成朝相反方向封闭。`RouterErrorType` 对失败进行分类,其取值集合预期会增长,因此一个会硬性拒绝无法识别分类的已生成客户端,恰恰会在已经出错的时候失败得最惨。而这一个表示的是生命周期,日后新增第四种状态对每一个针对它编写的轮询循环来说都是破坏性变更,无论它是否被声明为 enum,所以这里就把它声明为 enum,并把该约束写在客户端能看到的地方。 类型:[`RouterQueueStatus`](#routerqueuestatus) 在响应生成的那一刻,队列中有多少个请求排在本请求之前。零表示本请求位于队首。 类型:[`RouterQueuePosition`](#routerqueueposition) -- 至少为 0 本次请求的预检成本估算,在调用方启用了成本估算时,会出现在新的准入响应中。它给出的是本次请求被固定到的那条提供商链路(队列没有回退循环,因此 `fallback_provider` 永远不会改变实际运行的链路)。当无法给出任何数字时,该字段仍然存在,并带有 `source: unknown`;提交永远不会因为成本估算而失败。在幂等重放时会省略(`Idempotent-Replayed: true`),因为原始报价不会被存储。它只是估算,不是最终收费,也不是价格锁定:运行时按计费当时生效的费率收费,而最终金额以你工作区的用量与账单记录中的结算费用为准。 类型:[`RouterCostEstimate`](#routercostestimate) ### RouterQueueSubmitResponse 当运行被接纳进入队列时返回的句柄:包含请求的身份与状态,并组合了用于访问其生命周期其余部分的三个 URL。 组合了 [`RouterQueueUrls`](#routerqueueurls)、[`RouterQueueSubmitFields`](#routerqueuesubmitfields)。 类型:`object` ### RouterQueueUrls 这三条 URL 指向一个已入队请求剩余的生命周期,凡是携带有效句柄的响应都会返回它们,因此客户端无需自行拼接队列 URL。 **字段** 读取此请求状态的绝对 URL。 URI 用于收集此请求结果的绝对 URL。 URI 用于请求取消此请求的绝对 URL。 URI ### RouterValidationErrorContext 提供商提供的关于未通过验证的规则的详情。 类型:`object` ### RouterValidationErrorDetail 一个字段级验证失败。 **字段** 指向出错字段的路径,最外层片段在前,例如 `["body", "image_url"]`,或 `["body", "images", 0]`,其中整数表示数组中的索引。 对这一次失败的人类可读描述。 该失败的具体且机器可读的原因,由提供商原样传递。这是类型化 SDK 异常层次结构用于分支判断的值;响应头中的 `error_type` 只是它的粗略分类。 某个 `RouterValidationErrorDetail` 所违反的界限,由提供商原样携带,例如 `{"limit_value": 8}` 配合 `greater_than`,`{"min_width": 512}` 配合 `image_too_small`,或 `{"max_size_bytes": 10485760}` 配合 `file_too_large`。键集合特定于提供商和错误类型,因此这里刻意是一个开放对象:把它收窄为固定字段列表,或把它合并进 `msg` 字符串,正是移植后的集成能够编译、却静默丢失读取该界限的分支的原因。当错误类型不携带界限时,该字段缺省。 类型:[`RouterValidationErrorContext`](#routervalidationerrorcontext) 出错的输入值,原样回显,以便调用方无需再从 `loc` 重新推导就能看到被拒绝的内容。任意 JSON 类型,包括字符串、数字、布尔、数组、对象或 null,因此该 schema 被有意保持为无类型,而不是收窄为对象。当提供商不回显输入时,该字段缺省。 类型:[`RouterValidationErrorInput`](#routervalidationerrorinput) ### RouterValidationErrorInput 提供商包含该值时,被拒绝的输入值。 ### RouterValidationErrorResponse `422` 验证错误的响应体。读取 `X-Comfy-Error-Type` 以获取其类别。 **字段** 请求中发现的每一个验证失败项,每个出错的字段对应一个条目。 类型:[`RouterValidationErrorDetail`](#routervalidationerrordetail) 数组