tencent cloud

Media Processing Service

3D Generation Models

Download
Focus Mode
Font Size
Last updated: 2026-09-03 16:19:12
AI-Translated

Feature Introduction

The Tencent MPS AIGC aggregation platform provides 3D large model generation services, supporting the generation of high-quality 3D model assets from text descriptions (text-to-3D), a single image (image-to-3D), or multi-view images (multi-view image-to-3D). The generated 3D models include geometry and textures, support output in mainstream formats such as OBJ and GLB, and can be directly used in scenarios such as short dramas, e-commerce displays, and AR/VR. Developers can call different models and obtain generation results through the same set of APIs.

Billing Overview

When you use the MPS service to call AI 3D generation, the billing duration is calculated based on the duration of successfully generated task results, with the billing unit being seconds. For complete descriptions of the billing rules for each type, refer to the pay-as-you-go documentation.

Prerequisites

1. Activating the Service

1. Log in to the Tencent MPS console and follow the instructions to activate the MPS service.
2. To obtain the API key, go to API Key Management to get the SecretId and SecretKey.
3. (Optional) To store the generated results in COS, you also need to activate Cloud Object Storage (COS), create a bucket, and grant permissions to the MPS_QcsRole role. For details, refer to the Account Authorization documentation.

2. Installing Dependencies

The code examples in this guide use axios as the HTTP client, but it is not required. You can send HTTP requests in any of the following ways based on your project needs.
Solution
Installation Required or Not
Applicable Scenarios
axios (default example in this document)
npm install axios
Projects already use axios, or users prefer its API style.
Node.js native fetch
No installation required (built into Node.js 18 or later)
Zero dependencies, recommended for modern projects.
Node.js native https
No installation required
Compatible with older Node.js versions (< 18).
If you choose axios:
npm install axios
If you choose native fetch (Node.js 18 or later, zero dependencies), replace axios.post(...) in the code with:
// Replace the axios.post call
// Original: const resp = await axios.post(`https://${MPS_HOST}`, payload, { headers });
// return resp.data;
// Replace with:
const resp = await fetch(`https://${MPS_HOST}`, {
method: 'POST',
headers: headers,
body: JSON.stringify(payload)
});
return await resp.json();

Note:
The built-in crypto module in Node.js can handle signature generation, so no additional installation is required. The signing process has no external dependencies.

3. Key Configuration

{
"tencentCloud": {
"secretId": "Your SecretId",
"secretKey": "Your SecretKey",
"region": "ap-guangzhou"
}
}
Attention:
Security reminder: Never hard-code keys in your code or commit them to Git. Instead, use environment variables or a separate configuration file (add it to .gitignore).

API Overview

Core Capabilities
API
Action
Description
Concurrency Limit
Text-to-3D
SubmitHunyuan3DTask
QueryHunyuan3DTask
Generate a complete 3D model (geometry + texture) from a text Prompt.
1
Image-to-3D
Upload a reference image to generate the corresponding 3D model.
1
Multiview-to-3D
Provide multi-view images (front/back/left/right) for the highest fidelity.
1
Note:
General information:
Request domain: mps.intl.tencentcloudapi.com
Request method: POST (application/json)
API version: 2019-06-12
Signature method: TC3-HMAC-SHA256
Key constraints:
The input parameters Prompt / ImageUrl / MultiViewImages are mutually exclusive. You must specify exactly one of them, and you cannot pass in more than one at the same time.
The default number of concurrent generation tasks is 1 per root account.
MultiViewImages must contain at least 2 images (2 to 8) and must include the front view. The same ViewType cannot be repeated.

Signature Mechanism (TC3-HMAC-SHA256)

TencentCloud API 3.0 uses TC3-HMAC-SHA256 signature authentication. The signing process is as follows:
1. Construct the canonical request (CanonicalRequest): Concatenate the request method, URI, QueryString, Headers, and Payload Hash.
2. Construct the string to sign (StringToSign): Concatenate the algorithm, timestamp, CredentialScope, and CanonicalRequest Hash.
3. Calculate the signature (Signature): Derive the signing key by performing HMAC level by level with the SecretKey, and then sign the StringToSign.
4. Construct the Authorization Header: Assemble the final authentication header.

