Skip to main content
POST
Price a model call before running it, without running it.

Autorizaciones

Authorization
string
header
requerido

Bearer token authentication. Normally a Firebase or Cloud JWT. A 'comfyui-' prefixed API key is also accepted in this header: the prefix classifies the value as an API key and it is validated exactly as if it had been sent in X-API-Key. Accepted on the operations served by the comfyFirebase auth middleware (BE-9720, parity with ingest).

Parámetros de ruta

provider
string
requerido

Lowercase provider segment of the canonical {provider}/{model} model ID - the partner whose model is being run. The schema is RouterProviderSegment, the SAME component a catalog entry's provider field references, so an ID GET /v2/models lists cannot drift from the ids this route accepts. Its pattern is a CONTRACT statement, not enforcement: comfy-api installs no OpenAPI request validator and oapi-codegen binds path parameters as plain strings, so the handler must re-validate this segment itself before using it to select a provider or compose an upstream URL. Lowercase provider segment of the canonical {provider}/{model} model ID - the partner whose model is being addressed. The invocation route's provider path parameter and a catalog entry's provider field both reference this one schema, which is what keeps the listed IDs and the accepted IDs from drifting apart. The pattern is a CONTRACT statement, not enforcement: comfy-api installs no OpenAPI request validator and oapi-codegen binds path parameters as plain strings, so a handler must re-validate the segment itself before using it to select a provider or compose an upstream URL. The alphabet deliberately admits no /, no percent-encoding, and no repeated separator, so no accepted value can contain a . or .. path segment.

Maximum string length: 64
Pattern: ^[a-z0-9]+([._-][a-z0-9]+)*$
Ejemplo:

"bfl"

model
string
requerido

Lowercase model segment of the canonical {provider}/{model} model ID - the model to run within that provider. As with provider, the schema is the shared RouterModelSegment component and its pattern documents the contract rather than enforcing it - see RouterProvider. Lowercase model segment of the canonical {provider}/{model} model ID - the model to run within that provider. Shared by the invocation route's model path parameter and a catalog entry's model field, for the same no-drift reason as RouterProviderSegment. As with the provider segment, the pattern documents the contract and does not enforce it. Dots are permitted inside the segment because partner model IDs use them for versions (flux-pro-1.1), but a repeated separator is not, so .. cannot appear.

Maximum string length: 128
Pattern: ^[a-z0-9]+([._-][a-z0-9]+)*$
Ejemplo:

"flux-2-pro"

Parámetros de consulta

model_provider
string

