Endpoints

GET /convert/jobs/:id/download

Async job download

Use GET /convert/jobs/:id/download after a job finishes.

GET /convert/jobs/:id/download

Path parameters

Examples

curl

curl https://api.convert3d.org/convert/jobs/job_123/download \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -o model.glb

JavaScript

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

const token = process.env.CONVERT3D_API_TOKEN;
const jobId = "job_123";

const response = await fetch(
  `https://api.convert3d.org/convert/jobs/${jobId}/download`,
  {
    headers: {
      Authorization: `Bearer ${token}`,
    },
  }
);

if (response.status === 409) {
  throw new Error("Job is not ready yet");
}

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

const contentType = response.headers.get("content-type") || "";

if (contentType.includes("application/json")) {
  const { url } = await response.json();
  console.log(url);
} else {
  const bytes = new Uint8Array(await response.arrayBuffer());
  await writeFile("model.glb", bytes);
}

Python

import os
import requests

job_id = "job_123"

response = requests.get(
    f"https://api.convert3d.org/convert/jobs/{job_id}/download",
    headers={"Authorization": f"Bearer {os.environ['CONVERT3D_API_TOKEN']}"},
    timeout=300,
)

if response.status_code == 409:
    raise RuntimeError("Job is not ready yet")

response.raise_for_status()

if response.headers.get("content-type", "").startswith("application/json"):
    print(response.json()["url"])
else:
    with open("model.glb", "wb") as output:
        output.write(response.content)

Response

Depending on storage mode, the response is either:

  • A JSON object with a signed download URL.
  • The converted file bytes.

Signed URL response:

{
  "url": "https://storage.convert3d.org/converted/model.glb?signature=..."
}

If the file is not ready:

{
  "error": "Not ready"
}

HTTP status: 409.

Before downloading

Poll GET /convert/jobs/:id until the job status is success.