ComfyUI-compatible /comfy
Base URL https://YOUR-HOST/comfy (alias /comfy/api/…). Use a comfy-scoped key. Never point clients at the raw ComfyUI port — that skips auth, metering, and policy floors.
Core flow
- Resolve a checkpoint from
GET /comfy/object_info/CheckpointLoaderSimpleorGET /comfy/models/checkpoints— do not hardcode OSS demo filenames likev1-5-pruned-emaonly.safetensorsunless they appear in that list. POST /comfy/promptwith an API-format graph →{prompt_id, number, node_errors}- Poll
GET /comfy/history/{prompt_id}until the id appears (terminal jobs only) - Download via
GET /comfy/view?filename=…&subfolder=…&type=output
High-level compose (generate / edit)
POST /api/comfy/compose builds an allowlisted img2img or txt2img graph and submits it through the same floors, ownership, and queue path as POST /comfy/prompt. Use a comfy-scoped key. intent: "analyze" is refused — caption/OCR is chat-vision on /v1/chat/completions, not a Comfy node we allowlist.
# Dry-run: inspect the graph (floors still run)
curl -sS https://YOUR-HOST/api/comfy/compose \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{
"intent":"edit","prompt":"soft daylight, keep identity",
"checkpoint":"YOUR.safetensors","image":"USERID_….jpg",
"denoise":0.55,"dry_run":true
}'
# Or multipart: field spec=JSON + field image=@photo.pngPoll GET /comfy/history/{prompt_id} then GET /comfy/view as usual. Raw graph submit remains fully supported for power users.
Img2img with an upload (raw graph)
Upload first, put the returned basename into LoadImage, then prompt — or use /api/comfy/compose above. Inputs are namespaced: the name is always {your-user-id}_{uuid}.jpg. A foreign basename is rejected at submit.
POST /comfy/upload/imagemultipart fieldimage→{name, subfolder, type:"input"}. Decoded, bounded, child-safety scanned, then available to Comfy.- Build an API-format graph with
LoadImage→image: <name from step 1>, plus your edit / img2img chain (VAE encode, KSampler, etc.). POST /comfy/prompt→ poll history →GET /comfy/viewfor outputs underusers/<you>/…
HOST=https://YOUR-HOST
KEY=YOUR_COMFY_KEY
# 1) Upload
NAME=$(curl -sS -F "image=@photo.png" \
-H "Authorization: Bearer $KEY" \
"$HOST/comfy/upload/image" | jq -r .name)
# 2) Resolve a real checkpoint on this host
CKPT=$(curl -sS "$HOST/comfy/models/checkpoints" \
-H "Authorization: Bearer $KEY" | jq -r '.[0]')
# 3) Prefer POST /api/comfy/compose, or POST /comfy/prompt with a full graph
# 4) Poll GET /comfy/history/{prompt_id} then GET /comfy/view?...Differences from stock ComfyUI (intentional)
- prompt_id is our job id, not Comfy's internal UUID
- History returns an entry only when the job is terminal (
done/failed/cancelled). Queued/running polls get{}so clients do not exit with “No images found” - Unknown checkpoint / disallowed node → 400 JSON
{error, node_errors}(Comfy-shaped), not plain text /viewis namespaced: outputs underusers/<your-id>/…; inputs must be basename<your-id>_…from/upload/imagePOST /free, Manager, userdata, terminal, customnode → 403 with an explanatory body (operator-only on a shared GPU)GET /wsis synthetic from your job rows — status / execution_start / executed / errors. No binary previews, and no relay of another tenant's upstream traffic- The node allowlist covers still-image graphs; custom nodes cannot be installed with an API key
curl: submit after resolving ckpt
HOST=https://YOUR-HOST KEY=YOUR_COMFY_KEY # Discover installed checkpoints curl -sS "$HOST/comfy/models/checkpoints" \ -H "Authorization: Bearer $KEY" # Or via object_info enum curl -sS "$HOST/comfy/object_info/CheckpointLoaderSimple" \ -H "Authorization: Bearer $KEY"
Python pattern: call object_info/CheckpointLoaderSimple, pick the first (or preferred) ckpt_name, build a minimal KSampler graph, poll history, then /view. On failure, print the JSON body — unknown ckpts return value_not_in_list under node_errors.
Related
Design notes for operators: repo docs/COMFYUI-AUTHENTICATED-PROXY.md. Studio card REST: /api/jobs.