Quickstart
Start by creating your API key
Every request in this guide needs one. Creating a key takes seconds.
Create your API keyMake your first 3D model with the Meshy REST API in four steps, from creating an API key to downloading the model.
Using an AI coding assistant? To connect Claude Code, Cursor, Windsurf, or another MCP client to Meshy, see AI integration. For a chat agent without MCP support, use llms.txt.
1Get your API key
Create an API key on the API Keys page of the Developer Platform. You can't view the key again after you leave that screen, so store it somewhere safe. Send it in every request as a Bearer token in the Authorization header. See Authentication.
You need a paid plan to create and manage API keys. On the Free plan, you can't create keys of your own, and the Playground uses a built-in key for testing.

Keep the key out of your scripts. Store it in an environment variable instead, as the next step shows.
2Create an Image to 3D task
Send an image to Image to 3D. To start from a text prompt or several photos instead, use Text to 3D or Multi-Image to 3D.
First, store your key in an environment variable:
Export your key
export MESHY_API_KEY="<your-api-key>"
Run this in your terminal (Terminal on macOS, Command Prompt or PowerShell on Windows), not in a browser.
The following examples all use this photo. To try another image, change image_url.

Request
curl https://api.meshy.ai/openapi/v1/image-to-3d \
-X POST \
-H "Authorization: Bearer ${MESHY_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"image_url": "https://docs.meshy.ai/images/api/quick-start/source-photo.webp"
}'
3Check task status
The task runs in the background and usually takes a few minutes. Get the task from the same endpoint until status is SUCCEEDED, FAILED, or CANCELED. In the following request, replace <task_id> with the ID that step 2 returned. Between requests, wait the number of seconds in the Retry-After header.
For typical processing times, and how long to wait before you give up, see Task lifecycle.
Request
curl https://api.meshy.ai/openapi/v1/image-to-3d/<task_id> \
-H "Authorization: Bearer ${MESHY_API_KEY}"
Response: SUCCEEDED
{
"id": "018a210d-8ba4-705c-b111-1f1776f7f578",
"status": "SUCCEEDED",
"progress": 100,
"model_urls": {
"glb": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.glb?Expires=***",
"fbx": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.fbx?Expires=***"
},
"thumbnail_url": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview.png?Expires=***",
"task_error": null
}
If the task fails, status is FAILED, and task_error says why. Fix the input or create another task. See Errors.
To get notified when the task finishes instead of polling, stream the task or use a webhook.
4Download your model
The files are in model_urls of the preceding response. Each format (GLB, FBX, OBJ, USDZ, and STL) has a signed URL that works for a limited time. You can also paste the URL into your browser to download the file.
Download
curl -L "<model_urls.glb from the response above>" -o model.glb

On every plan except Enterprise, Meshy keeps the files for 3 days. Download the files you need before then. See Asset retention.
Put it all together
This script creates the task, waits for it to finish, and downloads the model.
Full script
import axios from 'axios';
import fs from 'fs';
const headers = { Authorization: `Bearer ${process.env.MESHY_API_KEY}` };
const imageUrl = 'https://docs.meshy.ai/images/api/quick-start/source-photo.webp';
// 1. Create the task
const { data: created } = await axios.post(
'https://api.meshy.ai/openapi/v1/image-to-3d',
{ image_url: imageUrl },
{ headers, timeout: 60_000 },
);
const taskId = created.result;
// 2. Poll until it finishes, for up to 60 minutes
const deadline = Date.now() + 60 * 60 * 1000;
let task;
while (true) {
const { data, headers: resHeaders } = await axios.get(
`https://api.meshy.ai/openapi/v1/image-to-3d/${taskId}`,
{ headers, timeout: 30_000 },
);
task = data;
if (['SUCCEEDED', 'FAILED', 'CANCELED'].includes(task.status)) break;
if (Date.now() > deadline) {
// The task is still running. Check it again later with the same task ID instead of creating a new one.
throw new Error(`Task ${taskId} is still ${task.status}; check it again later`);
}
const waitSeconds = Number(resHeaders['retry-after']) || 5;
await new Promise((resolve) => setTimeout(resolve, waitSeconds * 1000));
}
// 3. Download the result (only if the task succeeded)
if (task.status !== 'SUCCEEDED') {
throw new Error(`Task ${task.status}: ${task.task_error?.message || 'unknown error'}`);
}
const { data: model } = await axios.get(task.model_urls.glb, { responseType: 'arraybuffer' });
fs.writeFileSync('model.glb', model);
console.log('Saved model.glb');
Explore common workflows
Game-ready character
Rig a humanoid mesh with a skeleton so it's ready to animate in Unity or Unreal.
Learn more →Smart Topology mesh
Set model_type to smart-topology on Image to 3D for a clean, game-ready triangle mesh.
3D print model
Convert a finished model into a multi-color 3MF file, ready to slice and print.
Learn more →Next steps
- Browse every endpoint in the API reference.
- Before you go to production, check Pricing, Rate limits, and Errors.
- Follow step-by-step recipes in the Cookbook.