zlim
Sign inGet started

Zlim Docs

Zlim optimizes 3D models to GLB. Integrate three ways: the local CLI and MCP server run the engine in-process with no account or API key, and the hosted REST API runs async jobs at scale.

Quickstart

The fastest path is the local CLI. It runs the optimization engine in-process — no account, no API key, no upload:

bash
zlim optimize model.fbx -o model.glb -p balanced
# writes model.glb and prints a JSON report
# (input vs. output: faces, vertices, bytes)

Working inside an AI agent? The MCP server exposes the same local engine as tool calls. Need a hosted, async pipeline at scale? Use the REST API: create a job, upload the file, poll until it succeeds, then download the optimized GLB.

REST API reference

The hosted API is asynchronous and grant-based: you create a job, upload the raw file bytes to a signed URL, mark the upload complete, poll until the job reaches a terminal status, then fetch a signed download URL. All requests authenticate with a Bearer API key.

1. Create a job

POST /api/v1/jobs with a JSON body. Returns 201 with the job and an uploadGrant containing a putUrl.

bash
curl -X POST https://zlim.ai/api/v1/jobs \
  -H "Authorization: Bearer $ZLIM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "taskType": "model.optimize",
    "filename": "model.fbx",
    "options": { "preset": "balanced" }
  }'

# Response (201):
{
  "job": {
    "id": "1f3c…",
    "status": "waiting_upload",
    "taskType": "model.optimize"
  },
  "uploadGrant": {
    "putUrl": "https://…"
  }
}
FieldTypeDescription
taskTypestringTask to run. Use model.optimize (the default).
filenamestringOriginal filename; used to derive the input object key. Defaults to input.glb.
optionsobjectTask options. For model.optimize: { "preset": "fast" | "balanced" | "maximum" } (default balanced).
callbackUrlstringOptional webhook notified when the job reaches a terminal status.

2. Upload the file, then complete the upload

PUT the raw file bytes to uploadGrant.putUrl, then POST .../complete-upload to move the job from waiting_upload to queued.

bash
# Upload the raw bytes to the signed putUrl
curl -X PUT "$PUT_URL" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @model.fbx

# Mark the upload complete → job becomes "queued"
curl -X POST https://zlim.ai/api/v1/jobs/$JOB_ID/complete-upload \
  -H "Authorization: Bearer $ZLIM_API_KEY"

3. Poll status, then download

Poll GET /api/v1/jobs/:id until a terminal status (succeeded, failed, or cancelled). When succeeded, fetch a signed download URL from GET /api/v1/jobs/:id/result-url.

bash
# Poll until terminal
curl https://zlim.ai/api/v1/jobs/$JOB_ID \
  -H "Authorization: Bearer $ZLIM_API_KEY"
# { "job": { "id": "1f3c…", "status": "succeeded", … } }

# Get a signed download URL (only when status is "succeeded")
curl https://zlim.ai/api/v1/jobs/$JOB_ID/result-url \
  -H "Authorization: Bearer $ZLIM_API_KEY"
# { "url": "https://…", "expiresAt": "…" }

# Download the optimized GLB
curl -o model.glb "$RESULT_URL"

Endpoints

Method & pathDescription
POST /api/v1/jobsCreate a job. Returns 201 with the job and an upload grant (putUrl). Send an Idempotency-Key header to make retries safe.
PUT <uploadGrant.putUrl>Upload the raw input bytes to the signed storage URL.
POST /api/v1/jobs/:id/complete-uploadMark the upload complete; transitions the job to queued.
GET /api/v1/jobs/:idFetch the job's current status (includes hasReport once succeeded).
GET /api/v1/jobs/:id/result-urlSigned download URL for the output GLB (only when succeeded).
GET /api/v1/jobs/:id/report-urlSigned URL for the optimization report JSON (only when succeeded and hasReport).
Rate limits. Requests are rate-limited per API key: up to 120 job creations and 20 key creations per minute. Over the limit returns 429 with a Retry-Afterheader. This is separate from your plan's monthly optimization quota.

CLI

Runs locally. The Zlim CLI (@zlim/cli) runs the optimization engine in-process — no account, no API key, and no network call. Input files are read from and written to your local disk.

Commands

Four commands. All read a local model and write a GLB (or a JSON report).

CommandWhat it does
zlim optimize <input>Optimize a model to GLB with a preset (fast · balanced · maximum).
zlim convert <input>Turn any supported format into GLB — geometry repair only, no lossy optimization.
zlim analyze <input>Print a model's input metrics — format, faces, vertices, bytes — without writing output.
zlim batch <patterns...>Optimize many files or globs → one optimized GLB per input.

optimize

Runs the optimization pipeline for the chosen preset and prints a JSON report of input vs. output metrics.

bash
zlim optimize model.fbx -o model.glb -p balanced
# prints a JSON report:
{
  "input":  { "format": "fbx", "faces": 1240000, "vertices": 642000, "bytes": 18400000 },
  "output": { "faces": 286000, "vertices": 150000, "bytes": 3960000,
              "drawCalls": 12, "materials": 4, "textures": 3 },
  "stages": [ { "name": "repair-input", "ms": 12 } ],
  "warnings": []
}

