Civitai Orchestration runs image-generation workflows at https://orchestration.civitai.com. For Stable Diffusion / Z-Image style jobs, the important step type is $type: "imageGen" with input.engine: "sdcpp".
This skill records the working request shapes verified on Alex's VPS with CIVITAI_TOKEN / CIVITAI_API_KEY in /home/avalon/.hermes/.env.
sdcpp image generation.sdcpp failures around model URNs, ecosystems, LoRAs, or sampler fields.Do not use this for Civitai Site API model browsing alone; use the Site API docs/workflows for that.
Environment:
CIVITAI_TOKEN=...
# or
CIVITAI_API_KEY=...
Base URL:
https://orchestration.civitai.com
Submit:
POST /v2/consumer/workflows?wait=60&whatif=false
Authorization: Bearer <token>
Content-Type: application/json
Poll:
GET /v2/consumer/workflows/{workflowId}
Authorization: Bearer <token>
Use whatif=true first to validate and preview Buzz cost without executing.
All image workflows need a step discriminator:
{
"allowMatureContent": true,
"steps": [
{
"$type": "imageGen",
"input": {
"engine": "sdcpp",
"ecosystem": "zImage",
"model": "turbo",
"operation": "createImage",
"prompt": "...",
"width": 1024,
"height": 1024,
"steps": 9,
"cfgScale": 1,
"quantity": 1
}
}
]
}
For sdcpp, use these field names:
sampleMethod not samplerschedule not schedulerstrength not denoiseStrength for img2img / createVariantFor Comfy engines, the field names differ (sampler, scheduler, denoiseStrength). Do not mix them.
The sdcpp engine does not support createVariant or editImage for SD1/SDXL/Z-Image. Use the correct engine per goal:
| Goal | Ecosystem | Engine | Operation | Notes |
|---|---|---|---|---|
| txt2img | zImage | sdcpp |
createImage |
Fast, verified working |
| txt2img | sd1 | sdcpp |
createImage |
Use checkpoint AIR |
| txt2img | sdxl | sdcpp |
createImage |
Use checkpoint AIR |
| txt2img | flux1 | sdcpp |
createImage |
Verified working |
| txt2img | flux2Dev | sdcpp |
createImage |
Verified working |
| txt2img | flux2Klein | sdcpp |
createImage |
Simplest Flux, no extra model refs |
| img2img / remix | sd1 | comfy |
createVariant |
image + denoiseStrength + model AIR URN required |
| img2img / remix | sdxl | comfy |
createVariant |
image + denoiseStrength + model AIR URN required |
| img2img / remix | flux1 | comfy |
createVariant |
image + denoiseStrength + model AIR URN required |
| img2img / remix | flux2Dev | sdcpp |
createVariant |
image + strength |
| img2img / remix | flux2Klein | sdcpp |
createVariant |
image + strength — simplest and most reliable reference-image path |
| inpainting | flux2Dev | comfy |
editImage |
images[] array |
Critical: If you try sdcpp + ecosystem: sdxl + operation: createVariant, you get a 400 validation error: "JSON deserialization for type '...SdxlVariantImageGenInput' was missing required properties including: 'model'" — because the schema does not exist. Switch to engine: "comfy".
Flux1 sdcpp createVariant requires extra model refs: Unlike Flux2Dev/Flux2Klein, Flux1 sdcpp createVariant requires diffuserModel, vaeModel, clipLModel, and t5XXLModel AIR URNs. If missing, you get: "JSON deserialization ... was missing required properties including: 'diffuserModel'". Use Flux2Klein for simpler reference-image workflows instead.
flux2Klein + sdcpp is the simplest reference-image path. Unlike Flux1 sdcpp, it does not require diffuserModel, vaeModel, clipLModel, or t5XXLModel.
{
"allowMatureContent": true,
"steps": [{
"$type": "imageGen",
"input": {
"engine": "sdcpp",
"ecosystem": "flux2Klein",
"operation": "createVariant",
"image": "https://image.civitai.com/.../original=true/....jpg",
"strength": 0.65,
"prompt": "same characters, now in a luxurious bedroom with silk sheets, warm candlelight",
"width": 1216,
"height": 832,
"sampleMethod": "euler",
"schedule": "simple",
"steps": 8,
"cfgScale": 1,
"quantity": 1,
"modelVersion": "4b"
}
}]
}
Key:
- modelVersion: "4b" or "9b" (default "4b"). Much simpler than Flux1's full model AIRs.
- strength: 0.0 = no change, 1.0 = complete change. Default 0.7.
- Typical Flux2Klein params from ComfyUI workflows: Euler sampler, 8 steps, CFG 1, 1216×832.
Verified succeeded. Cost: 8 Buzz for 1024², 9 steps.
{
"allowMatureContent": true,
"steps": [
{
"$type": "imageGen",
"input": {
"engine": "sdcpp",
"ecosystem": "zImage",
"model": "turbo",
"operation": "createImage",
"prompt": "a cute robot reading a book in a sunlit library, crisp detailed illustration",
"negativePrompt": "blurry, low quality",
"width": 1024,
"height": 1024,
"steps": 9,
"cfgScale": 1,
"quantity": 1
}
}
]
}
Notes:
diffuserModel: "urn:air:zimageturbo:checkpoint:civitai:2168935@2442439".Verified succeeded. Cost: 20 Buzz for 1024², 20 steps.
{
"allowMatureContent": true,
"steps": [
{
"$type": "imageGen",
"input": {
"engine": "sdcpp",
"ecosystem": "zImage",
"model": "base",
"operation": "createImage",
"prompt": "a cozy cabin in snowy mountains at sunrise, cinematic, detailed",
"negativePrompt": "blurry, low quality",
"width": 1024,
"height": 1024,
"steps": 20,
"cfgScale": 4,
"quantity": 1
}
}
]
}
Notes:
model: "base" vs "turbo" as Civitai-managed aliases and inspect returned workflow input if exact backend matters.Verified succeeded. Cost: 4 Buzz for 512², 20 steps.
{
"allowMatureContent": true,
"steps": [
{
"$type": "imageGen",
"input": {
"engine": "sdcpp",
"ecosystem": "sd1",
"operation": "createImage",
"model": "urn:air:sd1:checkpoint:civitai:4384@128713",
"prompt": "masterpiece, best quality, a cute robot reading a book, studio lighting",
"negativePrompt": "worst quality, low quality, blurry",
"width": 512,
"height": 512,
"steps": 20,
"cfgScale": 7,
"clipSkip": 2,
"quantity": 1
}
}
]
}
Important: for SD1/SDXL checkpoints, use checkpoint in AIR URNs, not model:
urn:air:sd1:checkpoint:civitai:<modelId>@<versionId>
urn:air:sdxl:checkpoint:civitai:<modelId>@<versionId>
Using urn:air:sdxl:model:... caused silent worker failures in earlier tests.
Verified succeeded with the NexBlend Z-Image Turbo LoRA.
Working LoRA resource:
model id: 2669120
version id: 2997054
trained word: nexblend
tested AIR: urn:air:zimageturbo:lora:civitai:2669120@2997054
Payload:
{
"allowMatureContent": true,
"steps": [
{
"$type": "imageGen",
"input": {
"engine": "sdcpp",
"ecosystem": "zImage",
"model": "turbo",
"operation": "createImage",
"prompt": "nexblend, asian fashion model portrait, professional studio photo, elegant outfit, detailed skin texture, soft cinematic lighting",
"negativePrompt": "blurry, low quality, distorted hands",
"width": 1024,
"height": 1024,
"steps": 9,
"cfgScale": 1,
"quantity": 1,
"loras": {
"urn:air:zimageturbo:lora:civitai:2669120@2997054": 0.8
}
}
}
]
}
Cost preview showed fixed.additionalResources: 1, making total 9 Buzz.
Vision verification: professional Asian fashion-model portrait, high quality.
For Z-Image Turbo LoRAs, use lowercase/internal ecosystem in the LoRA AIR:
urn:air:zimageturbo:lora:civitai:<modelId>@<versionId>
These variants failed or stalled in tests:
urn:air:zImage:lora:civitai:2669120@2997054 # failed instantly
urn:air:zImageTurbo:lora:civitai:2669120@2997054 # failed instantly
urn:air:zimage:lora:civitai:2669120@2997054 # accepted but hung/processed slowly in test
Best rule: inspect the returned workflow steps[0].input.diffuserModel; for Z-Image Turbo it was urn:air:zimageturbo:checkpoint:..., so LoRAs should use zimageturbo too.
Successful image outputs are under:
workflow.steps[n].output.images[]
Not always under blobs[]. Each image has:
idavailableurlpreviewUrlnsfwLevelSigned URLs are temporary. For app integration, download immediately and persist to the app's own storage. Never expose signed URLs in logs or chat.
Use a Python or curl script that:
whatif=true.whatif=false&wait=60 or wait=0.succeeded, failed, or canceled.output.images[], not just output.blobs[].Minimal Python pattern:
import os, requests, time
TOKEN = os.environ["CIVITAI_TOKEN"]
BASE = "https://orchestration.civitai.com/v2/consumer/workflows"
HEADERS = {"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"}
payload = {"allowMatureContent": True, "steps": [{"$type": "imageGen", "input": {...}}]}
r = requests.post(BASE, params={"whatif": "true", "wait": 0}, headers=HEADERS, json=payload)
r.raise_for_status()
r = requests.post(BASE, params={"whatif": "false", "wait": 0}, headers=HEADERS, json=payload)
r.raise_for_status()
workflow = r.json()
wid = workflow["id"]
while workflow["status"] in {"scheduled", "pending", "processing", "unassigned"}:
time.sleep(10)
workflow = requests.get(f"{BASE}/{wid}", headers=HEADERS).json()
for step in workflow.get("steps", []):
images = (step.get("output") or {}).get("images") or []
for image in images:
if image.get("available") and image.get("url"):
data = requests.get(image["url"]).content
# write/upload data; do not log signed URL
Wrong AIR type: SD1/SDXL checkpoints should use checkpoint, not model.
Wrong Z-Image LoRA ecosystem: Use zimageturbo for Z-Image Turbo LoRA AIRs, not zImage or zImageTurbo.
Gallery URLs vs single image URLs: Civitai URLs like https://civitai.red/images/<postId> are gallery posts containing multiple images (often 50–100). The API GET /api/v1/images?ids=<postId> returns an items array. Filter by baseModel, prompt content, or modelVersionIds to find the specific image you want. Do not assume the first item is the right one.
Looking only for blobs[]: sdcpp image output appeared in output.images[].
Assuming wait=60 always returns terminal state: Z-Image Turbo took ~58s in one test and returned processing; poll after submit.
Mixing engine parameter names: sdcpp uses sampleMethod / schedule; Comfy uses sampler / scheduler.
Using SDXL clipSkip: SDXL docs say clipSkip is invalid. Use it only for SD1 if needed.
Silent failures: Bad resources can fail instantly with errors: [] and debit+credit refund. Check transactions, jobs[].status, and normalized input.
sdcpp does NOT support img2img for SD1/SDXL/Z-Image: Use engine: "comfy" with operation: "createVariant" for remixes. For Flux ecosystems, use flux2Klein or flux2Dev with sdcpp — the simplest reference-image path. See references/flux2klein-createVariant.md.
Blocking inline polls for hours: Civitai queues are often very slow. Inline scripts will time out. Submit with wait=0, then poll asynchronously via cron or a background process. See references/async-polling-and-queue-behavior.md and scripts/check_civitai_workflows.py.
Civitai image API ids lookup returns wrong image: GET /api/v1/images?ids=<imageId> returns a gallery/post with 50–100 items, not the specific image. The first item is often completely unrelated. Do not use this endpoint for metadata extraction. Use bulk feeds, direct image URLs, or upload local images to blob storage. See references/civitai-image-api-id-lookup-pitfall.md.
civitai.red gallery URLs are post IDs, not image IDs: URLs like https://civitai.red/images/<id> resolve to galleries containing multiple images. The ids parameter on the Site API returns the same post for many different IDs. Always filter bulk results or use direct image.civitai.com URLs.
From live testing (June 2026):
Succeeded:
- 6621915-20260603011327874 — Flux2Klein createImage, 3 Buzz, output nsfwLevel: r
- 6621915-20260603011339232 — Flux2Klein createVariant (uploaded reference → new scene), 3 Buzz, output nsfwLevel: pg13 (not explicit — Civitai may moderate or the prompt wasn't strong enough)
- 6621915-20260602234936834 — Z-Image Turbo no LoRA, 8 Buzz
- 6621915-20260602235037058 — Z-Image Base no LoRA, 20 Buzz
- 6621915-20260602235123246 — SD1/DreamShaper, 4 Buzz
- 6621915-20260602235313207 — Z-Image Turbo + NexBlend LoRA, 9 Buzz
- 6621915-20260603004705697 — Adult NSFW hardcore, eventually succeeded after hours in queue
Failed:
- 6621915-20260603010749753 — Comfy SDXL createVariant (cyberpunk remix): failed after 23 min, cost 0 (refunded), output.errors: [], job.result: None. Silent failure with no diagnostic message.
- LoRA AIR variants zImage/zImageTurbo for NexBlend: instant failure with errors: [].
Key Discovery: Flux2Klein sdcpp createVariant is the simplest confirmed working reference-image path on Civitai Orchestration. Comfy SDXL createVariant silently fails with empty errors.
references/sdcpp-vs-comfy-operation-matrix.md — OpenAPI-level confirmation of which engine supports which operations per ecosystem, with the exact 400 error text.references/flux2klein-createVariant.md — Flux2Klein sdcpp reference-image workflow, the simplest img2img/remix path on Civitai Orchestration.references/civitai-image-api-id-lookup-pitfall.md — Why GET /api/v1/images?ids=<id> returns the wrong image, and the correct workarounds for metadata extraction.references/async-polling-and-queue-behavior.md — Why workflows stay scheduled for hours, how to avoid inline timeouts, and the cron-based polling pattern.references/nsfw-moderation-notes.md — Observed nsfwLevel behavior and Civitai moderation on adult content.templates/comfy-sdxl-createVariant.json — Starter payload for Comfy SDXL img2img / character remix.scripts/check_civitai_workflows.py — Reusable polling script with state tracking and auto-download.GET https://civitai.com/api/v1/me returns 200 with the token.whatif=true returns expected cost and no validation error.succeeded.steps[0].output.images[0].available == true.fixed.additionalResources and prompt uses the LoRA trained word when applicable.