Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.runflow.io/llms.txt

Use this file to discover all available pages before exploring further.

Beta. ComfyUI Deploy is in public beta. The plugin, API surface, and pricing rate cards are stable but may evolve. Expect breaking changes to be called out in the changelog before they ship.
ComfyUI-Runflow is a custom-node plugin that publishes a ComfyUI workflow to Runflow as a callable API. The plugin captures the workflow graph, the runtime manifest (ComfyUI commit, custom-node commits, package versions, cached models), and uploads it on a single click. The deployed workflow gets a playground in the Runflow dashboard and a stable API surface invocable with any Runflow key that has the right scopes.
Two things to internalize before you click Deploy on anything you did not author:
  1. Never type your API key into the Deploy node’s api_key widget. ComfyUI persists widget values into the workflow JSON, so a key entered on the node travels with every export, screenshot, paste, and bug-report attachment. Configure the key under Settings → Runflow → Connection instead; that storage is local to your machine and never serialized into a workflow file. The same caution applies to the Deploy node’s host widget. A workflow you load from a stranger can pre-populate host to send your key to their server when you click Deploy. Before clicking Deploy on any imported workflow, clear both host and api_key on the Deploy node (or delete and recreate the node so the widgets reset to empty).
  2. Auto setup runs git clone and pip install from URLs declared by the loaded workflow. Treat it like any other untrusted shell script: only click Auto setup for workflows from sources you trust. A hostile workflow can use the button to execute arbitrary code on your machine.

What you’ll do

Three steps: install the plugin, configure your key under Settings, click Deploy. The optional Runflow Input / Output nodes give the deployed API a clean schema.

Video walkthrough

End-to-end walkthrough of everything below — install, configure, deploy, call:

Prerequisites

  • A working ComfyUI install.
  • A Runflow API key. Create one with the scopes below.
  • python, pip, and git on PATH (used by the optional Auto setup feature).

Key scopes, by what you actually do

DoingScopes
Publish a brand-new endpoint, never update from this clientcomfyui-workflows:read + comfyui-workflows:create
Iterate (redeploy to the same slug from this client)add comfyui-workflows:edit
Remove workflows from this clientadd comfyui-workflows:delete
The Deploy button uses read to detect existing slugs and either create (new) or edit (replace) accordingly. edit is broad: it lets the key replace the graph of any existing endpoint owned by the org without changing the slug. If the key leaks, an attacker holding edit can silently swap a production workflow’s graph. Issue the narrowest scope set you actually need and rotate on any suspicion of leak. The plugin sends Authorization: Bearer <key> and lets the API derive your organization from the key. No organization id is needed.

Step 1: install the plugin

Clone the plugin into your ComfyUI custom_nodes/ directory and restart ComfyUI. $COMFYUI_DIR below is your ComfyUI install root (the folder that contains main.py, custom_nodes/, models/, etc.):
cd "$COMFYUI_DIR/custom_nodes"
git clone https://github.com/runflow-io/ComfyUI-Runflow.git
# or, for development against a checkout you already have:
# ln -s /path/to/ComfyUI-Runflow ComfyUI-Runflow
Restart ComfyUI (a UI refresh is not enough; the Python process has to re-exec). After the restart you’ll see a new Runflow category in the node picker. The plugin is at 1.0.0 on main HEAD; no version tags are published yet. Pin the commit SHA after clone if you need a hard guarantee against future renames of node classes, widgets, or settings.

Step 2: configure your account

Open ComfyUI Settings → Runflow → Connection and fill in:
SettingDefaultWhat it is
Runflow.ApiUrlhttps://api.runflow.ioAPI base URL. Override only when running against a staging stack.
Runflow.ApiKey(empty)The Runflow API key from above.
Settings persist locally on your machine; they are not written into any workflow file. Do this once and forget the per-node widgets exist. The Deploy node also exposes host and api_key widgets, but, as called out at the top of this page, those values are persisted into the workflow JSON and travel with every export. The widgets are there for ephemeral multi-account testing on a machine you control; for normal use, leave them empty and rely on the global Settings.

Step 3: deploy