Must-Knows

1. Generated results are stored for only 24 hours.
The URLs of images and videos are valid for only 12 hours. Make sure to download them promptly after generation or transfer them to your own COS/server.
2. Frequency limit
Geometry (white model) generation: 1 concurrent
3D model (textured) generation: 1 concurrent
Implement concurrency control and request queues to avoid triggering rate limits.
3. Image input requirements
Size ≤ 10 MB. Short side resolution ≥ 512 and long side resolution ≤ 4096.
Supported formats: JPG, JPEG, PNG, WEBP.
The image URL must be accessible from the public network.
4. Prompt length limit
Character limit: no more than 1024 utf-8 characters.
Description suggestion: Use specific, vivid descriptions (subject + style + color + posture), and avoid abstract concepts and multiple subjects.
5. COS Storage
You can use StoreCosParam to store results directly in a specified COS bucket. To do so, you need:
Enable the COS service.
Create a bucket.
Grant the MPS_QcsRole role access to the bucket.

Core Code Implementation

1. Signature Tool (tencent-sign.js)

/**
* TencentCloud API signature tool (TC3-HMAC-SHA256)
*/
const crypto = require('crypto');

function sha256(message) {
return crypto.createHash('sha256').update(message).digest('hex');
}

function hmac256(key, message) {
return crypto.createHmac('sha256', key).update(message).digest();
}

/**
* Generate a TencentCloud API V3 signature.
* @param {string} secretId - Tencent Cloud SecretId
* @param {string} secretKey - Tencent Cloud SecretKey
* @param {string} service - Service name, such as 'mps'
* @param {string} action - API name, such as 'CreateAigcVideoTask'
* @param {string} payload - Request body JSON string
* @param {string} region - Region, such as 'ap-guangzhou'
* @param {string} [version] - API version, default '2019-06-12'
* @returns {{ headers: object }} - Request headers with the complete signature.
*/
function signRequest(secretId, secretKey, service, action, payload, region, version) {
const timestamp = Math.floor(Date.now() / 1000);
const date = new Date(timestamp * 1000).toISOString().split('T')[0];

// ===== Step 1: Concatenate the canonical request string =====
const httpRequestMethod = 'POST';
const canonicalUri = '/';
const canonicalQueryString = '';
const contentType = 'application/json';
const canonicalHeaders =
`content-type:${contentType}\\n` +
`host:${service}.tencentcloudapi.com\\n` +
`x-tc-action:${action.toLowerCase()}\\n`;
const signedHeaders = 'content-type;host;x-tc-action';
const hashedRequestPayload = sha256(payload);
const canonicalRequest =
`${httpRequestMethod}\\n${canonicalUri}\\n${canonicalQueryString}\\n` +
`${canonicalHeaders}\\n${signedHeaders}\\n${hashedRequestPayload}`;

// ===== Step 2: Concatenate the string to sign =====
const algorithm = 'TC3-HMAC-SHA256';
const credentialScope = `${date}/${service}/tc3_request`;
const hashedCanonicalRequest = sha256(canonicalRequest);
const stringToSign =
`${algorithm}\\n${timestamp}\\n${credentialScope}\\n${hashedCanonicalRequest}`;

// ===== Step 3: Calculate the signature =====
const secretDate = hmac256(`TC3${secretKey}`, date);
const secretService = hmac256(secretDate, service);
const secretSigning = hmac256(secretService, 'tc3_request');
const signature = crypto.createHmac('sha256', secretSigning)
.update(stringToSign).digest('hex');

// ===== Step 4: Concatenate the Authorization header =====
const authorization =
`${algorithm} Credential=${secretId}/${credentialScope}, ` +
`SignedHeaders=${signedHeaders}, Signature=${signature}`;

return {
headers: {
'Authorization': authorization,
'Content-Type': contentType,
'Host': `${service}.tencentcloudapi.com`,
'X-TC-Action': action,
'X-TC-Timestamp': String(timestamp),
'X-TC-Version': version || '2019-06-12',
'X-TC-Region': region || ''
}
};
}

