{"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/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","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}/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}},"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"},"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-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":"null"}],"title":"Camera","description":"{\"eye\":[x,y,z],\"target\":[x,y,z],\"fov\":40}"},"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-space","fibo-space","mock"]},{"type":"null"}],"title":"Backend"},"hf_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hf Token"}},"type":"object","title":"RetouchRequest"},"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-space","fibo-space","mock","external"],"title":"Backend","description":"qwen-space: official Qwen-Image-2.1 Space (default). fibo-space: Bria Fibo 2.0 Edit Turbo (non-commercial). mock: free dry run. external: you supply images.","default":"qwen-space"},"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."},"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."},"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: always bake into your UVs. 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"}}}}