API Chat (Direct Key) · Tank
Your API key gets saved inside the workflow
- image
- video_frames
- video
- response
- usage
- stats
- reasoning
- raw_response
There's no subtlety to API Chat (Direct Key) · Tank: it's an HTTP client wearing a ComfyUI costume. You paste a base URL, an exact model ID and a key into the node, attach an image or video if you like, and you get text back. Nothing loads on your GPU. Nothing needs the local Qwen3.8 stack. The API nodes in this pack work standalone, which is exactly why they're the right first stop when the model you want has no open weights at all.
That covers the honest reasons to use an API path - a closed model you can't download, a frontier-quality rewrite, or a loopback server like LM Studio or llama.cpp --server that speaks the OpenAI format. It also means accepting the tradeoffs the KB is blunt about: every call is metered, your prompts and reference images leave your machine, and the provider's content filter follows the model, with nothing local to patch. The community's default posture by mid-2026 is that an API node is the tool for a model you cannot run, and the wrong default for one you can.
And the one thing to internalize before you type: the key lives in the node, which means it lives in the workflow JSON. Screenshot it, share the workflow, dump it to Civitai, and you've handed over your key.
The inputs that matter
- base_url -
https://api.openai.com/v1by default. Do not append/chat/completions; the node builds that path itself. Point it athttp://127.0.0.1:1234/v1for LM Studio,http://127.0.0.1:8080/v1for a llama.cpp server, or your provider's/v1. - model - the provider's exact model ID string. No dropdown, no validation, no helpful guess. If it's wrong you get an API error and a wasted call.
- api_key - stored in the workflow. If you're using a hosted provider, this is the node you clean before sharing; the environment-key sibling exists precisely to avoid this.
- prompt and system_prompt - the request. System prompt is where you put format rules; leave it blank and you get the provider's default assistant behaviour, complete with its habits.
- max_tokens = 0 and temperature = 0 mean omit the parameter, not "zero of that thing" - the provider's own defaults apply. Temperature 0 here is not deterministic sampling; it's "don't send temperature at all."
- thinking_mode -
autoleaves the provider alone,offdisables reasoning where supported, and low/medium/high/xhigh/max are the five unified effort tiers. Providers that don't know a tier may reject it or clamp it. If you're doing short structured rewrites,offorlowis usually the better answer than a reasoner thinking out loud into your prompt.
Optional and only if you need them: image (one image or a whole batch - every frame gets sent, so watch the bill), video_frames sampled down by max_video_frames (8), and video with video_transport. frames is the safe default because it works broadly; video_url only if your provider accepts native video. auto tries to encode and falls back to frames - it will not retry a rejected request as frames, so a vague error there is worth reading twice.
Outputs
Five strings: response (the clean text - this is the one you feed into a prompt node), usage (provider-reported prompt and completion tokens, or n/a), stats (timing and backend info; also where the effective reasoning setting shows up), reasoning (empty when the provider doesn't expose it) and raw_response. The node is an output node, so it also renders the response as text on the canvas. One behaviour worth knowing: ComfyUI's interrupt button works here - hit it while waiting and the local request is closed. Whether the remote job stops and stops billing is the provider's business, not this node's.
Install
Part of TankNodes: ComfyUI Manager → search Tank (registry ID qwen38-vl), or git clone https://github.com/xzbdqian10nian/ComfyUI-TankNodes.git into ComfyUI/custom_nodes and restart. No llama-cpp-python needed for this node - the dependency list is intentionally tiny, and the pack uses the OpenAI SDK when it's already present, falling back to the aiohttp that ComfyUI ships with otherwise.
Where people get burned
404s. Almost always a base URL with /chat/completions already on it, or a missing /v1. 401s are the key, and remember it's the one in the node field, not in your environment - that's the other node's job. "model not found" means the exact ID is wrong; provider catalogues change names freely, so copy it from the provider's own docs rather than from a tutorial. Unexpectedly long or expensive output usually traces back to max_tokens = 0, which hands the length decision to the provider. And if the same image keeps costing you more than you expect, count the batch you sent: every item in the image input goes out in one request.
Inputs (14)
| Name | Type | Default | Description |
|---|---|---|---|
| base_url | STRING | https://api.openai.com/v1 | OpenAI-compatible API base URL; do not include /chat/completions. |
| model | STRING | Exact model ID exposed by the API provider. | |
| api_key | STRING | API key used for this request. It is not read from an environment variable. | |
| system_prompt | STRING | Optional persona and system-level instruction; leave blank for the provider default. | |
| prompt | STRING | User instruction sent to the API, together with any attached image or video input. | |
| max_tokens | INT | 00–32768 | Maximum output token count. 0 omits this parameter and uses the provider default. |
| temperature | FLOAT | 0.000–2 | Sampling temperature. 0 means do not send this parameter; use the provider default. |
| seed | INT | 10–4294967295 | Seed sent for sampling when the provider supports it; providers may ignore it. |
| thinking_mode | COMBO | auto | Reasoning control: auto leaves the provider unchanged, off disables reasoning when supported, and low/medium/high/xhigh/max are the five unified effort tiers. Unsupported tiers may be rejected or mapped by the provider. |
| max_video_framesopt | INT | 81–64 | Sample at most this many frames from video or video frames. Every image in the image input is still sent. |
| video_transportopt | COMBO | frames | Choose sampled image frames, native video_url, or automatic native-video fallback. The provider must support the selected format. |
| imageopt | IMAGE | One still image or an IMAGE batch; every item is sent in the same API request. | |
| video_framesopt | IMAGE | Decoded video as an IMAGE batch; frames are sampled according to max_video_frames. | |
| videoopt | VIDEO | ComfyUI VIDEO input; use frames for broad support or video_url only when the provider supports native video. |
Outputs (5)
| Name | Type | Description |
|---|---|---|
| response | STRING | Final API response text. |
| usage | STRING | Usage JSON returned by the provider, when available. |
| stats | STRING | Request timing and backend information. |
| reasoning | STRING | Reasoning text when the provider returns it; otherwise empty. |
| raw_response | STRING | Original assistant content or complete tool-call message. |