module.exports = { signRequest };

2. MPS API Wrapper (mps-api.js)


// mps-api.js — Hunyuan 3D Generation API wrapper (Node.js ≥ 18, native fetch, zero dependencies)
const { signRequest } = require('./sign');

const SERVICE = 'mps';
const VERSION = '2019-06-12';
const REGION = 'ap-guangzhou';
const ENDPOINT = 'mps.intl.tencentcloudapi.com';

const SECRET_ID = process.env.TENCENTCLOUD_SECRET_ID;
const SECRET_KEY = process.env.TENCENTCLOUD_SECRET_KEY;

/** Generic call: sign → send request → check for errors → return Response */
async function callMpsApi(action, params) {
const payload = params || {};
const { authorization, timestamp } = signRequest({
secretId: SECRET_ID,
secretKey: SECRET_KEY,
action,
payload,
});

const res = await fetch('https://' + ENDPOINT + '/', {
method: 'POST',
headers: {
Authorization: authorization,
'Content-Type': 'application/json',
'X-TC-Action': action,
'X-TC-Timestamp': String(timestamp),
'X-TC-Version': VERSION,
'X-TC-Region': REGION,
},
body: JSON.stringify(payload),
});

const data = await res.json();
const r = data.Response || {};

// Business error: check the standard error envelope Error.Code first, then the flat ErrorCode (such as ResourceNotFound.TaskId)
if (r.Error || r.ErrorCode) {
const code = (r.Error && r.Error.Code) || r.ErrorCode;
const message = (r.Error && r.Error.Message) || r.ErrorMessage;
throw new Error(`${action} failed: ${code} - ${message} (RequestId: ${r.RequestId})`);
}
return r;
}

/**
* Submit a 3D generation task (text-to-3D / image-to-3D / multi-view-to-3D, with mutually exclusive input parameters)
* @param {object} params
* @param {string} [params.Prompt] Text-to-3D prompt, up to 1024 utf-8 characters.
* @param {string} [params.ImageUrl] Image-to-3D reference image URL (jpg/jpeg/png/bmp/webp,
* Short side ≥ 512, long side ≤ 4096, recommended ≤ 10 MB, and must be publicly accessible)
* @param {Array<{ViewType: string, ViewImageUrl: string}>} [params.MultiViewImages]
* Multi-view-to-3D: 2 to 8 images, must include the front view, and ViewType cannot be repeated.
* Valid values: front / back / left / right / top / bottom / left_front / right_front
* @param {string} [params.GenerateType='Normal'] Normal: complete 3D asset (geometry + texture);
* Geometry: geometry only (faster, about 40s)
* @param {boolean} [params.EnablePBR=false] Whether to output PBR materials.
* @param {number} [params.FaceCount=500000] Number of faces, ranging from [3000, 1500000].
* @returns {Promise<{TaskId: string, RequestId: string}>}
* TaskId: unique task ID for subsequent queries. RequestId: request tracking ID. Provide this ID when locating issues.
*/
async function submitHunyuan3DTask(params) {
return callMpsApi('SubmitHunyuan3DTask', params);
}

/**
* Query a 3D generation task.
* @param {string} taskId The task ID returned by Submit.
* @returns {Promise<{
* Status: 'WAIT' | 'RUN' | 'DONE' | 'FAIL',
* Progress: number,
* ErrorCode?: string, // Returned only when the status is FAIL, for example, InternalError.ModelInference.
* ErrorMessage?: string, // Returned only when the status is FAIL.
* ResultFile3Ds?: Array<{ // Returned only when the status is DONE.
* Type: 'OBJ' | 'GLB' | 'MTL' | 'OBJ_ZIP',
* Url: string,
* PreviewImageUrl?: string
* }>,
* RequestId: string
* }>}
* ⚠️ The Url in ResultFile3Ds is a temporary signed URL with a validity period of about 24 hours. Download or transfer it promptly.
* By default, OBJ + GLB formats are output. For OBJ, a standalone file and a ZIP package containing MTL+textures are also provided.
*/
async function queryHunyuan3DTask(taskId) {
return callMpsApi('QueryHunyuan3DTask', { TaskId: taskId });
}

