{"openapi":"3.1.0","info":{"title":"projtex: projection texturing API","description":"Texture a 3D mesh by generating images from virtual cameras (Qwen-Image-2.1 via the official Qwen Space, or Bria Fibo 2.0 Edit Turbo), projecting them onto the geometry, blending in texture space and baking to the mesh's UVs. Designed for agents: every long operation is an asynchronous job; poll GET /api/jobs/{id} and follow its `next` list. Agent guide: /llms.txt. MCP: /mcp.","version":"1.0"},"paths":{"/health":{"get":{"tags":["service"],"summary":"Health","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Health Health Get"}}}}}}},"/api":{"get":{"tags":["service"],"summary":"Service description: samples, backends, quota, limits, workflow","operationId":"api_info_api_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Api Info Api Get"}}}}}}},"/api/identity":{"get":{"tags":["service"],"summary":"Which identity would pay for generation for this request","operationId":"api_identity_api_identity_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Api Identity Api Identity Get"}}}}}}},"/api/jobs":{"post":{"tags":["jobs"],"summary":"Create a texturing job (returns immediately)","operationId":"create_job_api_jobs_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TextureRequest"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Create Job Api Jobs Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/terrain":{"post":{"tags":["terrain"],"summary":"Texture a terrain: ground layers + a large top-down colour map (returns a job at once)","description":"The ground is a mesh (upload_id / mesh_url / mesh_base64, +Y up) or a heightmap. Layers (or a preset) say\nwhich ground goes where; the result is terrain.glb (with the colour map) plus a bundle with the splat maps,\nseamless detail textures and ready-made Blender / three.js materials. Poll GET /api/jobs/{id}.","operationId":"create_terrain_api_terrain_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TerrainRequest"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Create Terrain Api Terrain Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/uploads":{"post":{"tags":["jobs"],"summary":"Upload a mesh file (raw request body, or multipart field 'file'); returns an upload_id","description":"Send the file bytes as the body, e.g. `curl --data-binary @house.glb -H 'content-type: model/gltf-binary'\nURL/api/uploads`. Then create the job with JSON: POST /api/jobs {\"upload_id\": ..., \"prompt\": ...}.","operationId":"upload_mesh_api_uploads_post","parameters":[{"name":"filename","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filename"}}],"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Upload Mesh Api Uploads Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/jobs/upload":{"post":{"tags":["jobs"],"summary":"Create a job from an uploaded mesh file (multipart: file + params JSON)","operationId":"create_job_upload_api_jobs_upload_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_create_job_upload_api_jobs_upload_post"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/jobs/{job_id}":{"get":{"tags":["jobs"],"summary":"Job status, results and next actions","operationId":"get_job_status_api_jobs__job_id__get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"events","in":"query","required":false,"schema":{"type":"integer","default":12,"title":"Events"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Job Status Api Jobs  Job Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["jobs"],"summary":"Api Delete","operationId":"api_delete_api_jobs__job_id__delete","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Api Delete Api Jobs  Job Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/jobs/{job_id}/regenerate":{"post":{"tags":["quality loop"],"summary":"Regenerate views with new seeds, then re-bake","operationId":"api_regenerate_api_jobs__job_id__regenerate_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegenerateRequest"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Api Regenerate Api Jobs  Job Id  Regenerate Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/jobs/{job_id}/disable-views":{"post":{"tags":["quality loop"],"summary":"Api Disable","operationId":"api_disable_api_jobs__job_id__disable_views_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ViewsRequest"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Api Disable Api Jobs  Job Id  Disable Views Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/jobs/{job_id}/fill-gaps":{"post":{"tags":["quality loop"],"summary":"Add and generate cameras for still-uncovered surface","operationId":"api_fill_gaps_api_jobs__job_id__fill_gaps_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FillGapsRequest"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Api Fill Gaps Api Jobs  Job Id  Fill Gaps Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/jobs/{job_id}/retouch":{"post":{"tags":["quality loop"],"summary":"Local inpainting inside a feathered mask","operationId":"api_retouch_api_jobs__job_id__retouch_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetouchRequest"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Api Retouch Api Jobs  Job Id  Retouch Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/jobs/{job_id}/undo-retouch":{"post":{"tags":["quality loop"],"summary":"Api Undo","operationId":"api_undo_api_jobs__job_id__undo_retouch_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Api Undo Api Jobs  Job Id  Undo Retouch Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/jobs/{job_id}/bake":{"post":{"tags":["jobs"],"summary":"Re-bake at another resolution and/or as a single mesh","operationId":"api_bake_api_jobs__job_id__bake_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BakeRequest"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Api Bake Api Jobs  Job Id  Bake Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/jobs/{job_id}/pbr":{"post":{"tags":["jobs"],"summary":"Add PBR materials (albedo, roughness, metallic) to a finished texture job","operationId":"api_pbr_api_jobs__job_id__pbr_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/PbrRequest"},{"type":"null"}],"title":"Req"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Api Pbr Api Jobs  Job Id  Pbr Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/jobs/{job_id}/pick":{"post":{"tags":["quality loop"],"summary":"3D point / normal / UV under image pixels (to aim a retouch)","operationId":"api_pick_api_jobs__job_id__pick_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PickRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Api Pick Api Jobs  Job Id  Pick Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/jobs/{job_id}/views/{view}/image":{"post":{"tags":["external images"],"summary":"Upload your image for the pending view (backend 'external')","operationId":"api_submit_image_api_jobs__job_id__views__view__image_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"view","in":"path","required":true,"schema":{"type":"string","title":"View"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_api_submit_image_api_jobs__job_id__views__view__image_post"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/jobs/{job_id}/files/{path}":{"get":{"tags":["jobs"],"summary":"Download a result file","operationId":"api_file_api_jobs__job_id__files__path__get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"path","in":"path","required":true,"schema":{"type":"string","title":"Path"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"BakeRequest":{"properties":{"resolution":{"type":"integer","enum":[1024,2048,4096],"title":"Resolution","default":2048},"single_mesh":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Single Mesh","description":"true: one object, one material; false: your objects and materials; omitted: unchanged"}},"type":"object","title":"BakeRequest"},"Body_api_submit_image_api_jobs__job_id__views__view__image_post":{"properties":{"file":{"anyOf":[{"type":"string","contentMediaType":"application/octet-stream"},{"type":"null"}],"title":"File"}},"type":"object","title":"Body_api_submit_image_api_jobs__job_id__views__view__image_post"},"Body_create_job_upload_api_jobs_upload_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"},"params":{"type":"string","title":"Params","description":"TextureRequest fields as JSON (without mesh). Fields may also be sent as separate form fields.","default":"{}"}},"type":"object","required":["file"],"title":"Body_create_job_upload_api_jobs_upload_post"},"FillGapsRequest":{"properties":{"max_views":{"type":"integer","maximum":6.0,"minimum":1.0,"title":"Max Views","default":3},"hf_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hf Token"}},"type":"object","title":"FillGapsRequest"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"PbrRequest":{"properties":{"hf_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hf Token","description":"Your Hugging Face token, for your own ZeroGPU quota (or send it as the X-HF-Token header)"}},"type":"object","title":"PbrRequest"},"PickRequest":{"properties":{"pixels":{"items":{"items":{"type":"number"},"type":"array"},"type":"array","title":"Pixels","description":"[[x, y], ...] in pixels or 0-1 fractions of the image"},"view":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"View"},"render_camera":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Render Camera","description":"e.g. 'orbit02' (see files.renders)"}},"type":"object","required":["pixels"],"title":"PickRequest"},"RegenerateRequest":{"properties":{"views":{"items":{"type":"string"},"type":"array","title":"Views","description":"View names (see 'views' in the job status)."},"seeds":{"anyOf":[{"additionalProperties":{"type":"integer"},"type":"object"},{"type":"null"}],"title":"Seeds","description":"Optional seed per view (random new seeds otherwise)."},"prompt_extra":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prompt Extra","description":"Extra instruction appended to these views' prompts."},"backend":{"anyOf":[{"type":"string","enum":["qwen-turbo","qwen-space","fibo-space","mock","external"]},{"type":"null"}],"title":"Backend"},"hf_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hf Token"}},"type":"object","required":["views"],"title":"RegenerateRequest"},"RetouchRequest":{"properties":{"suggestion":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Suggestion","description":"Index into retouch_suggestions of the job status: uses its camera, mask and mode."},"mode":{"anyOf":[{"type":"string","enum":["repair","replace","upscale"]},{"type":"null"}],"title":"Mode","description":"repair (fix artifacts), replace (new content), upscale (re-imagine a low-res capture at higher resolution)."},"prompt":{"type":"string","title":"Prompt","default":""},"view":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"View","description":"Use the camera of this view."},"render_camera":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Render Camera","description":"Use a preview render camera, e.g. 'orbit03'."},"camera":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"string"},{"type":"null"}],"title":"Camera","description":"{\"eye\":[x,y,z],\"target\":[x,y,z],\"fov\":40} (a view or render camera name also works here)"},"focus":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Focus","description":"Frame a sphere: {\"point\":[x,y,z],\"radius\":r,\"direction\":[dx,dy,dz]}"},"mask":{"title":"Mask","description":"'all' | 'uncovered' | 'low_quality' | {'sphere':[x,y,z,r]} | {'rect':[x0,y0,x1,y1]} (0-1 fractions ok) | {'circle':[cx,cy,r]} | {'and'|'or':[...]}"},"capture_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Capture Size","description":"upscale: capture size, e.g. 256"},"output_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Output Size"},"softness":{"type":"number","title":"Softness","default":0.75},"grow_px":{"type":"integer","title":"Grow Px","default":0},"backend":{"anyOf":[{"type":"string","enum":["qwen-turbo","qwen-space","fibo-space","mock"]},{"type":"null"}],"title":"Backend"},"dry_run":{"type":"boolean","title":"Dry Run","description":"Only show where the mask lands (the capture with the mask outlined in red, aim_url) in seconds: nothing is generated or changed.","default":false},"hf_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hf Token"}},"type":"object","title":"RetouchRequest"},"TerrainHeightmap":{"properties":{"upload_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Upload Id","description":"From POST /api/uploads (a grey PNG, 16-bit preferred, or .npy)"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url","description":"Public URL of the PNG / .npy"},"base64":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Base64","description":"The PNG / .npy itself, base64-encoded"},"size_m":{"anyOf":[{"type":"number"},{"items":{"type":"number"},"type":"array"}],"title":"Size M","description":"Terrain width in metres, or [width, depth]"},"height_m":{"type":"number","title":"Height M","description":"Height difference in metres between black and white","default":100.0}},"type":"object","required":["size_m"],"title":"TerrainHeightmap"},"TerrainLayer":{"properties":{"name":{"type":"string","title":"Name","description":"Layer name, e.g. 'grass', 'rock' (used for file names)"},"prompt":{"type":"string","title":"Prompt","description":"What this ground looks like close up, e.g. 'short green grass with clover and small daisies' (it becomes a seamless photo texture)"},"where":{"anyOf":[{"additionalProperties":{"items":{"anyOf":[{"type":"number"},{"type":"null"}]},"type":"array"},"type":"object"},{"type":"null"}],"title":"Where","description":"Where the layer lies, as [min, max] ranges (null = no bound) of: slope (degrees), height (0 lowest .. 1 highest point), elevation (metres, the mesh's own heights: [-0.5, 1.5] for a beach above a sea at 0), curvature (-1 ridges .. 1 hollows and valleys), flow (0 .. 1 water flow: ~0.85+ streams and gullies). E.g. {\"slope\": [35, null]} for cliffs. No rules (and no paths/areas): everywhere, i.e. the base layer (put it first)."},"paths":{"anyOf":[{"items":{"$ref":"#/components/schemas/TerrainPath"},"type":"array"},{"type":"null"}],"title":"Paths","description":"Lines this layer is drawn along: roads, trails, rivers, e.g. [{\"points\": [[-500, 20], [300, 80]], \"width\": 5}]"},"areas":{"anyOf":[{"items":{"items":{"items":{"type":"number"},"type":"array"},"type":"array"},"type":"array"},{"type":"null"}],"title":"Areas","description":"Polygons this layer fills, [[[x, z], ...], ...]: fields, a village square, a car park"},"patches":{"anyOf":[{"type":"number","maximum":1.0,"minimum":0.0},{"type":"null"}],"title":"Patches","description":"Keep only this fraction of the layer's area, in natural patches (dirt patches in grass: 0.15)"},"breakup":{"anyOf":[{"type":"number","maximum":1.0,"minimum":0.0},{"type":"null"}],"title":"Breakup","description":"How irregular the layer's edges are (default 0.5)"},"tile_m":{"type":"number","maximum":50.0,"exclusiveMinimum":0.2,"title":"Tile M","description":"Size in metres of one repeat of the detail texture","default":4.0},"color":{"anyOf":[{"items":{"type":"number"},"type":"array"},{"type":"null"}],"title":"Color","description":"Optional [r, g, b] 0-255 (or 0-1) the layer shows in the overview guide (default: its detail texture's mean colour); the colour map is turned to its hue and kept within 15 (CIELAB) of it"},"triplanar":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Triplanar","description":"Project the detail texture from the sides on steep slopes (default: layers whose rules start at 30 degrees or more)"},"from_above":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From Above","description":"How the layer looks from high above in the colour map, if unlike its close-up (default for forests: their tree crowns)"}},"type":"object","required":["name","prompt"],"title":"TerrainLayer"},"TerrainPath":{"properties":{"points":{"items":{"items":{"type":"number"},"type":"array"},"type":"array","title":"Points","description":"[[x, z], ...] ground coordinates in metres (glTF/three.js axes; with axes 'z-up', Blender [x, y])"},"width":{"type":"number","title":"Width","description":"width in metres","default":4.0}},"type":"object","required":["points"],"title":"TerrainPath"},"TerrainRequest":{"properties":{"prompt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prompt","description":"The place as a whole, e.g. 'an alpine valley in early summer', 'English farmland', 'a red-rock desert canyon'"},"upload_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Upload Id","description":"The terrain mesh from POST /api/uploads (.glb/.obj/.ply/.stl): the ground only, +Y up (GLB)"},"mesh_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mesh Url"},"mesh_base64":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mesh Base64"},"heightmap":{"anyOf":[{"$ref":"#/components/schemas/TerrainHeightmap"},{"type":"null"}],"description":"Instead of a mesh: a heightmap image"},"preset":{"anyOf":[{"type":"string","enum":["alpine","temperate","desert","arctic","volcanic"]},{"type":"null"}],"title":"Preset","description":"Ready-made layer stack when `layers` is not given (default: chosen from the prompt's words; temperate otherwise)"},"layers":{"anyOf":[{"items":{"$ref":"#/components/schemas/TerrainLayer"},"type":"array"},{"type":"null"}],"title":"Layers","description":"Your ground layers (up to 8), bottom to top: the first covers everything, each next one covers the earlier ones where its rules/paths/areas hold"},"macro_size":{"type":"integer","enum":[1024,2048,4096],"title":"Macro Size","description":"Size of the top-down colour map: 1024 (one image), 2048 (9 refined tiles), 4096 (25)","default":2048},"uv":{"type":"string","enum":["planar","keep"],"title":"Uv","description":"planar: terrain.glb gets top-down UVs (the macro map as is); keep: the macro map is baked into your mesh's own UVs","default":"planar"},"axes":{"type":"string","enum":["y-up","z-up"],"title":"Axes","description":"Coordinates of paths/areas: y-up = glTF/three.js [x, z]; z-up = Blender [x, y]","default":"y-up"},"up":{"anyOf":[{"type":"string","enum":["y","z"]},{"type":"null"}],"title":"Up","description":"Up axis of OBJ/PLY/STL files (GLB is always +Y)"},"water_level":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Water Level","description":"Height of your water plane (sea, lake, pond) in the mesh's own heights: the colour map paints open water below it, so the painted shore meets your plane"},"backend":{"type":"string","enum":["qwen-turbo","qwen-space","mock"],"title":"Backend","default":"qwen-turbo"},"seed":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Seed"},"hf_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hf Token"}},"type":"object","title":"TerrainRequest"},"TextureRequest":{"properties":{"prompt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prompt","description":"Materials and colours of what the mesh models, e.g. 'worn olive military paint, gold visor'. Describe materials, not new geometry."},"upload_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Upload Id","description":"Id from POST /api/uploads (the mesh file sent as the raw request body). The recommended way to send a local file."},"mesh_base64":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mesh Base64","description":"The mesh file itself, base64-encoded (.glb/.obj/.ply/.stl or .zip, up to 20 MB). Handy for MCP clients."},"sample":{"anyOf":[{"type":"string","enum":["avocado","lantern","head"]},{"type":"null"}],"title":"Sample","description":"Use a built-in sample mesh."},"mesh_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mesh Url","description":"Public http(s) URL of a .glb/.obj/.ply/.stl, or a .zip with a .gltf and its files. Max 60 MB, 600000 triangles."},"mode":{"anyOf":[{"type":"string","enum":["object","character","environment"]},{"type":"null"}],"title":"Mode","description":"object: orbit views; character: + face close-ups, auto up-axis and facing; environment: 360° probes from inside (slow on this CPU machine). Default: object (or the sample's)."},"backend":{"type":"string","enum":["qwen-turbo","qwen-space","fibo-space","mock","external"],"title":"Backend","description":"qwen-turbo: Qwen-Image-2.1-Turbo, 8 steps (default, fastest, least GPU quota). qwen-space: full Qwen-Image-2.1 (40 steps, official Space). fibo-space: Bria Fibo 2.0 Edit Turbo (non-commercial). mock: free dry run. external: you supply images.","default":"qwen-turbo"},"part_prompts":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Part Prompts","description":"Description per material or object name of your file, e.g. {\"Walls\": \"white clapboard siding\", \"Roof\": \"grey asphalt shingles\", \"Door\": \"dark green panel door\"}. Each view's prompt then names only the parts that view shows, which stops doors, windows or faces being painted where the model has none. Recommended for models with several named parts; keep `prompt` for the overall style. Names are listed in the job status (model.materials / model.objects)."},"subject":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subject","description":"What the mesh is, e.g. 'a sci-fi pilot helmet'."},"preset":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Preset","description":"object/character: minimal (4 views) | balanced (7, default) | dense (12) | greedy; environment: probes | probes-greedy."},"probes":{"anyOf":[{"type":"integer","maximum":12.0,"minimum":1.0},{"type":"null"}],"title":"Probes","description":"environment: number of 360° probes (6 views each)."},"gap_views":{"type":"boolean","title":"Gap Views","description":"Add up to 3 cameras for surface the preset misses.","default":true},"focus_prompt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Focus Prompt","description":"character: prompt for the face close-ups only."},"lighting":{"anyOf":[{"type":"string","enum":["flat","soft","natural"]},{"type":"null"}],"title":"Lighting","description":"Lighting asked of the model (flat = albedo-like, default)."},"texture_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Texture Size","description":"Baked texture size: 1024, 2048 (default) or 4096."},"pbr":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Pbr","description":"Also make PBR materials: every view is split into albedo, roughness and metallic maps (a LoRA for Qwen-Image-Edit-2511 trained on MatSynth renders, on ZeroGPU with your quota), baked like the colour: files.textured_pbr_glb (base colour + metallicRoughness texture), albedo_pbr, roughness, metallic, metallic_roughness"},"view_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"View Size","description":"Generated image size per view (512-1024, default 1024)."},"up":{"anyOf":[{"type":"string","enum":["auto","y","z","-z","x"]},{"type":"null"}],"title":"Up","description":"Up axis of the asset if not +Y (GLB is always +Y). The result keeps the input's orientation."},"color_guide":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Color Guide","description":"Show your materials' base colours to the image model as a guide to which part is which (default: automatic when at least two materials have clearly different colours). Turn it off if your colours are placeholders."},"single_mesh":{"type":"boolean","title":"Single Mesh","description":"Return one object with one material (a game-ready prop) instead of your objects and materials. Also settable later with /bake.","default":false},"inside":{"anyOf":[{"type":"string","enum":["plain","paint"]},{"type":"null"}],"title":"Inside","description":"The inside of a mug, vase or pot (seen only from above through its opening). plain (default): the main colour of its material. paint: views may paint it too (a bowl decorated inside)."},"pattern_swatches":{"anyOf":[{"type":"string","enum":["auto","on","off"]},{"type":"null"}],"title":"Pattern Swatches","description":"Show each view a close-up of the decoration already painted on the part it must paint, so an all-over pattern (porcelain florals, folk art, fabric) continues onto every side instead of stopping. auto (default): on, except for parts described as a scene (landscape, river, mountains), where views should continue the scene rather than repeat its motifs."},"metal":{"anyOf":[{"type":"string","enum":["keep","flat"]},{"type":"null"}],"title":"Metal","description":"Mirror-like metal (metallic >= 0.9 and roughness <= 0.3 in your file, e.g. chrome). keep (default): the painted reflections, which read as chrome in any renderer. flat: an even base colour, for renderers with environment lighting (Cycles/Eevee with an HDRI, three.js with an environment map), where painted reflections would show twice."},"uv":{"anyOf":[{"type":"string","enum":["auto","keep","regen"]},{"type":"null"}],"title":"Uv","description":"auto (default): bake into your UVs when they are a valid non-overlapping 0-1 layout, else repack per material or unwrap anew. keep: bake into your UVs even with small overlaps (more than 10 % shared: as auto, output.uv_layout says why). regen: always unwrap anew (xatlas)."},"seed":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Seed"},"hf_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hf Token","description":"Optional Hugging Face token whose ZeroGPU quota pays for generation. Kept in memory for this job only, never stored or logged. Alternatively send it as header X-HF-Token."}},"type":"object","title":"TextureRequest"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"ViewsRequest":{"properties":{"views":{"items":{"type":"string"},"type":"array","title":"Views"}},"type":"object","required":["views"],"title":"ViewsRequest"}}}}