@3dcade/sdk
v1.0.0
Published
Official 3Dcade SDK & CLI — text-to-3D generation, embeddable viewers, scenes, and marketplace API for Node.js
Downloads
122
Maintainers
Readme
@3dcade/sdk
Create, animate, embed, buy and sell 3D assets — from your terminal or Node.js app.
Official JavaScript / TypeScript SDK and CLI for the 3Dcade API. Turn text prompts into web-ready .glb models in seconds, embed them anywhere, and tap into scenes, marketplace, and advanced Meshy generation.
Links: Website · Twitter / X · npm @3dcade
Features
- Text-to-3D — generate
.glbmodels from a prompt (realistic,lowpoly,toon) - CLI —
3dcade generate,download,embed,list, and more from any terminal - TypeScript-first — full types, ESM + CJS, Node.js 18+
- Advanced Meshy API — text/image-to-3D, retexture, rig, animate
- Scenes & marketplace — create scenes, browse gallery, list and purchase assets
- Embeddable viewer — get iframe HTML and viewer URLs for any ready model
Table of Contents
- Install
- Get an API Key
- Quick Start — CLI
- CLI Commands
- Quick Start — SDK
- SDK API Reference
- Error Handling
- Environment Variables
- Troubleshooting
Install
Global (for the CLI)
npm install -g @3dcade/sdk
# or
pnpm add -g @3dcade/sdk
# or
yarn global add @3dcade/sdkLocal (for the SDK in your project)
npm install @3dcade/sdk
# or
pnpm add @3dcade/sdkGet an API Key
- Sign in at 3dcade.studio
- Open Developer → API Keys
- Click New key, copy it
Quick Start — CLI
Step 1. Create a .env file in any directory:
echo "THREEDCADE_API_KEY=3dc_live_YOUR_KEY_HERE" > .envStep 2. Generate your first model:
# Generate and wait for it to finish
3dcade generate "a low poly dragon" --style lowpoly --wait
# Output:
# ✓ Job created! Model ID: abc123xyz
# ✓ Model is ready!
# ID abc123xyz
# GLB URL https://cdn.3dcade.studio/models/abc123xyz.glb
# Viewer https://3dcade.studio/viewer/abc123xyzStep 3. Download the .glb file:
3dcade download abc123xyz --output dragon.glb
# ✓ Saved: /your/dir/dragon.glbCLI Commands
| Command | Description |
|---|---|
| 3dcade generate "<prompt>" | Generate a 3D model from a text prompt |
| 3dcade status <id> | Check the status of a model |
| 3dcade list | List all your models |
| 3dcade download <id> | Download a model's .glb file |
| 3dcade embed <id> | Get the viewer URL + iframe HTML |
| 3dcade me | Show your account info and usage limits |
| 3dcade health | Check API connectivity |
| 3dcade help | Show full help |
generate options
| Flag | Default | Description |
|---|---|---|
| --style | realistic | Art style: realistic, lowpoly, toon |
| --wait | false | Block until the model is ready |
| --output <file> | — | Also download .glb to this path when --wait is used |
list options
| Flag | Default | Description |
|---|---|---|
| --status | — | Filter: pending, ready, failed |
| --limit | 20 | Number of results per page |
| --page | 1 | Page number |
download options
| Flag | Default | Description |
|---|---|---|
| --output <file> | <id>.glb | Output file path |
Quick Start — SDK
import ThreeDcadeClient from "@3dcade/sdk";
const client = new ThreeDcadeClient(process.env.THREEDCADE_API_KEY!);
// One-shot: generate + wait for completion
const model = await client.generateAndWait("a futuristic spaceship", "realistic", {
onProgress: (m) => console.log(`Status: ${m.status} — ID: ${m.id}`),
});
console.log(model.glb_url); // https://... .glb file URL
console.log(model.viewer_url); // https://... embeddable viewer URLWith .env via dotenv
import "dotenv/config"; // loads .env automatically
import ThreeDcadeClient from "@3dcade/sdk";
const client = new ThreeDcadeClient(process.env.THREEDCADE_API_KEY!);CommonJS
const { ThreeDcadeClient } = require("@3dcade/sdk");
const client = new ThreeDcadeClient(process.env.THREEDCADE_API_KEY);SDK API Reference
Constructor
new ThreeDcadeClient(apiKey: string, options?: { baseUrl?: string })| Param | Type | Required | Description |
|---|---|---|---|
| apiKey | string | ✅ | Your 3dc_live_... API key |
| options.baseUrl | string | ❌ | Override base URL (default: https://3dcade.studio/api) |
Text-to-3D (Simple)
client.generate(prompt, style?)
Start a generation. Returns immediately with a task ID.
const result = await client.generate("a red sports car", "realistic");
// result.id — use to poll
// result.poll_url — polling URL| Param | Type | Default | Description |
|---|---|---|---|
| prompt | string | required | Text description (max 300 chars) |
| style | GenerationStyle | "realistic" | "realistic" | "lowpoly" | "toon" |
client.waitForModel(id, options?)
Poll until the model is ready or failed.
const model = await client.waitForModel("abc123", {
intervalMs: 3000,
timeoutMs: 300_000,
onProgress: (m) => console.log(m.status),
});| Option | Default | Description |
|---|---|---|
| intervalMs | 3000 | Polling interval in milliseconds |
| timeoutMs | 300000 | Maximum wait time in milliseconds |
| onProgress | — | Called on every poll with the current Model |
client.generateAndWait(prompt, style?, options?)
Shorthand: generate + wait. Returns the finished Model.
const model = await client.generateAndWait("a castle on a hill", "realistic");client.getModel(id)
Fetch a model by ID.
const model = await client.getModel("abc123");
console.log(model.status); // "pending" | "ready" | "failed"client.listModels(options?)
List models for this API key.
const { data, pagination } = await client.listModels({
page: 1,
limit: 20,
status: "ready",
});client.getEmbed(id)
Get embed data for a ready model.
const embed = await client.getEmbed("abc123");
console.log(embed.iframe_html); // ready-to-paste <iframe>
console.log(embed.viewer_url); // URL to the 3D viewer
console.log(embed.glb_url); // direct .glb download linkclient.deleteModel(id)
Delete a model.
await client.deleteModel("abc123");Advanced Generation (Meshy)
These use your advanced daily quota and return a MeshyTask.
client.textTo3d(input)
const task = await client.textTo3d({
prompt: "a medieval knight",
art_style: "realistic",
enable_pbr: true,
});
const finished = await client.waitForMeshyTask(task.task_id, {
onProgress: (t) => console.log(`${t.status} — ${t.progress}%`),
});
console.log(finished.model_urls?.glb);client.imageTo3d(input)
const task = await client.imageTo3d({
image_url: "https://example.com/my-image.png",
enable_pbr: true,
});client.retexture(input)
Retexture an existing model with a new style prompt.
const task = await client.retexture({
model_url: "https://cdn.../model.glb",
prompt: "rusty iron armor",
});client.rig(input) & client.animate(input)
const rigTask = await client.rig({ model_url: "https://cdn.../model.glb" });
const animTask = await client.animate({
model_url: "https://cdn.../model.glb",
prompt: "walking cycle",
});client.waitForMeshyTask(taskId, options?)
Poll a Meshy task until SUCCEEDED or FAILED.
const result = await client.waitForMeshyTask(task.task_id, {
intervalMs: 5000,
timeoutMs: 600_000,
onProgress: (t) => console.log(`${t.status} ${t.progress ?? 0}%`),
});Scenes
// List scenes
const scenes = await client.listScenes({ page: 1, limit: 20 });
// Create
const scene = await client.createScene({ name: "My Scene", config: { ... } });
// Get / Update / Delete
await client.getScene(scene.id);
await client.updateScene(scene.id, { name: "Updated" });
await client.deleteScene(scene.id);
// Public embed (no auth needed)
const pub = await client.getPublicScene(scene.id);
// Snapshots
const snaps = await client.getSceneSnapshots(scene.id);
// Like
await client.toggleSceneLike(scene.id);Community & Gallery
// Public gallery
const gallery = await client.getGallery({ sort: "trending", limit: 24 });
// Creator profile
const profile = await client.getCreatorProfile("wallet_address_here");Marketplace
// Browse listings
const listings = await client.getMarketplace({ sort: "newest", limit: 12 });
// Detail + reviews
const detail = await client.getListingDetail("listing_id");
// Create a listing
const listing = await client.createListing({
title: "Sci-Fi Ship Pack",
price_sol: 0.1,
scene_id: "scene_id",
});
// Purchase
await client.purchaseListing(listing.id, { transaction_signature: "sig..." });
// Review
await client.createReview(listing.id, { rating: 5, comment: "Amazing!" });Account & Payments
// Your profile + usage limits
const me = await client.getMe();
console.log(me.tier);
console.log(me.limits.advanced_used, "/", me.limits.advanced_daily);
// SOL prices
const prices = await client.getPrices();
// Verify payment / upgrade tier
const updated = await client.verifyPayment({
transaction_signature: "...",
tier: "pro",
});
// Purchases & earnings
const library = await client.getPurchases();
const earnings = await client.getEarnings();Error Handling
All API errors throw ThreeDcadeError:
import ThreeDcadeClient, { ThreeDcadeError } from "@3dcade/sdk";
const client = new ThreeDcadeClient(process.env.THREEDCADE_API_KEY!);
try {
const model = await client.getModel("invalid-id");
} catch (err) {
if (err instanceof ThreeDcadeError) {
console.log(err.name); // "ThreeDcadeError"
console.log(err.code); // "NOT_FOUND" | "MISSING_KEY" | "TIMEOUT" | ...
console.log(err.message); // Human-readable description
console.log(err.status); // HTTP status code (e.g. 404)
}
}Common Error Codes
| Code | Status | Meaning |
|---|---|---|
| MISSING_KEY | — | apiKey was empty or not provided |
| INVALID_PROMPT | — | Prompt is empty or over 300 chars |
| NOT_FOUND | 404 | Model/scene/listing does not exist |
| UNAUTHORIZED | 401 | Invalid or expired API key |
| LIMIT_REACHED | 429 | Daily generation quota exhausted |
| GENERATION_FAILED | — | Model failed during generation |
| MESHY_TASK_FAILED | — | Advanced Meshy task failed or expired |
| TIMEOUT | — | Polling timed out |
| REQUEST_FAILED | varies | Generic HTTP error |
Environment Variables
| Variable | Required | Description |
|---|---|---|
| THREEDCADE_API_KEY | ✅ | Your 3dc_live_... API key |
| THREEDCADE_BASE_URL | ❌ | Override the API base URL |
| NO_COLOR | ❌ | Disable CLI color output |
| DEBUG | ❌ | Print full error stack traces in CLI |
The CLI automatically reads .env from the current working directory — no extra setup needed.
Troubleshooting
command not found: 3dcade
You installed locally, not globally. Either:
npm install -g @3dcade/sdk # install globally
# OR use npx:
npx @3dcade/sdk generate "prompt"THREEDCADE_API_KEY is not set
Create a .env file in the directory where you run the command:
echo "THREEDCADE_API_KEY=3dc_live_YOUR_KEY" > .envOr export it in your shell:
export THREEDCADE_API_KEY=3dc_live_YOUR_KEYModel stuck on pending
Generation can take 1–3 minutes. Use --wait to block, or poll:
3dcade status <id>LIMIT_REACHED error
You've used your daily generation quota. Upgrade your tier at 3dcade.studio → Pricing.
TypeScript: fetch is not defined
Requires Node.js ≥ 18 (which has fetch built-in). Check your version:
node --version # should be v18.0.0 or higherREST API (curl reference)
# Health check
curl https://3dcade.studio/api/v1/health
# Generate
curl -X POST https://3dcade.studio/api/v1/generate \
-H "Authorization: Bearer 3dc_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"prompt": "a futuristic spaceship", "style": "realistic"}'
# Poll status
curl https://3dcade.studio/api/v1/model/TASK_ID \
-H "Authorization: Bearer 3dc_live_YOUR_KEY"
# List models
curl "https://3dcade.studio/api/v1/models?page=1&limit=10" \
-H "Authorization: Bearer 3dc_live_YOUR_KEY"License
MIT — see LICENSE
