Skip to main content
Quick answers to the questions we hear most about ComfyUI Deploy. For the full walkthrough (install, configure, deploy, call), see Deploy a ComfyUI workflow. For the bare API, see ComfyUI workflows API.
Beta. ComfyUI Deploy is in beta. Access to create and run deployed workflows is enabled per organization (see How do I get access?). The plugin, API surface, and pricing are stable but may still change; breaking changes are called out in the changelog before they ship.

Access and beta

Not yet. It is in beta, and creating or running deployed workflows is enabled per organization. The ComfyUI workflows area is visible to everyone in the dashboard, but an organization has to be enrolled before it can deploy or dispatch runs.

How do I get access?

Open the ComfyUI workflows section in the dashboard. If your organization is not enrolled yet, you will see a beta gate with a Request Beta Access button. Click it to register your interest. The Runflow team enrolls organizations from there; once your organization is enrolled the page shows your workflows and the API stops returning the beta error.
Creating a workflow and dispatching a run are gated on your organization being enrolled in the beta. Until then, both return 403 with the error code COMFYUI_DEPLOY_BETA_NOT_ENABLED. Read endpoints (listing and fetching workflows) are not gated. The gate also applies when you try to run another organization’s public workflow, so being able to see a workflow does not by itself let you run it. Request access in the dashboard, and the same calls will succeed once you are enrolled.
Yes. Beta access is granted per organization, so every member of an enrolled organization can use ComfyUI Deploy. Any of your organization’s API keys with the right scopes can deploy and call endpoints, and runs bill to the organization regardless of which member or key triggered them.

Install and setup

ComfyUI loaded before the plugin was on disk, the plugin landed in the wrong custom_nodes/ directory, or you only refreshed the browser tab. A browser refresh is not enough: the Python process has to re-exec. Confirm the plugin is under custom_nodes/, then fully restart the ComfyUI server process. After the restart a Runflow category appears in the node picker.
Put it under ComfyUI Settings, Runflow, Connection (the Runflow.ApiKey field). That storage is local to your machine and is never written into a workflow file. The Deploy node also exposes host and api_key widgets, but ComfyUI persists widget values into the workflow JSON, so a key typed there travels with every export, screenshot, and paste. Leave those widgets empty for normal use.
Before you click Deploy on a workflow you did not author, clear both the host and api_key widgets on the Deploy node (or delete and recreate the node). A workflow from a stranger can pre-fill host to send your key to their server.
It depends on what you do. Publishing a brand-new endpoint needs comfyui-workflows:read plus comfyui-workflows:create. Redeploying to the same slug from the same client also needs comfyui-workflows:edit. Deleting endpoints needs comfyui-workflows:delete. The Deploy button uses read to detect an existing slug, then create (new) or edit (replace). Issue the narrowest set you need: edit lets a key replace the graph of any existing endpoint your organization owns, so rotate the key on any suspicion of a leak. Dispatching a run (calling your deployed endpoint) uses the standard runs:create scope, the same as any model run, which is separate from the comfyui-workflows:* deploy and manage scopes above. Create a key.
There are no version tags published yet; the plugin tracks main. If you need a hard guarantee against future renames of node classes, widgets, or settings, pin the commit SHA after you clone. Watch the releases page for breaking changes.

Deploying your workflow

The slug comes from the Deploy node’s endpoint_name: lowercased, whitespace mapped to -, and anything outside a-z, 0-9, -, _ stripped. So Background Removal v2.1 becomes background-removal-v21 (the . is dropped). The default name is default, so rename it before deploying or you will publish to a slug literally called default. Pick a name without surprises.
Renaming endpoint_name changes the slug, which creates a new endpoint rather than updating the old one. To replace an existing endpoint, keep the same name and rely on the comfyui-workflows:edit scope so the deploy overwrites the same slug in place.
The plugin shows the underlying error in a browser alert. The usual causes:
  • Alert about an unconfigured key or URL. Runflow.ApiKey is blank in Settings (and the node’s api_key widget is also blank), or Runflow.ApiUrl was cleared. Save the key under Settings and deploy again.
  • A failed alert citing 401 or an invalid key. The key is missing, revoked, or for the wrong environment. Reissue it and re-save under Settings.
  • lookup failed or 403 on redeploy. Deploy first looks up the existing slug, then replaces it. A key with create but no read fails at the lookup; a key with read but no edit fails at the replace. Use read, create, and edit together for iterative deploys.
  • endpoint_name must be URL-safe. The slug came out empty after stripping characters. Pick a name with at least one letter or number.
