Thrixel API

Download

Unified download endpoint and async format conversion.

GLB is produced when a submission completes. Other formats are converted on-demand: either inline via the unified /download endpoint (which waits for the result), or asynchronously via the /convert job API.


Download a submission asset

GET /api/v1/{submission_id}/download

Public.

Unified endpoint for all downloadable artifacts. GLB is always ready; FBX/OBJ/STL/USDZ trigger an on-demand conversion if not yet cached.

Path Parameters

NameTypeDescription
submission_idstring (required)UUID of the submission.

Query Parameters

NameTypeDescription
formatstringAsset format. Values: glb, fbx, obj, stl, usdz, thumbnail, reference_image. Default: glb.
texturesstringGLB only. png (default) or webp.
dracobooleanGLB only. Draco geometry compression. Default: false.
targetstringFBX only. The engine the file is for: generic (default), roblox, unity or ue5. See FBX for an engine.
skeletonbooleanFBX only. false drops a rigged model's skeleton and skin weights, keeping its rest pose. Default: true.
indexintegerIndex for reference_image format (0–5). Default: 0.

Example Request

GLB is served straight from storage:

GET /a1b2c3d4-.../download?format=glb
curl -L -o model.glb https://api.thrixel.com/api/v1/a1b2c3d4-.../download?format=glb

Any other format triggers a conversion, so the first request for it may take a few seconds:

GET /a1b2c3d4-.../download?format=fbx
curl -L -o model.fbx https://api.thrixel.com/api/v1/a1b2c3d4-.../download?format=fbx

Shipping a GLB to a browser

If the model is going into a web page or a browser game, ask for WebP textures:

GET /a1b2c3d4-.../download?format=glb&textures=webp
curl -L -o model.glb https://api.thrixel.com/api/v1/a1b2c3d4-.../download?format=glb&textures=webp

Measured at export on real submissions:

ModelDefault (png)textures=webp+ draco=true
Geometry-heavy (15% textures)7.00 MB6.28 MB1.18 MB
Texture-heavy (100% textures)18.33 MB0.95 MB0.91 MB

Textures are where most of the weight is on most models, and WebP is a plain image format the browser decodes natively - nothing extra to install, and a reader that cannot handle it fails visibly. This is the setting to reach for first. Thrixel's own web viewer serves exactly this: textures=webp, no Draco.

When to add Draco

draco=true compresses the geometry rather than the textures, so it only pays off on models that are mostly geometry - the first row above, where it turns 6.28 MB into 1.18 MB. On a texture-heavy model it buys about 4%.

Draco needs a decoder on the other end

KHR_draco_mesh_compression is read by three.js (with DRACOLoader), Babylon, model-viewer and Blender 4.x, but three.js fetches a ~200KB WASM decoder at runtime and you have to wire it up. A reader without a Draco decoder usually does not raise an error - it returns the mesh with every vertex at the origin. Do not hand a Draco file to an unknown tool, and do not feed one back into a pipeline of your own.

Both flags are independent, and neither changes the model: same parts, same triangle count, same bounds.

FBX for an engine

Every FBX embeds its textures, carries metallic and roughness maps, and writes no extra end bones. Any mesh over 20,000 triangles is split into pieces under that, so a high-detail model still imports into engines with a per-mesh limit. Add target to shape the file for one engine:

targetWhat changes
genericNothing beyond the above.
robloxA .zip: the FBX as a Roblox R15 rig, textures at 1024 px, and a textures/ folder with each material's ColorMap, NormalMap, RoughnessMap and MetalnessMap PNGs for a SurfaceAppearance. See Roblox R15.
unityBones renamed for Unity's Humanoid avatar (Hips, LeftUpperLeg...).
ue5Bones renamed to the UE5 Mannequin (pelvis, thigh_l...), with a root bone above pelvis.

Bone names only change on a humanoid Rig; any other model gets the same file as generic, except that roblox still applies its texture size and maps.

GET /a1b2c3d4-.../download?format=fbx&target=roblox
curl -L -o model-roblox.zip https://api.thrixel.com/api/v1/a1b2c3d4-.../download?format=fbx&target=roblox

Roblox R15

On a humanoid Rig, target=roblox rebuilds the skeleton to Roblox's R15 layout:

  • 15 bones (LowerTorso, UpperTorso, Head, and Upper/Lower/Hand and Upper/Lower/Foot on each side) under Root > HumanoidRootNode.
  • Joints R15 does not have fold into the bone they sit on, weights included: the spine and clavicles into UpperTorso, the neck into Head, fingers into the hand, toes into the foot.
  • LowerTorso and Root at the origin, at most 4 bones per vertex, none on Root.
  • One mesh per body part, named after its bone (LeftUpperArm_Geo...). A part over 20,000 triangles is still split, so it arrives as two meshes.

The advanced R15 bones (fingers, extra spine joints) and the avatar attachments are not included.

Importing into Roblox Studio. Roblox does not build materials from an FBX, so a model imported on its own shows grey. Import the .fbx with the 3D Importer, then for each MeshPart add a SurfaceAppearance and set its ColorMap, NormalMap, RoughnessMap and MetalnessMap from the matching PNGs in the zip's textures/ folder (each file is named after its material). SurfaceAppearance.txt in the zip lists, per material, the MeshParts that use it and the files to set.

Glowing parts. A part that glows in the model (a lamp, a headlight, a neon sign) comes with an EmissiveMask PNG, a flat ColorMap, and an EmissiveStrength and EmissiveTint in SurfaceAppearance.txt: set EmissiveMaskContent, EmissiveStrength and EmissiveTint on that part's SurfaceAppearance. This covers models made with Create and Edit; Sculptor and Detailer results do not carry a glow yet.

On this page