API reference · Media
Image generation
Generate an image from a text prompt — five frame formats.
All image generation is asynchronous: the call charges and enqueues the render, answering 202 immediately with one job id per take. Poll GET /v1/images/generations/{id} every few seconds until status is succeeded (the image is in data) or failed (refunded). This is the same contract as video — a slow cold start never times out your request.
Set store: true to unlock a permanent public static URL for the render — the same media that is always persisted, served at a fixed address your users can hotlink. The Store's rate (2 credits / started 10MB — one block for any 1024×1024 image) is charged on top and itemized in your ledger. Without it, completed jobs answer with a short-lived signed URL (30 minutes) — mint a fresh one by re-fetching the job or the creation.
Image engines come in two families: text-to-image and reference-driven renders. Text-to-image: the eroq engines eroq-anime, eroq-flash-image and eroq-flux-image, plus the third-party engines gpt-image-2-5-sunburst, gpt-image-2-5-flare, nano-banana-2-1, seedream-5-0-pro, nano-banana-pro, flux-3-image and grok-imagine-2-0. Reference-driven: eroq-one reads up to 10 reference photos, eroq-uncensored / eroq-krea2 hold up to 4. EDIT is a mode, not a model: send edit: true and the chosen engine runs its instruction editor — picture 1 (references[0]) is the scene being edited, picture 2 an optional subject ref, and the prompt is the plain-language instruction (Krea 2 takes 2 pictures, Eroq One up to 10). cfg_scale applies to the engines eroq runs itself (eroq-krea2, eroq-uncensored, eroq-one, eroq-anime) and negative_prompt to eroq-anime; the third-party engines render from the prompt and the aspect alone. Prompts outside the acceptable-use policy return content_blocked and are not charged.
Every render is saved to your creation library (the completed job carries library_id — manage with /v1/creations). The first 5 GB of unpublished media per workspace are stored free; bytes beyond the quota are charged once at the Store rate.
Subject gate: a character (char:<id>) or visual element (location/object) referenced in elements must carry an accepted look sheet — otherwise the call answers 422 sheet_required before charging (see /v1/sheets). A sheeted subject feeds exactly ONE picture slot: its sheet (avatars are card art, never fed). Styles, previous renders (creation:) and Storage refs (upload:) are ingredients, not subjects — never gated.
@-mentions bind to slots: an @Name in the prompt (matched case-insensitively against the elements you sent) is rewritten server-side to a slot-aware phrase — @Mina becomes “the woman from Picture 2”, @Rooftop “the place from Picture 3” — and the neutral Picture N is then bound to the engine's own slot vocabulary (<imageN> on Eroq One). You never write the slot number yourself, and a name that is also an ordinary word is never over-matched (only the @ sigil triggers the binding). Mentions of elements the engine could not fit keep their bare name.
model: "auto" has the routing model choose the engine (it is not available in advanced mode, which needs a named ComfyUI model); an auto request is charged at the price of the engine it picks, reported back in model.
Request body
What to draw, up to 2400 characters. Address a cast character or element with @Name — the server binds it to that element's reference slot automatically.
eroq-uncensored (default), or any image id from GET /v1/models (e.g. eroq-krea2, eroq-one, eroq-anime, nano-banana-pro, seedream-5-0-pro) — fields are validated against the DEPLOYED roster, so an unknown id answers 400 invalid_body with the list. Premium engines are plan-gated (403 plan_required before any charge) — GET /v1/engines lists what your plan unlocks. auto lets the engine decide: the routing model picks the image engine whose strengths best fit the prompt (among the deployed ones your plan unlocks), from the same call that reads the edit intent. The 202 answers with the resolved model in model.
Ordered reference photo URLs for the reference-driven engines (eroq-one ≤ 10, eroq-uncensored / eroq-krea2 ≤ 4). URLs AND base64 data:image/... URIs are accepted — a data URI is passed THROUGH to the engine and stored nowhere (the private-mode transport). Address one inside the prompt as Picture N (1-based over these references; element sheets are appended after them): the render layer binds it to the matching engine slot (<imageN> on Eroq One; Krea 2 keeps the Picture N prose — its reference node labels the inputs itself). Dropped on engines that read no pictures.
Edit mode — treat the first reference as the picture to edit and the prompt as a plain-language instruction. Requires at least one reference and an engine with an editor (eroq-krea2/eroq-uncensored take 2 — scene then optional subject; eroq-one up to 10). The routing model also reads the edit SCOPE from the prompt — a local change (swap an attribute, keep the composition) vs a reimagine (repose the subject, change the setting, framing or style) — and rewrites with the matching guide; you never pass the scope. It also reads the change MAGNITUDE on the Krea 2 editor: a rebuild (remove/replace/reveal visible content — "make her nude", "take off the jacket") loosens the editor's source fidelity so the instruction wins, since the source is held in context and would otherwise keep what you asked to remove. 400 edit_unsupported on a model with no editor, 400 reference_required with no reference. Default false.
Krea 2 reference renders only — the Krea2EditRebalance prompt-vs-reference gain, -2–2. 1 pushes the prompt (scene/pose change), lower (or negative) holds the reference (identity/face). Omitted = 0.6 when a cast character rides, else 1.0. Ignored by every other engine.
Frame format: 1:1 (default, 1024×1024), 3:4, 4:3, 9:16 or 16:9 — rendered at the engine's native resolution for that ratio, same price. retain matches the FIRST attached reference's ratio at the engine's usual ~1MP (ratio retained, resolution not): valid on an edit (edit: true) and on a create that rides a reference. Omitting aspect on an edit defaults to retain.
Element ids from your library — characters as char:<id>, previous renders as creation:<id>, Storage references as upload:<id> (their image joins the references): descriptions join the prompt, photos the references (a sheeted subject appends its single sheet). Order is preserved and decides each element's Picture N slot. Characters and visual elements must have a look sheet or the call 422s (see /v1/sheets). Manage them via /v1/elements, /v1/creations and /v1/uploads.
Cinema rack: noir, documentary, music-video, commercial, arthouse, horror, romance.
Cinema rack: 1920s, 1960s, 1980s, 1990s, 2000s, 2010s, futuristic.
Cinema rack: 35mm, imax, vhs, drone, gopro, cctv, smartphone.
Glass: clean-sharp, anamorphic, vintage-anamorphic, soft-portrait, macro, fisheye.
Depth of field: f1-4 (wide open), f4, f11 (deep focus).
Lighting rack: silhouette, practicals, window-light, overhead-fall, contre-jour, soft-cross, neon-glow.
Color palette: neon-noir, candy-pop, film-warm, nostalgic-blue, emerald, pastel-dawn, monochrome, sepia, industrial-fog, twilight, blood-gold, bleach-bypass.
1–4 renders per call. Charged upfront; each failed take refunds itself, successes come back in data (plus a failed count).
What to steer away from, on the engines with a negative-prompt control (eroq-anime). Every other engine renders from the prompt alone and ignores it.
Prompt adherence (CFG) on the engines eroq runs itself — the studio offers 0–3 on eroq-krea2, eroq-uncensored and eroq-one, 0–10 on eroq-anime (the API accepts up to 20). Ignored by every other engine. Engine default when omitted.
Unlock a permanent public static URL for the render. +2 credits per started 10MB. Default false.
Library folder the render lands in — one of yours (GET /v1/folders). Omitted = the Library root; an unknown id answers 404 folder_not_found before anything is billed.
A flow to run on each render once it lands — one of your flows (GET /v1/flows) that starts « After a render » of images. Checked before anything is billed: 404 flow_not_found, 400 flow_trigger_missing / flow_kind_mismatch / flow_not_ready, 403 plan_required below the plan flows take. Ignored by private renders. See Flows.
Do not retain on our side: the render is returned once (inline) but NEVER stored — no CDN upload, no creation row, nothing kept in our database. Browser-only. (Prompt retention upstream follows the per-model privacy value: private models never retain it — see /v1/engines.) Default false.
Advanced mode (eroq-uncensored/eroq-anime only): the prompt rides RAW — no rack folding, no style anchor, no enhancement — and LoRA dials attach exactly as given. The only server edit is binding @Name mentions to their reference slots. 400 advanced_requires_comfy on any other model.
Two-pass hires render on engines advertising it (Anima — ON by default there): 1.5× latent upscale + a light second pass paints real detail into new pixels (~2× render time, output at 1.5× the grid). Omitted = engine default, false = single pass. Ignored elsewhere.
Eroq One only: run 7 Viggle Turbo steps then 2 BASE steps (the turbo adapter dropped) so a base-trained detail LoRA resolves instead of smearing on the few-step distilled pass. Omitted = auto — engaged whenever an anatomy LoRA (catalogued nineStep) is attached; false forces the fast 6-step pass. ~4 s more than the 6-step. Ignored elsewhere.
Advanced-mode LoRA dials (up to 16 — every dial rides, one Power Lora Loader takes them all): exact catalog names + strengths, sent exactly as set. Only honored when advanced: true. Each LoRA must match the model's base family — 400 lora_incompatible otherwise (Krea 2 dials do not ride the Anima engine).
b64_json (default) or url when available. Deprecated for non-private renders — completed jobs answer with a signed URL.
curl https://eroq.ai/v1/images/generations \
-H "Authorization: Bearer $EROQ_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "eroq-krea2",
"prompt": "portrait of a starship mechanic, grease-stained overalls, warm hangar light, 35mm",
"negative_prompt": "blurry, extra fingers"
}'Response
{
"object": "image.generation",
"jobs": [{ "id": "b7e6c2d4-…", "poll": "/v1/images/generations/b7e6c2d4-…" }],
"created": 1756118400,
"model": "eroq-krea2",
"usage": { "credits_spent": 10, "credits_remaining": 987 }
}