{"info":{"title":"ZenCreator Public API","version":"1.0.0","contact":{"name":"ZenCreator Support","email":"support@zencreator.pro","url":"https://zencreator.pro"},"description":"ZenCreator Public API gives programmatic access to ZenCreator's AI generation tools: image generation, face swap, upscaling, video generation, lipsync and more. Every generation is asynchronous: you start it, poll its status and download the outputs.\n\n## Quickstart for AI Integration\n\nMachine-readable resources for AI agents, MCP clients and code generators:\n\n| Resource | URL |\n|----------|-----|\n| OpenAPI JSON | [`https://api.zencreator.pro/api/public/openapi.json`](https://api.zencreator.pro/api/public/openapi.json) |\n| SKILL.md for AI agents | [`https://api.zencreator.pro/api/public/skill.md`](https://api.zencreator.pro/api/public/skill.md) |\n| Get an API key | [https://app.zencreator.pro/api-keys](https://app.zencreator.pro/api-keys) |\n\n**3-step quickstart:**\n\n1. Create an API key at [https://app.zencreator.pro/api-keys](https://app.zencreator.pro/api-keys) and send it as `Authorization: Bearer zc_live_...`.\n2. Call `GET /api/public/v1/tools` — every tool comes with `input_schema` (JSON Schema) describing exactly which fields it accepts, their allowed values and defaults.\n3. `POST /api/public/v1/generations` with `{\"tool\": \"<name>\", \"input\": {...}}`, poll `GET /api/public/v1/generations/{id}` until the status is terminal, then fetch `GET /api/public/v1/generations/{id}/result`.\n\n## Access Points\n\n| Environment | Base URL |\n|-------------|----------|\n| Current | `https://api.zencreator.pro` |\n\nAll endpoints are prefixed with `/api/public/v1`.\n\n## Authentication\n\nAuthenticate every request with an **API key** sent as a Bearer token:\n\n```bash\ncurl \"https://api.zencreator.pro/api/public/v1/tools\" \\\n  -H \"Authorization: Bearer zc_live_<key_id>_<secret>\"\n```\n\n### How to get an API key\n\n1. Sign in to [app.zencreator.pro](https://app.zencreator.pro).\n2. Open [API Keys](https://app.zencreator.pro/api-keys).\n3. Create a key and copy it — the full key is shown **only once**.\n\nKeys carry scopes: `read` (list tools, poll generations, read transactions) and `generate` (start generations, upload assets). Pick the scopes when creating the key.\n\n## Generation Workflow\n\n**1. Pick a tool and read its input schema:**\n\n```bash\ncurl \"https://api.zencreator.pro/api/public/v1/tools/by_prompt\" \\\n  -H \"Authorization: Bearer $ZC_API_KEY\"\n```\n\n**2. Start a generation:**\n\n```bash\ncurl -X POST \"https://api.zencreator.pro/api/public/v1/generations\" \\\n  -H \"Authorization: Bearer $ZC_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"tool\": \"by_prompt\", \"input\": {\"positive_prompt\": \"portrait of a woman, golden hour\", \"ratio\": \"3:4\"}}'\n# -> {\"id\": \"0196...\", \"status\": \"queued\", \"created_at\": \"...\"}\n```\n\nThe `input` payload is validated against the tool's `input_schema` before any credits are charged — invalid payloads are rejected with `422` and a message pointing at the offending field.\n\n**3. Poll the status** (every 5-10 seconds):\n\n```bash\ncurl \"https://api.zencreator.pro/api/public/v1/generations/<id>\" \\\n  -H \"Authorization: Bearer $ZC_API_KEY\"\n# -> {\"id\": \"...\", \"status\": \"processing\", \"progress\": 50, \"error\": null}\n```\n\nStatuses: `queued` → `processing` → `succeeded` | `partial` | `failed`. When the status is `failed` or `partial`, the `error` field explains why.\n\n**4. Fetch the outputs:**\n\n```bash\ncurl \"https://api.zencreator.pro/api/public/v1/generations/<id>/result\" \\\n  -H \"Authorization: Bearer $ZC_API_KEY\"\n# -> {\"status\": \"succeeded\", \"outputs\": [{\"asset_id\": \"...\", \"url\": \"...\", \"download_url\": \"...\"}], \"error\": null}\n```\n\nTools that take images, video or audio as input reference **asset IDs** — upload the file first (see below) and pass the returned `asset_id` in the tool input.\n\n## Tools & Pricing\n\nEvery generation tool with the exact credit prices charged by the billing engine and the JSON `input` parameters it accepts. Prices on this page are computed by the same calculator that charges your generations, so they always match the actual charge. The machine-readable version of this catalog (with `input_schema` as JSON Schema) is `GET /api/public/v1/tools`.\n\n| Tool | Description | Credits |\n|---|---|---|\n| `upscaler` | Increase the resolution of an existing image while restoring or adding detail. Best for low-resolution sources that need to be cleaned up and improved; gains are limited on an already-sharp 4K image. Input: one image asset. Output: one higher-resolution image. | 1-4 |\n| `faceswap` | Swap a face on a photo: the face from `face_asset` is placed onto the person in `ref_asset`, keeping the reference image's body, pose and scene. Image only — there is no video face swap. Output: one image with the face replaced. | 1 |\n| `by_prompt` | Generate an image from a text prompt, with no input image (text-to-image). The entry point for creation: use it when there is no source image and the picture is described in words — building a character or content from scratch, concepts, backgrounds, NSFW from a description, quick drafts and final hero shots. Supports fast/quality modes, batches, aspect ratios and body-shape LoRAs. | 1-2 |\n| `by_ref` | Generate a similar image from a reference photo (image-to-image). With `GENERAL` you can bring a character's face plus a reference photo and get a similar shot featuring **your** character; with `SDXL` you bring only a photo and get a similar one. *Legacy tool — for most real tasks `image_editor` is more flexible and is the recommended choice.* | 1-2 |\n| `photoshoot` | Run a consistent photoshoot of one character from a photo of the face and a photo of the body (without a face): each shot is generated from scratch, so poses come out organically different between frames — unlike `image_editor`, which keeps the source composition. The tool feeds the references through prepared prompt presets and returns a batch of images. Presets are grouped by category, so you can produce a set in a given style or action. Strength: reproducible, satisfying results with no manual prompting — at the cost of fine-grained control. | 3 / image |\n| `facegen` | Generate a brand-new face from structured attributes: gender, age, ethnicity, body type, eye/hair/beard colour, hairstyle, beard and makeup. No reference image; returns several variants per request. Strength: full parametric control over the appearance — use it to create a fresh persona to reuse in other tools. For each attribute the accepted values are listed in that field's enum. Niche — used occasionally. | 1 |\n| `carousel` | Bring an image and get the same subject from different camera angles (up to 10). Use it for social-media carousels and a \"3D\"/product overview of an object or character. Niche — used occasionally. | 1 / image |\n| `videogen` | Animate a photo into a video (image-to-video). Cost depends on the model, duration (5-15 s) and resolution (480p-1080p). Supports prompt enhancement, fixed camera, LoRAs and optional audio. Quick guide: general content (best price/quality) — Seedance; NSFW content — `wan@2.7-nsfw` or `wan@2.2-lora`; tasteful content with complex actions — Kling (censored). | 2-51 |\n| `image_editor` | Edit and composite existing images by prompt — the main, most flexible image tool. Bring references, edit and combine them; bring your character and dress them from a reference photo; keep a product or object **exactly** (fabric, pattern, shape) while changing the scene. It offers both SFW and NSFW models, plus LoRA presets that extend NSFW capability. You are limited mainly by your imagination. Edits inherit the source composition (pose, framing), so for a photoshoot-style series of varied organic poses of one character use `photoshoot` instead. | 1-4 / image |\n| `collaber` | Put two characters together in one frame: bring two reference subjects and an optional background/location photo; the tool combines them into a single scene (1-4 images). Strength: keeps both characters' likeness — a convenient preset for collabs and duets. | 1 / image |\n| `video2video` | Transfer motion or replace a character in a video using a reference video or an Instagram/TikTok URL; the original soundtrack can be kept. SFW and NSFW modes. Provide the source as exactly one of `video_asset`, `instagram_url` or `tiktok_url`. Output: one video. | 1-2.8 / second |\n| `lipsync` | Make a character speak your audio (talking head): bring an audio file and a portrait first frame, and get a video in which the character talks or sings in sync. Up to 35 seconds of audio; image JPG/PNG under 5 MB. Use it to voice a character or avatar. Niche — used occasionally. Priced at 3 credits per second of audio. | 3 / second of audio |\n| `undress` | Fully removes clothing from the character in an image. Input: one image. Output: one image. A male variant exists as a separate tool for trusted accounts. This is a convenience preset built on a Flux Klein LoRA — the same result is available through `image_editor` with the Flux Klein LoRA presets, including presets that handle paired photos. | 3 |\n| `video_upscaler` | Bring a medium-quality video and get a sharper, higher-resolution result, up to 5K on the longest side. Use it as a final polish or to restore low-quality footage. Niche — used occasionally. Priced by output megapixels x duration x a frame-rate multiplier. | by output size |\n| `video_merger` | Concatenate 2-5 video clips with transitions | 1 |\n\n### upscaler\n\nIncrease the resolution of an existing image while restoring or adding detail. Best for low-resolution sources that need to be cleaned up and improved; gains are limited on an already-sharp 4K image. Input: one image asset. Output: one higher-resolution image.\n\n**Versions:**\n- `basic` / `basic_safe_face` — Baseline upscale; the `*_safe_face` variant preserves the face.\n- `natural_clarity` — Cheap and natural-looking, at any size.\n- `premium_realism` / `premium_safe_face` — Photorealistic detail; `*_safe_face` preserves the face.\n- `ultra_clarity` — Maximum detail and sharpness.\n\n`megapixels` sets the target size and `creativity` how freely the engine may invent new detail.\n\n**Price** (credits):\n\n| `version` | `megapixels` | Credits |\n|---|---|---|\n| `basic`, `basic_safe_face` | `4`, `16`, `24`, `32` | 1 |\n| `basic`, `basic_safe_face` | `8` | 2 |\n| `natural_clarity` | *any* | 1 |\n| `premium_realism`, `premium_safe_face` | `4`, `16`, `24`, `32` | 2 |\n| `premium_realism`, `premium_safe_face` | `8` | 4 |\n| `ultra_clarity` | `4`, `8` | 1 |\n| `ultra_clarity` | `16` | 2 |\n| `ultra_clarity` | `24` | 3 |\n| `ultra_clarity` | `32` | 4 |\n\n**Input parameters:**\n\n| Field | Type | Required | Default | Description |\n|---|---|---|---|---|\n| `image_asset` | string | yes | — | Asset ID of the image to upscale (upload via POST /assets). |\n| `version` | enum |  | `basic` | One of: `basic`, `basic_safe_face`, `natural_clarity`, `premium_realism`, `premium_safe_face`, `ultra_clarity`. Upscale engine. `basic` — fast, faithful enlargement; `basic_safe_face` — basic but protects facial identity; `premium_realism` — adds photoreal texture and detail; `premium_safe_face` — premium while protecting the face; `natural_clarity` — gentle, natural sharpening; `ultra_clarity` — maximum detail and sharpness. Use a `*_safe_face` version when keeping the exact face matters. Default `basic`. |\n| `megapixels` | enum |  | `4` | One of: `4`, `8`, `16`, `24`, `32`. Target output size in megapixels: one of 4, 8, 16, 24, 32. Higher means a larger image and a higher price. Default 4. |\n| `creativity` | enum |  | `3` | One of: `0`, `1`, `2`, `3`, `4`, `5`. How freely the model may invent new detail, 0-5 (0 = stay faithful to the source, 5 = most creative). Default 3. |\n\n**Outputs:** `image_asset` (string)\n\n### faceswap\n\nSwap a face on a photo: the face from `face_asset` is placed onto the person in `ref_asset`, keeping the reference image's body, pose and scene. Image only — there is no video face swap. Output: one image with the face replaced.\n\n**Models:**\n- `SDXL` *(default)* — Lowest likeness of the set.\n- `GENERAL` — Better likeness, but not always stable.\n- `GENERAL_ADVANCED` — Improved general swap with stronger identity preservation.\n- `FULL_HEAD` — Replaces the entire head, not just the face — use it when the target's hairstyle or head shape differs strongly from the source.\n\n**Price:** 1 credit.\n\n**Input parameters:**\n\n| Field | Type | Required | Default | Description |\n|---|---|---|---|---|\n| `ref_asset` | string | yes | — | Asset ID of the target image whose face will be replaced. |\n| `face_asset` | string | yes | — | Asset ID of the image providing the new face. |\n| `model` | enum |  | `SDXL` | One of: `FULL_HEAD`, `GENERAL`, `GENERAL_ADVANCED`, `SDXL`. Face-swap model (e.g. a general model, an SDXL model, an advanced model and a full-head variant). |\n| `resolution` | enum |  | `4K` | One of: `2K`, `4K`. Output resolution, e.g. `2K` or `4K`. |\n\n**Outputs:** `image_asset` (string)\n\n### by_prompt\n\nGenerate an image from a text prompt, with no input image (text-to-image). The entry point for creation: use it when there is no source image and the picture is described in words — building a character or content from scratch, concepts, backgrounds, NSFW from a description, quick drafts and final hero shots. Supports fast/quality modes, batches, aspect ratios and body-shape LoRAs.\n\n**Three content groups (pick by what you need):**\n- **Top cloud models, censored** (`GENERAL_NSFW`, `NANO_BANANA`) — highest quality and realism, but they block full NSFW content.\n- **Uncensored, not built for full NSFW** (`WAN_2_7_IMAGE`, `QWEN_IMAGE`, `SEEDREAM_5`) — high quality and won't block, but won't create full NSFW content from scratch; they accurately **transform NSFW references** you provide.\n- **Local, built for full NSFW** (`SDXL_NSFW`, `FLUX_KLEIN_NSFW`) — slightly lower quality and more artifacts, but real full-NSFW capability.\n\n**Models:**\n- `GENERAL_NSFW` *(default, trusted)* — General-purpose workhorse with a good quality/speed/price balance and strong facial likeness; the NSFW version is uncensored but does not produce full NSFW anatomy from text alone (it covers it up). Older model — occasional hand/limb artifacts.\n- `GENERAL_SFW` — The same pipeline, SFW only.\n- `SDXL_NSFW` *(trusted)* — Best choice for full NSFW anatomy from text alone (it knows anatomy from training). Local model: slightly lower quality, more artifacts. Text-only — does not accept reference images.\n- `WAN_2_7_IMAGE` / `WAN_2_7_IMAGE_PRO` — Modern model with higher quality and detail (Pro = top consistency). Renders bodies, scenes and composition more aesthetically and has fewer hand/limb artifacts. Weaker at in-image text. Uncensored, but transforms your NSFW references rather than inventing full NSFW content.\n- `WAN` — Legacy WAN image model; prefer `WAN_2_7_IMAGE`.\n- `QWEN_IMAGE` / `QWEN_IMAGE_PRO` — Aesthetic results with good facial likeness and few artifacts; great for stylized / illustrative / anime subjects. Pro adds realism. Uncensored; transforms NSFW references.\n- `SEEDREAM_5` — Newer generation: better prompt understanding, stronger stylization, better likeness, fewer artifacts. Uncensored; transforms NSFW references.\n- `NANO_BANANA` — Among the best for realism, and the only model that reliably renders legible in-image text (posters, signage, captions); strong real-world knowledge. Heavily censored — won't produce even mildly suggestive content. Weaker facial likeness.\n- `FLUX_KLEIN_NSFW` *(trusted)* — The most advanced local full-NSFW model: creates uncensored NSFW content and also works with references — bring a character's face and create an action. Slightly lower quality, occasional artifacts.\n\nModels marked *(trusted)* unlock NSFW behaviour only for trusted accounts (or accounts with an NSFW content policy).\n\n**Price** (credits):\n\n| `model` | `mode` | Credits |\n|---|---|---|\n| `FLUX_KLEIN_NSFW`, `NANO_BANANA`, `QWEN_IMAGE_PRO`, `WAN_2_7_IMAGE_PRO` | *any* | 2 |\n| `GENERAL_NSFW`, `GENERAL_SFW`, `QWEN_IMAGE`, `SEEDREAM_5`, `WAN`, `WAN_2_7_IMAGE` | *any* | 1 |\n| `SDXL_NSFW` | `fast` | 1 |\n| `SDXL_NSFW` | `quality` | 2 |\n\n**Input parameters:**\n\n| Field | Type | Required | Default | Description |\n|---|---|---|---|---|\n| `positive_prompt` | string | yes | — | Text describing what to generate. |\n| `negative_prompt` | string |  | `\"\"` | Text describing what to avoid in the image. |\n| `loras` | object or null |  | `null` | Allowed keys: `bombshell_v2`, `breast_slider_pony_alpha1_0_rank4_noxattn_last`, `breast_slider_sdxl_alpha1_0_rank4_noxattn_last`, `cameltoe_xl_000007`, `chubby_cellulite_fat_bbw`, `curvy_bodies`, `euromilf_mature`, `extrmusc`, `fbb_photo_sdxl_1_6_lite`, `hourglass_body_shape`, `slimwoman_v2`, `softtummy_xl`, `uz_bbw`. Named LoRA styles to apply, as a map of LoRA name to strength (typically 0-1). The allowed names are the keys listed for this field; see the model prompt guide for what each style does. |\n| `batch_size` | integer |  | `1` | How many images to generate in one call (default 1). |\n| `model` | enum |  | `GENERAL_NSFW` | One of: `FLUX_KLEIN_NSFW`, `GENERAL_NSFW`, `GENERAL_SFW`, `NANO_BANANA`, `QWEN_IMAGE`, `QWEN_IMAGE_PRO`, `SDXL_NSFW`, `SEEDREAM_5`, `WAN`, `WAN_2_7_IMAGE`, `WAN_2_7_IMAGE_PRO`. Generation model, covering the general/SDXL NSFW, WAN (incl. WAN 2.7 image), Nano Banana, Seedream, Qwen and Flux Klein families; `*_PRO` variants trade speed for higher quality. |\n| `ratio` | enum |  | `1:1` | One of: `16:9`, `1:1`, `21:9`, `2:3`, `3:2`, `3:4`, `4:3`, `9:16`. Aspect ratio: 1:1, 16:9, 9:16, 4:3, 3:4, 2:3, 3:2 or 21:9. |\n| `mode` | enum |  | `fast` | One of: `fast`, `quality`. Generation mode: `fast` (quicker and cheaper) or `quality` (slower, higher fidelity). |\n| `width` | integer or null |  | `null` | Optional output width in pixels; if omitted a size is derived from `ratio`. |\n| `height` | integer or null |  | `null` | Optional output height in pixels; if omitted a size is derived from `ratio`. |\n\n**Outputs:** `image_asset` (string)\n\n### by_ref\n\nGenerate a similar image from a reference photo (image-to-image). With `GENERAL` you can bring a character's face plus a reference photo and get a similar shot featuring **your** character; with `SDXL` you bring only a photo and get a similar one. *Legacy tool — for most real tasks `image_editor` is more flexible and is the recommended choice.*\n\n**Models:**\n- `SDXL` *(default)* — Local, NSFW-capable. Input is a photo only.\n- `GENERAL` — Higher quality and realism; can carry a character's face into a reference-like shot.\n\n**Price** (credits):\n\n| `model` | `mode` | Credits |\n|---|---|---|\n| `GENERAL` | *any* | 1 |\n| `SDXL` | `fast` | 1 |\n| `SDXL` | `quality` | 2 |\n\n**Input parameters:**\n\n| Field | Type | Required | Default | Description |\n|---|---|---|---|---|\n| `ref_asset` | string | yes | — | Asset ID of the reference image to guide the generation. |\n| `face_asset` | string or null |  | `null` | Optional asset ID of a face to preserve in the result. |\n| `model` | enum |  | `SDXL` | One of: `GENERAL`, `SDXL`. Generation model. |\n| `mode` | enum |  | `fast` | One of: `fast`, `quality`. Generation mode (e.g. `fast` vs `quality`). |\n| `positive_prompt` | string |  | `\"\"` | Text describing what to generate. |\n| `negative_prompt` | string |  | `\"\"` | Text describing what to avoid. |\n| `batch_size` | integer |  | `4` | Number of images to generate, 1-10. Default 4. |\n| `strength` | number |  | `1.0` | How strongly the reference image constrains the result, 0.0-1.0 (higher sticks closer to the reference). |\n| `keep_pose` | boolean |  | `false` | One of: `true`, `false`. Preserve the pose of the reference image. Default false. |\n| `swap_background` | boolean |  | `false` | One of: `true`, `false`. Replace the background of the reference image. Default false. |\n| `loras` | object or null |  | `null` | Allowed keys: `bombshell_v2`, `breast_slider_pony_alpha1_0_rank4_noxattn_last`, `breast_slider_sdxl_alpha1_0_rank4_noxattn_last`, `cameltoe_xl_000007`, `chubby_cellulite_fat_bbw`, `curvy_bodies`, `euromilf_mature`, `extrmusc`, `fbb_photo_sdxl_1_6_lite`, `hourglass_body_shape`, `slimwoman_v2`, `softtummy_xl`, `uz_bbw`. Named LoRA styles to apply, as a map of LoRA name to strength (typically 0-1). The allowed names are the keys listed for this field; see the model prompt guide for what each style does. |\n\n**Outputs:** `image_assets` (array[string])\n\n### photoshoot\n\nRun a consistent photoshoot of one character from a photo of the face and a photo of the body (without a face): each shot is generated from scratch, so poses come out organically different between frames — unlike `image_editor`, which keeps the source composition. The tool feeds the references through prepared prompt presets and returns a batch of images. Presets are grouped by category, so you can produce a set in a given style or action. Strength: reproducible, satisfying results with no manual prompting — at the cost of fine-grained control.\n\n**Price:** 3 credits per image (multiplied by `number_of_images`).\n\n**Input parameters:**\n\n| Field | Type | Required | Default | Description |\n|---|---|---|---|---|\n| `face_ref` | string | yes | — | Asset ID of the face reference (upload via POST /assets). |\n| `body_ref` | string | yes | — | Asset ID of the body/pose reference (upload via POST /assets). |\n| `prompt` | string |  | `\"\"` | Free-text description of the shot (scene, outfit, lighting). Provide `prompt` for a custom shot, or `category_id` to use a curated category instead. If both are given, `category_id` takes precedence. |\n| `category_id` | string or null |  | `null` | ID of a curated photoshoot category (see GET /photoshoot-categories). When set, the shot's prompts are taken from the category and `image_count` images are produced; it takes precedence over `prompt`. |\n| `image_count` | integer |  | `1` | Total number of images to generate (min 1). Drives how many shots are produced from the chosen `category_id` (or how many times `prompt` is repeated). |\n| `ratio` | enum |  | `1:1` | One of: `16:9`, `1:1`, `21:9`, `2:3`, `3:2`, `3:4`, `4:3`, `9:16`. Aspect ratio of the output image. |\n| `width` | integer |  | `1024` | Output width in pixels (default 1024). |\n| `height` | integer |  | `1024` | Output height in pixels (default 1024). |\n| `number_of_images` | integer |  | `1` | Parallel images per shot (default 1); leave at 1 — use `image_count` to control the total. |\n\n**Outputs:** `image_assets` (array[string])\n\n### facegen\n\nGenerate a brand-new face from structured attributes: gender, age, ethnicity, body type, eye/hair/beard colour, hairstyle, beard and makeup. No reference image; returns several variants per request. Strength: full parametric control over the appearance — use it to create a fresh persona to reuse in other tools. For each attribute the accepted values are listed in that field's enum. Niche — used occasionally.\n\n**Price:** 1 credit.\n\n**Input parameters:**\n\n| Field | Type | Required | Default | Description |\n|---|---|---|---|---|\n| `gender` | enum | yes | — | One of: `Female`, `Male`. Gender of the face. |\n| `age` | enum | yes | — | One of: `18-25`, `26-35`, `36-45`, `46-55`, `56-65`, `66-75`, `75-85`, `85+`. Apparent age band. |\n| `origin` | enum | yes | — | One of: `Central American`, `Central Asian`, `East Asian`, `European`, `Middle Eastern`, `North African`, `North American`, `Oceanian / Pacific Islander`, `South American`, `South Asian`, `Southeast Asian`. Ethnic origin / look. |\n| `body_type` | enum or null |  | `null` | One of: `Chubby`, `Curvy`, `Fit`, `Muscular`, `Normal`, `Slim`. Body type. |\n| `eye_color` | enum or null |  | `null` | One of: `Albino`, `Amber`, `Blue`, `Brown`, `Gray`, `Green`, `Hazel`, `Heterochromia`, `Red`, `Violet`. Eye colour. |\n| `hair_color` | enum or null |  | `null` | One of: `Black`, `Blonde`, `Blue`, `Brunette`, `Gray`, `Green`, `Honey`, `Ombre`, `Pink`, `Platinum`, `Red`, `Salt and Pepper`, `Violet`. Hair colour. |\n| `hair_type` | enum or null |  | `null` | One of: `Bald`, `Coily`, `Curly`, `Frizzy`, `Silky`, `Straight`, `Thick`, `Thin`, `Wavy`. Hair type, e.g. straight/wavy/curly. |\n| `hair_style` | enum or null |  | `null` | One of: `Afro`, `Bob`, `Bowl`, `Braids`, `Bun`, `Buzzcut`, `Caesar`, `Mohawk`, `Pigtails`, `Pixie`, `Ponytail`, `Shag`, `Undercut`, `Updo`. Hair style. |\n| `beard` | enum or null |  | `null` | One of: `Anchor Beard`, `Balbo Beard`, `Chevron Mustache`, `Chinstrap Beard`, `Circle Beard`, `Corporate Beard`, `Ducktail Beard`, `Friendly Mutton Chops`, `Full Beard`, `Garibaldi Beard`, `Goatee`, `Handlebar Mustache`, `Horseshoe Mustache`, `Imperial Mustache`, `Mutton Chops`, `Pencil Mustache`, `Soul Patch`, `Stubble Beard`, `Van Dyke Beard`, `Zappa Mustache`. Beard style. |\n| `beard_color` | enum or null |  | `null` | One of: `Black`, `Blonde`, `Blue`, `Brunette`, `Gray`, `Green`, `Honey`, `Ombre`, `Pink`, `Platinum`, `Red`, `Salt and Pepper`, `Violet`. Beard colour. |\n| `makeup` | enum or null |  | `null` | One of: `Anime Makeup`, `Artistic Makeup`, `Avant-garde Makeup`, `Bohemian Makeup`, `Boho Makeup`, `Classic Makeup`, `Cut Crease Makeup`, `Dewy Makeup`, `Edgy Makeup`, `Festival Makeup`, `Glam Makeup`, `Glowy Makeup`, `Golden Makeup`, `Monochromatic Makeup`, `Natural Makeup`, `Party Makeup`, `Retro Makeup`, `Sunset Eye Makeup`, `Vintage Makeup`, `Watercolor Makeup`. Makeup style. |\n\n**Outputs:** `image_assets` (array[string])\n\n### carousel\n\nBring an image and get the same subject from different camera angles (up to 10). Use it for social-media carousels and a \"3D\"/product overview of an object or character. Niche — used occasionally.\n\n**Price:** 1 credit per image (multiplied by `number_of_images`).\n\n**Input parameters:**\n\n| Field | Type | Required | Default | Description |\n|---|---|---|---|---|\n| `asset_ref` | string | yes | — | Asset ID of the subject/reference image. |\n| `ratio` | enum |  | `1:1` | One of: `16:9`, `1:1`, `21:9`, `2:3`, `3:2`, `3:4`, `4:3`, `9:16`. Aspect ratio of the outputs (e.g. 1:1, 16:9, 9:16). |\n| `width` | integer |  | `1024` | Output width in pixels (used when `ratio` is not set). |\n| `height` | integer |  | `1024` | Output height in pixels (used when `ratio` is not set). |\n| `number_of_images` | integer |  | `4` | Number of angle variations to generate, 1-10. Default 4. |\n\n**Outputs:** `image_assets` (array[string])\n\n### videogen\n\nAnimate a photo into a video (image-to-video). Cost depends on the model, duration (5-15 s) and resolution (480p-1080p). Supports prompt enhancement, fixed camera, LoRAs and optional audio. Quick guide: general content (best price/quality) — Seedance; NSFW content — `wan@2.7-nsfw` or `wan@2.2-lora`; tasteful content with complex actions — Kling (censored).\n\n**Wan** — the `wan@2.7` line understands prompts best and animates a first frame well (1080p, good physics, up to 5 references):\n- `wan@2.7` — Latest line; top prompt understanding and first-frame animation.\n- `wan@2.7-nsfw` — Wan 2.7 for NSFW; the best choice when you have a first frame (or a frame with an action) to animate.\n- `wan@2.6` / `wan@2.6-flash` — Cheaper and older; **flash** is even cheaper and faster.\n- `wan@2.5` — Older generation; prefer `wan@2.6` or `wan@2.7`.\n- `wan@2.2` — Animates a first frame; uncensored NSFW base.\n- `wan@2.2-lora` — Presets with action-trained LoRAs that turn a first frame into a complex action. Includes \"Blink\" LoRAs: bring any photo of your character and the frame morphs into the desired NSFW action. The **easiest option for beginners** — no prompt needed, just a photo similar to the example's first frame.\n\n**Kling** — censored, but animates a first frame well; newer versions cost more and understand prompts and complex actions better:\n- `kling@2.6` — Top motion and physics, plus native audio (dialogue, effects).\n- `kling@2.5` — High quality, cheaper, consistent at volume.\n- `kling@2.1` — Stable motion.\n- `kling@1.6` — Oldest and cheapest Kling.\n\n**Seedance** — uncensored; best price/quality balance for content:\n- `seedance_pro_fast` — Faster and cheaper, less \"smart\".\n- `seedance_pro` — Pricier and smarter.\n- `seedance_v1_5_pro` — Best quality and result; joint audio+video, micro-expressions, first+last frame.\n\n**Grok:**\n- `grok@4.1` — Censored; animates a first frame, top image-to-video, always with native audio.\n\nModel capabilities differ — read the `model`, `last_frame` and `resolution` fields for which model supports what.\n\n**Price** (credits):\n\n| `model` | `duration` | `generate_audio` | Credits (480p) | Credits (720p) | Credits (1080p) |\n|---|---|---|---|---|---|\n| `grok@4.1` | `5` | *any* | 10 | 15 | 15 |\n| `grok@4.1` | `6` | *any* | 12 | 18 | 18 |\n| `grok@4.1` | `8` | *any* | 16 | 24 | 24 |\n| `grok@4.1` | `10` | *any* | 20 | 30 | 30 |\n| `grok@4.1` | `12` | *any* | 24 | 36 | 36 |\n| `grok@4.1` | `15` | *any* | 30 | 45 | 45 |\n| `kling@1.6`, `kling@2.1`, `kling@2.5` | `5`, `6`, `8`, `12`, `15` | *any* | 7 | 7 | 7 |\n| `kling@1.6`, `kling@2.1`, `kling@2.5` | `10` | *any* | 13 | 13 | 13 |\n| `kling@2.6` | `5` | `true` | 10 | 10 | 10 |\n| `kling@2.6` | `5` | `false` | 5 | 5 | 5 |\n| `kling@2.6` | `6` | `true` | 12 | 12 | 12 |\n| `kling@2.6` | `6` | `false` | 6 | 6 | 6 |\n| `kling@2.6` | `8` | `true` | 16 | 16 | 16 |\n| `kling@2.6` | `8` | `false` | 8 | 8 | 8 |\n| `kling@2.6` | `10` | `true` | 20 | 20 | 20 |\n| `kling@2.6` | `10` | `false` | 10 | 10 | 10 |\n| `kling@2.6` | `12` | `true` | 24 | 24 | 24 |\n| `kling@2.6` | `12` | `false` | 12 | 12 | 12 |\n| `kling@2.6` | `15` | `true` | 30 | 30 | 30 |\n| `kling@2.6` | `15` | `false` | 15 | 15 | 15 |\n| `seedance_pro` | `5` | *any* | 4 | 8 | 15 |\n| `seedance_pro`, `seedance_pro_fast` | `6`, `8`, `12`, `15` | *any* | 7 | 7 | 7 |\n| `seedance_pro` | `10` | *any* | 8 | 15 | 30 |\n| `seedance_pro_fast` | `5` | *any* | 2 | 4 | 7 |\n| `seedance_pro_fast` | `10` | *any* | 4 | 8 | 13 |\n| `seedance_v1_5_pro` | `5` | `true` | 8 | 8 | 16 |\n| `seedance_v1_5_pro` | `5` | `false` | 4 | 4 | 8 |\n| `seedance_v1_5_pro` | `6`, `8`, `15` | `true` | 8 | 8 | 8 |\n| `seedance_v1_5_pro` | `6`, `8`, `15` | `false` | 4 | 4 | 4 |\n| `seedance_v1_5_pro` | `10` | `true` | 8 | 16 | 32 |\n| `seedance_v1_5_pro` | `10` | `false` | 4 | 8 | 16 |\n| `seedance_v1_5_pro` | `12` | `true` | 8 | 20 | 40 |\n| `seedance_v1_5_pro` | `12` | `false` | 4 | 10 | 20 |\n| `wan@2.2` | `5`, `6`, `10`, `12`, `15` | *any* | 10 | 10 | 10 |\n| `wan@2.2` | `8` | *any* | 13 | 13 | 13 |\n| `wan@2.2-lora` | *any* | *any* | 10 | 10 | 10 |\n| `wan@2.5`, `wan@2.7` | `5` | *any* | 5 | 10 | 15 |\n| `wan@2.5`, `wan@2.7` | `6` | *any* | 6 | 12 | 18 |\n| `wan@2.5`, `wan@2.7` | `8` | *any* | 8 | 16 | 24 |\n| `wan@2.5`, `wan@2.7` | `10` | *any* | 10 | 20 | 30 |\n| `wan@2.5`, `wan@2.7` | `12` | *any* | 12 | 24 | 36 |\n| `wan@2.5`, `wan@2.7` | `15` | *any* | 15 | 30 | 45 |\n| `wan@2.6` | `5` | *any* | 10 | 10 | 15 |\n| `wan@2.6`, `wan@2.7-nsfw` | `6` | *any* | 12 | 12 | 18 |\n| `wan@2.6`, `wan@2.7-nsfw` | `8` | *any* | 16 | 16 | 24 |\n| `wan@2.6` | `10` | *any* | 20 | 20 | 30 |\n| `wan@2.6`, `wan@2.7-nsfw` | `12` | *any* | 24 | 24 | 36 |\n| `wan@2.6` | `15` | *any* | 30 | 30 | 45 |\n| `wan@2.6-flash` | `5` | `true` | 5 | 5 | 7 |\n| `wan@2.6-flash` | `5`, `6` | `false` | 3 | 3 | 4 |\n| `wan@2.6-flash` | `6` | `true` | 6 | 6 | 9 |\n| `wan@2.6-flash` | `8` | `true` | 8 | 8 | 12 |\n| `wan@2.6-flash` | `8` | `false` | 4 | 4 | 6 |\n| `wan@2.6-flash` | `10` | `true` | 10 | 10 | 14 |\n| `wan@2.6-flash` | `10` | `false` | 5 | 5 | 7 |\n| `wan@2.6-flash` | `12` | `true` | 12 | 12 | 17 |\n| `wan@2.6-flash` | `12` | `false` | 6 | 6 | 8 |\n| `wan@2.6-flash` | `15` | `true` | 15 | 15 | 21 |\n| `wan@2.6-flash` | `15` | `false` | 8 | 8 | 10 |\n| `wan@2.7-nsfw` | `5` | *any* | 10 | 13 | 17 |\n| `wan@2.7-nsfw` | `10` | *any* | 20 | 26 | 34 |\n| `wan@2.7-nsfw` | `15` | *any* | 30 | 39 | 51 |\n\n**Input parameters:**\n\n| Field | Type | Required | Default | Description |\n|---|---|---|---|---|\n| `ref_asset` | string | yes | — | Asset ID of the starting image to animate (image-to-video). |\n| `model` | enum |  | `wan@2.2` | One of: `grok@4.1`, `kling@1.6`, `kling@2.1`, `kling@2.5`, `kling@2.6`, `seedance_pro`, `seedance_pro_fast`, `seedance_v1_5_pro`, `wan@2.2`, `wan@2.2-lora`, `wan@2.5`, `wan@2.6`, `wan@2.6-flash`, `wan@2.7`, `wan@2.7-nsfw`. Video model. Kling: `kling@1.6`, `kling@2.1` (supports last_frame), `kling@2.5`, `kling@2.6`. WAN: `wan@2.2` (image-to-video, no last_frame), `wan@2.2-lora` (same as wan@2.2 but accepts `loras`), `wan@2.5`, `wan@2.6`, `wan@2.6-flash` (faster), `wan@2.7`, `wan@2.7-nsfw`. Seedance: `seedance_pro_fast`, `seedance_pro` (supports last_frame), `seedance_v1_5_pro` (supports last_frame). Grok: `grok@4.1`. Default `wan@2.2`. |\n| `last_frame` | string or null |  | `null` | Asset ID of the target final frame: the video interpolates from `ref_asset` to this frame. Only honoured by models that support it (`kling@2.1`, `seedance_pro`, `seedance_v1_5_pro`); WAN models (incl. wan@2.2 and wan@2.7) do not support a last frame. |\n| `audio_asset` | string or null |  | `null` | Asset ID of an audio track to drive the video, for models that support audio input. |\n| `prompt` | string |  | `\"\"` | Text describing the desired motion and scene. |\n| `duration` | enum |  | `5` | One of: `5`, `6`, `8`, `10`, `12`, `15`. Clip length in seconds: one of 5, 6, 8, 10, 12, 15. The values a model accepts depend on the model. Default 5. |\n| `negative_prompt` | string |  | `\"\"` | Text describing what to avoid in the video. |\n| `resolution` | enum |  | `720p` | One of: `1080p`, `480p`, `720p`. Output resolution. Most models accept `720p` and `1080p`. `480p` is NOT supported by `wan@2.6`, `wan@2.6-flash`, `wan@2.7`, `wan@2.7-nsfw` or `seedance_v1_5_pro` (use 720p or 1080p for those). `grok@4.1` accepts only `480p` or `720p`. Default `720p`. |\n| `generate_audio` | boolean |  | `true` | One of: `true`, `false`. Generate an audio track too, for models that support it. Default true. |\n| `camera_fixed` | boolean |  | `false` | One of: `true`, `false`. Keep the camera fixed instead of letting it move. Default false. |\n| `prompt_extend` | boolean |  | `false` | One of: `true`, `false`. Let the model auto-expand and enhance your prompt. Default false. |\n| `loras` | object or null |  | `null` | LoRA styles to apply, as a map of LoRA id to scale settings. Only `wan@2.2-lora` uses this; browse compatible ids via GET /loras?model=wan@2.2. |\n\n**Outputs:** `video_asset` (string)\n\n### image_editor\n\nEdit and composite existing images by prompt — the main, most flexible image tool. Bring references, edit and combine them; bring your character and dress them from a reference photo; keep a product or object **exactly** (fabric, pattern, shape) while changing the scene. It offers both SFW and NSFW models, plus LoRA presets that extend NSFW capability. You are limited mainly by your imagination. Edits inherit the source composition (pose, framing), so for a photoshoot-style series of varied organic poses of one character use `photoshoot` instead.\n\n**Models:**\n- `GENERAL_NSFW` *(default, trusted)* — Universal default, uncensored, good facial likeness; general NSFW edits such as outfit or pose changes. Older model — occasional limb artifacts.\n- `NANO_BANANA` — High realism and the most precise prompt-driven edits; **required for any edit involving in-image text**. Heavily censored (no NSFW); weaker likeness.\n- `QWEN_IMAGE` / `QWEN_IMAGE_PRO` — Aesthetic, good likeness, few artifacts; Pro adds realism. Uncensored; transforms your NSFW references rather than creating full NSFW content from scratch.\n- `SEEDREAM_5` — Newer than the default: better prompt understanding, stronger stylization, better likeness, fewer artifacts. Uncensored; transforms NSFW references.\n- `WAN_2_7_IMAGE` / `WAN_2_7_IMAGE_PRO` — Aesthetic bodies and composition, few artifacts, precise editing; Pro = higher quality. Uncensored; transforms NSFW references. Weaker at in-image text.\n- `FLUX_KLEIN_NSFW` *(trusted)* — Local flagship for full NSFW with references: it knows anatomy and accepts a face reference. Slightly lower quality, occasional artifacts.\n- `FLUX_KLEIN_LORA` *(trusted)* — LoRA presets that extend NSFW capability (including undress presets) and style templates; pass a `lora_id` (browse via GET /templates).\n\nModels marked *(trusted)* unlock NSFW behaviour only for trusted accounts (or accounts with an NSFW content policy).\n\n**Price** (credits per image, multiplied by `number_of_images`):\n\n| `model` | Credits |\n|---|---|\n| `FLUX_KLEIN_LORA` | 3 |\n| `FLUX_KLEIN_NSFW`, `GENERAL_NSFW`, `QWEN_IMAGE`, `SEEDREAM_5`, `WAN_2_7_IMAGE` | 1 |\n| `NANO_BANANA` | 4 |\n| `QWEN_IMAGE_PRO`, `WAN_2_7_IMAGE_PRO` | 2 |\n\n**Input parameters:**\n\n| Field | Type | Required | Default | Description |\n|---|---|---|---|---|\n| `image_assets` | array[string] | yes | — | Asset ID(s) of the source image(s). Pass a single id to edit one image, or several (as an array) to combine them into one result (unless `batch_mode` is set). |\n| `prompt` | string | yes | — | Instruction describing the edit to apply. |\n| `model` | enum |  | `GENERAL_NSFW` | One of: `FLUX_KLEIN_LORA`, `FLUX_KLEIN_NSFW`, `GENERAL_NSFW`, `NANO_BANANA`, `QWEN_IMAGE`, `QWEN_IMAGE_PRO`, `SEEDREAM_5`, `WAN_2_7_IMAGE`, `WAN_2_7_IMAGE_PRO`. Editing model. `GENERAL_NSFW` — general-purpose editor (default, allows NSFW); `NANO_BANANA` — Google Nano Banana; `QWEN_IMAGE` / `QWEN_IMAGE_PRO` — Qwen editors (Pro = higher quality); `SEEDREAM_5` — Seedream; `FLUX_KLEIN_NSFW` — Flux Klein editor; `FLUX_KLEIN_LORA` — Flux Klein with a style template (requires `lora_id`); `WAN_2_7_IMAGE` / `WAN_2_7_IMAGE_PRO` — WAN 2.7 editors (Pro = higher quality). |\n| `ratio` | enum or null |  | `null` | One of: `16:9`, `1:1`, `21:9`, `2:3`, `3:2`, `3:4`, `4:3`, `9:16`. Aspect ratio (e.g. 1:1, 16:9, 9:16). Overrides width/height when set. |\n| `width` | integer |  | `1024` | Output width in pixels (default 1024). Used when `ratio` is not set. |\n| `height` | integer |  | `1024` | Output height in pixels (default 1024). Used when `ratio` is not set. |\n| `batch_mode` | boolean |  | `false` | One of: `true`, `false`. When several `image_assets` are given, edit each one separately (one result per image) instead of combining them into a single image. Default false. |\n| `number_of_images` | integer |  | `1` | How many images to generate (default 1). |\n| `sequential_generation` | boolean |  | `false` | One of: `true`, `false`. Generate the requested images one after another, each conditioned on the previous result (for consistent, story-like sequences) instead of independently. Default false. |\n| `lora_id` | string or null |  | `null` | ID of a LoRA style template to apply (required when `model=FLUX_KLEIN_LORA`). Browse available templates and their ids via GET /templates. |\n\n**Outputs:** `image_assets` (array[string])\n\n### collaber\n\nPut two characters together in one frame: bring two reference subjects and an optional background/location photo; the tool combines them into a single scene (1-4 images). Strength: keeps both characters' likeness — a convenient preset for collabs and duets.\n\n**Price:** 1 credit per image (multiplied by `number_of_images`).\n\n**Input parameters:**\n\n| Field | Type | Required | Default | Description |\n|---|---|---|---|---|\n| `asset_image_1` | string | yes | — | Asset ID of the first persona/subject. |\n| `asset_image_2` | string | yes | — | Asset ID of the second persona/subject. |\n| `location_asset` | string or null |  | `null` | Optional asset ID of a location/background reference for the scene. |\n| `prompt` | string or null |  | `null` | What the two subjects are doing together and the scene to place them in. |\n| `ratio` | enum |  | `1:1` | One of: `16:9`, `1:1`, `21:9`, `2:3`, `3:2`, `3:4`, `4:3`, `9:16`. Aspect ratio of the output (e.g. 1:1, 16:9, 9:16). |\n| `width` | integer |  | `1024` | Output width in pixels (used when `ratio` is not set). |\n| `height` | integer |  | `1024` | Output height in pixels (used when `ratio` is not set). |\n| `number_of_images` | integer |  | `1` | Number of images to generate, 1-4. Default 1. |\n\n**Outputs:** `image_assets` (array[string])\n\n### video2video\n\nTransfer motion or replace a character in a video using a reference video or an Instagram/TikTok URL; the original soundtrack can be kept. SFW and NSFW modes. Provide the source as exactly one of `video_asset`, `instagram_url` or `tiktok_url`. Output: one video.\n\n**Modes:**\n- `kling_2_6_sfw` — Handles character replacement best (censored); billed per second.\n- `replace_sfw` / `replace_nsfw` — Replace the person in the source video with your image's subject; `replace_nsfw` is uncensored.\n- `animate_sfw` / `animate_nsfw` — Motion transfer / animation of your image; `animate_nsfw` is uncensored.\n- `dreamactor_m2` — Same character-replacement logic, uncensored.\n\n*Note:* the uncensored modes trade some quality and prompt understanding — you may need to change the input (the source video or the character) to get a good result on the first try.\n\n**Price:** depends on `mode` and the duration of the source video (`video_asset` / `instagram_url` / `tiktok_url`): `dreamactor_m2` — 1 credit per second; `kling_2_6_sfw` — 2 credits per second (both capped at 30 seconds of source video); other modes — at 480p flat 7 credits for videos up to 5 seconds, then 1.4 credits per second; at 720p flat 13 credits up to 5 seconds, then 2.8 credits per second; at 1080p always 2.8 credits per second.\n\n**Input parameters:**\n\n| Field | Type | Required | Default | Description |\n|---|---|---|---|---|\n| `image_asset` | string | yes | — | Asset ID of the image whose subject is animated or swapped in. |\n| `video_asset` | string or null |  | `null` | Asset ID of the source/driving video (one source only). |\n| `instagram_url` | string or null |  | `null` | Instagram post/reel URL used as the source video (one source only). |\n| `tiktok_url` | string or null |  | `null` | TikTok post/reel URL used as the source video (one source only). |\n| `mode` | enum |  | `replace_sfw` | One of: `animate_nsfw`, `animate_sfw`, `dreamactor_m2`, `kling_2_6_sfw`, `replace_nsfw`, `replace_sfw`. How the image and source video are combined. `replace_sfw` / `replace_nsfw` — replace the person in the source video with your image's subject; `animate_sfw` / `animate_nsfw` — animate your image using the source video's motion; `kling_2_6_sfw` — Kling 2.6 driven animation; `dreamactor_m2` — DreamActor M2 driven animation. |\n| `resolution` | enum |  | `720p` | One of: `1080p`, `480p`, `720p`. Output resolution: `480p`, `720p` or `1080p`. |\n| `keep_original_sound` | boolean |  | `true` | One of: `true`, `false`. Keep the source video's audio (only for `kling_2_6_sfw`). Default true. |\n\n**Outputs:** `video_asset` (string)\n\n### lipsync\n\nMake a character speak your audio (talking head): bring an audio file and a portrait first frame, and get a video in which the character talks or sings in sync. Up to 35 seconds of audio; image JPG/PNG under 5 MB. Use it to voice a character or avatar. Niche — used occasionally. Priced at 3 credits per second of audio.\n\n**Price:** 3 credits per second of audio, measured from the uploaded `audio_asset` (audio longer than 35 seconds is rejected).\n\n**Input parameters:**\n\n| Field | Type | Required | Default | Description |\n|---|---|---|---|---|\n| `image_asset` | string | yes | — | Asset ID of the portrait image (JPG/PNG, under 5MB, up to 4096x4096). |\n| `audio_asset` | string | yes | — | Asset ID of the audio track to lip-sync to (under 35 seconds). |\n| `prompt` | string |  | `\"\"` | Optional text to guide expression/performance. |\n| `model` | enum |  | `GENERAL_NSFW` | One of: `GENERAL_NSFW`. Lip-sync model (e.g. `GENERAL_NSFW`). |\n\n**Outputs:** `video_asset` (string)\n\n### undress\n\nFully removes clothing from the character in an image. Input: one image. Output: one image. A male variant exists as a separate tool for trusted accounts. This is a convenience preset built on a Flux Klein LoRA — the same result is available through `image_editor` with the Flux Klein LoRA presets, including presets that handle paired photos.\n\n**Price:** 3 credits.\n\n**Input parameters:**\n\n| Field | Type | Required | Default | Description |\n|---|---|---|---|---|\n| `image_asset` | string | yes | — | Asset ID of the image to process. |\n\n**Outputs:** `image_asset` (string)\n\n### video_upscaler\n\nBring a medium-quality video and get a sharper, higher-resolution result, up to 5K on the longest side. Use it as a final polish or to restore low-quality footage. Niche — used occasionally. Priced by output megapixels x duration x a frame-rate multiplier.\n\n**Price:** 2 credits x output megapixels x duration in seconds x FPS multiplier (x1 up to 30 fps, x2 up to 60 fps, x3 above). Output size is the source resolution multiplied by `scale_factor`; `\"max\"` upscales to at most 5120 px on the longest side.\n\n**Input parameters:**\n\n| Field | Type | Required | Default | Description |\n|---|---|---|---|---|\n| `video_asset` | string | yes | — | Asset ID of the video to upscale. |\n| `scale_factor` | string |  | — | How much to enlarge the video. `max` upscales to at most 5120px on the longest side; otherwise a multiplier of the source size: 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 40, 50, 75 or 100. |\n\n**Outputs:** `video_asset` (string)\n\n### video_merger\n\nConcatenate 2-5 video clips with transitions\n\n**Price:** 1 credit.\n\n**Input parameters:**\n\n| Field | Type | Required | Default | Description |\n|---|---|---|---|---|\n| `clips` | array[object] | yes | — | Clips to concatenate (asset_id + trim + duration) |\n| `transition` | enum |  | `cut` | One of: `cut`, `dissolve`, `fade`, `slide`. cut \\| fade \\| slide \\| dissolve |\n| `keep_audio` | boolean |  | `true` | One of: `true`, `false`. Preserve audio tracks |\n| `fps` | integer |  | `30` | Output FPS (24 or 30) |\n| `width` | integer |  | `1280` | Output width |\n| `height` | integer |  | `720` | Output height |\n\n**Outputs:** `video_asset` (string)\n\n## Uploading Files\n\n`POST /api/public/v1/assets` accepts `multipart/form-data` with two parts: `media_type` and `file` (max **50 MB**):\n\n```bash\ncurl -X POST \"https://api.zencreator.pro/api/public/v1/assets\" \\\n  -H \"Authorization: Bearer $ZC_API_KEY\" \\\n  -F \"media_type=image/png\" \\\n  -F \"file=@face.png\"\n# -> {\"asset_id\": \"0196...\", \"media_type\": \"image/png\"}\n```\n\nSupported media types: images `image/png`, `image/jpeg`, `image/jpg`, `image/webp`, `image/heic`, `image/heif`; video `video/mp4`, `video/mov`, `video/quicktime`; audio `audio/mpeg`, `audio/mp3`, `audio/wav`, `audio/x-wav`, `audio/x-m4a`.\n\n## Templates, LoRA styles & Photoshoot categories\n\nSeveral tools accept *presets* — ready-made styles you reference by id instead of crafting from scratch:\n\n- **Templates** — `GET /api/public/v1/templates` lists ready-to-use generation presets (`id`, `name`, `tags`, `description`, and the baked-in `input`). Send a template's `input` straight to `POST /generations`, or pass its `id` as the `lora_id` of tools that accept one (e.g. `image_editor` with `model=FLUX_KLEIN_LORA`).\n- **LoRA styles** — `GET /api/public/v1/loras?model=<model>` lists LoRA styles for a model; pass a LoRA's `id` (or name) in the `loras` / `lora_id` field of tools that support it and include its `trigger_word` in the prompt.\n- **Photoshoot categories** — `GET /api/public/v1/photoshoot-categories` lists curated categories; pass a category's `id` as `category_id` to the `photoshoot` tool to generate `image_count` images from that category.\n\n## Credits & Billing\n\nGenerations are paid in **credits**. Exact prices per tool are listed in the Tools & Pricing section above; the `price` field of `GET /tools` is the tool's base price — the actual charge can vary with the input (model, duration, resolution, number of images). The exact amount charged for every generation is recorded in your transaction history (`GET /api/public/v1/transactions`). Credits are charged when a generation is accepted and **automatically refunded** if it fails.\n\n- Check your balance: `GET /api/public/v1/balance`.\n- Top up credits: [https://app.zencreator.pro/billing](https://app.zencreator.pro/billing).\n- When the balance is too low, the API responds `402` with code `insufficient_credits`.\n\n## Rate Limits\n\nLimits are applied per API key over a 60-second sliding window:\n\n| Operation | Limit |\n|-----------|-------|\n| Read (GET endpoints) | 60/min |\n| Start generation | 10/min |\n| Upload asset | 30/min |\n\nEvery response carries `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset` headers. On `429` also check `Retry-After` (seconds).\n\n## Idempotency\n\n`POST /generations` supports the `Idempotency-Key` header. Requests repeated with the same key within **24 hours** return the original generation instead of creating (and charging for) a new one. Use it to make network retries safe.\n\n## Errors\n\nAll errors share one envelope:\n\n```json\n{\"error\": {\"code\": \"validation_error\", \"message\": \"Invalid enum value 'NOT_A_MODEL' - at `$.model`\"}}\n```\n\n| HTTP | Code | Meaning |\n|------|------|---------|\n| 400 | `bad_request` | Malformed request or JSON body |\n| 401 | `missing_api_key` | No `Authorization: Bearer` header |\n| 401 | `invalid_api_key` | Key not found, revoked or expired |\n| 402 | `insufficient_credits` | Not enough credits — top up at [https://app.zencreator.pro/billing](https://app.zencreator.pro/billing) |\n| 403 | `insufficient_scope` | The key lacks the required scope (`read` / `generate`) |\n| 403 | `forbidden` | The resource belongs to another account |\n| 403 | `user_blocked` | The account is blocked |\n| 404 | `not_found` | Unknown tool, generation or route |\n| 409 | `conflict` | Conflicting state |\n| 413 | `payload_too_large` | Upload exceeds 50 MB |\n| 415 | `unsupported_media_type` | Media type not supported |\n| 422 | `validation_error` | Input failed validation — the message names the offending field |\n| 429 | `rate_limit_exceeded` | Rate limit hit — retry after `Retry-After` seconds |\n| 500 | `internal_error` | Unexpected server error |\n\nA *failed generation* is not an HTTP error: the generation responds `200` with `\"status\": \"failed\"` and a human-readable `error` field.\n\n## Polling\n\nThere are no webhooks yet — poll `GET /generations/{id}` every 5-10 seconds. Generations typically finish within 10-120 seconds depending on the tool.\n"},"openapi":"3.1.0","servers":[{"url":"https://api.zencreator.pro"}],"paths":{"/api/public/v1/tools/{tool_name}":{"get":{"tags":["Tools"],"summary":"Get a tool","description":"Get a single tool by name, including the JSON Schema of its `input` payload and the shape of the outputs it produces.\n\n**Required scope:** `read`","operationId":"ApiPublicV1ToolsToolNameGetTool","parameters":[{"name":"tool_name","in":"path","schema":{"type":"string"},"required":true,"deprecated":false}],"responses":{"200":{"description":"Request fulfilled, document follows","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolPublicDTO"},"example":{"name":"by_prompt","description":"Generate an image from a text prompt, with no input image (text-to-image).","price":1,"pricing":"1-4 / image","input_schema":{"type":"object","required":["positive_prompt"],"properties":{"positive_prompt":{"type":"string","description":"What to generate."},"ratio":{"type":"string","enum":["1:1","3:4","16:9"],"default":"3:4"},"image_count":{"type":"integer","minimum":1,"maximum":8,"default":1}}},"output_schema":{"type":"object","properties":{"image_assets":{"type":"array","items":{"type":"string"}}}}}}}},"404":{"$ref":"#/components/responses/NotFound"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"422":{"$ref":"#/components/responses/ValidationError"},"400":{"$ref":"#/components/responses/BadRequest"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"deprecated":false,"security":[{"publicApiKey":[]}],"x-required-scope":"read"}},"/api/public/v1/tools":{"get":{"tags":["Tools"],"summary":"List tools","description":"List every generation tool available to your account with its price and a JSON Schema describing the `input` payload it accepts. Use `input_schema` to build a valid POST /generations request: respect `required`, `enum` and `default` for each field.\n\n**Required scope:** `read`","operationId":"ApiPublicV1ToolsListTools","responses":{"200":{"description":"Request fulfilled, document follows","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolsPublicDTO"},"example":{"tools":[{"name":"by_prompt","description":"Generate an image from a text prompt, with no input image (text-to-image).","price":1,"pricing":"1-4 / image","input_schema":{"type":"object","required":["positive_prompt"],"properties":{"positive_prompt":{"type":"string","description":"What to generate."},"ratio":{"type":"string","enum":["1:1","3:4","16:9"],"default":"3:4"},"image_count":{"type":"integer","minimum":1,"maximum":8,"default":1}}},"output_schema":{"type":"object","properties":{"image_assets":{"type":"array","items":{"type":"string"}}}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"401":{"$ref":"#/components/responses/Unauthorized"}},"deprecated":false,"security":[{"publicApiKey":[]}],"x-required-scope":"read"}},"/api/public/v1/generations":{"post":{"tags":["Generations"],"summary":"Start a generation","description":"Start an asynchronous generation with the given tool. The `input` payload is validated against the tool's `input_schema` (see GET /tools/{tool_name}) before any credits are charged: invalid payloads get an immediate 422 with the offending field. Credits are deducted on acceptance; if the generation later fails they are refunded automatically. Poll GET /generations/{generation_id} until the status is terminal, then fetch the outputs from GET /generations/{generation_id}/result. Send an `Idempotency-Key` header to make retries safe: repeated requests with the same key return the original generation for 24 hours.\n\n**Required scope:** `generate`","operationId":"ApiPublicV1GenerationsCreateGeneration","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGenerationRequest"},"example":{"tool":"by_prompt","input":{"positive_prompt":"portrait of a woman, golden hour, 85mm","ratio":"3:4"}}}},"required":true},"responses":{"201":{"description":"Document created, URL follows","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerationDTO"},"example":{"id":"0196f7a0-5f2e-7a10-8c3a-2b9d4e6f8a01","status":"queued","created_at":"2026-06-10T12:00:00Z"}}}},"404":{"$ref":"#/components/responses/NotFound"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"422":{"$ref":"#/components/responses/ValidationError"},"400":{"$ref":"#/components/responses/BadRequest"},"429":{"$ref":"#/components/responses/TooManyRequests"},"402":{"$ref":"#/components/responses/PaymentRequired"}},"deprecated":false,"security":[{"publicApiKey":[]}],"x-required-scope":"generate"}},"/api/public/v1/generations/{generation_id}":{"get":{"tags":["Generations"],"summary":"Get generation status","description":"Poll the status of a generation. Statuses: `queued` -> `processing` -> `succeeded` | `partial` | `failed`. When the status is `failed` or `partial`, `error` explains why. Poll every 5-10 seconds; generations typically take 10-120 seconds depending on the tool.\n\n**Required scope:** `read`","operationId":"ApiPublicV1GenerationsGenerationIdGetGeneration","parameters":[{"name":"generation_id","in":"path","schema":{"type":"string","format":"uuid"},"required":true,"deprecated":false}],"responses":{"200":{"description":"Request fulfilled, document follows","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerationStatusDTO"},"example":{"id":"0196f7a0-5f2e-7a10-8c3a-2b9d4e6f8a01","status":"processing","progress":50}}}},"404":{"$ref":"#/components/responses/NotFound"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"422":{"$ref":"#/components/responses/ValidationError"},"400":{"$ref":"#/components/responses/BadRequest"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"deprecated":false,"security":[{"publicApiKey":[]}],"x-required-scope":"read"}},"/api/public/v1/generations/{generation_id}/result":{"get":{"tags":["Generations"],"summary":"Get generation result","description":"Fetch the outputs of a finished generation. Each output has a preview `url` and a `download_url`. `outputs` is empty while the generation is still running and when it failed; in the latter case `error` explains why.\n\n**Required scope:** `read`","operationId":"ApiPublicV1GenerationsGenerationIdResultGetGenerationResult","parameters":[{"name":"generation_id","in":"path","schema":{"type":"string","format":"uuid"},"required":true,"deprecated":false}],"responses":{"200":{"description":"Request fulfilled, document follows","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerationResultDTO"},"example":{"id":"0196f7a0-5f2e-7a10-8c3a-2b9d4e6f8a01","status":"succeeded","outputs":[{"asset_id":"0196f7a2-9c4d-7b50-a1e2-3f4a5b6c7d8e","url":"https://cdn.zencreator.pro/assets/0196f7a2-9c4d-7b50-a1e2-3f4a5b6c7d8e.jpg","download_url":"https://cdn.zencreator.pro/assets/0196f7a2-9c4d-7b50-a1e2-3f4a5b6c7d8e.jpg?download=1"}]}}}},"404":{"$ref":"#/components/responses/NotFound"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"422":{"$ref":"#/components/responses/ValidationError"},"400":{"$ref":"#/components/responses/BadRequest"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"deprecated":false,"security":[{"publicApiKey":[]}],"x-required-scope":"read"}},"/api/public/v1/assets":{"post":{"tags":["Assets"],"summary":"Upload an asset","description":"Upload an image, video or audio file (multipart/form-data, max 50 MB) to use as a generation input. Pass the returned `asset_id` in tool input fields that reference assets, e.g. `image_asset`, `ref_asset` or `face_asset`. Supported media types: `image/png`, `image/jpeg`, `image/jpg`, `image/webp`, `image/heic`, `image/heif`, `video/mp4`, `video/mov`, `video/quicktime`, `audio/mpeg`, `audio/mp3`, `audio/wav`, `audio/x-wav`, `audio/x-m4a`.\n\n**Required scope:** `generate`","operationId":"ApiPublicV1AssetsUploadAsset","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/AssetUploadRequest"}}},"required":true},"responses":{"201":{"description":"Document created, URL follows","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetUploadDTO"},"example":{"asset_id":"0196f79e-1b2c-7d30-9e4f-5a6b7c8d9e0f","media_type":"image/png"}}}},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"422":{"$ref":"#/components/responses/ValidationError"},"400":{"$ref":"#/components/responses/BadRequest"},"429":{"$ref":"#/components/responses/TooManyRequests"},"413":{"$ref":"#/components/responses/PayloadTooLarge"}},"deprecated":false,"security":[{"publicApiKey":[]}],"x-required-scope":"generate"}},"/api/public/v1/balance":{"get":{"tags":["Balance"],"summary":"Get balance","description":"Current credit balance of the account. Compare it with a tool's `price` before starting a generation; when the balance is too low, POST /generations responds 402 `insufficient_credits`.\n\n**Required scope:** `read`","operationId":"ApiPublicV1BalanceGetBalance","responses":{"200":{"description":"Request fulfilled, document follows","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BalancePublicDTO"},"example":{"credits":4200}}}},"400":{"$ref":"#/components/responses/BadRequest"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"401":{"$ref":"#/components/responses/Unauthorized"}},"deprecated":false,"security":[{"publicApiKey":[]}],"x-required-scope":"read"}},"/api/public/v1/loras":{"get":{"tags":["LoRAs"],"summary":"List LoRAs","description":"List LoRA styles compatible with the given model. Pass a LoRA's `id` as `lora_id` in tool inputs that support it (see the tool's `input_schema`), and include its `trigger_word` in the prompt to activate the style.\n\n**Required scope:** `read`","operationId":"ApiPublicV1LorasListLoras","parameters":[{"name":"model","in":"query","schema":{"$ref":"#/components/schemas/LoraModel"},"required":true,"deprecated":false,"allowEmptyValue":false,"allowReserved":false},{"name":"page","in":"query","schema":{"type":"integer","minimum":1.0,"description":"Page number","default":1},"description":"Page number","required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false},{"name":"limit","in":"query","schema":{"type":"integer","maximum":100.0,"minimum":1.0,"description":"Items per page","default":10},"description":"Items per page","required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false}],"responses":{"200":{"description":"Request fulfilled, document follows","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LorasPublicDTO"},"example":{"loras":[{"id":"0196f1d4-6e5f-7890-a3b4-c5d6e7f8a9b0","name":"Slim Body V2","trigger_word":"slimbody","is_nsfw":false,"is_new":true}],"pagination":{"page":1,"limit":10,"total":34,"total_pages":4}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"422":{"$ref":"#/components/responses/ValidationError"},"400":{"$ref":"#/components/responses/BadRequest"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"deprecated":false,"security":[{"publicApiKey":[]}],"x-required-scope":"read"}},"/api/public/v1/templates/{template_id}":{"get":{"tags":["Templates"],"summary":"Get a template","description":"Fetch a single public template by id, including its preset `input` payload.\n\n**Required scope:** `read`","operationId":"ApiPublicV1TemplatesTemplateIdGetTemplate","parameters":[{"name":"template_id","in":"path","schema":{"type":"string","format":"uuid"},"required":true,"deprecated":false}],"responses":{"200":{"description":"Request fulfilled, document follows","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplatePublicDTO"},"example":{"id":"0196f3c8-2a1b-7c40-b5d6-7e8f9a0b1c2d","name":"Golden Hour Portrait","description":"Warm backlit portrait preset for by_prompt.","tool_name":"by_prompt","tags":["by_prompt","portrait"],"version":"1.0","input":{"positive_prompt":"portrait of a woman, golden hour, 85mm","ratio":"3:4"}}}}},"404":{"$ref":"#/components/responses/NotFound"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"422":{"$ref":"#/components/responses/ValidationError"},"400":{"$ref":"#/components/responses/BadRequest"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"deprecated":false,"security":[{"publicApiKey":[]}],"x-required-scope":"read"}},"/api/public/v1/templates":{"get":{"tags":["Templates"],"summary":"List templates","description":"Browse public, ready-to-use generation presets. Each template bundles a `tool` with a baked-in `input` payload you can send straight to POST /generations (overriding asset ids and any field you want). Filter by `tool_name` or `tags`. Templates also back the `lora_id` preset of tools that accept one — pass the template `id` as `lora_id`.\n\n**Required scope:** `read`","operationId":"ApiPublicV1TemplatesListTemplates","parameters":[{"name":"tool_name","in":"query","schema":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Filter by the tool the template is built for"},"description":"Filter by the tool the template is built for","required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false},{"name":"tags","in":"query","schema":{"oneOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"description":"Filter by tags (tool or purpose tags)"},"description":"Filter by tags (tool or purpose tags)","required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false},{"name":"page","in":"query","schema":{"type":"integer","minimum":1.0,"description":"Page number","default":1},"description":"Page number","required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false},{"name":"limit","in":"query","schema":{"type":"integer","maximum":100.0,"minimum":1.0,"description":"Items per page","default":10},"description":"Items per page","required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false}],"responses":{"200":{"description":"Request fulfilled, document follows","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplatesPublicDTO"},"example":{"templates":[{"id":"0196f3c8-2a1b-7c40-b5d6-7e8f9a0b1c2d","name":"Golden Hour Portrait","description":"Warm backlit portrait preset for by_prompt.","tool_name":"by_prompt","tags":["by_prompt","portrait"],"version":"1.0","input":{"positive_prompt":"portrait of a woman, golden hour, 85mm","ratio":"3:4"}}],"pagination":{"page":1,"limit":10,"total":52,"total_pages":6}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"422":{"$ref":"#/components/responses/ValidationError"},"400":{"$ref":"#/components/responses/BadRequest"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"deprecated":false,"security":[{"publicApiKey":[]}],"x-required-scope":"read"}},"/api/public/v1/photoshoot-categories":{"get":{"tags":["Photoshoot Categories"],"summary":"List photoshoot categories","description":"List the curated photoshoot categories. Pass a category's `id` as `category_id` in the photoshoot tool input (instead of a free-text `prompt`) to generate `image_count` images from that category's prompt set.\n\n**Required scope:** `read`","operationId":"ApiPublicV1PhotoshootCategoriesListCategories","parameters":[{"name":"gender","in":"query","schema":{"oneOf":[{"$ref":"#/components/schemas/PhotoshootGender"},{"type":"null"}],"description":"Filter by gender (male or female)"},"description":"Filter by gender (male or female)","required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false},{"name":"page","in":"query","schema":{"type":"integer","minimum":1.0,"description":"Page number","default":1},"description":"Page number","required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false},{"name":"limit","in":"query","schema":{"type":"integer","maximum":100.0,"minimum":1.0,"description":"Items per page","default":20},"description":"Items per page","required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false}],"responses":{"200":{"description":"Request fulfilled, document follows","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PhotoshootCategoriesPublicDTO"},"example":{"categories":[{"id":"0196f2e6-4d3c-7ab0-8f9e-0a1b2c3d4e5f","name":"Beach Lifestyle","gender":"female","is_new":false}],"pagination":{"page":1,"limit":20,"total":57,"total_pages":3}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"422":{"$ref":"#/components/responses/ValidationError"},"400":{"$ref":"#/components/responses/BadRequest"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"deprecated":false,"security":[{"publicApiKey":[]}],"x-required-scope":"read"}},"/api/public/v1/transactions":{"get":{"tags":["Transactions"],"summary":"List transactions","description":"Credit transaction history, newest first: top-ups, generation spends, refunds and bonuses. `amount` is positive for credits added and negative for credits deducted; `resulting_amount` is the balance right after the transaction.\n\n**Required scope:** `read`","operationId":"ApiPublicV1TransactionsListTransactions","parameters":[{"name":"channel","in":"query","schema":{"oneOf":[{"$ref":"#/components/schemas/Channel"},{"type":"null"}],"description":"Filter by origin channel (product, api, mcp)"},"description":"Filter by origin channel (product, api, mcp)","required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false},{"name":"type","in":"query","schema":{"oneOf":[{"$ref":"#/components/schemas/CreditTransactionType"},{"type":"null"}],"description":"Filter by transaction type (topup, spend, refund, bonus)"},"description":"Filter by transaction type (topup, spend, refund, bonus)","required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false},{"name":"date_from","in":"query","schema":{"oneOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only include transactions at or after this time"},"description":"Only include transactions at or after this time","required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false},{"name":"date_to","in":"query","schema":{"oneOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only include transactions at or before this time"},"description":"Only include transactions at or before this time","required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false},{"name":"page","in":"query","schema":{"type":"integer","minimum":1.0,"description":"Page number","default":1},"description":"Page number","required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false},{"name":"limit","in":"query","schema":{"type":"integer","maximum":100.0,"minimum":1.0,"description":"Items per page","default":10},"description":"Items per page","required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false}],"responses":{"200":{"description":"Request fulfilled, document follows","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTransactionsDTO"},"example":{"transactions":[{"id":"0196f7a3-8b7a-7c60-9d0e-1f2a3b4c5d6e","channel":"api","type":"spend","source":"task","amount":-1,"resulting_amount":4199,"created_at":"2026-06-10T12:00:05Z"}],"pagination":{"page":1,"limit":10,"total":128,"total_pages":13}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"422":{"$ref":"#/components/responses/ValidationError"},"400":{"$ref":"#/components/responses/BadRequest"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"deprecated":false,"security":[{"publicApiKey":[]}],"x-required-scope":"read"}}},"components":{"schemas":{"AssetUploadDTO":{"properties":{"asset_id":{"type":"string","format":"uuid","description":"Identifier of the uploaded asset; pass it into tool inputs"},"media_type":{"$ref":"#/components/schemas/MediaType"}},"type":"object","required":["asset_id","media_type"],"title":"AssetUploadDTO"},"AssetUploadRequest":{"properties":{"media_type":{"$ref":"#/components/schemas/MediaType"},"file":{"type":"string","format":"binary","contentMediaType":"application/octet-stream","description":"The binary file to upload"}},"type":"object","required":["file","media_type"],"title":"AssetUploadRequest"},"BalancePublicDTO":{"properties":{"credits":{"type":"integer","description":"Current credit balance of the account"}},"type":"object","required":["credits"],"title":"BalancePublicDTO"},"Channel":{"type":"string","enum":["product","api","mcp"],"title":"Channel"},"CreateGenerationRequest":{"properties":{"tool":{"type":"string","description":"Name of the tool to run. See GET /tools for the catalog."},"input":{"additionalProperties":{"oneOf":[{"oneOf":[{"type":"string"},{"type":"integer"},{"type":"number"},{"type":"boolean"},{"type":"null"}]},{"additionalProperties":{"oneOf":[{"oneOf":[{"type":"string"},{"type":"integer"},{"type":"number"},{"type":"boolean"},{"type":"null"}]},{"additionalProperties":{"oneOf":[{"type":"string"},{"type":"integer"},{"type":"number"},{"type":"boolean"},{"type":"null"}]},"type":"object"}]},"type":"object"},{"items":{"oneOf":[{"oneOf":[{"type":"string"},{"type":"integer"},{"type":"number"},{"type":"boolean"},{"type":"null"}]},{"additionalProperties":{"oneOf":[{"oneOf":[{"type":"string"},{"type":"integer"},{"type":"number"},{"type":"boolean"},{"type":"null"}]},{"additionalProperties":{"oneOf":[{"type":"string"},{"type":"integer"},{"type":"number"},{"type":"boolean"},{"type":"null"}]},"type":"object"}]},"type":"object"}]},"type":"array"}]},"type":"object","description":"Input payload conforming to the tool's `input_schema` from GET /tools/{tool_name}. Invalid payloads are rejected with 422 and a message pointing at the offending field."}},"type":"object","required":["input","tool"],"title":"CreateGenerationRequest"},"CreditTransactionType":{"type":"string","enum":["topup","spend","refund","bonus"],"title":"CreditTransactionType"},"GenerationDTO":{"properties":{"id":{"type":"string","format":"uuid","description":"The unique identifier of the generation"},"status":{"$ref":"#/components/schemas/GenerationStatus"},"created_at":{"type":"string","format":"date-time","description":"When the generation was created"}},"type":"object","required":["created_at","id","status"],"title":"GenerationDTO"},"GenerationOutputDTO":{"properties":{"asset_id":{"type":"string","format":"uuid","description":"The unique identifier of the output asset"},"url":{"type":"string","description":"Public preview URL of the asset"},"download_url":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Direct download URL of the asset"}},"type":"object","required":["asset_id","url"],"title":"GenerationOutputDTO"},"GenerationResultDTO":{"properties":{"id":{"type":"string","format":"uuid","description":"The unique identifier of the generation"},"status":{"$ref":"#/components/schemas/GenerationStatus"},"outputs":{"items":{"$ref":"#/components/schemas/GenerationOutputDTO"},"type":"array","description":"The produced output assets"},"error":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Human-readable failure reason. Present when status is `failed` or `partial`."}},"type":"object","required":["id","outputs","status"],"title":"GenerationResultDTO"},"GenerationStatus":{"type":"string","enum":["queued","processing","succeeded","partial","failed"],"title":"GenerationStatus"},"GenerationStatusDTO":{"properties":{"id":{"type":"string","format":"uuid","description":"The unique identifier of the generation"},"status":{"$ref":"#/components/schemas/GenerationStatus"},"progress":{"type":"integer","maximum":100.0,"minimum":0.0,"description":"Completion percentage (0-100)"},"error":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Human-readable failure reason. Present when status is `failed` or `partial`."}},"type":"object","required":["id","progress","status"],"title":"GenerationStatusDTO"},"LoraModel":{"type":"string","enum":["wan@2.2","flux_klein"],"title":"LoraModel"},"LoraPaginationDTO":{"properties":{"page":{"type":"integer","description":"Current page number"},"limit":{"type":"integer","description":"Items per page"},"total":{"type":"integer","description":"Total number of LoRAs"},"total_pages":{"type":"integer","description":"Total number of pages"}},"type":"object","required":["limit","page","total","total_pages"],"title":"LoraPaginationDTO","description":"Pagination information"},"LoraPublicDTO":{"properties":{"id":{"type":"string","format":"uuid","description":"LoRA identifier to pass as `lora_id` in tool inputs"},"name":{"type":"string","description":"LoRA name"},"trigger_word":{"type":"string","description":"Trigger word that activates the LoRA"},"is_nsfw":{"type":"boolean","description":"Whether the LoRA is NSFW"},"is_new":{"type":"boolean","description":"Whether the LoRA was added recently"}},"type":"object","required":["id","is_new","is_nsfw","name","trigger_word"],"title":"LoraPublicDTO"},"LorasPublicDTO":{"properties":{"loras":{"items":{"$ref":"#/components/schemas/LoraPublicDTO"},"type":"array","description":"LoRAs available for the requested model"},"pagination":{"$ref":"#/components/schemas/LoraPaginationDTO"}},"type":"object","required":["loras","pagination"],"title":"LorasPublicDTO"},"MediaType":{"type":"string","enum":["image/png","image/jpeg","image/jpg","image/webp","image/heic","image/heif","video/mp4","video/mov","video/quicktime","audio/mpeg","audio/mp3","audio/wav","audio/x-wav","audio/x-m4a"],"title":"MediaType"},"PhotoshootCategoriesPublicDTO":{"properties":{"categories":{"items":{"$ref":"#/components/schemas/PhotoshootCategoryPublicDTO"},"type":"array","description":"Available photoshoot categories."},"pagination":{"$ref":"#/components/schemas/PhotoshootCategoryPaginationDTO"}},"type":"object","required":["categories","pagination"],"title":"PhotoshootCategoriesPublicDTO"},"PhotoshootCategoryPaginationDTO":{"properties":{"page":{"type":"integer","description":"Current page number (1-indexed)."},"limit":{"type":"integer","description":"Items per page."},"total":{"type":"integer","description":"Total number of categories."},"total_pages":{"type":"integer","description":"Total number of pages."}},"type":"object","required":["limit","page","total","total_pages"],"title":"PhotoshootCategoryPaginationDTO","description":"Pagination information."},"PhotoshootCategoryPublicDTO":{"properties":{"id":{"type":"string","format":"uuid","description":"Category id. Pass it as `category_id` to the photoshoot tool."},"name":{"type":"string","description":"Category name."},"gender":{"$ref":"#/components/schemas/PhotoshootGender"},"is_new":{"type":"boolean","description":"Whether the category was added recently."}},"type":"object","required":["gender","id","is_new","name"],"title":"PhotoshootCategoryPublicDTO"},"PhotoshootGender":{"type":"string","enum":["male","female"],"title":"PhotoshootGender"},"PublicTransactionDTO":{"properties":{"id":{"type":"string","format":"uuid","description":"Transaction identifier"},"channel":{"$ref":"#/components/schemas/Channel"},"type":{"$ref":"#/components/schemas/CreditTransactionType"},"source":{"type":"string","description":"Granular reason for the transaction (task, paypal, refund, ...)"},"amount":{"type":"integer","description":"Credits added (positive) or deducted (negative)"},"resulting_amount":{"type":"integer","description":"Credit balance after the transaction"},"created_at":{"type":"string","format":"date-time","description":"When the transaction occurred"}},"type":"object","required":["amount","channel","created_at","id","resulting_amount","source","type"],"title":"PublicTransactionDTO"},"PublicTransactionsDTO":{"properties":{"transactions":{"items":{"$ref":"#/components/schemas/PublicTransactionDTO"},"type":"array","description":"Credit transactions, newest first"},"pagination":{"$ref":"#/components/schemas/TransactionPaginationDTO"}},"type":"object","required":["pagination","transactions"],"title":"PublicTransactionsDTO"},"TemplatePaginationDTO":{"properties":{"page":{"type":"integer","description":"Current page number (1-indexed)."},"limit":{"type":"integer","description":"Items per page."},"total":{"type":"integer","description":"Total number of templates matching the query."},"total_pages":{"type":"integer","description":"Total number of pages."}},"type":"object","required":["limit","page","total","total_pages"],"title":"TemplatePaginationDTO","description":"Pagination information."},"TemplatePublicDTO":{"properties":{"id":{"type":"string","format":"uuid","description":"Template identifier. Pass it as `template_id` in POST /generations."},"name":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Human-readable template name."},"description":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"What the template produces and when to use it (may be empty until curated)."},"tool_name":{"type":"string","description":"The tool this template is built for. Use it as `tool` in POST /generations."},"tags":{"items":{"type":"string"},"type":"array","description":"Tool/model and purpose tags for filtering and discovery."},"version":{"type":"string","description":"Template version."},"input":{"additionalProperties":{},"type":"object","description":"Preset `input` payload baked into the template. Send it as the `input` of POST /generations (overriding asset ids and any field you want to change). For tools with a `lora_id` field, the template id doubles as the `lora_id` preset."}},"type":"object","required":["description","id","input","name","tags","tool_name","version"],"title":"TemplatePublicDTO"},"TemplatesPublicDTO":{"properties":{"templates":{"items":{"$ref":"#/components/schemas/TemplatePublicDTO"},"type":"array","description":"Templates matching the query."},"pagination":{"$ref":"#/components/schemas/TemplatePaginationDTO"}},"type":"object","required":["pagination","templates"],"title":"TemplatesPublicDTO"},"ToolPublicDTO":{"properties":{"name":{"type":"string","description":"Unique tool name. Pass it as `tool` in POST /generations."},"description":{"type":"string","description":"What the tool does"},"price":{"type":"integer","description":"Credits charged for a call with default input parameters. The actual charge can vary with the input (model, duration, resolution, number of images) — see `pricing` and the Tools & Pricing section of the documentation for exact prices."},"input_schema":{"additionalProperties":{},"type":"object","description":"JSON Schema of the `input` payload for POST /generations. Lists every field with its type, allowed values (`enum`), default and whether it is required."},"output_schema":{"additionalProperties":{},"type":"object","description":"JSON Schema of the outputs produced by the tool. Output asset IDs resolve to URLs via GET /generations/{generation_id}/result."},"pricing":{"type":"string","description":"Human-readable pricing summary: a credit amount or range for the tool's input combinations (e.g. \"1-2\", \"3 / image\", \"3 / second of audio\").","default":""}},"type":"object","required":["description","input_schema","name","output_schema","price"],"title":"ToolPublicDTO"},"ToolsPublicDTO":{"properties":{"tools":{"items":{"$ref":"#/components/schemas/ToolPublicDTO"},"type":"array","description":"Available tools"}},"type":"object","required":["tools"],"title":"ToolsPublicDTO"},"TransactionPaginationDTO":{"properties":{"page":{"type":"integer","description":"Current page number"},"limit":{"type":"integer","description":"Items per page"},"total":{"type":"integer","description":"Total number of transactions"},"total_pages":{"type":"integer","description":"Total number of pages"}},"type":"object","required":["limit","page","total","total_pages"],"title":"TransactionPaginationDTO","description":"Pagination information"},"PublicApiError":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation of what went wrong."}}}}}},"securitySchemes":{"publicApiKey":{"type":"http","scheme":"bearer","description":"Public API key: `Authorization: Bearer zc_live_<key_id>_<secret>`."}},"headers":{"RateLimitLimit":{"description":"Requests allowed per API key in the current 60-second window.","schema":{"type":"integer"}},"RateLimitRemaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"}},"RateLimitReset":{"description":"Seconds until the rate-limit window resets.","schema":{"type":"integer"}},"RetryAfter":{"description":"Seconds to wait before retrying after a 429.","schema":{"type":"integer"}}},"responses":{"BadRequest":{"description":"Malformed request or JSON body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiError"},"example":{"error":{"code":"bad_request","message":"Malformed JSON body."}}}}},"Unauthorized":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiError"},"examples":{"missing_api_key":{"value":{"error":{"code":"missing_api_key","message":"No `Authorization: Bearer` header was provided."}}},"invalid_api_key":{"value":{"error":{"code":"invalid_api_key","message":"API key not found, revoked or expired."}}}}}}},"PaymentRequired":{"description":"Not enough credits to start the generation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiError"},"example":{"error":{"code":"insufficient_credits","message":"Balance too low."}}}}},"Forbidden":{"description":"The key lacks the required scope, the account is blocked, or the resource is not yours.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiError"},"examples":{"insufficient_scope":{"value":{"error":{"code":"insufficient_scope","message":"Missing required scope: generate"}}},"forbidden":{"value":{"error":{"code":"forbidden","message":"The resource belongs to another account."}}},"user_blocked":{"value":{"error":{"code":"user_blocked","message":"The account is blocked."}}}}}}},"NotFound":{"description":"Unknown tool, generation, template, category or route.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiError"},"example":{"error":{"code":"not_found","message":"Tool not found."}}}}},"PayloadTooLarge":{"description":"The uploaded file exceeds the 50 MB limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiError"},"example":{"error":{"code":"payload_too_large","message":"Upload exceeds 50 MB."}}}}},"UnsupportedMediaType":{"description":"The uploaded media type is not supported.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiError"},"example":{"error":{"code":"unsupported_media_type","message":"Media type not supported."}}}}},"ValidationError":{"description":"The input failed validation; the message names the offending field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiError"},"example":{"error":{"code":"validation_error","message":"Invalid enum value 'NOT_A_MODEL' - at `$.model`"}}}}},"TooManyRequests":{"description":"Rate limit hit. Retry after the `Retry-After` interval (seconds).","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiError"},"example":{"error":{"code":"rate_limit_exceeded","message":"Rate limit exceeded."}}}}}}},"security":[{"publicApiKey":[]}],"tags":[{"name":"Tools","description":"Catalog of generation tools with prices and machine-readable input schemas."},{"name":"Generations","description":"Start generations, poll their status and fetch the produced outputs."},{"name":"Assets","description":"Upload images, videos and audio to use as generation inputs."},{"name":"Templates","description":"Browse ready-to-use generation presets (id, name, tags, description) usable as input or `lora_id`."},{"name":"LoRAs","description":"Browse LoRA styles to reference from tool inputs."},{"name":"Photoshoot Categories","description":"Browse photoshoot categories to pass as `category_id` to the photoshoot tool."},{"name":"Balance","description":"Check the current credit balance of your account."},{"name":"Transactions","description":"Credit transaction history: top-ups, spends, refunds and bonuses."}]}