Selects an alternate provider to serve this model, instead of its current default. Omitting it runs native dispatch on the model's own default provider; default, comfy, and comfyui are aliases for that same native behavior and name no override, because Comfy Router is never itself a serving backend. The alternate providers Router can retarget a model onto are fal, wavespeed, runware, and higgsfield; which of them a given model supports is reported by GET /v2/models/{provider}/{model}. When an alternate provider is selected, the native request body is translated into that provider's real schema unless strict_mode=true; see strict_mode and fallback_provider. Its refusals are checked in a fixed order, and an earlier one answers whether or not a later one would. A value that is not a registered provider at all is refused 400 with error_type: invalid_input. Then a request whose body selects a multipart operation (an edit - for example gpt-image's image field) is refused 409, also with error_type: invalid_input, whose detail begins "this request's image selects the edit operation" - but only when the named provider's translator for this model cannot itself serve that operation; a leg whose translator does carry the media is not refused and proceeds normally, so this is a per-leg refusal rather than a blanket one. Then a request that has already resolved a bring-your-own-key credential for the provider in the path is refused 409, also with error_type: invalid_input, whose detail begins this request resolved a BYOK credential - see the 409 on this route, where that detail is the only thing separating this case, and the multipart case above, from the Idempotency-Key one. That BYOK check runs whether or not the named provider has a leg for this model. Then the named provider's own gate refuses 403 with error_type: not_enabled when that provider is not turned on for you, and 503 with error_type: service_unavailable when the gate cannot be evaluated - a flag-evaluation failure, or a missing or nil gate entry. Only past all of those is a real provider that does not serve this model refused 400 with error_type: invalid_input, the same answer as a value that is not a registered provider at all - both mean the model_provider value cannot serve this model, and that 400's detail is human-readable and not a contract, so read GET /v2/models/{provider}/{model} to learn which providers a model does support rather than parsing it; past that 400, this workspace's partner-provider policy for the named vendor is evaluated too and can refuse 403 or 503 of its own. Neither this parameter nor fallback_provider is available on a BYOK request, and the two are unavailable in different ways: the credential was resolved for the provider named in the path while every alternate leg dispatches on Comfy's own key, so an explicit model_provider is refused with that 409, and fallback_provider is inert rather than refused - no retry against an alternate provider is attempted and the first attempt's own failure is what the caller receives. The same split applies to a multipart body: only an explicit model_provider reaches the 409 above, and only for a leg whose translator cannot serve the operation, while the automatic on-failure retry fallback_provider controls is simply skipped (inert, not refused) for any multipart body. Router defines no provider_not_available or validation_error error_type: these conditions fold onto invalid_input. The error_type set can still grow, so treat any value you do not recognize as internal_error rather than switching exhaustively.

Cuerpo

application/json

The partner model's native JSON input, identical to the body the synchronous route accepts for this model. It is validated against the model's own input schema as a default run validates it (this route takes no strict_mode or reject_unknown_fields), and its own fields (the output count, the operation an input image selects) decide what is priced.

A partner model's native JSON input document, forwarded to the provider as-is. Its concrete shape is owned by the partner rather than by Comfy, so this is an open object: Router does not narrow, rename, or re-envelope the fields. It is a named component (never an inline anonymous object) because ComfyUI's spec-driven codegen needs a class to generate. Declaring an object here is a codegen requirement, not a licence to re-decode the payload: numeric fidelity is the handler's job, since decoding into a Go map[string]any rounds integers above 2^53 (partner seeds and IDs) to float64. Forward the raw bytes rather than round-tripping them through a generic map. Body size is likewise bounded at the handler - comfy-api caps comparable bodies with http.MaxBytesReader - not by this schema.

Respuesta

The quote. Read source before reading any amount: only exact carries amount, and an unknown quote carries a reason instead of a figure.

A pre-flight estimate of what this call will cost, in US dollars, priced before dispatch from the same rate card the run is billed against. It is not the final charge: the settled charge in your workspace's usage and billing records is what you pay. X-Comfy-Credits-Used, reported after the run, is a rounded post-hoc figure, not a receipt. source says how much to trust the number: exact carries amount; estimated carries min_amount and max_amount and no amount; unknown carries neither and a reason. Never read an absent amount as free. Not a price lock: see pricing_as_of.

currency
string
requerido

Always USD.

model
string
requerido

A canonical Comfy Router model ID, {provider}/{model} - exactly the value that addresses the model on POST /v2/models/{provider}/{model}, so a caller can interpolate it into that path without re-deriving it from anything. Its pattern is RouterProviderSegment and RouterModelSegment joined by a single /, and maxLength is their sum plus that separator. TestRouterCatalogIdsMatchInvocationRoute probes all three patterns behaviourally against one corpus, so loosening or tightening any of them alone fails CI rather than silently letting the catalog advertise an ID the invocation route would reject. The optional variant third segment is deliberately absent: how a variant is addressed is not settled by the invocation contract, so the catalog must not list an ID that route is not yet defined to accept. The PUBLIC lead paragraphs of RouterProviderSegment, RouterModelSegment and the RouterProvider / RouterModel path parameters therefore spell the canonical ID {provider}/{model} with no variant suffix, and must keep doing so while the variant form is unsettled: those leads are the only text the SDK projection publishes, so a three-segment form there vendors an ID shape every published pattern rejects and no path template accepts AS A MODEL ID. (/v2/models/{provider}/{model}/openapi.json does match a third segment, but only when it is that one literal - which is exactly the collision getRouterModelInputSchema reserves against, not an ID the route accepts.) The reservation is argued in the rationale paragraphs, which are never projected, and that is where it belongs. ONE bound does not survive the composition: maxLength here is the TOTAL, so a 193-character ID made of a 100-character provider and a 92-character model satisfies this schema while its provider segment exceeds RouterProviderSegment's own 64. A single pattern cannot express a per-segment length bound - the structural alphabet and a character count are not jointly expressible without lookahead, which this repo's Go-side pattern probes cannot compile. The per-segment bounds are therefore carried by the sibling provider and model fields of RouterModelListEntry, which reference the bounded segment schemas directly, so no CONFORMING entry can carry such an id. TestRouterCatalogIdsMatchInvocationRoute pins that this residual is length-only: over-length segments are in its corpus, and any divergence that is not purely a per-segment length overrun fails.

Maximum string length: 193
Pattern: ^[a-z0-9]+([._-][a-z0-9]+)*/[a-z0-9]+([._-][a-z0-9]+)*$
Ejemplo:

"bfl/flux-2-pro"

pricing_as_of
string<date-time>
requerido

When the rate card this quote was priced from was fetched. The estimate is not a price lock: the run is charged at the rates in force when it is rated, not at this instant. Whenever no rate card was read (reason: pricing_unavailable, byok, or a not_quotable call that cannot be priced from any card), this is when the quote was answered.

provider
string
requerido

The provider leg this quote is for. On a queued submit it is the leg that will run.

source
string
requerido

exact | estimated | unknown; read any other value as unknown. exact and estimated both label an estimate; neither is the final charge. unknown carries no figure.

amount
string

The estimated cost in dollars as a decimal string, e.g. "0.04", with up to 8 decimals and no exponent. A chargeable sub-cent price is never rendered as "0". Present only when source is exact. Not the final charge: the settled charge in your workspace's usage and billing records is.

amount_cents
number<double>

The same figure in US cents, unrounded, for arithmetic. Present with amount.

credits
number<double>

amount in Comfy credits using the platform conversion ($1 = 211 credits), rounded to 2 decimals - the figure X-Comfy-Credits-Used is expected to carry for an exact quote. That header is a rounded post-hoc figure, not a receipt; the settled charge in your workspace's usage and billing records is final.

max_amount
string

The high end of the estimate in dollars as a decimal string. It is an estimate, not a guaranteed cap: a call can be billed more, for example when the provider returns more than was asked (such as more images than requested), when the estimate is learned from past calls, or when the price does not rise steadily with the amount requested. Present only when source is estimated.

max_amount_cents
number<double>

max_amount in US cents. Present with max_amount.

min_amount
string

The low end of the estimate in dollars as a decimal string. It is an estimate, not a guaranteed floor: a call can be billed less, for example when the provider returns less than the request asked for (such as no images), when the estimate is a typical price learned from past calls, or when the price does not rise steadily with the amount requested. Present only when source is estimated.

min_amount_cents
number<double>

min_amount in US cents, unrounded. Present with min_amount.

reason
string

Present only when source is unknown: not_quotable (Router cannot price this call before it runs - its price depends on what the provider reports back, or the body does not bound a billed quantity), unpriced_model (the rate card does not price this request), byok (queued submit only: the run uses your own provider key, so Comfy bills nothing for it), or pricing_unavailable (queued submit only: the rate card could not be read when the request was admitted; this is transient, and the run is still charged as usual). Read any other value as not_quotable.