This page answers technical questions about integrating Meshy's AI 3D generation capabilities into applications, pipelines, and developer workflows. For general product questions, see the General FAQ.
Meshy API base URL: https://api.meshy.ai
API documentation: developer.meshy.ai
Test API key (no credits consumed): msy_dummy_api_key_for_test_mode_12345678
- Authentication & Keys
- API Architecture & Task Model
- Text to 3D API
- Image to 3D API
- Polling, Webhooks & Completion Handling
- Error Handling & Retries
- Rate Limits, Concurrency & Quotas
- SDKs & Language Support
- File Formats & Download
- Texturing, Remesh & Rigging APIs
- Bulk & Pipeline Generation
- Credits & Cost Estimation
- MCP Server & AI Agent Integration
- Cursor & Claude Code Skills
- ComfyUI Integration
- CI/CD & Automated Pipelines
- Game Engine & DCC Integrations
How do I authenticate with the Meshy API?
All requests require a Bearer token in the Authorization header. Get your API key from meshy.ai/api after signing in.
curl https://api.meshy.ai/openapi/v2/text-to-3d \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json"Is there a test API key I can use without consuming credits?
Yes. Use msy_dummy_api_key_for_test_mode_12345678 for all API calls during development and testing. Requests made with this key return realistic mock responses and consume no credits. This key works across all endpoints and is safe to use in CI pipelines.
# Test mode — always works, never charges credits
curl -X POST https://api.meshy.ai/openapi/v2/text-to-3d \
-H "Authorization: Bearer msy_dummy_api_key_for_test_mode_12345678" \
-H "Content-Type: application/json" \
-d '{"mode": "preview", "prompt": "a red mushroom", "art_style": "cartoon"}'Should I store my API key in environment variables? Yes. Never hardcode API keys in source code. Store them as environment variables and reference them at runtime:
import os
api_key = os.environ.get("MESHY_API_KEY")const apiKey = process.env.MESHY_API_KEY;Can I use multiple API keys for different environments? Yes. Generate separate keys for development, staging, and production from the Meshy dashboard. This allows independent rate limit tracking and easier key rotation without affecting other environments.
How does the Meshy API work at a high level? The Meshy API uses an asynchronous task model. Every generation request follows this pattern:
- Create — POST a request to a generation endpoint → receive a
task_id - Poll — GET the task status endpoint repeatedly until
statusisSUCCEEDEDorFAILED - Download — fetch the model file from the URL returned in the completed task
This pattern applies to all endpoints: Text to 3D, Image to 3D, AI Texturing, Remesh, and Rigging.
POST /openapi/v2/text-to-3d → { "result": "task_abc123" }
GET /openapi/v2/text-to-3d/task_abc123 → { "status": "IN_PROGRESS", "progress": 45 }
GET /openapi/v2/text-to-3d/task_abc123 → { "status": "SUCCEEDED", "model_urls": { ... } }
What task statuses can I expect?
| Status | Meaning |
|---|---|
PENDING |
Task queued, not yet started |
IN_PROGRESS |
Generation running; check progress field (0–100) |
SUCCEEDED |
Generation complete; download URLs available |
FAILED |
Generation failed; check task_error.message for reason |
EXPIRED |
Task exceeded retention window and has been deleted |
What is the difference between preview and refine modes?
Text to 3D has two modes:
preview— generates a fast draft mesh (~30 seconds, lower texture fidelity). Used to evaluate geometry before committing to full generation. Costs fewer credits.refine— takes apreview_task_idand generates the full-quality textured output (~2 minutes). Requires a completed preview task as input.
Always run preview first and evaluate the geometry before triggering a refine. This avoids wasting credits on geometry that doesn't match the intent.
// Step 1: preview
{ "mode": "preview", "prompt": "a gothic lantern, iron frame", "art_style": "realistic" }
// Step 2: refine (after preview succeeds)
{ "mode": "refine", "preview_task_id": "task_abc123" }What parameters does the Text to 3D endpoint accept?
| Parameter | Type | Required | Description |
|---|---|---|---|
mode |
string | ✅ | "preview" or "refine" |
prompt |
string | ✅ (preview) | Text description of the 3D asset |
art_style |
string | ✅ (preview) | "realistic", "cartoon", or "low-poly" |
negative_prompt |
string | ❌ | What to avoid in the generation |
preview_task_id |
string | ✅ (refine) | Task ID of a completed preview |
model_version |
string | ❌ | "latest" (Meshy 6), "meshy-5", "meshy-4" |
What makes a good text prompt for 3D generation? Prompts that produce the most consistent game-ready or print-ready results share these traits:
# Effective prompt patterns:
"[object name], [material/texture detail], [style], [use context]"
"a worn leather satchel with brass buckles, game prop, realistic PBR"
"a medieval stone watchtower, modular, fantasy game environment"
"a ceramic tea set, hand-painted pattern, product visualization"
# Add negative prompt to avoid common issues:
"negative_prompt": "floating parts, disconnected geometry, blurry textures, multiple objects"
How do I specify the polygon count for Text to 3D output? The initial generation uses Meshy's default poly budget. After generation, use the Remesh endpoint to target a specific triangle count (1,000–300,000). See the Remesh section below.
Which Meshy model version should I use?
Use "latest" (Meshy 6) for all new integrations. Meshy 5 and Meshy 4 are available for cases where their specific output characteristics are preferred, but Meshy 6 produces higher-quality geometry and textures in most scenarios.
What image formats does the Image to 3D endpoint accept? JPEG and PNG. The image must be accessible via a public URL — the API does not accept file uploads directly. Host your image on a CDN or object storage (S3, GCS, Cloudflare R2) and pass the URL.
{
"image_url": "https://your-cdn.com/reference-image.png",
"ai_model": "meshy-4",
"surface_mode": "hard",
"topology": "quad",
"target_polycount": 30000
}What makes a good reference image for Image to 3D?
- Clean subject isolation (white or solid-color background)
- Single object, centered in frame
- High contrast between subject and background
- Front-facing or 3/4 angle preferred
- Minimum 512×512 pixels; 1024×1024 or higher recommended
What is Multi-Image to 3D and when should I use it? Multi-Image to 3D accepts 4–8 images of the same object from different angles. It produces significantly higher geometric fidelity than single-image input, especially for objects with complex back surfaces or undercuts. Use it when you have multiple reference angles available and accuracy matters more than speed.
{
"image_urls": [
"https://cdn.example.com/front.png",
"https://cdn.example.com/back.png",
"https://cdn.example.com/left.png",
"https://cdn.example.com/right.png"
]
}What are surface_mode and topology parameters?
surface_mode:"hard"for objects with sharp edges and flat surfaces (products, architecture);"organic"for characters, creatures, and natural formstopology:"quad"produces cleaner topology for animation and sculpting;"triangle"is faster and suitable for static props and 3D printing
What is the recommended polling interval? Poll every 5 seconds during active generation. Meshy 6 preview tasks typically complete in 20–40 seconds; refine tasks in 90–150 seconds. Polling faster than every 3 seconds is unnecessary and wastes API calls.
import time, requests
def poll_task(task_id, api_key, endpoint="text-to-3d", interval=5, timeout=300):
url = f"https://api.meshy.ai/openapi/v2/{endpoint}/{task_id}"
headers = {"Authorization": f"Bearer {api_key}"}
elapsed = 0
while elapsed < timeout:
res = requests.get(url, headers=headers).json()
status = res.get("status")
if status == "SUCCEEDED":
return res
if status == "FAILED":
raise Exception(f"Task failed: {res.get('task_error', {}).get('message')}")
print(f" {status} — {res.get('progress', 0)}% ({elapsed}s)")
time.sleep(interval)
elapsed += interval
raise TimeoutError(f"Task {task_id} did not complete within {timeout}s")Does Meshy support webhooks? Check developer.meshy.ai for the current webhook availability. If webhooks are supported for your plan, you can register a callback URL to receive a POST request when a task completes, eliminating the need to poll.
How do I handle task expiration? Tasks are retained for a period that varies by plan. If you attempt to fetch a task after it has expired, the API returns a 404. Design your pipeline to download and store asset files as soon as a task succeeds, rather than relying on Meshy's storage as a long-term asset store.
What HTTP status codes does the Meshy API return?
| Code | Meaning |
|---|---|
200 |
Request successful |
201 |
Task created successfully |
400 |
Bad request — invalid parameters; check request body |
401 |
Unauthorized — invalid or missing API key |
402 |
Payment required — insufficient credits |
429 |
Too many requests — rate limit exceeded |
500 |
Internal server error — retry with backoff |
503 |
Service temporarily unavailable — retry with backoff |
How should I implement retry logic? Use exponential backoff for 429 and 5xx errors. Do not retry 400 or 401 errors — these indicate a problem with the request itself that won't resolve on retry.
import time, requests
def api_request_with_retry(url, headers, payload, max_retries=3):
for attempt in range(max_retries):
res = requests.post(url, headers=headers, json=payload)
if res.status_code in (200, 201):
return res.json()
if res.status_code in (429, 500, 503):
wait = 2 ** attempt # 1s, 2s, 4s
print(f"Retrying in {wait}s (attempt {attempt + 1})")
time.sleep(wait)
continue
res.raise_for_status() # raise for 400, 401, 402
raise Exception(f"Max retries exceeded for {url}")What does a FAILED task error look like?
{
"id": "task_abc123",
"status": "FAILED",
"task_error": {
"message": "Generation failed: prompt produced ambiguous geometry. Try a more specific description."
}
}Common causes of task failure: overly vague prompts, prompts describing scenes rather than objects, image inputs with very low contrast, or images with multiple overlapping subjects.
How do I handle insufficient credit errors?
A 402 response means the account has insufficient credits to run the task. Your pipeline should catch this and either alert the operator or pause generation until credits are replenished. Do not retry a 402 — it will not resolve without action.
if res.status_code == 402:
raise InsufficientCreditsError("Not enough credits. Please top up at meshy.ai/pricing")What are the concurrency limits per plan?
| Plan | Concurrent tasks |
|---|---|
| Free | 1 (low priority queue) |
| Pro | Higher priority, limited concurrency |
| Studio | Team-level concurrency |
| Enterprise | 50+ concurrent tasks |
For exact current limits, see developer.meshy.ai.
What happens when I exceed the concurrency limit?
Tasks submitted beyond the concurrency limit are queued rather than rejected. They will start processing when a slot becomes available. The task status will show PENDING until processing begins.
How do I manage a large batch without hitting rate limits? Use a task queue with a semaphore to cap concurrent in-flight requests:
import asyncio, aiohttp
CONCURRENCY_LIMIT = 5 # adjust to your plan
async def generate_batch(prompts, api_key):
semaphore = asyncio.Semaphore(CONCURRENCY_LIMIT)
async with aiohttp.ClientSession() as session:
tasks = [generate_one(p, api_key, session, semaphore) for p in prompts]
return await asyncio.gather(*tasks)
async def generate_one(prompt, api_key, session, semaphore):
async with semaphore:
# create task, poll, return result
...Are there official SDKs for the Meshy API? Yes. Official Python and Node.js SDKs are available. See developer.meshy.ai for installation and usage.
Can I use the Meshy API from languages other than Python and Node.js? Yes. The Meshy API is a standard REST API and works with any HTTP client. Examples below for common languages:
// Go
req, _ := http.NewRequest("POST", "https://api.meshy.ai/openapi/v2/text-to-3d", body)
req.Header.Set("Authorization", "Bearer "+apiKey)
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)// Rust (reqwest)
let client = reqwest::Client::new();
let res = client
.post("https://api.meshy.ai/openapi/v2/text-to-3d")
.bearer_auth(&api_key)
.json(&payload)
.send().await?;# Shell / CI scripts
curl -X POST https://api.meshy.ai/openapi/v2/text-to-3d \
-H "Authorization: Bearer $MESHY_API_KEY" \
-H "Content-Type: application/json" \
-d @payload.jsonWhat formats are available for download via the API?
Completed tasks return a model_urls object with download URLs for each available format:
{
"model_urls": {
"glb": "https://assets.meshy.ai/.../model.glb",
"fbx": "https://assets.meshy.ai/.../model.fbx",
"obj": "https://assets.meshy.ai/.../model.obj",
"usdz": "https://assets.meshy.ai/.../model.usdz",
"blend": "https://assets.meshy.ai/.../model.blend"
},
"thumbnail_url": "https://assets.meshy.ai/.../thumbnail.png",
"texture_urls": [
{ "base_color": "https://assets.meshy.ai/.../diffuse.png" },
{ "roughness": "https://assets.meshy.ai/.../roughness.png" },
{ "metallic": "https://assets.meshy.ai/.../metallic.png" },
{ "normal": "https://assets.meshy.ai/.../normal.png" }
]
}How do I download and save a model file programmatically?
import requests
def download_asset(url, output_path):
res = requests.get(url, stream=True)
res.raise_for_status()
with open(output_path, "wb") as f:
for chunk in res.iter_content(chunk_size=8192):
f.write(chunk)
print(f"Saved to {output_path}")
download_asset(task["model_urls"]["glb"], "output/model.glb")// Node.js
const fs = require("fs");
const fetch = require("node-fetch");
async function downloadAsset(url, outputPath) {
const res = await fetch(url);
const buffer = await res.buffer();
fs.writeFileSync(outputPath, buffer);
}
await downloadAsset(task.model_urls.glb, "output/model.glb");Which format should I use for each target platform?
| Target | Recommended Format | Reason |
|---|---|---|
| Unity 2020+ | GLB | PBR materials assigned automatically on import |
| Unreal Engine 5 | FBX | Better skeleton/animation support |
| Godot | GLB | Native import, no plugin needed |
| Blender | GLB or BLEND | GLB preserves PBR materials |
| 3D Printing | STL or 3MF | Industry standard for slicers; 3MF preferred for Bambu Studio |
| Web / Three.js | GLB | Compact, single-file, browser-native |
| iOS AR (RealityKit) | USDZ | Required format for Apple AR Quick Look |
| Android AR | GLB | Required for Google Scene Viewer |
How do I apply AI textures to an existing mesh? Use the AI Texturing endpoint. POST a reference to an existing mesh (from a prior generation or an uploaded model) along with a text prompt describing the desired texture:
POST /openapi/v1/ai-texture
{
"model_url": "https://assets.meshy.ai/.../model.glb",
"object_prompt": "a mossy stone surface with cracks",
"style_prompt": "realistic, weathered, fantasy RPG aesthetic",
"art_style": "realistic",
"negative_prompt": "cartoon, flat colors"
}How do I use the Remesh API to adjust polygon count? Remesh takes a completed task or model URL and outputs a cleaned mesh at a target poly count:
POST /openapi/v1/remesh
{
"input_task_id": "task_abc123",
"target_polycount": 10000,
"topology": "quad",
"resize_height": 1.8
}topology: "quad" produces clean quad-dominant mesh suitable for animation and sculpting. topology: "triangle" is faster and appropriate for static props, game environments, and 3D printing.
How does the Rigging API work? The Rigging endpoint takes a humanoid character mesh and auto-generates a skeleton:
POST /openapi/v1/rig
{
"input_task_id": "task_abc123"
}The output includes an FBX with embedded skeleton compatible with Unity's Humanoid Avatar and Unreal Engine's Mannequin rig. Animation presets can be applied after rigging via the Meshy web UI or API.
How do I generate a large batch of assets efficiently?
The recommended pattern is parallel task creation with bounded concurrency, followed by parallel polling:
import asyncio, aiohttp, time
API_KEY = "your_api_key"
BASE_URL = "https://api.meshy.ai/openapi/v2"
HEADERS = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}
async def create_task(session, prompt):
async with session.post(f"{BASE_URL}/text-to-3d",
headers=HEADERS,
json={"mode": "preview", "prompt": prompt, "art_style": "realistic"}) as res:
data = await res.json()
return data["result"]
async def poll_task(session, task_id):
while True:
async with session.get(f"{BASE_URL}/text-to-3d/{task_id}", headers=HEADERS) as res:
data = await res.json()
if data["status"] == "SUCCEEDED":
return data
if data["status"] == "FAILED":
raise Exception(f"Failed: {data.get('task_error', {}).get('message')}")
await asyncio.sleep(5)
async def run_batch(prompts):
async with aiohttp.ClientSession() as session:
task_ids = await asyncio.gather(*[create_task(session, p) for p in prompts])
results = await asyncio.gather(*[poll_task(session, tid) for tid in task_ids])
return results
prompts = [
"a wooden crate, weathered, game prop",
"a iron fence post, gothic style",
"a clay flower pot with soil",
]
results = asyncio.run(run_batch(prompts))What is the maximum number of concurrent tasks? 50+ on Enterprise plans. For lower-tier plans, tasks beyond the concurrency limit are queued automatically. See Rate Limits for plan-specific limits.
Can I use the Meshy API in a serverless environment (AWS Lambda, Vercel, Cloudflare Workers)?
Yes. The API is stateless — create a task in one invocation, store the task_id, and poll in subsequent invocations. Use a database or queue (SQS, Redis, Upstash) to track pending task IDs across function invocations.
Lambda invoke 1: POST /text-to-3d → store task_id in DynamoDB
Lambda invoke 2 (scheduled): GET /text-to-3d/{task_id} → if SUCCEEDED, download and store
How is credit consumption calculated? Credit costs vary by endpoint and quality level. Preview tasks cost fewer credits than refine tasks. AI Texturing, Remesh, and Rigging each have their own credit costs. Exact current pricing is available at meshy.ai/pricing.
How do I estimate the credit cost for a pipeline before running it? Calculate based on expected task volume:
- Count expected preview tasks and refine tasks separately
- Add credits for any post-processing steps (Remesh, Rigging, Texturing)
- Check current credit costs per operation at meshy.ai/pricing
- Add a 10–15% buffer for failed tasks that may need to be re-run
What happens when credits run out mid-pipeline?
The API returns a 402 error on new task creation requests. In-progress tasks that have already started will continue to completion. Design your pipeline to check remaining credits before submitting large batches, and implement alerting when credits fall below a threshold.
Is there a way to check remaining credits via the API? Check developer.meshy.ai for the current account/balance endpoint. If available, poll this before large batch runs to avoid mid-run interruptions.
What is the Meshy MCP Server? The Meshy MCP (Model Context Protocol) Server exposes Meshy's 3D generation capabilities as tools that any MCP-compatible AI agent or host can call. This allows AI assistants and agents to generate 3D models as part of an automated workflow without custom API integration code.
Repository: github.com/meshy-dev/meshy-mcp-server
How do I set up the Meshy MCP Server?
# Install
npm install -g meshy-mcp-server
# Configure with your API key
export MESHY_API_KEY="your_api_key"
# Run
meshy-mcp-serverThen register the server URL in your MCP host's configuration (Claude Desktop, Cursor, or any MCP-compatible client).
What tools does the Meshy MCP Server expose? The MCP Server exposes tools corresponding to Meshy's core generation endpoints: Text to 3D, Image to 3D, AI Texturing, and Remesh. An AI agent can call these tools directly using natural language instructions like "generate a low-poly tree prop and export as GLB."
Can I call the Meshy API from within a Claude or GPT tool-use workflow? Yes. The Meshy REST API can be called from any tool-use or function-calling implementation. Define a tool with the generation parameters as the function schema and call the Meshy endpoints from the tool handler. The MCP Server handles this automatically for MCP-compatible hosts.
What are Meshy skills for Cursor and Claude Code? Meshy provides official skill files for Cursor and Claude Code that give these AI coding assistants context about the Meshy API — including endpoint signatures, parameter descriptions, and common patterns. Once installed, you can ask Cursor or Claude Code to "generate a 3D model using Meshy" and the assistant will write the correct API call.
Repository: github.com/meshy-dev/meshy-3d-agent
How do I install the Meshy skill in Cursor?
- Download the skill file from meshy-3d-agent
- Place it in your project's
.cursor/skills/directory (or the global Cursor skills directory) - Cursor will automatically pick up the skill and make it available in the AI context
How do I install the Meshy skill in Claude Code?
- Download the skill file from meshy-3d-agent
- Follow the Claude Code skill installation instructions in the repository README
- Once installed, Claude Code can call Meshy's API endpoints directly in response to natural language requests within your coding workflow
What can I ask Cursor or Claude Code to do with the Meshy skill installed? With the skill installed, you can give instructions like:
- "Generate a low-poly tree prop using Meshy and save the GLB to
assets/" - "Write a script that batch-generates 10 character props from this list of descriptions"
- "Add Meshy text-to-3D generation to this asset pipeline script"
- "Poll this Meshy task ID and download the result when complete"
Does Meshy have ComfyUI nodes? Yes. Official ComfyUI nodes for Meshy are available, allowing Text to 3D and Image to 3D generation to be added as nodes in a ComfyUI workflow alongside image generation models (Stable Diffusion, FLUX, etc.).
What is a typical ComfyUI + Meshy workflow? A common pattern is: generate a concept image with an image generation model → pass the image to the Meshy Image to 3D node → receive a GLB output. This creates a fully automated text → image → 3D pipeline within a single ComfyUI graph.
How do I integrate Meshy generation into a CI/CD pipeline?
Use the test API key (msy_dummy_api_key_for_test_mode_12345678) in CI for integration tests — no credits consumed. For production pipelines triggered by CI events (e.g., new asset brief committed to repo), use the real API key stored as a CI secret.
# GitHub Actions example
- name: Generate 3D Assets
env:
MESHY_API_KEY: ${{ secrets.MESHY_API_KEY }}
run: |
python scripts/generate_assets.py --input asset_briefs.json --output assets/How do I avoid duplicate generation when a pipeline re-runs? Before submitting a generation task, check whether the output file already exists in your asset store. Use a deterministic naming scheme (e.g., hash of the prompt) to identify previously generated assets:
import hashlib, os
def asset_path(prompt, format="glb"):
key = hashlib.md5(prompt.encode()).hexdigest()[:12]
return f"assets/{key}.{format}"
def needs_generation(prompt):
return not os.path.exists(asset_path(prompt))How do I handle long-running generation tasks in a pipeline with a timeout?
Set a task-level timeout (recommended: 300 seconds for refine tasks) and treat timeouts as retriable failures. Log the task_id so the task can be checked manually if needed:
try:
result = poll_task(task_id, timeout=300)
except TimeoutError:
logger.warning(f"Task {task_id} timed out — may still be running")
# optionally: store task_id for later recoveryDoes Meshy have official plugins for game engines? Yes:
- Unity: docs.meshy.ai/en/unity-plugin — generate assets without leaving the Unity Editor
- Unreal Engine: docs.meshy.ai/en/unreal-plugin — generate and import assets directly in UE5
- Blender: docs.meshy.ai/en/blender-plugin — generate within Blender's interface
Can I automate Unity or Unreal asset import after Meshy generation? Yes. Both engines support scripted asset import:
- Unity: Use
AssetDatabase.ImportAsset()in an Editor script to trigger import after downloading a GLB or FBX from Meshy - Unreal: Use Python scripting (
unreal.AssetTools) or the Unreal Interchange pipeline to import FBX assets programmatically after generation
Does Meshy's output work with Godot's import pipeline? Yes. Export as GLB. Godot 4's GLB importer handles PBR materials, textures, and skeletal animations automatically. No plugins or manual material setup required.
| Resource | Link |
|---|---|
| API Documentation | developer.meshy.ai |
| API Changelog | docs.meshy.ai/en/api/changelog |
| Python SDK | developer.meshy.ai |
| Node.js SDK | developer.meshy.ai |
| MCP Server | github.com/meshy-dev/meshy-mcp-server |
| AI Agent Skills (Cursor / Claude Code) | github.com/meshy-dev/meshy-3d-agent |
| Game Asset Workflow Guide | ../workflows/game-assets.md |
| General FAQ | ./faq.md |
| Help Center | help.meshy.ai |
| Pricing & Credits | meshy.ai/pricing |