Add a Runflow Deploy node (under the Runflow category) and set its endpoint_name widget. The default is default; rename it before clicking Deploy or you’ll publish to a slug literally called default. The slug is derived from this name: lowercased, with whitespace mapped to -, and anything outside a-z, 0-9, -, _ stripped. So Background Removal v2.1 becomes background-removal-v21 (the . is silently dropped); pick a name without surprises.
The Runflow Deploy node in ComfyUI with endpoint_name, host, and api_key widgets visible. Two buttons are shown below the widgets.
Click Deploy. The button flashes Deployed ✓ on success. On failure the plugin shows a browser alert() with the underlying error (missing API key, missing scopes, slug validation, HTTP failure, etc.) and the button returns to Deploy. The HTTP response is the terminal state; there is no separate deployment job to poll. On success, open the workflow in app.runflow.io, test it in the playground, inspect the graph the platform recorded, and adjust any settings exposed by your Runflow Input nodes.

Call the deployed workflow

The deployed workflow is a normal Runflow model invocation. Dispatch a run against your-org/your-endpoint, where your-org is your organization slug (visible at the top of the dashboard, derived from the API key) and your-endpoint is what endpoint_name slugified to. The example below assumes a workflow with three Runflow Input nodes (input_id set to prompt, width, height); replace those keys with whatever input_id you set on your own input nodes.
curl -X POST https://api.runflow.io/v1/models/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, studio photography",
      "width": 1024,
      "height": 1024
    },
    "callback_url": "https://your-server.com/webhook"
  }'
Omit callback_url to poll GET /v1/runs/{id} instead. See Runs for the lifecycle, Callbacks + Verify callback signatures for the async pattern, and the JavaScript SDK guide for a typed client. Invocations bill against the calling key like any other model run.

What you get back

The completed run’s output is keyed by the output_id of each Runflow Output node in the workflow. A workflow with one RunflowOutputImage(output_id="image") returns presigned image URLs under that key:
{
  "id": "01J0...",
  "status_code": "succeeded",
  "output": {
    "image": ["https://..."]
  }
}
Output URLs are presigned and time-limited. Download or re-upload them to your own storage on receipt.

Billing & GPU pricing

Deployed ComfyUI workflows bill per second of GPU wall-time: from the moment the worker boots the container for your run to the moment it returns the result. Idle workers cost nothing (the platform scales to zero between runs); cold starts on a new GPU type are billed alongside the run.

What you pay per second

GPUPer-second customer rateTypical use
L4 (24 GB)$0.000147/sSDXL-class inference, light workflows.
A10G (24 GB)$0.000222/sMid-range SDXL, smaller video models.
L40S (48 GB)$0.000444/sFlux, Wan, larger image models.
A100 80 GB$0.000917/sHeavy video, large memory footprints.
H100 80 GB$0.00125/sFastest path for production video workloads.
Rates above are indicative for the launch tier. The current authoritative rate card lives at runflow.io/pricing - check there before sizing a budget. Rates apply uniformly across runs from any caller (your API key, the playground, embedded Studio).

Picking a GPU

GPU selection is set on the workflow, not per run. Each ComfyUI workflow carries a gpu_mode of either:
  • auto (default): the platform routes each run to the cheapest GPU that fits the workflow’s memory footprint. Use this unless you have a specific reason.
  • explicit: the workflow is pinned to a chosen set of GPU models in gpu_explicit_models[] (e.g. a100_80gb, h100_80gb). Use this when a workflow needs guaranteed VRAM or a known fast path.
Set or change it via PATCH /v1/comfyui-workflows/{id} (workflow owner only). Once a workflow is explicit, every run uses that GPU set regardless of caller; rates above apply.

Scale-to-zero behavior

The platform keeps a deployed workflow’s worker warm only while runs are arriving. After a short idle window the worker spins down and the next run pays a cold-start cost (typically 10-40s of GPU time depending on the model weights). For latency-sensitive workloads, send a warming run on a schedule, or keep the playground open during a session.

What the run record shows

GET /v1/runs/{id} returns billing metrics for completed ComfyUI runs (GPU model used and GPU seconds consumed). Use those to attribute spend per pipeline; they also surface in webhook delivery payloads.

Define the external schema with Runflow Input / Output nodes

