Examples
API examples
JavaScript, Python, React, and model-viewer examples
These examples use the async job flow:
- Create a job with POST /convert/jobs.
- Poll GET /convert/jobs/:id.
- Use the returned signed URL, or call GET /convert/jobs/:id/download.
JavaScript
Use this in a browser or frontend app where you already have a File.
async function convertModel(file, apiToken, to = "glb") {
const form = new FormData();
form.append("file", file);
form.append("from", file.name.split(".").pop().toLowerCase());
form.append("to", to);
const createResponse = await fetch("https://api.convert3d.org/convert/jobs", {
method: "POST",
headers: {
Authorization: `Bearer ${apiToken}`,
},
body: form,
});
if (!createResponse.ok) {
throw new Error(await createResponse.text());
}
const job = await createResponse.json();
while (true) {
const statusResponse = await fetch(
`https://api.convert3d.org/convert/jobs/${job.id}`,
{
headers: {
Authorization: `Bearer ${apiToken}`,
},
}
);
if (!statusResponse.ok) {
throw new Error(await statusResponse.text());
}
const status = await statusResponse.json();
if (status.status === "success") {
return status.signedUrl;
}
if (status.status === "failed") {
throw new Error(status.error || status.message || "Conversion failed");
}
await new Promise((resolve) => setTimeout(resolve, 2000));
}
}Node.js
Use this in a backend script. Keep API tokens on the server.
import { openAsBlob } from "node:fs";
const token = process.env.CONVERT3D_API_TOKEN;
const file = await openAsBlob("model.stl");
const form = new FormData();
form.append("file", file, "model.stl");
form.append("from", "stl");
form.append("to", "glb");
const createResponse = await fetch("https://api.convert3d.org/convert/jobs", {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
},
body: form,
});
if (!createResponse.ok) {
throw new Error(await createResponse.text());
}
const job = await createResponse.json();
console.log(job);Python
Use requests for scripts and backend jobs.
import os
import time
import requests
token = os.environ["CONVERT3D_API_TOKEN"]
headers = {"Authorization": f"Bearer {token}"}
with open("model.stl", "rb") as file:
create_response = requests.post(
"https://api.convert3d.org/convert/jobs",
headers=headers,
files={"file": ("model.stl", file)},
data={"from": "stl", "to": "glb"},
timeout=300,
)
create_response.raise_for_status()
job = create_response.json()
while True:
status_response = requests.get(
f"https://api.convert3d.org/convert/jobs/{job['id']}",
headers=headers,
timeout=30,
)
status_response.raise_for_status()
status = status_response.json()
if status["status"] == "success":
print(status.get("signedUrl"))
break
if status["status"] == "failed":
raise RuntimeError(status.get("error") or status.get("message"))
time.sleep(2)React with model-viewer
This renders the converted GLB in <model-viewer> after conversion.
"use client";
import { useEffect, useState } from "react";
export function ConvertedModelViewer({
file,
apiToken,
}: {
file: File;
apiToken: string;
}) {
const [modelUrl, setModelUrl] = useState<string | null>(null);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const script = document.createElement("script");
script.type = "module";
script.src = "https://unpkg.com/@google/model-viewer/dist/model-viewer.min.js";
document.head.appendChild(script);
return () => script.remove();
}, []);
useEffect(() => {
let cancelled = false;
convertModel(file, apiToken, "glb")
.then((url) => {
if (!cancelled) setModelUrl(url);
})
.catch((err) => {
if (!cancelled) setError(err instanceof Error ? err.message : String(err));
});
return () => {
cancelled = true;
};
}, [file, apiToken]);
if (error) return <p>{error}</p>;
if (!modelUrl) return <p>Converting...</p>;
return (
<model-viewer
src={modelUrl}
alt="Converted 3D model"
auto-rotate
camera-controls
shadow-intensity="1"
environment-image="neutral"
style={{ width: "100%", height: 400 }}
/>
);
}Plain HTML viewer
Use this after you have a converted model URL.
<!doctype html>
<html>
<head>
<script
type="module"
src="https://unpkg.com/@google/model-viewer/dist/model-viewer.min.js"
></script>
</head>
<body>
<model-viewer
src="YOUR_CONVERTED_MODEL_URL"
alt="3D model"
auto-rotate
camera-controls
shadow-intensity="1"
environment-image="neutral"
style="width: 100%; height: 400px;"
></model-viewer>
</body>
</html>