Hyper3DHyper3D Docs
开始使用

快速开始

完成鉴权、提交 Rodin 任务、轮询状态并下载结果。

准备工作

先在 API 控制台创建 API key。

不要在代码中保留凭据

切勿将 API key 或其他凭据硬编码到代码中或提交到代码仓库。请改用环境变量或密钥管理服务加载凭据,例如:

export RODIN_API_KEY='replace-with-your-api-key'

所有受保护的请求都使用以下请求头:

Authorization: Bearer YOUR_RODIN_API_KEY

1. 提交生成任务

下面的示例向 Rodin Gen-2.5 提交一张图片。最多可上传五张图片;多图请求需要重复提交 images 表单字段。

curl --fail-with-body --request POST 'https://api.hyper3d.com/api/v2/rodin' \
  --header "Authorization: Bearer ${RODIN_API_KEY}" \
  --form 'images=@./input.png' \
  --form 'tier=Gen-2.5-Medium' \
  --form 'mesh_mode=Raw' \
  --form 'quality=medium'

响应中有两个用途不同的标识:

  • jobs.subscription_key:传给 /status
  • 顶层 uuid:作为 task_uuid 传给 /download
{
  "message": "Submitted.",
  "uuid": "123e4567-e89b-12d3-a456-426614174000",
  "jobs": {
    "uuids": ["223e4567-e89b-12d3-a456-426614174000"],
    "subscription_key": "subscription-key-from-generation-response"
  },
  "consumed": 0.5
}

2. 查询状态

首次查询前至少等待 5 秒,后续请求逐步退避;收到 HTTP 429 时遵循 Retry-After。任一 job 为 Failed 时立即停止;仅当所有 job 都为 Done 时进入下载步骤。

curl --fail-with-body --request POST 'https://api.hyper3d.com/api/v2/status' \
  --header "Authorization: Bearer ${RODIN_API_KEY}" \
  --header 'Content-Type: application/json' \
  --data '{"subscription_key":"subscription-key-from-generation-response"}'

3. 下载结果

全部 job 完成后,使用生成响应顶层的 uuid 调用 /download

curl --fail-with-body --request POST 'https://api.hyper3d.com/api/v2/download' \
  --header "Authorization: Bearer ${RODIN_API_KEY}" \
  --header 'Content-Type: application/json' \
  --data '{"task_uuid":"123e4567-e89b-12d3-a456-426614174000"}'

完整 Python 流程

这个示例在 5 秒后开始轮询,逐步增加到最长 30 秒的间隔,总期限为 20 分钟;它会处理 HTTP 429、在 job 失败时终止,并且只在全部完成后下载。

import os
import time
from email.utils import parsedate_to_datetime
from pathlib import Path

import requests

BASE_URL = "https://api.hyper3d.com/api/v2"
DEADLINE_SECONDS = 20 * 60


def request_with_rate_limit(session, method, url, **kwargs):
    while True:
        response = session.request(method, url, timeout=60, **kwargs)
        if response.status_code != 429:
            response.raise_for_status()
            return response.json()

        retry_after = response.headers.get("Retry-After", "5")
        try:
            delay = max(1, int(retry_after))
        except ValueError:
            delay = max(1, int((parsedate_to_datetime(retry_after) - parsedate_to_datetime(response.headers["Date"])).total_seconds()))
        time.sleep(delay)


session = requests.Session()
session.headers["Authorization"] = f"Bearer {os.environ['RODIN_API_KEY']}"

with Path("input.png").open("rb") as image_file:
    generation = request_with_rate_limit(
        session,
        "POST",
        f"{BASE_URL}/rodin",
        files={"images": ("input.png", image_file, "image/png")},
        data={"tier": "Gen-2.5-Medium", "mesh_mode": "Raw", "quality": "medium"},
    )

subscription_key = generation["jobs"]["subscription_key"]
task_uuid = generation["uuid"]
started_at = time.monotonic()
delay = 5

while True:
    if time.monotonic() - started_at >= DEADLINE_SECONDS:
        raise TimeoutError("Generation did not finish within 20 minutes")
    time.sleep(delay)
    status = request_with_rate_limit(
        session,
        "POST",
        f"{BASE_URL}/status",
        json={"subscription_key": subscription_key},
    )
    states = [job["status"] for job in status["jobs"]]
    if "Failed" in states:
        raise RuntimeError(f"Generation failed: {status}")
    if states and all(state == "Done" for state in states):
        break
    delay = min(delay + 5, 30)

downloads = request_with_rate_limit(
    session,
    "POST",
    f"{BASE_URL}/download",
    json={"task_uuid": task_uuid},
)
print(downloads)

下一步

On this page