The plugin ships typed input and output nodes that declare the deployed API surface. Wire them into your workflow; everything else stays an internal implementation detail.
A ComfyUI workflow with three Runflow Input nodes (prompt, width, height) feeding a model node, with a Runflow Output (IMAGE) and the Runflow Deploy node also wired in.
The node classes available today:
NodeClassDefault input_id / output_idPurpose
Runflow Input (STRING)RunflowInputStringstring_inputString field on the deployed API.
Runflow Input (INT)RunflowInputIntint_inputInteger field.
Runflow Input (FLOAT)RunflowInputFloatfloat_inputFloating-point field.
Runflow Input (BOOLEAN)RunflowInputBooleanboolean_inputBoolean field.
Runflow Input (IMAGE)RunflowInputImageimage_inputImage input; callers send a URL or upload an asset.
Runflow Output (IMAGE)RunflowOutputImageimage_outputNames an IMAGE output. Each image in the batch is saved as PNG and returned.
Each input has three widgets: input_id (the stable join key the deployed API uses; never mutated at deploy time), display_name (label shown in the playground), description (help text). The output has output_id and output_name. Change input_id and output_id to something meaningful in your workflow; two inputs of the same type with the default ids will collide. Locally these nodes are pure pass-throughs of the value socket. At deploy time, the Runflow inference service rewrites each input’s upstream to inject the caller-supplied value and maps each output node id to its output_id so the callable API returns a stable, named set of artifacts.

Auto setup

Directly below Deploy on the same node, the Auto setup button installs every custom node and downloads every model the active workflow references. Useful when you load someone else’s workflow and want to skip chasing dependencies by hand. It is also the worst possible button to click on a workflow you do not trust (see the warning at the top of the page). Clicking the button opens a modal with two checkboxes (Install missing custom nodes, Download missing models) and a Start button. While the job runs, the modal shows a byte-progress bar for the current model download and a count-progress bar for custom-node installs; models and nodes install in parallel. When the job finishes, click Restart ComfyUI in the modal so the newly installed nodes register. Auto setup uses git clone --depth=1 plus git fetch --depth=1 origin <sha> plus git checkout <sha> (with a full-clone fallback if the host disables SHA-targeted fetches), then python -m pip install -r requirements.txt if the cloned repo carries one. Works on Linux, macOS, and Windows. Workflows can also declare model-download URLs in properties.models[].url. The deploy worker fetches those server-side before running the workflow. A hostile URL there is a server-side problem the platform mitigates, but review the URLs before deploying a community workflow; the dashboard surfaces the recorded graph after deploy if you want to double-check.

Troubleshooting

  • No Runflow category in the node picker. ComfyUI loaded before the plugin was on disk, the plugin landed in the wrong custom_nodes/ directory, or you only refreshed the browser tab. Confirm the path, then fully restart the ComfyUI server process.
  • Clicking Deploy raises an alert about an unconfigured key or URL. Either 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 click Deploy again.
  • Deploy returns 401 Unauthorized. The key is missing or revoked. Reissue and re-save under Settings.
  • Deploy raises a lookup failed or 403 Forbidden alert on redeploy. Deploy first GETs the existing slug, then PATCHes it. A key with comfyui-workflows:create but no :read fails at the lookup with lookup failed; a key with :read but no :edit fails at the PATCH with 403. Reissue with all three of read, create, edit for iterative deploys.
  • Deploy alerts that endpoint_name must be URL-safe. The slug came out empty after stripping characters outside a-z, 0-9, -, _. Pick a name with at least one allowed character.
  • A workflow that runs locally fails on Runflow. Local-only models or custom nodes are not on the worker. Click Auto setup locally first to confirm the workflow resolves (only on workflows you trust). Models declared via properties.models URLs deploy without needing a local copy; widget-selected models must exist locally or carry a URL fallback.
  • The endpoint slug changed unexpectedly. Renaming endpoint_name creates a new slug. To replace an existing endpoint, keep the same name and rely on comfyui-workflows:edit.

Pick a model

Decision tree from task to model.

Runs

Lifecycle, polling, callbacks.

Verify callback signatures

HMAC verification for the callback you set above.

JavaScript SDK

Typed client for the deployed API.