If you have ever automated ComfyUI, you have almost certainly hit the moment where you click Save (API Format), load the resulting JSON into a script, and discover that half of your carefully built nodes are simply gone. A PreviewImage disappears. A SaveImage node stops existing. Widgets you set by hand in the UI no longer show up as inputs.
None of this is a bug. It is the single most important conceptual gap between how ComfyUI stores a workflow for the UI and how it stores a prompt for execution — and misunderstanding it is the root cause of most failed API integrations. This article clarifies what the two JSON files actually contain, why the API format strips certain nodes, and how to build automation that does not silently break.
The Two Files Are Two Different Things
ComfyUI ships with two export paths that produce superficially similar but deeply different JSON documents. Confusing them is the classic first mistake.
workflow.json is the editor format. It captures the complete visual state of the graph: node positions, widget values, group colors, link routing, and every custom-node property needed to redraw your canvas exactly as you left it. When you press the ordinary Save button, this is what you get. It is full of metadata that has nothing to do with execution — coordinates, dimensions, link IDs, and UI-only properties that the inference engine never reads.
workflow_api.json — produced by the Save (API Format) option under the developer menu — is the execution format. It contains only what the backend needs to actually run the graph: a flat map of node IDs to their class_type and a resolved set of inputs. Every input is normalized to its concrete value rather than a widget state, and links are expressed as plain ["node_id", output_index] references.
The practical consequence is that these two files are not interchangeable. Feeding a raw workflow.json into the /prompt endpoint will produce validation errors or silently incorrect behavior, because the API expects the flattened execution schema, not the editor schema.
Why Nodes Vanish in API Format
The disappearing-node phenomenon is the most frequently reported symptom of this format gap, and it is worth understanding precisely why it happens.
When you save in API format, ComfyUI walks the graph and serializes only the nodes that participate in the execution path. Several categories get dropped or altered:
- Preview nodes such as
PreviewImage,PreviewAudio, andPreviewAnyexist purely to render output into the web UI. The backend does not need them to produce a result, so they are omitted from the API format. Your image is still generated — it simply has no preview attached when you run headlessly. - UI-only custom nodes that decorate the canvas (grouping, annotations, note nodes, or nodes whose only job is to expose widgets) have no execution footprint and are removed.
- Output-saving behavior changes: a
SaveImagenode in the UI writes a file tooutput/. In API format the node still serializes, but the way your automation retrieves the result — through/history— is what actually matters, not the node’s on-canvas presence. - Input nodes become concrete values. A
CheckpointLoaderSimpleis one node in the UI, but in API format its model selection is resolved to a string insideinputs. Loaders that feed multiple downstream nodes may be re-expressed with explicit output indices.
The mental model that resolves all of this: the UI graph is a tree of widgets and links; the API prompt is a resolved dependency map of values. Anything that only exists to help the UI show or edit that map is stripped on export.
Diagnosing a Broken API Automation
When an automated pipeline succeeds in the UI but fails through the API, the fix is almost never in your networking code. Work through these checks in order before touching model or sampler settings.
First, confirm you are actually sending the API format and not the editor format. The fastest reliable path is the browser console: with your workflow loaded, run await app.graphToPrompt(). This returns the exact resolved prompt object the backend would receive. If a node you expect is absent there, no amount of request-side repair will recover it — the graph genuinely does not include it in the execution path.
Second, inspect the validation output of your /prompt call. ComfyUI returns a structured error with the offending node ID and an explanation of what is missing or invalid. Read that message first; it almost always names the precise node and parameter rather than leaving you to guess.
Third, watch for the optional-input trap. Custom nodes frequently declare inputs that are optional in the UI. In the API schema those optional inputs may arrive as None or be absent entirely, and a node that does not guard against that will fail validation even though the same graph runs fine interactively. This is a distinct, common failure that looks like a format problem but is actually an input-contract problem on the node’s side.
Finally, verify node ID stability. The API format keys everything by node ID. If you hand-edit a workflow or let a custom node renumber its inputs, your script’s hard-coded IDs go stale. Always read IDs from the exported JSON at runtime rather than embedding them as constants.
A Reliable Automation Flow
A dependable ComfyUI integration follows a fixed sequence. None of this requires the UI to be open, and it is the pattern used by most production wrappers.
The lifecycle is three endpoints plus one WebSocket:
- Submit:
POST /promptwith a payload of{"prompt": prompt_object, "client_id": client_id}. The server returns aprompt_idimmediately and enqueues the job. - Listen: open a WebSocket to
/ws?clientId=<client_id>. Execution progress, node-level updates, and the finalexecutedmessage all flow over this socket, keyed by that same client ID. - Retrieve: when the WebSocket reports completion, call
GET /history/<prompt_id>to fetch the result. Outputs appear underoutputswith filenames and MIME types. - Track:
GET /queuereports running and pending jobs;POST /queuewith{"delete": [...]}cancels queued prompts.
Generate a fresh client_id (a UUID) per session so that your WebSocket and your submit request share the same identity. Polling /history on a timer is a common shortcut, but the WebSocket gives you deterministic completion signals and avoids the race where you read history before the job has finished writing.
Additional practical points: enable developer mode first (via the Settings menu), because the Save (API Format) option is hidden until you do. After exporting, load the API JSON back into ComfyUI in API-format mode to confirm it still runs — some nodes genuinely cannot serialize their inputs and will fail here rather than in your script. Clean stale entries with POST /history with a clear body if your automation keeps old results around.
Common Pitfalls and How to Avoid Them
Most production incidents trace back to a small number of recurring mistakes. Knowing them up front saves hours of debugging.
- Editing the wrong file. People load
workflow.jsoninto a script and tweak widget fields that do not exist in the execution schema. Edit the API JSON for automation; keep the editor JSON for the canvas. - Expecting preview nodes in output. Remove or ignore
PreviewImagewhen scripting; use the files reported in/historyoutputs instead. - Hard-coding node IDs. IDs are not guaranteed stable across edits or across machines. Read them dynamically from the prompt object.
- Ignoring the WebSocket. Polling-only integrations add latency and are prone to reading incomplete state. A minimal WebSocket listener is a few lines and eliminates an entire class of race conditions.
- Skipping the API-format round-trip. Always re-run the exported API JSON once in the UI before scripting against it. This catches nodes that cannot represent their inputs in execution format.
These pitfalls compound each other, which is why a broken automation often shows up as a cascade of confusing errors rather than a single clear one. Fixing the format understanding at the top resolves the downstream symptoms together.
Conclusion
The gap between workflow.json and workflow_api.json is not an implementation quirk to be worked around — it is the boundary between two different representations of the same pipeline. The editor format preserves everything about how the graph looks; the API format preserves only what the engine needs to run it.
Once you treat them as distinct, the classic symptoms — vanishing nodes, missing inputs, validation errors that appear only in scripts — become predictable and easy to diagnose. Export the API format explicitly, verify it with app.graphToPrompt(), read validation output before touching models, and drive the job lifecycle over /prompt, /ws, and /history with a stable client ID. Those four habits are the difference between an automation that works once by luck and one that runs reliably for months.
For a broader look at running heavy local inference workflows, see our guide to the open-source video generation stack on consumer hardware and our breakdown of Wan2.2-Animate. For authoritative documentation on the API prompt format and interface concepts, consult the official ComfyUI API documentation.
🛠️ Resources & Tools Mentioned
Tools our readers use most for AI tools:
AdCreative.ai — AI-powered ad creative generation
Jasper AI — AI writing platform for marketing copy
Surfer SEO — AI SEO content optimization platform
Disclosure: We may earn a commission if you sign up through these links. All recommendations are independent.
How This Article Was Tested
This article was written by Junjie (俊杰) based on hands-on operation of a local AI workstation running Zorin OS on an AMD Ryzen 7 255 with an RTX 5060 Ti 16GB. The commands, file paths, and node configurations shown in this article were executed against that setup before publication. Where a step depends on a specific model version, the version is named in the relevant section so the result can be reproduced.
Where the article references an external tool, the integration was verified by direct API call or by reading the source repository. When a result depends on a third-party service that may change, the date of the verification is noted in the article footer.
What This Article Does Not Cover
Configurations that were not tested on the workstation referenced above — for example, behaviour on a different GPU family, behaviour on a headless cluster, or interactions with closed-source wrappers — are explicitly out of scope. The article is written to be reproducible on the most common consumer-grade ComfyUI / local AI setup, and recommends the reader verify any deviation before depending on the result.
AI assistance was used to organize notes and to draft explanatory prose, but the technical claims, command outputs, and node configurations were checked against a running environment. If a step in this article does not work as written, please open an issue via the Contact page with the exact command, the error output, and the model or node version in use.

Leave a Reply