Skip to main content

TypeScript SDK

Official TypeScript / Node.js SDK for the Aholo Open API.

Installation

Install only the packages you need:

npm install @manycore/aholo-sdk-asset # file upload
npm install @manycore/aholo-sdk-world # world reconstruction & generation
npm install @manycore/aholo-sdk-lux3d # Lux3D generation

Authentication

Recommended: set the environment variable; the SDK reads AHOLO_API_KEY:

export AHOLO_API_KEY=your_api_key_here

Or pass it in code:

import { createWorldClient } from '@manycore/aholo-sdk-world';

const world = createWorldClient({ apiKey: 'your_api_key_here', region: 'com' });
Security

Never hardcode API keys in source code, packages, or public repositories.

Region

ValueDescriptionAPI endpoint
cnChinahttps://api.aholo3d.cn
comGlobalhttps://api.aholo3d.com

Asset upload

import { createAssetClient } from '@manycore/aholo-sdk-asset';

const asset = createAssetClient({ region: 'com' });

Upload a file

const result = await asset.uploadFile('./video.mp4');
console.log(result.url); // public URL

Upload a Buffer

import { readFileSync } from 'node:fs';

const data = readFileSync('./image.jpg');
const result = await asset.uploadBuffer(data, { filename: 'image.jpg' });

Upload with progress

const result = await asset.uploadFile('./video.mp4', {
onProgress: (uploaded, total) => {
const pct = Math.round((uploaded / total) * 100);
process.stdout.write(`\rUploading: ${pct}%`);
},
});

UploadOptions

OptionTypeDescription
filenamestringOverride filename (defaults to basename)
onProgress(uploaded: number, total: number) => voidProgress callback (bytes)
partTimeoutMsnumberPer-part timeout (default 120,000 ms)
signalAbortSignalCancellation signal

UploadResult

FieldTypeDescription
urlstringPublic URL of the uploaded file
md5stringFile MD5

World

import { createWorldClient } from '@manycore/aholo-sdk-world';

const world = createWorldClient({ region: 'com' });

3DGS reconstruction (video / images)

const { worldId } = await world.reconstructions.create({
name: 'Living room',
resources: [{ url: 'https://cdn.example.com/room.mp4', type: 'video' }],
taskQuality: 'normal', // 'low' | 'normal' | 'high'
scene: 'model', // 'model' | 'space'
useMask: false, // optional: segment uploaded resources when true
});

const detail = await world.waitFor(worldId);
console.log(detail.assets?.splats?.urls?.plyPath); // PLY download URL
Image reconstruction requirement

When using images, you need ≥ 20 image resources (type: 'image' or omit type).

3DGS generation (from prompt)

const { worldId } = await world.generations.create({
name: 'Forest cabin',
prompt: 'A modern cabin in the forest',
});

const detail = await world.waitFor(worldId);

Get world detail

const detail = await world.retrieve(worldId);
console.log(detail.status);

Task status & polling

PhaseStatusDescription
In progressPENDINGQueued
In progressPREPROCESSINGPreprocessing
In progressRUNNINGRunning
SuccessSUCCEEDEDSuccess
FailedFAILEDFailed
FailedCANCELEDCanceled
FailedTIMEOUTTimed out
FailedREJECTEDRejected

world.waitFor(worldId) polls until SUCCEEDED and returns WorldDetail. Terminal failures throw PollingFailedError.

List worlds

const list = await world.list({ pageNum: 1, pageSize: 20 });
list.result?.forEach((w) => console.log(w.worldId, w.status));

WorldDetail fields

FieldTypeDescription
worldIdstringWorld ID
namestring?Name
statusstringSee task status table above
assets.splats.urls.plyPathstring?PLY download URL
assets.splats.urls.spzPathstring?SPZ download URL
assets.splats.urls.lodMetaPathstring?LOD metadata URL (if generated)
assets.imagery.panoUrlstring?AI panorama URL (Spatial Gen only, after pano subtask succeeds)
assets.semanticsMetadata.upAxis"Y" | "Z"?World up axis (Y = glTF/USD; Z = 3DGS convention)
createTimenumber?Created at (Unix ms)
updateTimenumber?Updated at (Unix ms)

Lux3D

import { createLux3dClient } from '@manycore/aholo-sdk-lux3d';

const lux3d = createLux3dClient({ region: 'com' });

Image to 3D

// From URL
const taskId = await lux3d.imgTo3d.create({
img: 'https://example.com/object.jpg',
version: 'v2.0-preview', // 'v1.0-pro' | 'v2.0-preview' (default)
});

// From local file
const taskId2 = await lux3d.imgTo3d.createFromFile('./object.jpg');

const result = await lux3d.tasks.waitFor(taskId);
console.log(result.outputs[0]?.content); // download URL

Text to 3D

const taskId = await lux3d.textTo3d.create({
prompt: 'A wooden chair with carved legs',
// style: 'photorealistic', // see styles below
});
const result = await lux3d.tasks.waitFor(taskId);

Text-to-3D styles: photorealistic (default) | cartoon | anime | hand_painted | cyberpunk | fantasy | glass

Material transfer

const taskId = await lux3d.materialTransfer.create({
img: 'https://example.com/material.jpg',
meshUrl: 'https://example.com/model.glb',
});
const result = await lux3d.tasks.waitFor(taskId);

Version differences

VersionDefaultOutput formatsNotes
v2.0-previewYes.zip + .glb + .usdz (3 files)Enhanced text & texture detail
v1.0-pro.lux3d (1 file)Full PBR, supports transparent materials

Lux3dTaskResult

FieldTypeDescription
taskIdnumberTask ID
status0 | 1 | 3 | 40 init; 1 running; 3 success; 4 failed
outputsTaskOutput[]Output files (outputs[n].content is download URL, ~2 h TTL after success)

lux3d.tasks.waitFor(taskId) returns when status === 3; throws PollingFailedError on 4. Poll every 10–15 seconds.


Error handling

import {
AuthenticationError,
RateLimitError,
BusinessError,
PollingTimeoutError,
PollingFailedError,
} from '@manycore/aholo-sdk-core';

try {
const detail = await world.waitFor(worldId);
} catch (e) {
if (e instanceof AuthenticationError) {
console.error('Invalid or missing API Key');
} else if (e instanceof RateLimitError) {
console.error('Rate limit exceeded');
} else if (e instanceof BusinessError) {
console.error('API error:', e.code, e.message);
} else if (e instanceof PollingTimeoutError) {
console.error('Polling timed out');
} else if (e instanceof PollingFailedError) {
console.error('Task failed:', e.message);
}
}
ErrorDescription
AuthenticationErrorInvalid or missing API Key
RateLimitErrorRate limit exceeded
BusinessErrorAPI business error (includes code)
PollingTimeoutErrorPolling timed out
PollingFailedErrorTask execution failed

More examples

See GitHub examples:

  • upload-file.mts — upload a local file
  • world-reconstruct.mts — full 3DGS reconstruction flow
  • lux3d-img-to-3d.mts — image to 3D

GitHub README is for installation only. If it conflicts with this page, this page wins. Source and runnable examples: GitHub.