module.exports = { submitHunyuan3DTask, queryHunyuan3DTask };


Complete Usage Process

This API operates in asynchronous task mode. A single generation involves two steps: Submit a task → Query by polling. The Status transitions from WAIT → RUN → DONE / FAIL.

1. Text-to-3D (Generating Textured Geometric Models from Prompts)

Generate a complete 3D model (geometry + textures) from a text description:

const { submitHunyuan3DTask, queryHunyuan3DTask } = require('./mps-api');

async function main() {
// ① Submit a task
const submitResp = await submitHunyuan3DTask({
Prompt: 'a cute cartoon dinosaur, green, small horns',
FaceCount: 500000,
});
const taskId = submitResp.TaskId;
console.log('TaskId:', taskId);

// ② Poll every 8 seconds.
while (true) {
const r = await queryHunyuan3DTask(taskId);
console.log('Status:', r.Status, 'Progress:', r.Progress);

if (r.Status === 'DONE') {
// ⚠️ The following URLs are temporary signed URLs with a validity period of about 24 hours. Download or transfer them promptly.
for (const f of r.ResultFile3Ds) {
console.log(f.Type, '->', f.Url);
}
break;
}
if (r.Status === 'FAIL') {
console.error('FAIL:', r.ErrorCode, r.ErrorMessage);
break;
}
await new Promise(resolve => setTimeout(resolve, 8000));
}
}

main().catch(console.error);

2. Image-to-3D (Single Image / Multi-View Generation of 3D Models)

Generate a complete 3D model from a single reference image, or achieve the highest fidelity with multiple reference images from different angles:
const { submitHunyuan3DTask } = require('./mps-api');

// Scenario A: Image to 3D (full assets + PBR)
await submitHunyuan3DTask({
ImageUrl: 'https://example.com/test.png',
EnablePBR: true,
});

// Scenario B: Image to 3D (geometry only, faster speed)
await submitHunyuan3DTask({
ImageUrl: 'https://example.com/test.png',
GenerateType: 'Geometry',
FaceCount: 100000,
});

// Scenario C: Multi-view image to 3D (at least 2 images, must include the front view; add left/right views for higher quality)
await submitHunyuan3DTask({
MultiViewImages: [
{ ViewType: 'front', ViewImageUrl: 'https://example.com/front.png' },
{ ViewType: 'back', ViewImageUrl: 'https://example.com/back.png' },
],
EnablePBR: true,
});

// Scenario D: Multi-view image to geometry
await submitHunyuan3DTask({
MultiViewImages: [
{ ViewType: 'front', ViewImageUrl: 'https://example.com/front.png' },
{ ViewType: 'back', ViewImageUrl: 'https://example.com/back.png' },
],
GenerateType: 'Geometry',
});

3. Production-Grade Usage with Task Queues

In real-world projects, implement a task queue to control concurrency and avoid exceeding API rate limits:
const { submitHunyuan3DTask, queryHunyuan3DTask } = require('./mps-api');

/**
* Generic polling function: with timeout and interval control
* @param {string} taskId Task ID.
* @param {object} [options]
* @param {number} [options.timeoutMs=600000] Timeout in milliseconds. Defaults to 600000 (10 minutes).
* @param {number} [options.intervalMs=8000] Polling interval in milliseconds. Defaults to 8000 (8 seconds). Do not set this value below 1000 (1 second), as it may trigger rate limiting.
* @returns {Promise<object>} The complete Response in the DONE state.
*/
async function pollTaskResult(taskId, options = {}) {
const { timeoutMs = 10 * 60 * 1000, intervalMs = 8000 } = options;
const deadline = Date.now() + timeoutMs;

while (Date.now() < deadline) {
const r = await queryHunyuan3DTask(taskId);
if (r.Status === 'DONE') return r;
if (r.Status === 'FAIL') {
throw new Error(`task failed: ${r.ErrorCode} - ${r.ErrorMessage}`);
}
await new Promise(resolve => setTimeout(resolve, intervalMs));
}
throw new Error(`poll timeout after ${timeoutMs} ms, TaskId: ${taskId}`);
}

