Obraz documentation

What is Obraz

Obraz renders and edits a Wisent image. One service owns the job: the recipe that turns a creator, a pose and a description into a prompt, the adapter that makes the image that creator's, the render itself, the picture that comes back, and the edits made to it afterwards.

Editing takes the tools of a photo editor — crop, turn, resize, canvas and collage; tone controls, looks, duotone and colour tables; blur, mosaic, sharpening, vignette and grain; text, stickers and shapes — as one plan of steps, and sends the steps a model does (generating, background removal and replacement, erasing, extending the frame, restyling, colourising, restoring, retouching, relighting) to an image-model service: Brama in a Wisent deployment, or the OpenAI API. A person edits in the browser editor Obraz serves at /; the quickstart goes from installing Obraz to the first edited picture.

The recipe

  • The trigger word leads the prompt, because an adapter whose trigger word arrives late renders a stranger. Then the description (prompt), or the pose (pose_id) with its caption. The prompt sent is <trigger word>, <description>.
  • The adapter: one LoRA file (lora.filename) and its lora.strength, both required and passed to ComfyUI as given; how strongly a creator's adapter applies is the creator's recipe, not Obraz's.
  • The frame: width and height together, or neither, in which case the deployment's OBRAZ_FRAME (configuration) is used. Any size limit is ComfyUI's, and its refusal comes back as Obraz's error.

A request that carries graph, a ComfyUI graph the caller assembled, is executed as written and the recipe is not used.

The service

POST /v1/images            render one image
POST /v1/edits             edit pictures with a plan of steps (see Editing pictures)
GET  /v1/edits/operations  the steps an edit plan can hold
GET  /health               the process is up
GET  /                     the editor, in a browser
GET  /readyz               the renderer's address, and the image-model service model steps go to or why there is none
POST /v1/images
x-obraz-secret: <the deployment's secret>

{"prompt": "on a balcony at sunset",
 "trigger_word": "isre",
 "lora": {"filename": "isre_portrait_r64_v1", "strength": 0.9}}

The request also takes pose_id, caption, width, height, seed, character_id, graph and deliver_inline; any other field is refused. The answer is success, job_id, prompt (as rendered), url, and error when there is no image. With deliver_inline: true Obraz fetches the image from the renderer and adds image_base64 and mime_type; a fetch that fails is a failed render.

A Rust caller uses obraz::client::ObrazClient and never assembles a graph itself; the CLI is that client on a shell.

Refusals the service answers

Every refusal is the same answer shape with success: false and the reason in error.

  • 401 unauthorized: a missing or wrong x-obraz-secret.
  • 400 trigger_word is required: without it the adapter renders a stranger
  • 400 lora is required: name the creator's adapter file and strength
  • 400 lora.filename must name an adapter file
  • 400 lora.strength must be a number
  • 400 either prompt or pose_id is required
  • 400 width and height are required: this Obraz declares no OBRAZ_FRAME for a request that names no size
  • 400 width and height are named together, or neither
  • 400 width and height must be at least 1
  • 422 a lora without strength, refused by the JSON reader naming the field: missing field `strength`.
  • 503 this Obraz has no renderer: its deployment sets OBRAZ_COMFYUI_URL
  • 502 the renderer's refusal in its own words, or a failed inline fetch: the backend answered <status> for the image it had just rendered, the backend answered with an empty image.