convert

Converts any supported format to GLB with geometry repair only — no lossy optimization. Use optimize when you want size reduction.

bash
zlim convert assembly.step -o part.glb
# Converted assembly.step -> part.glb (3960000 bytes, step -> glb)

analyze

Inspects a model and prints its input metrics without producing output. Add --json for machine-readable output.

bash
zlim analyze model.fbx
# Format:   fbx
# Faces:    1240000
# Vertices: 642000
# Bytes:    18400000

batch

Pass files or glob patterns. Each input becomes its own optimized GLB in the output directory, with per-file failure isolation; the command exits non-zero if any file fails.

bash
zlim batch "assets/**/*.fbx" "assets/**/*.obj" -o dist/ -p balanced --concurrency 4
# STATUS  INPUT             BYTES                REDUCTION  FACES               NOTE
# ok      assets/chair.fbx  18400000 -> 3960000  78.5%      1240000 -> 286000
# ok      assets/table.obj  9200000 -> 2300000   75%        420000 -> 110000
#
# 2 ok, 0 failed (2 total)

CLI flags

FlagDefaultDescription
-o, --out <out>out.glbOutput GLB path (optimize, convert)
-p, --preset <preset>balancedfast · balanced · maximum (optimize, batch)
-o, --out-dir <dir>out/Output directory (batch)
--concurrency <n>4Max parallel jobs (batch)
--jsonoffEmit JSON instead of text (analyze, batch)

MCP server

Zlim ships an MCP (Model Context Protocol) server (@zlim/mcp) so AI agents — Claude, Cursor, or any MCP-compatible host — can optimize, convert, and analyze 3D models as tool calls.

Local-first. By default the server runs the engine in-process — no credentials required. Cloud mode (which delegates jobs to the hosted API) activates only when both ZLIM_API_URL and ZLIM_API_KEY are set.

Tools exposed

Tool nameDescription
zlim_optimizeOptimize a local model to GLB. Inputs: filePath, preset? (fast · balanced · maximum), outputPath? (local only).
zlim_convertConvert any supported format to GLB. Inputs: filePath, outputPath? (local only).
zlim_analyzeReturn a model's format and mesh statistics (faces, vertices, bytes). Input: filePath.
zlim_job_statusCloud only: query the status of an existing job. Input: jobId.
zlim_job_resultCloud only: fetch the signed download URL of a completed job. Input: jobId.

Connect to Claude Desktop (local)

Add the following to your claude_desktop_config.json. No env vars are needed for local mode:

json
{
  "mcpServers": {
    "zlim": {
      "command": "npx",
      "args": ["-y", "@zlim/mcp"]
    }
  }
}

Cloud mode (optional)

To delegate work to the hosted API instead of running locally, set both env vars. This also enables the zlim_job_status and zlim_job_result tools:

json
{
  "mcpServers": {
    "zlim": {
      "command": "npx",
      "args": ["-y", "@zlim/mcp"],
      "env": {
        "ZLIM_API_URL": "https://zlim.ai",
        "ZLIM_API_KEY": "your_api_key_here"
      }
    }
  }
}
Note: ZLIM_API_KEY is the same API key you use for the REST API. In local mode the job tools report that they are not applicable.

Authentication

The local CLI and MCP server need no authentication. The hosted REST API authenticates each request with a bearer API key in the Authorization header (an x-api-key header or a signed-in dashboard session also work):

http
Authorization: Bearer <your_api_key>

Keys are managed from the Keys dashboard. Create multiple keys to scope access per environment (dev, staging, production).

Jobs reference

Job statuses

StatusMeaning
waiting_uploadJob created; the input file has not been uploaded yet.
waiting_manifestJob created via a manifest path; the manifest is not yet resolved.
queuedUpload complete; ready for a worker to claim.
processingClaimed by a worker; the lease is active.
retry_waitProcessing failed; queued for retry after a delay.
succeededTerminal. The output GLB is ready; fetch it via result-url.
failedTerminal. Processing failed after retries were exhausted.
cancelledTerminal. The job was cancelled.

Terminal statuses are succeeded, failed, and cancelled. Poll GET /api/v1/jobs/:id until one of these is reached.

Supported formats

Every supported format outputs to GLB. More formats are on the roadmap — marked coming soon below.

FormatExtensionsKindStatus
glTF / GLB.gltf / .glbDCCAvailable
FBX.fbxDCCAvailable
OBJ.objDCCAvailable
Collada.daeDCCAvailable
USD / USDZ.usd / .usdzDCCAvailable
STL.stlPrintAvailable
PLY.plyPrintAvailable
3MF.3mfCADAvailable
STEP.stp / .stepCADAvailable
Creo.prtCADAvailable
CATIA.CATPart / .CATProductCADAvailable
IGES.igs / .igesCADComing soon
SolidWorks.sldprt / .sldasmCADComing soon
DXF.dxfCADComing soon
3DS.3dsDCCComing soon
VRML / X3D.wrl / .x3dDCCComing soon