/**
* Production-grade workflow: Use Geometry mode to quickly validate the structure, and generate full assets once satisfied.
* (Geometry only: about 40s. Full asset: about 120s. P50 reference values.)
*/
async function generateWithPreview(prompt) {
// ① Run a geometry-only task first to quickly evaluate the model skeleton.
const geometryTask = await submitHunyuan3DTask({
Prompt: prompt,
GenerateType: 'Geometry',
FaceCount: 200000,
});
const geometryResult = await pollTaskResult(geometryTask.TaskId);
console.log('Geometry preview completed. File count:', geometryResult.ResultFile3Ds.length);

// ② Once satisfied, submit the full asset task (geometry + texture [+ PBR]).
const finalTask = await submitHunyuan3DTask({
Prompt: prompt,
GenerateType: 'Normal',
FaceCount: 500000,
EnablePBR: true,
});
const finalResult = await pollTaskResult(finalTask.TaskId);

// ⚠️ Download and transfer the file immediately after receiving DONE (URLs expire in about 24 hours).
return finalResult.ResultFile3Ds; // List of OBJ / GLB files.
}


Configuration File Reference

The following is a complete configuration example that covers all configurable options for image and video generation:
{
"tencentCloud": {
"secretId": "TENCENTCLOUD_SECRET_ID",
"secretKey": "TENCENTCLOUD_SECRET_KEY",
"region": "ap-guangzhou"
},
"hunyuan3d": {
"generateType": "Normal",
"enablePBR": false,
"faceCount": 500000,
"multiView": {
"enabled": false,
"minViews": 2,
"maxViews": 8,
"requiredViewType": "front"
}
},
"concurrency": {
"maxConcurrentTasks": 1,
"pollIntervalSeconds": 8,
"pollTimeoutMinutes": 10
}
}

FAQs

Why Does Task Creation Report an InvalidParameter Error?

Error Code
Description
InvalidParameter.NoInputSpecified
None of Prompt / ImageUrl / MultiViewImages is passed.
InvalidParameter.PromptImageConflict
Prompt and ImageUrl / MultiViewImages are provided at the same time.
InvalidParameter.MultiInputConflict
ImageUrl and MultiViewImages are provided at the same time.
InvalidParameter.MissingFrontView
MultiViewImages does not contain the front view.
InvalidParameter.InsufficientViews
The number of MultiViewImages is less than 2.
InvalidParameter.DuplicateViewType
Duplicate ViewType exists.
InvalidParameter.FaceCountOutOfRange
FaceCount is not within [3000, 1500000].
InvalidParameter.PromptTooLong
Prompt exceeds 1024 utf-8 characters.

Why Does Task Creation Report an AuthFailure Error?

Error Code
Reason
AuthFailure.SignatureExpire
The deviation between the local time and Tencent CVM exceeds 5 minutes. Calibrate NTP.
AuthFailure.SecretIdNotFound
SecretId does not exist or has been deleted.
AuthFailure.UnauthorizedOperation / UnauthorizedOperation
The root account AppId is not yet in the Hunyuan 3D service allowlist (contact our business team to enable it), or the sub-account is not bound to the CAM policy QcloudMPSFullAccess.

Why Does Polling Always Return the WAIT/RUN Status?

A full 3D asset (Normal) takes about 180 seconds, while geometry-only (Geometry) takes about 80 seconds (P50 reference values). Queue time depends on platform load and is typically less than 10 minutes. We recommend setting the polling timeout to 10 minutes with an interval of 5 to 10 seconds. After Progress reaches 90 or above for the first time, you can reduce the interval to 3 to 5 seconds, but do not set it below 1 second, as this will trigger rate limiting.

