3 FREE PREVIEWS / DAY SIGN IN →

API

One call. Same refiner.

POST a prompt, poll the run, and get every pass with critique and prompt-match score. The API uses the same spend rules as the web app: 15cr converged, free-with-cap close/no-lock outcomes, 2cr hedge past cap, and up-front reserve/refund for full renders.

Authentication

For programmatic API use, pass your key as a bearer token or use the X-API-Key header. The same key works across products. Browser session auth is separate; /refine/mine lists runs for the signed-in web session only.

Authorization: Bearer csk_your_key_here
# or
X-API-Key: csk_your_key_here

One key, every product — the same csk_ key authenticates to both estimate and refine and spends from your one shared codershack wallet. See and manage all your keys at https://wallet.codershack.com/account.

See and manage all your keys ->

POST /refine

Submit a run. Accepts application/json or multipart/form-data (for image file uploads). The response returns a job_id to poll. Full runs charge on the outcome; preview runs are free.

# −15 cr; close/diverged free (3/day)
curl -X POST https://refine.codershack.com/refine \
  -H "Authorization: Bearer csk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"prompt": "A backlit portrait bust with violet rim light"}'

Response:

{ "job_id": "8f3c1e2a-..." }

Request body

FieldTypeNotes
promptstringRequired. 1–8000 chars. Prose, or a JSON brief (see JSON mode).
paramsobjectOptional generation params (below). Unknown keys ignored.
max_itersint | nullCap the number of passes. Server clamps to max_image_iters (5); default runs to the cap.
previewboolDefault false. Preview mode (below).
input_imagesarrayImage-to-image / reference input. Up to 8 {url XOR b64, media_type?}. Exactly one of url / b64 per image.
reference_refinebool | nullWith input_images: true starts pass 1 from the reference; false/omitted uses the reference for critique only.
prompt_formatstring"auto" (default) · "prose" · "json". See JSON mode.

params

FieldTypeNotes
widthint256–2560, multiple of 32. Default 1024.
heightint256–2560, multiple of 32. Default 1024.
seedint | nullOptional. Fix for reproducible generation.

width × height must not exceed 4MP.

multipart/form-data

For file uploads, POST multipart/form-data with fields prompt, params (a JSON string), prompt_format, max_iters, preview, reference_refine, and one or more input_images file parts — in addition to the JSON body form above.

Preview mode & unlock

Set "preview": true for a fast, free look: 2 passes, the base arm only, no tournament. Previews are free subject to a daily cap (3/day). A preview that converges is locked — the full render is withheld (preview_locked: true, image_url: null) until you unlock it.

curl -X POST https://refine.codershack.com/refine/{job_id}/unlock \
  -H "Authorization: Bearer csk_your_key_here"

Unlock spends 15 credits and returns the job status with the full render now available. Close/diverged previews are not locked — their best pass is downloadable for free.

JSON structured prompt mode

When prompt_format is "json" — or "auto" and the prompt parses as a top-level JSON object — the prompt is treated as a structured brief. The refiner pins your leaf values (yours always win), deep-merges its own enrichment under them, sends compact JSON to JSON-capable arms and a deterministic prose flattening to the others, all within an 8000-char budget. Unparseable JSON (or "auto" with a non-JSON prompt) degrades to prose.

The request field prompt is still a string, so send the brief as serialized JSON:

{
  "prompt": "{\"subject\":\"a backlit portrait bust\",\"style\":\"editorial studio photography\",\"lighting\":\"violet rim light, soft key\",\"camera\":{\"lens\":\"85mm\",\"aperture\":\"f/1.8\"}}",
  "prompt_format": "json"
}

Every leaf you set (subject, lighting, camera.lens, …) is preserved verbatim; enrichment only adds keys you left out. It never overwrites what you specified.

GET /refine/{job_id}

Poll until status is done or failed. Ownership-enforced: you can only poll your own jobs (403 otherwise). Close and diverged runs still expose the best pass via image_url; locked previews return image_url: null until unlocked.

{
  "status": "done",
  "verdict": "converged",
  "prompt_match": 0.94,
  "passes": 3,
  "max_passes": 5,
  "mode": "full",
  "preview_locked": false,
  "unlocked": false,
  "image_url": "https://refine.codershack.com/refine/images/8f3c.../3.png",
  "input_image_urls": [],
  "error": null,
  "history": [
    {
      "pass": 3,
      "match": 0.94,
      "note": "",
      "render_call": "flux.2-pro",
      "critic": "claude-opus-4-8",
      "tokens": 4820,
      "latency_ms": 7310,
      "verdict": "CONVERGED",
      "image_url": "https://refine.codershack.com/refine/images/8f3c.../3.png",
      "prompt": "A backlit portrait bust with violet rim light, ..."
    }
  ]
}
FieldTypeNotes
statusstringqueued · running · done · failed.
verdictstring | nullconverged · close · diverged. Null until the run finishes.
prompt_matchfloat | nullBest pass's critic score, 0–1.
passesintPasses run.
max_passesint | nullCap for this run.
modestringfull · preview.
preview_lockedboolA converged preview awaiting unlock.
unlockedboolWhether a preview has been unlocked.
image_urlstring | nullFinal or best render. Null while no render exists, or while a converged preview is locked.
input_image_urlsarrayStored refs for any input images you sent.
errorstring | nullSet when status is failed.
history[]arrayPer pass: pass, match, note, render_call, critic, tokens (per-call token usage), latency_ms, verdict, image_url, prompt.

GET /refine/mine

List the signed-in web session's runs. This endpoint uses the browser session and returns 401 when there is no session; API keys are not accepted here. Query params limit (1–100, default 20) and offset. Returns { "jobs": [...], "limit", "offset" }; each job carries id, created_at, prompt, verdict, prompt_match, passes, mode, preview_locked, unlocked, and a thumbnail_ref (null while a preview is locked).

GET /refine/images/{job_id}/{image_name}

Fetch a stored render or input image (PNG). Ownership-enforced (403 otherwise). A locked preview's renders return 402 until you unlock — input images stay accessible. Use the image_url / input_image_urls values from the poll payload directly.

Credits

// −15 cr; close/diverged free (3/day)

Converged full runs charge 15 credits. Close and diverged runs return the pass history and the best pass for free up to the daily cap; past the cap, API hedges settle 2 credits. Full runs reserve 15 credits up front and refund when the outcome is free. Previews are free (3/day); unlocking a converged preview spends 15 credits.