Yes. The plugin is the convenient path, but the workflow resource has a REST surface you can call directly with any Runflow key that has the right scopes. Create with a POST to the workflows collection, replace the graph or swap GPU mode with a PATCH, and soft-delete with a DELETE. See ComfyUI workflows API for the full endpoint list and request bodies.
Delete the workflow with DELETE /v1/comfyui-workflows/{id} (needs the comfyui-workflows:delete scope). The delete is a soft delete: new runs are rejected with 404 on the dispatch route, but the workflow’s historical runs stay reachable through GET /v1/runs/{id}.

Calling your deployed workflow

What URL do I call to run my deployed workflow?

Dispatch a run against your workflow’s canonical owner and slug path. your-org is your organization slug (shown at the top of the dashboard, derived from your API key) and your-endpoint is what endpoint_name slugified to:
curl -X POST "https://api.runflow.io/v1/comfyui-workflows/your-org/your-endpoint/runs" \
  -H "Authorization: Bearer $RUNFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "input": {
      "prompt": "a sea otter holding a smooth pebble",
      "width": 1024,
      "height": 1024
    },
    "callback_url": "https://your-server.com/webhook"
  }'
The response is intentionally minimal: { "run_id": "...", "status": "queued" }. Track the run by polling GET /v1/runs/{id} until its status_code reaches a terminal state (succeeded or failed), or by passing a callback_url. See ComfyUI workflows API for the request body fields.
The input object is keyed by the input_id of each Runflow Input node in your workflow. The plugin ships typed input nodes: Runflow Input (String), (Int), (Float), (Boolean), (Image), and (File). Set a meaningful input_id on each one in your workflow; two inputs of the same type that keep the default id will collide. Send values under those same keys at call time.
Use a Runflow Input (Image) or Runflow Input (File) node, then send its value as either a runflow://assets/{uuid} reference to a previously uploaded asset or any https:// URL (plain http:// is rejected). A runflow:// asset used for an image input must be a PNG, JPEG, WebP, or GIF; a Runflow Input (File) accepts any file type. Runflow does not fetch or size-check an external URL when you submit the run; the worker downloads it at run time, so an unreachable or wrong-type URL surfaces as a run failure rather than a submit error.
A completed run’s output carries kind: "comfyui_outputs" and an outputs array — one entry per emitted artifact file, each labeled by the output_id of the Runflow Output node that produced it. A node that emits several files (a batch, say) yields several entries that share one output_id, so treat output_id as a node label, not a unique key:
{
  "id": "01J0...",
  "status_code": "succeeded",
  "output": {
    "kind": "comfyui_outputs",
    "outputs": [
      {
        "output_id": "image",
        "url": "https://...",
        "content_type": "image/png",
        "size_bytes": 1048576
      },
      {
        "output_id": "image",
        "url": "https://...",
        "content_type": "image/png",
        "size_bytes": 1041923
      }
    ]
  }
}
Iterate the whole array and group by output_id when you need per-node outputs. Each entry’s url is presigned and time-limited; download or copy outputs to your own storage on receipt. If a URL expires before you fetch it, re-request the run with GET /v1/runs/{id} and Runflow returns freshly signed URLs.
Dispatch is asynchronous. Pass a callback_url and Runflow POSTs the terminal run to it once the run reaches a final state, or omit it and poll GET /v1/runs/{id} until the status is terminal. See Runs for the lifecycle and Callbacks plus Verify callback signatures for the webhook pattern.

GPUs and billing

Deployed workflows bill per second of GPU wall-time: from when a worker picks up your run until it returns a result. There is no fixed per-call price, because the workflow is yours. The charge is applied once per run, to the organization that calls the run (the API key’s organization), not the workflow’s owner. Idle workers cost nothing, because the platform scales to zero between runs.
GPU selection is set on the workflow, not per run, through its gpu_mode. In auto (the default) the platform routes each run to the cheapest GPU that fits the workflow’s memory needs and promotes to a larger one if a run runs out of memory. In explicit the workflow is pinned to a chosen set of GPU models. You can switch gpu_mode with a PATCH to the workflow (owner only); changing the specific set of GPUs an explicit workflow is pinned to is done by redeploying it. The GPU types currently available and their rates are on runflow.io/pricing.
Rates are per GPU second and depend on the GPU your run lands on. The authoritative, current rate card lives at runflow.io/pricing; check there before sizing a budget. Total cost for a run is the GPU seconds it used multiplied by that GPU’s rate, which is why a faster GPU is not always more expensive overall. To estimate your own workflow, run it once and read the cost and GPU seconds back from GET /v1/runs/{id}, then multiply by your expected volume.
It depends on where it failed. If a worker picked up your run and then it failed during execution, or the worker was lost after claiming the job, you are billed for the GPU time that was actually consumed, because the platform pays its GPU provider for that time. Failures that happen before any worker starts (input validation, no compatible GPU available, or being rejected at admission for balance or pricing) are not charged. Cancelled runs are not charged.
Before dispatch, Runflow checks that your organization has a positive credit balance and that every GPU your run could land on has an active price. A non-positive balance is rejected with 402. A workflow pinned to a GPU that is inactive or unpriced is rejected with 422; redeploy it with an available GPU. These checks run before any work starts, so a rejected run is never charged.
The platform keeps a deployed workflow’s worker warm only while runs are arriving, then spins it down. The next run after an idle window pays a cold start while the worker boots and loads the model weights, and that startup time is part of the billed GPU wall-time. For latency-sensitive work, send a warming run on a schedule or keep the playground open during a session.
GET /v1/runs/{id} returns the cost and a cost breakdown for completed ComfyUI runs, including the GPU models used and the GPU seconds consumed per model. The webhook delivery payload does not carry cost — it has the run’s status, output, and duration_ms — so call GET /v1/runs/{id} for the cost and the per-GPU breakdown. To attribute spend per pipeline, set a metadata object when you create the run; it is echoed back on both the webhook and the run record.
Yes. Runs are bounded by a platform execution-time cap; a run that hits it is stopped. Because billing meters only the GPU time actually consumed, a run stopped at the cap is billed for the GPU seconds it used up to that point. If a workflow legitimately needs a longer ceiling, contact Runflow.