Will I Be Charged for Failed Tasks?

No. Billing occurs only when Query returns Status=DONE for the first time. Tasks that are not DONE are not billed, and repeated queries do not incur duplicate charges.

What Causes the ResourceNotFound.TaskId Error in Query?

TaskId is retained on the server for 7 days and automatically cleaned up after expiration. This error is returned with HTTP 200 and carried in the ErrorCode / ErrorMessage fields of the response body (the response does not contain a Status field). Recommended client-side check order: first check whether Response.ErrorCode exists. If it exists, treat it as an error branch. Otherwise, dispatch business logic based on Response.Status.

What Information Should I Provide When Submitting Feedback?

RequestId (the RequestId from the Submit or Query response, which is critical), TaskId (if available), the full request Body (after desensitization), and the difference between the expected result and the actual result.

Appendix: Examples of Raw HTTP Requests

If you use other languages (Python / Go / Java, and so on), refer to the following raw HTTP request format:

Creating a 3D Generation Task (Text-to-3D)

Input example
curl -X POST https://mps.intl.tencentcloudapi.com/ \\
-H "Authorization: TC3-HMAC-SHA256 Credential=AKIDxxxxxxxx/2026-08-30/mps/tc3_request, SignedHeaders=content-type;host, Signature=fe5f6f..." \\
-H "Content-Type: application/json" \\
-H "X-TC-Action: SubmitHunyuan3DTask" \\
-H "X-TC-Version: 2019-06-12" \\
-H "X-TC-Timestamp: 1756543200" \\
-H "X-TC-Region: ap-guangzhou" \\
-d '{
"Prompt": "a cute cartoon dinosaur, green, small horns",
"FaceCount": 500000
}'
Output example
{
"Response": {
"TaskId": "r_44504e4b9a3b11f186b56a073b12405b",
"RequestId": "d344d00c-b131-45ec-8de9-829e0c427dca"
}
}

Querying 3D Generation Tasks

Input example
POST / HTTP/1.1
Host: mps.intl.tencentcloudapi.com
Content-Type: application/json
X-TC-Action: QueryHunyuan3DTask
X-TC-Version: 2019-06-12

{
"TaskId": "r_44504e4b9a3b11f186b56a073b12405b"
}

Output example - Completed
{
"Response": {
"Status": "DONE",
"Progress": 100,
"ResultFile3Ds": [
{
"Type": "GLB",
"Url": "https://hunyuan-3d-12583xxxx3.cos.ap-guangzhou.myqcloud.com/gen_tmp_test/<task_hash>/<file_hash>.glb?q-sign-algorithm=sha1&...",
"PreviewImageUrl": "https://hunyuan-base-prod-12583xxxx3.cos.ap-guangzhou.myqcloud.com/openapi/text2img/<preview_hash>.png?q-sign-algorithm=sha1&..."
},
{
"Type": "OBJ",
"Url": "https://hunyuan-3d-12583xxxx3.cos.ap-guangzhou.myqcloud.com/gen_tmp_test/<task_hash>/<file_hash>.obj?q-sign-algorithm=sha1&..."
},
{
"Type": "OBJ",
"Url": "https://hunyuan-3d-12583xxxx3.cos.ap-guangzhou.myqcloud.com/gen_tmp_test/<task_hash>/<file_hash>.zip?q-sign-algorithm=sha1&..."
}
],
"RequestId": "8189fa91-1c54-499c-8ce3-e182ec9c19ce"
}
}
Output example - In progress
{
"Response": {
"Status": "RUN",
"Progress": 0,
"RequestId": "f3193547-4119-48d8-aa13-b27d29b49224"
}
}
Output example - Task does not exist or has expired
{
"Response": {
"ErrorCode": "ResourceNotFound.TaskId",
"ErrorMessage": "task not found or expired",
"RequestId": "0ba287dc-f6b3-4f93-bc3a-887e7f971f90"
}
}

Help and Support

Was this page helpful?

Help us improve! Rate your documentation experience in 5 mins.

Feedback