Endpoints

GET /upload-url

Large-file upload URL

Use GET /upload-url when you want to upload the source file before creating the conversion job.

GET /upload-url?file={filename}

This is the large-file flow:

  1. Request an upload URL.
  2. Upload the file with PUT.
  3. Create a job with POST /convert/jobs using the returned bucket and key.

Query parameters

Step 1. Request an upload URL

curl

curl "https://api.convert3d.org/upload-url?file=large-model.glb" \
  -H "Authorization: Bearer YOUR_API_TOKEN"

JavaScript

const token = process.env.CONVERT3D_API_TOKEN;
const fileName = "large-model.glb";

const response = await fetch(
  `https://api.convert3d.org/upload-url?file=${encodeURIComponent(fileName)}`,
  {
    headers: {
      Authorization: `Bearer ${token}`,
    },
  }
);

if (!response.ok) {
  throw new Error(await response.text());
}

const upload = await response.json();
console.log(upload);

Python

import os
import requests

response = requests.get(
    "https://api.convert3d.org/upload-url",
    headers={"Authorization": f"Bearer {os.environ['CONVERT3D_API_TOKEN']}"},
    params={"file": "large-model.glb"},
    timeout=30,
)
response.raise_for_status()
upload = response.json()
print(upload)

Response:

{
  "uploadUrl": "https://storage.convert3d.org/uploads/...",
  "bucket": "uploads",
  "key": "uploads/abc123/large-model.glb"
}

Step 2. Upload the file

Use the returned uploadUrl as a presigned PUT target.

curl

curl -X PUT "$UPLOAD_URL" \
  --data-binary @large-model.glb

JavaScript

import { readFile } from "node:fs/promises";

const bytes = await readFile("large-model.glb");

const uploadResponse = await fetch(upload.uploadUrl, {
  method: "PUT",
  body: bytes,
});

if (!uploadResponse.ok) {
  throw new Error(await uploadResponse.text());
}

Python

with open("large-model.glb", "rb") as file:
    upload_response = requests.put(upload["uploadUrl"], data=file, timeout=300)

upload_response.raise_for_status()

Step 3. Create the conversion job

Send JSON to POST /convert/jobs.

curl

curl https://api.convert3d.org/convert/jobs \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "bucket": "uploads",
    "key": "uploads/abc123/large-model.glb",
    "fileName": "large-model.glb",
    "from": "glb",
    "to": "usdz"
  }'

JavaScript

const createResponse = await fetch("https://api.convert3d.org/convert/jobs", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${token}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    bucket: upload.bucket,
    key: upload.key,
    fileName: fileName,
    from: "glb",
    to: "usdz",
  }),
});

if (!createResponse.ok) {
  throw new Error(await createResponse.text());
}

console.log(await createResponse.json());

Python

create_response = requests.post(
    "https://api.convert3d.org/convert/jobs",
    headers={
        "Authorization": f"Bearer {os.environ['CONVERT3D_API_TOKEN']}",
        "Content-Type": "application/json",
    },
    json={
        "bucket": upload["bucket"],
        "key": upload["key"],
        "fileName": "large-model.glb",
        "from": "glb",
        "to": "usdz",
    },
    timeout=30,
)
create_response.raise_for_status()
print(create_response.json())

Notes

  • The bucket value must match the bucket returned by GET /upload-url.
  • The key value must match the uploaded object key.
  • Poll and download the job the same way as any async job.