Limits and behavior

A deployed workflow has to be reproducible on the worker, and Runflow enforces that when you run it, not when you deploy it. Deploy itself does not check reproducibility, so a non-reproducible workflow saves and deploys cleanly, then its first run is rejected with 422. At run time Runflow rejects a custom node that has no pinned commit or whose origin is not https:// (a short allowlist of Runflow-internal origins aside), and rejects a model with no sha256 (the worker resolves model weights by that hash from its cache, so a public download URL is not required). ComfyUI itself must report an origin and commit. In practice this means public, pinned dependencies: a private repository the worker cannot clone fails the run. Local working-copy edits are recorded for audit but do not by themselves block a run.
The worker does not have your local-only models or custom nodes. Click Auto setup locally first to confirm the workflow resolves all of its dependencies (only on workflows you trust, since Auto setup runs git clone and pip install from URLs declared by the workflow). Models declared as download URLs in the workflow’s properties.models deploy without a local copy, but each still needs a sha256 to run: a URL-only entry with no hash is rejected at run time with an invalid_sha error. Widget-selected models must exist locally or carry a URL fallback, and likewise need a sha256.
Yes. Redeploy replaces the workflow in place under the same slug. Each run snapshots the workflow at the moment it is created, and that snapshot is what executes, so a run already in flight is unaffected by a redeploy that lands while it is running.
Workflows are private to your organization by default (is_public is false on create). A private workflow’s graph and endpoint are not visible or runnable by other organizations. Making a workflow public lets anyone who has its exact owner and slug load and run it by direct link, but it does not appear in Runflow’s browseable catalog unless the Runflow team approves it for listing. Either way, callers still need their own beta access and credits to run it.
Yes. The API applies a request-rate limit; if you exceed it, calls return 429 with the error code RATE_LIMITED. Retry with backoff (exponential backoff is a safe default). Separately, when all suitable GPU workers are busy, a dispatched run waits in queued until one frees up rather than being rejected. See Rate limits for more, and use the contact link there if you need a higher limit.
Not in the current version. There is no customer-facing way to cancel an in-progress ComfyUI run today; runs end on their own when they complete, fail, or hit the maximum duration.
ComfyUI ships with no authentication, and custom nodes can run arbitrary code on the host, so a ComfyUI port reachable from the public internet is a real risk. The Runflow settings panel has two controls for this: password authentication and a port exposure scan that reports your listen binding and checks whether your ports are reachable from the internet. Password auth takes two steps: set a username and password, and turn on the Enable password authentication toggle, which is off by default. Only with the toggle on and both fields set does the plugin require HTTP Basic auth on every request; a username and password alone leave the server open. If a port is open, enable password auth (toggle included), put ComfyUI behind a firewall or an authenticated proxy, or bind to localhost only.
The port exposure scan sends your public IP address to a third-party service (portchecker.io) so it can probe your ports from outside. No workflow data is sent.

Getting help

The main place to reach us is the Runflow Discord community. For bugs in the ComfyUI-Runflow plugin (the node package) you can also open an issue on GitHub, and for account or billing questions you can talk to the team. Including your organization slug, the endpoint slug, and a run id (when a specific run is involved) helps us respond faster.

Deploy a ComfyUI workflow

The full install, configure, deploy, and call walkthrough.

ComfyUI workflows API

The REST surface: dispatch, manage, inputs and outputs.

Runs

Run lifecycle, polling, and callbacks.

Pricing

The current GPU rate card.