Skip to content
Immersive AI

Hunyuan3D v3 — take a brand mark off the screen

3D Hunyuan3D v3 by Henri Huotari · Oct 28, 2026

Reconstruct a reference-led image of the Immersive wave sculpture as a textured GLB with PBR materials. The source image and actual interactive mesh are included, so geometry and thickness can be inspected from every side.

This file couldn't be loaded. The link may have expired.
This file couldn't be loaded. The link may have expired.
Input images
The 3D model couldn't be loaded. Download result.glb
This file couldn't be loaded. The link may have expired.
Output · drag to rotate result.glb

Run it yourself

Set IMMERSIVE_API_KEY to an API key from your account. Create a free account to get one.

curl -X POST 'https://ai.im.inc/api/v1/3d/generate' \
  -H "Authorization: Bearer $IMMERSIVE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "image": "https://s3.eu-central-1.amazonaws.com/ai.im.inc/examples/inputs/8144a5f0-13b1-40eb-b2f8-e8a0cfc295ea/input_image.png",
  "model": "hunyuan3d-v3",
  "enable_pbr": true,
  "generate_type": "Normal"
}'

# Set JOB_ID to the response's "id", then poll every few seconds until the job has finished:
curl "https://ai.im.inc/api/v1/3d/$JOB_ID" \
  -H "Authorization: Bearer $IMMERSIVE_API_KEY"

# The finished response has the result at url.
const headers = { Authorization: `Bearer ${process.env.IMMERSIVE_API_KEY}` };

const response = await fetch("https://ai.im.inc/api/v1/3d/generate", {
  method: "POST",
  headers: { ...headers, "Content-Type": "application/json" },
  body: JSON.stringify({
    "image": "https://s3.eu-central-1.amazonaws.com/ai.im.inc/examples/inputs/8144a5f0-13b1-40eb-b2f8-e8a0cfc295ea/input_image.png",
    "model": "hunyuan3d-v3",
    "enable_pbr": true,
    "generate_type": "Normal"
  }),
});
const job = await response.json();

// Poll every few seconds while the job is still running.
const running = ["pending", "queued", "submitted", "starting", "processing", "running", "streaming", "in_queue", "in_progress"];
let result;
do {
  await new Promise((resolve) => setTimeout(resolve, 5000));
  result = await (await fetch(`https://ai.im.inc/api/v1/3d/${job.id}`, { headers })).json();
} while (running.includes(String(result.status).toLowerCase()));

console.log(result.url);
import os
import time

import requests

headers = {"Authorization": f"Bearer {os.environ['IMMERSIVE_API_KEY']}"}

job = requests.post(
    "https://ai.im.inc/api/v1/3d/generate",
    headers=headers,
    json={
        "image": "https://s3.eu-central-1.amazonaws.com/ai.im.inc/examples/inputs/8144a5f0-13b1-40eb-b2f8-e8a0cfc295ea/input_image.png",
        "model": "hunyuan3d-v3",
        "enable_pbr": True,
        "generate_type": "Normal",
    },
    timeout=300,
).json()

# Poll every few seconds while the job is still running.
running = {"pending", "queued", "submitted", "starting", "processing", "running", "streaming", "in_queue", "in_progress"}
while True:
    time.sleep(5)
    result = requests.get(f"https://ai.im.inc/api/v1/3d/{job['id']}", headers=headers, timeout=60).json()
    if str(result.get("status", "")).lower() not in running:
        break

print(result["url"])
{
    "id": "01a18184-20a6-7d61-9226-caa8b70be93a",
    "url": "https://s3.eu-central-1.amazonaws.com/ai.im.inc/examples/outputs/8144a5f0-13b1-40eb-b2f8-e8a0cfc295ea/result.glb",
    "model": "hunyuan3d-v3",
    "status": "succeeded"
}

Your browser blocked the clipboard. Select the text and copy it by hand.

How the job runs

  1. POST returns the job's id and status right away.
  2. Poll GET /api/v1/3d/{id} every few seconds while the job is running.
  3. When status is succeeded, download url. Failed jobs are refunded automatically.
Endpoint
POST /api/v1/3d/generate
Model
hunyuan3d-v3
Output
3D model · GLB