APIMaster Text to Image
Gpt-image-2 inside your graph, and why 4k keeps timing out
- config
- images
- urls
The greenest thing you can do in ComfyUI is generate locally. Sometimes that isn't an option: you can't download gpt-image-2, Seedream or a Midjourney model - there are no weights, so there's no checkpoints folder you can put them in. The other reason is duller and more common: you don't have a GPU that can run what you want.
APIMaster Text to Image is the door for both. It's a prompt in, IMAGE out - a tensor that behaves like any local sampler's output, so it sits next to your upscaler, your mask nodes, your Save Image, and nothing downstream knows the pixels came from a server.
What it actually does
Your widgets become a JSON payload, and the payload goes to {base_url}/images/generations with your key in a bearer header. In sync mode you wait for the response and the image comes back in one request. In async mode the node POSTs to /images/generations/async, gets a task_id, then polls /tasks/{task_id} every four seconds (first poll after a deliberate twelve-second sleep - an immediate poll just burns a request on a job that cannot be finished yet), up to about thirteen minutes before it gives up.
Either way it then downloads each returned URL, decodes the bytes into a float tensor of shape [1, H, W, 3], and concatenates the batch. That's the reason this pairs with anything: the API result is converted into the exact IMAGE contract local nodes use.
Inputs you'll actually set
config comes from an APIMaster Config node - wire it in once, point every generator at it. prompt is the multiline text box. model is a dropdown of five ids (gpt-image-2, doubao-seedream-5-0-pro-260628, gemini-3.1-flash-image, midjourney-v8.2, midjourney-niji-7) - ids are case-sensitive and catalogues move, so treat the dropdown as a snapshot. size is the aspect ratio (sixteen options, default 1:1); it's omitted from the request entirely when you leave it on auto, which lets the gateway decide. resolution is 1k / 2k / 4k, and it's the setting that changes both your bill and your failure mode. batch_size (1–8) sets n in the payload, and mode is sync or async.
Outputs: images is an IMAGE batch - wire it to Preview Image to eyeball it, or to Save Image, or straight into a local resample/upscale pass. urls is a newline-joined STRING of the generated image URLs, which is handy when you want the hosted link rather than the tensor.
The sync vs async trap
This is the one thing to learn before you spend money. Sync mode is simpler and fine at 1k. Under the hood the client scales its own read timeout by resolution - about 200 seconds at 1k, 320 at 2k, 620 at 4k - because a fast timeout would abort healthy jobs. But your gateway's timeout is a separate number you don't control, and at 2k and especially 4k the job can outlive it and come back as HTTP 408. Retrying the same way won't help. Switch mode to async and it becomes a submit-and-poll job with a far longer horizon.
Be aware that sync mode blocks the whole queue while it waits. The canvas looks frozen, there's no progress bar, and the node prints one line to the console when it's done. Async at least prints a status every fifth poll, roughly every 20 seconds.
Install
ComfyUI Manager: search APIMaster and restart. Manually:
cd ComfyUI/custom_nodes
git clone https://github.com/apimaster-ai/ComfyUI-APIMaster
Nothing to pip install; the dependency list is intentionally empty and the client is standard library only, so this is one of the very few packs that can't wreck your environment. Then export your key before starting ComfyUI:
export APIMASTER_API_KEY=sk-...
Leave the api_key field on the Config node empty. Anything you type there is saved into the workflow JSON, and workflow JSON gets shared - that's how keys leak.
Where people get burned
HTTP 400 ... use the Images API means a chat model id ended up on an image node - that's what a model_override typo looks like. HTTP 402 is an empty balance. HTTP 429 is a rate limit, retry shortly. If the endpoint returns different-sized images in one batch, the node raises instead of quietly resizing them. That's a deliberate choice and I agree with it: silently stretching a mixed batch is a bug you'd debug for an hour. Set batch_size to 1, or pin an explicit size so every image matches.
On price: the README warns that quality, background and format options narrow which upstream channels can serve a request and can route you to a pricier one - but the shipped node doesn't expose those fields at all. Your real cost levers are resolution, model and batch_size, and resolution is the big one.
Last, unromantic point: picking a closed model means accepting its filter. These are hosted models with a moderation pass you can't patch, and they change behaviour on the vendor's schedule, not yours. If a prompt that worked last month refuses today, that's the vendor, not the node.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| config | APIMASTER_CONFIG | — | |
| prompt | STRING | a corgi astronaut on the moon, cinematic | — |
| model | COMBO | gpt-image-2 | 5 options: gpt-image-2, doubao-seedream-5-0-pro-260628, gemini-3.1-flash-image, midjourney-v8.2, midjourney-niji-7 |
| size | COMBO | 1:1 | 16 options: auto, 1:1, 3:2, 2:3, 4:3, 3:4, +10 |
| resolution | COMBO | 1k | 3 options: 1k, 2k, 4k |
| batch_size | INT | 11–8 | — |
| mode | COMBO | sync | 2 options: sync, async |
| model_overrideopt | STRING | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| images | IMAGE | — |
| urls | STRING | — |