# Meshy API > Meshy is an AI-powered 3D model generation platform. The Meshy API is a RESTful API that allows you to programmatically generate 3D models, textures, images, rig characters, and animate them. - API Base URL: `https://api.meshy.ai/openapi/` - Documentation: https://docs.meshy.ai - Status Page: https://status.meshy.ai > **For agents:** For single-fetch full content (all docs pages concatenated), see https://docs.meshy.ai/llms-full.txt. For tool-calling access, install the Meshy MCP server — see https://docs.meshy.ai/api/ai. ## Instructions for Large Language Models When generating code that integrates with the Meshy API, follow these guidelines: ### 1. Authentication All requests require a Bearer token in the `Authorization` header: ``` Authorization: Bearer msy_YOUR_API_KEY ``` API keys are created at https://www.meshy.ai/settings/api and have the format `msy_`. **Tip:** For tool-calling access from MCP-compatible agents (Claude Code, Cursor, Windsurf, Claude Desktop, Codex CLI, etc.), install the Meshy MCP server instead of calling this REST API directly: ``` claude mcp add meshy --env MESHY_API_KEY=msy_YOUR_API_KEY -- npx -y @meshy-ai/meshy-mcp-server ``` See https://docs.meshy.ai/api/ai for the full install matrix (8 clients) and tool reference. ### 2. Asynchronous Task Model Meshy uses an asynchronous execution model. All generation endpoints return a task ID, not the result directly. You retrieve results via one of three mechanisms: - **Polling** — GET the task endpoint until `status` is terminal (shown in the examples below) - **SSE streaming** — connect to `//:id/stream` for real-time updates (see section 3) - **Webhooks** — register a URL to receive a POST when the task completes (see https://docs.meshy.ai/api/webhooks.md) **Correct pattern:** ```python import requests, time, os headers = {"Authorization": f"Bearer {os.environ['MESHY_API_KEY']}"} # Step 1: Create a task response = requests.post( "https://api.meshy.ai/openapi/v2/text-to-3d", headers=headers, json={"mode": "preview", "prompt": "a monster mask"}, ) task_id = response.json()["result"] # Step 2: Poll until completion while True: task = requests.get( f"https://api.meshy.ai/openapi/v2/text-to-3d/{task_id}", headers=headers, ).json() if task["status"] == "SUCCEEDED": break if task["status"] == "FAILED": raise Exception(task["task_error"]["message"]) time.sleep(5) # Step 3: Download result model_url = task["model_urls"]["glb"] ``` **WRONG pattern** (expecting synchronous result): ```python # WRONG - the POST does not return a model response = requests.post("https://api.meshy.ai/openapi/v2/text-to-3d", ...) model = response.json()["model_urls"] # WRONG ``` ### 3. SSE Streaming (Alternative to Polling) All task endpoints support Server-Sent Events streaming at `//:id/stream`: ```python import requests, json headers = { "Authorization": f"Bearer {API_KEY}", "Accept": "text/event-stream" } response = requests.get( f"https://api.meshy.ai/openapi/v2/text-to-3d/{task_id}/stream", headers=headers, stream=True ) for line in response.iter_lines(): if line and line.startswith(b"data:"): data = json.loads(line.decode("utf-8")[5:]) print(data["status"], data.get("progress")) if data["status"] in ["SUCCEEDED", "FAILED", "CANCELED"]: break response.close() ``` ### 4. Task Statuses All tasks follow the same lifecycle: `PENDING` -> `IN_PROGRESS` -> `SUCCEEDED` | `FAILED` | `CANCELED` ### 5. Timestamps All timestamps in the API are Unix epoch milliseconds (not seconds). For example, `1693569600000` represents September 1, 2023 12:00:00 PM UTC. ### 6. Model Output Formats 3D model outputs are available in multiple formats: GLB, FBX, OBJ, USDZ. Access them via `model_urls.glb`, `model_urls.fbx`, etc. Not all formats are always available; omitted properties mean that format was not generated. ### 7. Asset Retention Generated assets are retained for a maximum of **3 days** for non-Enterprise customers. Download and store models locally if you need them longer. ### 8. Rate Limits | Tier | Requests/Second | Queue Tasks | Priority | |------|-----------------|-------------|----------| | Pro | 20 | 10 | Default | | Studio | 20 | 20 | Higher | | Enterprise | 100 | 50+ | Highest | Exceeding limits returns `429 Too Many Requests`. ### 9. Choosing the Right AI Model - Use `"latest"` or `"meshy-6"` for the best quality (default). - Use `"meshy-5"` for the previous generation model. - `"latest"` always resolves to the newest model (currently Meshy 6). ### 10. Common Mistakes to Avoid - **Don't call CORS-restricted endpoints from browser JavaScript.** The API blocks CORS requests. Use a server-side proxy. - **Don't forget `enable_pbr: true`** if you need metallic/roughness/normal maps. - **Don't set both `texture_prompt` and `texture_image_url`** — if both are provided, `texture_prompt` takes precedence. - **Don't assume model format availability.** Check that the URL key exists in `model_urls` before downloading. --- ## Complete Code Example: Text to 3D (Preview + Refine) ```python import requests, os, time headers = {"Authorization": f"Bearer {os.environ['MESHY_API_KEY']}"} # 1. Create preview task preview_resp = requests.post( "https://api.meshy.ai/openapi/v2/text-to-3d", headers=headers, json={ "mode": "preview", "prompt": "a monster mask", "should_remesh": True, }, ) preview_resp.raise_for_status() preview_task_id = preview_resp.json()["result"] # 2. Poll preview task while True: task = requests.get( f"https://api.meshy.ai/openapi/v2/text-to-3d/{preview_task_id}", headers=headers, ).json() if task["status"] == "SUCCEEDED": break if task["status"] == "FAILED": raise Exception(task["task_error"]["message"]) time.sleep(5) # 3. Download preview model with open("preview_model.glb", "wb") as f: f.write(requests.get(task["model_urls"]["glb"]).content) # 4. Create refine task (texturing) refine_resp = requests.post( "https://api.meshy.ai/openapi/v2/text-to-3d", headers=headers, json={ "mode": "refine", "preview_task_id": preview_task_id, "enable_pbr": True, }, ) refine_resp.raise_for_status() refine_task_id = refine_resp.json()["result"] # 5. Poll refine task while True: task = requests.get( f"https://api.meshy.ai/openapi/v2/text-to-3d/{refine_task_id}", headers=headers, ).json() if task["status"] == "SUCCEEDED": break if task["status"] == "FAILED": raise Exception(task["task_error"]["message"]) time.sleep(5) # 6. Download refined (textured) model with open("refined_model.glb", "wb") as f: f.write(requests.get(task["model_urls"]["glb"]).content) ``` ## Complete Code Example: Image to 3D ```python import requests, os, time headers = {"Authorization": f"Bearer {os.environ['MESHY_API_KEY']}"} response = requests.post( "https://api.meshy.ai/openapi/v1/image-to-3d", headers=headers, json={ "image_url": "https://example.com/photo.jpg", "should_texture": True, "enable_pbr": True, }, ) response.raise_for_status() task_id = response.json()["result"] while True: task = requests.get( f"https://api.meshy.ai/openapi/v1/image-to-3d/{task_id}", headers=headers, ).json() if task["status"] == "SUCCEEDED": break if task["status"] == "FAILED": raise Exception(task["task_error"]["message"]) time.sleep(5) with open("model.glb", "wb") as f: f.write(requests.get(task["model_urls"]["glb"]).content) ``` --- --- # API Reference # Quickstart Source: https://docs.meshy.ai/api/quick-start # Quickstart This is the API reference for programmatically interacting with Meshy. > **Note:** **Using an AI coding assistant?** See our [AI Integration](/api/ai) page — install the Meshy MCP server for tool-calling access from Claude Code, Cursor, Windsurf, and other MCP-compatible tools, or point a plain chat agent at [`llms.txt`](/llms.txt). --- The Meshy API provides a simple interface to generate 3D models and textures from text prompts and images. Follow this guide to get started quickly. ## Create an API Key [Create an API key in the API settings page here](https://www.meshy.ai/settings/api), which you'll use to securely [authenticate your requests](/api/authentication). The API key's format is `msy-`. ![Generate API Key](https://cdn.meshy.ai/docs-assets/api/quick-start/generate-api-key.webp) Once you've generated an API key, store it somewhere in a secure location. ### Test Mode API Key During development and testing, you can use our test mode API key to explore the API without consuming your credits: ```javascript msy_dummy_api_key_for_test_mode_12345678 ``` This special API key has the following characteristics: - It can be used to make requests to all Meshy API endpoints - No credits are consumed when using this key - All valid requests will return the same sample task results, regardless of the input parameters - The response data structure will match the production API exactly - Perfect for testing your API integration before switching to your real API key > **Note:** The test mode API key is for development purposes only. For production use, please use your own API key. ## Make Your First "Text to 3D" API Request In this example, we will generate a 3D model from a text prompt using the [`text-to-3d` endpoint](/api/text-to-3d). The process involves two stages: the preview stage and the refine stage. In the preview stage, a base mesh is generated with no texture applied, allowing you to evaluate the geometry. In the refine stage, the preview mesh is textured based on the text prompt. We will show you how to make these requests in a Python script. ### Preview Meshy provides a set of REST API endpoints. You can use them with any HTTP client of your choice. Regardless of which API you call, the API key is always passed as a header named `Authorization`. Please remember to export your API key as an environment variable named `MESHY_API_KEY` before using this script. The key parameters to the preview request are `mode`, which is always `"preview"`, and `prompt`, a description of the model you need. In this example, we have also specified `should_remesh`, but it is optional. **api_request.py** ```python import requests import os import time headers = { "Authorization": f"Bearer {os.environ['MESHY_API_KEY']}" } # 1. Generate a preview model and get the task ID generate_preview_request = { "mode": "preview", "prompt": "a monster mask", "should_remesh": True, } generate_preview_response = requests.post( "https://api.meshy.ai/openapi/v2/text-to-3d", headers=headers, json=generate_preview_request, ) generate_preview_response.raise_for_status() preview_task_id = generate_preview_response.json()["result"] print("Preview task created. Task ID:", preview_task_id) ``` This completes the preview API call. Please bear in mind that Meshy API adopts an asynchronous execution model, meaning that when you create a task, the API endpoint only returns a task ID. You must then poll the task status endpoint with this ID to check if the task has finished. **api_request.py** ```python # 2. Poll the preview task status until it's finished preview_task = None while True: preview_task_response = requests.get( f"https://api.meshy.ai/openapi/v2/text-to-3d/{preview_task_id}", headers=headers, ) preview_task_response.raise_for_status() preview_task = preview_task_response.json() if preview_task["status"] == "SUCCEEDED": print("Preview task finished.") break print("Preview task status:", preview_task["status"], "| Progress:", preview_task["progress"], "| Retrying in 5 seconds...") time.sleep(5) ``` Once the task has finished, you will be able to access the model URLs from its response. Let's download the model from the `model_urls` field in the response. **api_request.py** ```python # 3. Download the preview model in glb format preview_model_url = preview_task["model_urls"]["glb"] preview_model_response = requests.get(preview_model_url) preview_model_response.raise_for_status() with open("preview_model.glb", "wb") as f: f.write(preview_model_response.content) print("Preview model downloaded.") ``` If everything works out so far, your `preview_model.glb` should look similar to this. It will not be an exact match, due to the intrinsic randomness in the AI pipeline. ![Preview model](https://cdn.meshy.ai/docs-assets/api/quick-start/preview-model.webp) ### Refine Let's proceed to the refine stage. To initiate the refine request, provide the preview task ID as an input parameter. **api_request.py** ```python # 4. Generate a refined model and get the task ID generate_refined_request = { "mode": "refine", "preview_task_id": preview_task_id, } generate_refined_response = requests.post( "https://api.meshy.ai/openapi/v2/text-to-3d", headers=headers, json=generate_refined_request, ) generate_refined_response.raise_for_status() refined_task_id = generate_refined_response.json()["result"] print("Refined task created. Task ID:", refined_task_id) # 5. Poll the refined task status until it's finished refined_task = None while True: refined_task_response = requests.get( f"https://api.meshy.ai/openapi/v2/text-to-3d/{refined_task_id}", headers=headers, ) refined_task_response.raise_for_status() refined_task = refined_task_response.json() if refined_task["status"] == "SUCCEEDED": print("Refined task finished.") break print("Refined task status:", refined_task["status"], "| Progress:", refined_task["progress"], "| Retrying in 5 seconds...") time.sleep(5) # 6. Download the refined model in glb format refined_model_url = refined_task["model_urls"]["glb"] refined_model_response = requests.get(refined_model_url) refined_model_response.raise_for_status() with open("refined_model.glb", "wb") as f: f.write(refined_model_response.content) print("Refined model downloaded.") ``` The 3D model `refined_model.glb` is now fully textured ✨. ![Refined model](https://cdn.meshy.ai/docs-assets/api/quick-start/refined-model.webp) ### Put It Together Here is the complete code for using the Text to 3D API. **api_request.py** ```python import requests import os import time headers = { "Authorization": f"Bearer {os.environ['MESHY_API_KEY']}" } # 1. Generate a preview model and get the task ID generate_preview_request = { "mode": "preview", "prompt": "a monster mask", "should_remesh": True, } generate_preview_response = requests.post( "https://api.meshy.ai/openapi/v2/text-to-3d", headers=headers, json=generate_preview_request, ) generate_preview_response.raise_for_status() preview_task_id = generate_preview_response.json()["result"] print("Preview task created. Task ID:", preview_task_id) # 2. Poll the preview task status until it's finished preview_task = None while True: preview_task_response = requests.get( f"https://api.meshy.ai/openapi/v2/text-to-3d/{preview_task_id}", headers=headers, ) preview_task_response.raise_for_status() preview_task = preview_task_response.json() if preview_task["status"] == "SUCCEEDED": print("Preview task finished.") break print("Preview task status:", preview_task["status"], "| Progress:", preview_task["progress"], "| Retrying in 5 seconds...") time.sleep(5) # 3. Download the preview model in glb format preview_model_url = preview_task["model_urls"]["glb"] preview_model_response = requests.get(preview_model_url) preview_model_response.raise_for_status() with open("preview_model.glb", "wb") as f: f.write(preview_model_response.content) print("Preview model downloaded.") # 4. Generate a refined model and get the task ID generate_refined_request = { "mode": "refine", "preview_task_id": preview_task_id, } generate_refined_response = requests.post( "https://api.meshy.ai/openapi/v2/text-to-3d", headers=headers, json=generate_refined_request, ) generate_refined_response.raise_for_status() refined_task_id = generate_refined_response.json()["result"] print("Refined task created. Task ID:", refined_task_id) # 5. Poll the refined task status until it's finished refined_task = None while True: refined_task_response = requests.get( f"https://api.meshy.ai/openapi/v2/text-to-3d/{refined_task_id}", headers=headers, ) refined_task_response.raise_for_status() refined_task = refined_task_response.json() if refined_task["status"] == "SUCCEEDED": print("Refined task finished.") break print("Refined task status:", refined_task["status"], "| Progress:", refined_task["progress"], "| Retrying in 5 seconds...") time.sleep(5) # 6. Download the refined model in glb format refined_model_url = refined_task["model_urls"]["glb"] refined_model_response = requests.get(refined_model_url) refined_model_response.raise_for_status() with open("refined_model.glb", "wb") as f: f.write(refined_model_response.content) print("Refined model downloaded.") ``` Copy and paste the code into a Python script and run it. **Run the script** ```bash python api_request.py ``` You should see output in your terminal like the following: ![Run the script](https://cdn.meshy.ai/docs-assets/api/quick-start/run-script.webp) ## Next Steps - You can find the complete API reference in the "API Endpoints" section, which provides detailed information about each API. - Explore details about [Pricing](/api/pricing), [Rate Limits](/api/rate-limits), and how to troubleshoot [common errors](/api/errors). - Don't forget to check out our [Changelog](/api/changelog) regularly for updates and bug fixes. - Have feedback or facing issues? Join our [Discord](https://discord.com/invite/KgD5yVM9Y4) community - we'd love to hear from you! --- # Authentication Source: https://docs.meshy.ai/api/authentication # Authentication Using the Meshy API requires authentication. This guide will show you how to create an account and API keys. --- ## API Keys ### Creating a Meshy Account Meshy API requires you to have a Meshy account to create and manage API keys. If a request is made to the API without an API key, the API will respond with an invalid credentials error. You can create a Meshy account by visiting the [Meshy official website](https://www.meshy.ai/) and sign up. ### Creating API Keys Once you have created a Meshy account, you can create API keys by visiting the [API settings page](https://www.meshy.ai/settings/api). You can create multiple API keys for different purposes. For example, you can create one API key for your iOS app and another for your web app. The usage of each API key is tracked separately, and you can revoke them at any time. To create an API key, click on the `Create API Key` button on the API page, and then enter a name for your API key. Once you have created an API key, you will be shown the API key value. You can copy the API key value and store it in a secure location. **You will not be able to see this API key value again.** ### Using API Keys Once you have created an API key, you can use it to authenticate your requests to the Meshy API. You can pass your API key to the API in the `Authorization` header, an example header is shown below. ```json { "Authorization": "Bearer msy_sOmEbOgUsApIkEyFoReXaMpLe1234567890" } ``` > **Note:** The `Bearer `   prefix in the header value is mandatory to interact with the Meshy API programatically. > You can learn more about it at [IETF RFC 6750](https://datatracker.ietf.org/doc/html/rfc6750) --- ## Security We take security very seriously at Meshy, and we work hard to ensure that Meshy API is secure. We hope your data and your users' data is safe with us. Here are some high-level guidelines to help you keep your data and requests safe when using Meshy API, but please also make sure to follow the guidelines practiced at your team or workplace. ### Transport Layer Security While your data is encrypted at rest once it's stored in Meshy, Meshy API uses and enforces [TLS](https://en.wikipedia.org/wiki/Transport_Layer_Security), to encrypt data in transit. It means that all requests to and from Meshy API are sent over HTTPS, and any request made over HTTP will get an `301 Moved Permanently` status code. Although not recommended, in some cases, if you have to talk to HTTP, you need to explicity tell your HTTP client to follow HTTP to HTTPS redirections. Here are some examples: ```bash # use `-L` to follow HTTP to HTTPS redirections curl -L -X 'POST' \ https://api.meshy.ai/openapi/v1/text-to-texture ``` ```python import requests # use `allow_redirects=True` to follow HTTP to HTTPS redirections response = requests.post("https://api.meshy.ai/openapi/v1/text-to-texture", allow_redirects=True) ``` ```javascript // use `followRedirects: true` to follow HTTP to HTTPS redirections const response = await fetch("https://api.meshy.ai/openapi/v1/text-to-texture", { redirect: "follow", }); ``` ### API Key Safety > **Note:** Please note that even Meshy team members cannot view or recover revoked API keys for you! Once minted, API keys are **not** visible in the dashboard anymore, so please download and keep it safe and securely since anyone who obtains it can use it to talk to Meshy API on your behalf. If you believe your API key has been compromised, you can revoke it at any time from the dashboard, once revoked, it will no longer be valid. ### Security Disclosure If you believe you've discovered a security issue in Meshy API, please [get in touch](mailto:support@meshy.ai?subject=%5BSupport%5D%20Enter%20your%20question%20or%20problem%E2%80%A6&body=How%20can%20we%20assist%20you%3F%20Please%20provide%20any%20relevant%20details%20that%20will%20help%20us%20respond%20to%20your%20inquiry.) with us. We appreciate your responsible disclosure and will make every effort to acknowledge your contributions. --- # Errors Source: https://docs.meshy.ai/api/errors # Errors In this guide, we will talk about what happens when something goes wrong while you work with the Meshy API. --- ## Request Errors These errors are returned immediately when your API request is rejected. Check the HTTP status code and `message` field to understand what went wrong. ### Response Format The error response contains a single `message` field describing what went wrong: - `message` · *string* A short description of the error. ### Status Codes - `2xx` A 2xx status code indicates a successful response. - `200 - OK` By default if everything worked as expected a 200 status code will be returned. - `202 - Accepted` Your request has been accepted for processing, but the processing has not been completed. This is a non-committal response from Meshy API. For example, a request to create a new task will return a 202 status code. - `4xx` A 4xx status code indicates a client error. - `400 - Bad Request` The request was unacceptable, often due to missing a mandatory parameter or one of the parameters was malformed. - `401 - Unauthorized` No valid API key provided or the API key provided is not authorized to access the Meshy API endpoint. - `402 - Payment Required` Insufficient funds in the account associated with the provided API key. - `403 - Forbidden` Access to the requested resource is forbidden. This might happen if you try to access the Meshy API directly from client-side JavaScript code, as Cross-Origin Resource Sharing (CORS) requests from browsers are not permitted. Consider using a server-side proxy for such requests. For more details, see the [MDN CORS guide](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS/Errors). - `404 - Not Found` The requested resource doesn't exist. For example, when you try to retrieve a task by its ID but provided an invalid ID, you will get a 404 status code. - `429 - Too Many Requests` Too many requests hit the Meshy API too quickly. Please refer to the [Rate Limits](/api/rate-limits) guide for details. - `5xx` A 5xx status code indicates a server error. If you see one, please check our [status page](https://status.meshy.ai) for more information and contact us via [Discord](https://discord.com/invite/KgD5yVM9Y4) for help. **Example: 400 Bad Request** ```bash { "message": "Invalid model file extension: .3dm" } ``` --- ## Task Errors These errors occur after a task has been created and is processing. Check the `task_error` object on the task response for error details. The `task_error` object contains the following fields: - `type` · *string* The error category. Always present on failed tasks. See [Error Types](#error-types) below. - `message` · *string* A human-readable description of the error. Always present on failed tasks. - `code` · *string* A specific error code identifying the problem. Present when additional details are available. See [Error Codes](#error-codes) below. - `doc_url` · *string* A link to detailed documentation for this error code, including resolution guidance. Present when `code` is present. **Error with details** ```json { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "status": "FAILED", "task_error": { "type": "invalid_input", "code": "image_too_complex", "message": "The uploaded image is too complex for 3D generation.", "doc_url": "https://docs.meshy.ai/en/api/errors#image-too-complex" } } ``` **Error without details** ```json { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "status": "FAILED", "task_error": { "type": "server_error", "message": "An internal error occurred. Please retry." } } ``` --- ## Error Types The `type` field tells you the broad category of the failure. Use it to decide your retry strategy. - `invalid_input` Something is wrong with the input you provided. Check the `code` and `message` fields for specifics, fix the issue, and retry. - `timeout` Processing exceeded the time limit. This is often transient. Retry the request, and if it keeps failing, try simplifying your input. - `service_unavailable` The service is temporarily unavailable. Wait a moment and retry. - `server_error` An internal error occurred during processing. Retry the request. If the issue persists, contact support with your task ID. --- ## Error Codes When the `code` field is present, it identifies a specific, actionable problem. Below is the full reference for each error code. ### `image_too_complex` This error occurs when the input image or prompt describes a subject that is too geometrically complex for the 3D generation model to process. Common examples include: - **Dense piles of small objects** (e.g., a crate full of fruit, a stack of books) - **Intricate repeating patterns** (e.g., lattice structures, scaffolding, wire meshes) - **Complex building structures** (e.g., multi-story buildings with many windows and balconies) - **Multiple distinct objects in one image** instead of a single subject **Examples of inputs that are likely too complex:**
A crate of mixed berries An intricate cathedral ceiling A building under construction with scaffolding A honeycomb lattice sphere
**Resolution:** 1. **Use a single object per image.** The model works best with one clear subject. Don't include multiple separate objects in the same image or prompt. 2. **Simplify your subject.** Reduce the level of detail. For example, a simple vase instead of a vase filled with dozens of flowers. 3. **Avoid scene-level prompts.** Entire buildings, city blocks, interiors filled with furniture, or landscapes are likely to exceed the model's capacity. Focus on a single object instead. 4. **Avoid dense repeating structures.** Subjects like scaffolding, wire meshes, lattice patterns, or piles of many small items are common triggers. ### `model_missing_uv` This error occurs when you upload a model for texturing with `enable_original_uv` set to `true`, but the model has no UV coordinates. UV coordinates define how a 2D texture wraps onto the 3D surface of your model. ![No UVs vs Good UVs](/images/errors/uv_missing_vs_good.png) **Resolution:** The right fix depends on why you set `enable_original_uv` to `true`: - **If you need to preserve your model's original UV layout** (e.g., custom seam placement for precise texture mapping): your model must have valid UV coordinates. Verify UVs exist in your 3D software's UV editor before uploading. Note that STL files cannot store UV data, so use GLB, FBX, or OBJ instead. - **If you don't need specific UV control** (or you're not sure): omit `enable_original_uv` or set it to `false`. The system will automatically generate a UV layout for your model. The auto-generated UVs are optimized for coverage but you won't have control over where texture seams are placed. ### `model_insufficient_uv` This error occurs when a model has UV coordinates, but the UV coverage is too small for quality texturing. This commonly happens with models exported from 3D tools that generate placeholder or collapsed UVs without a proper unwrap. ![Insufficient UVs vs Good UVs](/images/errors/uv_insufficient_vs_good.png) **Resolution:** - **If you need to preserve your original UV layout:** re-unwrap the model's UVs in your 3D software. Ensure UV islands are properly spread across the UV space rather than collapsed into a small area. - **If you don't need specific UV control:** omit `enable_original_uv` or set it to `false`. The system will automatically generate a new UV layout. The tradeoff is you lose your original seam placement, but the auto-generated UVs will have proper coverage for texturing. ### `invalid_input` This is the fallback error code when the input fails validation but no more specific code applies. The `message` field contains the specific reason for the failure. Common causes include: - Empty or corrupted model files - Unsupported file format variations (e.g., ASCII FBX files, meshopt-compressed GLB) - No valid 3D objects found in the uploaded model (e.g., file contains only armatures, cameras, or lights) - Content that does not pass safety filters **Resolution:** Check the `message` field for specifics on what went wrong. Verify your input files and parameters match the endpoint's requirements. ### `moderation_blocked` This error occurs when your prompt or reference images are rejected by AI safety filters. The filter evaluates both the text prompt and any reference images together. **Resolution:** - Rephrase your text prompt to remove suggestive or sensitive descriptions. - Adjust reference images if they depict content that may trigger safety filters. ### `timeout` This error means your task's processing time exceeded the allowed limit. This can happen due to high system load or because the input is too complex to process within the time limit. **Resolution:** 1. **Retry the request.** Timeouts are often transient and a retry may succeed. 2. **Simplify your input.** If retries keep failing, your input may be too complex. Try reducing the level of detail in your image or prompt. See [`image_too_complex`](#image-too-complex) for guidance on what types of inputs are harder to process. ### `format_conversion_failed` This error occurs when the generated 3D model could not be converted to your requested output format. The model was generated successfully, but the conversion step failed. **Resolution:** 1. **Retry the request.** 2. **Try a different output format.** If a specific format keeps failing, switch to another format that suits your needs. --- ## Best Practices 1. **Implement retry logic.** For `timeout` and `service_unavailable` errors, implement exponential backoff retry logic. 2. **Log task IDs.** Always log the task ID for debugging purposes. Include it when contacting support. 3. **Validate inputs.** Ensure your input images and models meet the format requirements before submission. --- # Pricing Source: https://docs.meshy.ai/api/pricing # Pricing Simple and flexible pricing. --- Meshy API for generation is a pay-before-you-go product. You need to purchase API usage based on your application's need before using Meshy API. You can purchase API usage from the [API settings page](https://www.meshy.ai/settings/api). For volume API pricing and custom contracts, please [contact sales](https://share.hsforms.com/1MiMAkL-dSVejYLqOA4V10grx1uq). The Meshy API pricing is based on credits. Here's a detailed breakdown of the API pricing: | API | Price per call | | --- | --- | | Text to 3D (Preview) - Mesh Generation | Meshy-6 models and low poly models: 20 credits
Other models: 5 credits | | Text to 3D (Refine) - Texture Generation | 10 credits (texture generation) | | Image to 3D | Meshy-6 models and low poly models: 20 credits (without texture), 30 credits (with texture)
Other models: 5 credits (without texture), 15 credits (with texture) | | Multi Image to 3D | Meshy-6 models: 20 credits (without texture), 30 credits (with texture)
Other models: 5 credits (without texture), 15 credits (with texture) | | Retexture | 10 credits (texture generation) | | Remesh | 5 credits | | Convert | 1 credit | | Resize | 1 credit | | Auto-Rigging | 5 credits | | Animation | 3 credits | | Text to Image | nano-banana: 3 credits, nano-banana-2: 6 credits, nano-banana-pro: 9 credits, gpt-image-2: 9 credits | | Image to Image | nano-banana: 3 credits, nano-banana-2: 6 credits, nano-banana-pro: 9 credits, gpt-image-2: 12 credits | | 3D Print (Multi-Color) | 10 credits | | 3D Print (Analyze Printability) | Free | | 3D Print (Repair Printability) | 10 credits | | Creative Lab — Keychain (Prototype) | 6 credits | | Creative Lab — Keychain (Build) | 30 credits | | Creative Lab — Fridge Magnet (Prototype) | 6 credits | | Creative Lab — Fridge Magnet (Build) | 30 credits | | Creative Lab — Figure (Prototype) | 6 credits | | Creative Lab — Figure (Build) | 30 credits | | Creative Lab — Lamp (Prototype) | 6 credits | | Creative Lab — Lamp (Build) | 30 credits | The API is subject to change in the future. If you need more API usage with a lower price, please [contact sales by filling out this form](https://www.meshy.ai/contact). --- # Rate Limits Source: https://docs.meshy.ai/api/rate-limits # Rate Limits Rate limits are restrictions that our API imposes on the number of times a user or client can access our services within a specified period of time. --- ## Why Limits We've put rate limits in place on our API to help create the best experience for everyone. Here's why they're important: - To keep our service safe and sound! Think of rate limits as friendly bouncers - they make sure nobody can overwhelm our API with too many requests at once. This helps protect our service from potential misuse and keeps everything running smoothly. - To make sure everyone gets their fair share. Just like sharing toys in a playground, we want to make sure all our users have equal access to the API. By gently limiting how many requests each user can make, we ensure nobody has to wait too long for their turn. - To keep performance zippy and reliable. By managing the overall flow of requests, we can maintain fast response times and stable service for all our wonderful users. It's like making sure a highway doesn't get too crowded - traffic flows better when we prevent congestion! --- ## How Limits Work Rate limits are measured in 2 ways: - **Requests per Second**: This is the number of network requests your can make per second. - **Queue Tasks**: This is the number of concurrent generation tasks your can run in queue at any given time. Queue tasks include Text to 3D, Image to 3D, Text to Texture, and Remesh endpoints. Other endpoints like Upload and Balance are not included in this limit. The limits are applied on a per-account basis. This means that the limits are shared across all of your API keys. Besides rate limits, task processing priority will also affect the speed of your tasks. Each user tier has specific rate limits and priority levels designed to match their needs. Here are the current limits by tier: | User Tier | Requests per Second | Queue Tasks | Priority Level | | --- | --- | --- | --- | | Pro | 20 | 10 | Default | | Studio | 20 | 20 | Higher than Pro | | Enterprise | 100 | Default to 50, can be customized | Highest | If you exceed these limits, you'll receive a `429 Too Many Requests` response from our API. There are two types of hits that can trigger this, each with a different response: - **Request Hit**: This happens when you make too many requests per second. You'll receive a `429 Too Many Requests` response with a `RateLimitExceeded` message. - **Queue Hit**: This happens when you have too many concurrent generation tasks running. You'll receive a `429 Too Many Requests` response with a `NoMoreConcurrentTasks` message. --- # Asset Retention Source: https://docs.meshy.ai/api/asset-retention # Asset Retention Asset Retention is the amount of time that Meshy retains your generated assets. --- Please note that any models generated through our API will only be retained for a maximum of **3 days**. After this period, the models will be automatically deleted from our servers. If you're not an Enterprise customer, we kindly ask for your understanding and recommend downloading and storing your models locally if you need them for a longer duration. Enterprise customers can retain their models indefinitely. --- # Webhooks Source: https://docs.meshy.ai/api/webhooks # Webhooks Webhooks allow you to receive real-time updates from Meshy when your API tasks are completed or change status. Once configured, Meshy will POST event payloads in json format to the URLs you specify. --- ## Why Create Webhooks Using webhooks has several advantages, especially with regards to checking on API task statuses automatically. Webhooks require less effort and costs than continuously polling the API to get task status updates. Webhooks also allow near real-time updates and ultimately scale better than API polling. This also enables you to better manage your rate limits, especially if you are polling constantly. --- ## Setup & Configuration To enable webhooks, navigate to the API settings page when logged in to the Meshy web application. Find the "Webhooks" section below your API Keys and click the "Create Webhook" button. Provide your desired https URL to receive webhooks from and enable the webhook to automatically receive task updates from Meshy. You may have a maximum of 5 active webhooks per Meshy account. When a webhook is enabled, all API task status updates will be automatically sent to the payload URL. For security purposes, we only allow sending webhooks to https URLs at this time. If you would like to configure local testing, see the following section. --- ## Webhook Delivery Requirements For your webhook to function normally and continue receiving events: - Your server must respond with an **HTTP status code below 400** (e.g., `200 OK`, `202 Accepted`). - Any response with a status code `>= 400` will be treated as a failed delivery. - Multiple consecutive failures may: - Cause progress updates to be delayed or arrive out of order - Automatically disable your webhook after repeated attempts (see Auto-Disable Policy) **Tip:** Always return a success response after you validate and store the webhook payload, even if further processing happens asynchronously. --- ## Forwarding Webhooks for Local Testing If you would like to test your webhook code locally, which typically is at an http address, you can use a webhook proxy URL to forward webhooks to your computer or codespace. The below are recommended steps using smee.io, but you may use any service you'd like to generate a webhook proxy URL. ### Get a webhook proxy URL: 1. In your browser, navigate to https://smee.io/ 2. Click "Start a new channel" 3. Copy the full URL under "Webhook Proxy URL". You will use this URL in the following setup steps. ### Forward webhooks: 1. If you don't already have smee-client installed, run the following command in your terminal. ```text npm install --global smee-client ``` 2. To receive forwarded webhooks from smee.io, run the following command in your terminal. Replace `WEBHOOK_PROXY_URL` with your webhook proxy URL from earlier. ```text smee --url WEBHOOK_PROXY_URL --path /webhook --port 3000 ``` You should see output that looks like this, where `WEBHOOK_PROXY_URL` is your webhook proxy URL: ```text Forwarding WEBHOOK_PROXY_URL to http://127.0.0.1:3000/webhook Connected WEBHOOK_PROXY_URL ``` 3. Keep this running while you test out your webhook. When you want to stop forwarding webhooks, enter Ctrl+C. Note that the path is /webhook and the port is 3000. These values may come in handy when you want to set up your own code to receive webhook deliveries later on. ### Create a webhook: You may now use the webhook proxy URL to create a new webhook in the Meshy API settings page. --- ## Sample Response When a task status changes, Meshy will POST a webhook payload to your configured URL. The payload contains the task object in JSON format. For a complete description of all task object properties and example payloads, see: - [Text to 3D Task Object](/api/text-to-3d#example-text-to-3d-task-object) - [Image to 3D Task Object](/api/image-to-3d#example-image-to-3d-task-object) - [Multi-Image to 3D Task Object](/api/multi-image-to-3d#example-multi-image-to-3d-task-object) - [Remesh Task Object](/api/remesh#example-remesh-task-object) - [Retexture Task Object](/api/retexture#example-retexture-task-object) - [Rigging Task Object](/api/rigging#example-rigging-task-object) - [Animation Task Object](/api/animation#example-animation-task-object) --- # AI Integration Source: https://docs.meshy.ai/api/ai # AI Integration Meshy exposes two channels for AI agents and coding assistants: the Meshy MCP server for tool-calling, and `llms.txt` / `llms-full.txt` for docs ingestion. If you are integrating Meshy from Claude Code, Cursor, Windsurf, Codex, or any other MCP-compatible tool, install the MCP server below. If you are integrating from a plain chat agent with no MCP support, point it at [`https://docs.meshy.ai/llms.txt`](/llms.txt) instead. --- ## What is MCP The [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) is an open standard that lets AI assistants call external tools and retrieve structured context. The Meshy MCP server wraps the Meshy REST API as a set of tools your agent can invoke — generate a model, check a task, download the result — without hand-writing HTTP code. The MCP server is open source and published on npm as [`@meshy-ai/meshy-mcp-server`](https://www.npmjs.com/package/@meshy-ai/meshy-mcp-server). Source: [github.com/meshy-dev/meshy-mcp-server](https://github.com/meshy-dev/meshy-mcp-server). > **Note:** You need a Meshy API key. Create one at [https://www.meshy.ai/settings/api](https://www.meshy.ai/settings/api). The MCP server reads it from the `MESHY_API_KEY` environment variable. --- ## Quick Install **add-mcp** ```bash # Detects installed AI clients and configures Meshy for each npx add-mcp @meshy-ai/meshy-mcp-server --env MESHY_API_KEY=msy_YOUR_API_KEY ``` **Claude Code** ```bash # macOS / Linux / WSL claude mcp add meshy --env MESHY_API_KEY=msy_YOUR_API_KEY -- npx -y @meshy-ai/meshy-mcp-server # Windows PowerShell — use add-json to avoid `--` parsing issues claude mcp add-json meshy '{"command":"npx","args":["-y","@meshy-ai/meshy-mcp-server"],"env":{"MESHY_API_KEY":"msy_YOUR_API_KEY"}}' ``` **Cursor** ```json // .cursor/mcp.json { "mcpServers": { "meshy": { "command": "npx", "args": ["-y", "@meshy-ai/meshy-mcp-server"], "env": { "MESHY_API_KEY": "msy_YOUR_API_KEY" } } } } ``` **Windsurf** ```json // ~/.codeium/windsurf/mcp_config.json { "mcpServers": { "meshy": { "command": "npx", "args": ["-y", "@meshy-ai/meshy-mcp-server"], "env": { "MESHY_API_KEY": "msy_YOUR_API_KEY" } } } } ``` **Claude Desktop** ```json // ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) // %APPDATA%\Claude\claude_desktop_config.json (Windows) { "mcpServers": { "meshy": { "command": "npx", "args": ["-y", "@meshy-ai/meshy-mcp-server"], "env": { "MESHY_API_KEY": "msy_YOUR_API_KEY" } } } } ``` **Codex** ```bash codex mcp add meshy --env MESHY_API_KEY=msy_YOUR_API_KEY -- npx -y @meshy-ai/meshy-mcp-server ``` **VS Code** ```json // .vscode/mcp.json (workspace) or User settings > MCP Servers { "servers": { "meshy": { "command": "npx", "args": ["-y", "@meshy-ai/meshy-mcp-server"], "env": { "MESHY_API_KEY": "msy_YOUR_API_KEY" } } } } ``` **Other** ```json // Generic stdio MCP config. Consult your client's docs for the exact file. { "mcpServers": { "meshy": { "command": "npx", "args": ["-y", "@meshy-ai/meshy-mcp-server"], "env": { "MESHY_API_KEY": "msy_YOUR_API_KEY" } } } } ``` > **Note:** **Prefer a drop-in skill instead?** The open-source [`meshy-3d-agent`](https://github.com/meshy-dev/meshy-3d-agent) skill pack ships pre-written Meshy workflows (generate → poll → download) for Claude Code, Cursor, and OpenClaw. It calls the Meshy REST API directly — no MCP server required. > > ```bash > npx skills add meshy-dev/meshy-3d-agent > ``` --- ## Available Tools The MCP server exposes the Meshy REST API as tools, grouped by capability. ### 3D Generation - `meshy_text_to_3d` — create a 3D model from a text prompt - `meshy_image_to_3d` — create a 3D model from one image - `meshy_multi_image_to_3d` — create a 3D model from multiple images of the same object - `meshy_text_to_3d_refine` — add texture to a preview mesh ### Post-Processing - `meshy_remesh` — change topology and/or polycount of an existing model - `meshy_retexture` — apply a new texture to an existing model - `meshy_rig` — add a skeleton to a 3D humanoid character - `meshy_animate` — apply an animation to a rigged character ### Image Generation - `meshy_text_to_image` — 2D image from text - `meshy_image_to_image` — 2D image from a reference image ### Task Management - `meshy_get_task_status` — check task status and download URLs - `meshy_list_tasks` — list recent tasks, optionally filtered by type/status - `meshy_cancel_task` — cancel a pending or in-progress task - `meshy_download_model` — fetch a completed model file and save locally ### Workspace - `meshy_list_models` — list all models in the authenticated user's workspace ### 3D Printing - `meshy_send_to_slicer` — detect installed slicers and launch the model in one (runs locally on your machine; no Meshy API call) - `meshy_analyze_printability` — **currently returns a manual print-readiness checklist** (wall thickness, overhangs, manifold mesh, etc.). Will be upgraded to automated analysis once the Meshy printability API is available. - `meshy_process_multicolor` — convert a textured model into a multi-color 3MF file for printing ### Account - `meshy_check_balance` — query remaining credits > **Note:** Tool names and behaviors may evolve. The authoritative list lives in the [MCP server source](https://github.com/meshy-dev/meshy-mcp-server/tree/main/src/tools). --- ## Example Prompts Drop these into your MCP-enabled chat as a starting point. ``` Generate a 3D fox from the prompt "a cartoon fox sitting", preview it, then texture it with PBR maps. Download the final GLB to ./outputs. ``` ``` Take the image at https://example.com/sculpture.jpg and convert it into a riggable 3D character. Use `should_remesh: true` and 50k target polycount. ``` ``` What's my current Meshy credit balance? ``` ``` List my last 10 successful text-to-3d tasks and download the top 3 as GLB into ./downloads/. ``` --- ## llms.txt and llms-full.txt If your agent doesn't support MCP, or you want to ingest the Meshy docs into a prompt directly, point it at our plain-text surfaces: - [`llms.txt`](/llms.txt) — compact index + integration instructions (the correct async-polling pattern, auth rules, rate limits, model choice, common mistakes). - [`llms-full.txt`](/llms-full.txt) — every API page concatenated in a single file for single-fetch ingestion. - Per-page Markdown: append `.md` to any endpoint URL. Example: [`https://docs.meshy.ai/api/text-to-3d.md`](/api/text-to-3d.md). All three are regenerated every time the docs site builds, so they never drift from the HTML docs. --- ## FAQ ### Is the MCP server stateless? Yes. Your `MESHY_API_KEY` is used per request and never persisted on the server side. ### Does MCP cost the same as the REST API? Yes — every MCP tool call maps to a single REST call and consumes credits at the exact same rate. See [Pricing](/api/pricing) for the full matrix. ### What are the rate limits? The MCP server shares the same rate-limit plane as the REST API. See [Rate Limits](/api/rate-limits) for per-tier limits. ### What Meshy data can the MCP access? Only what the `MESHY_API_KEY` can access via REST. Scopes and permissions are identical. ### How do I report issues? File an issue at [github.com/meshy-dev/meshy-mcp-server](https://github.com/meshy-dev/meshy-mcp-server/issues). --- # Changelog Source: https://docs.meshy.ai/api/changelog # Changelog See all of the latest features and updates to the Meshy API and plugins. --- ## June 2026 ### `Jun 12` - Updated **Creative Lab API** Build pricing to **30 credits** per call for [Keychain](/api/creative-lab-keychain), [Fridge Magnet](/api/creative-lab-fridge-magnet), and [Figure](/api/creative-lab-figure) (previously 20). [Lamp](/api/creative-lab-lamp) is unchanged at 30 credits. Prototype pricing is unchanged at 6 credits per image. See [Pricing](/api/pricing) for the full breakdown. ### `Jun 5` - Added the optional `alpha_thumbnail` parameter to the [Image to 3D](/api/image-to-3d), [Multi-Image to 3D](/api/multi-image-to-3d), [Text to 3D](/api/text-to-3d), [Retexture](/api/retexture), [Remesh](/api/remesh), and [Repair Printability](/api/repair-printability) APIs. When set to `true`, the task additionally renders a transparent-background (RGBA) version of the preview and returns it under the new `alpha_thumbnail_url` response field. The existing `thumbnail_url` is unchanged. Defaults to `false`. ### `Jun 1` - New **Creative Lab APIs**: a family of product-scoped endpoints that turn a source photo (or text prompt) into a 3D-printable consumer product. Four products at launch — [Keychain](/api/creative-lab-keychain), [Fridge Magnet](/api/creative-lab-fridge-magnet), [Figure](/api/creative-lab-figure), and [Lamp](/api/creative-lab-lamp). Each follows a two-stage `prototype` → `build` workflow chained via `input_task_id`, served under product-scoped URLs (`/openapi/creative-lab//v1/...`) with per-product versioning so products can evolve on independent version lines. Prototype: 6 credits per call. Build: 30 credits per call. --- ## May 2026 ### `May 26` - Added `multi_view_thumbnails` parameter to the [Multi-Image to 3D](/api/multi-image-to-3d) API. When set to `true`, the task additionally renders four cardinal-view thumbnails (front, right, back, left) and returns them under the new `thumbnail_urls` response field. The existing `thumbnail_url` field is unchanged. Adds approximately 3 seconds to task latency. ### `May 22` - The convert and resize functionality from the [Remesh API](/api/remesh) is now available as standalone [Convert API](/api/convert) and [Resize API](/api/resize) endpoints. The deprecated parameters on Remesh will continue to work for backward compatibility. ### `May 13` - Added `multi_view_thumbnails` parameter to the [Image to 3D](/api/image-to-3d) API. When set to `true`, the task additionally renders four cardinal-view thumbnails (front, right, back, left) and returns them under the new `thumbnail_urls` response field. The existing `thumbnail_url` field is unchanged. Adds approximately 3 seconds to task latency. ### `May 12` - Added `resize_longest_side` parameter to the [Remesh](/api/remesh) API. Resizes the model so the longest bounding-box dimension equals the specified value in meters. Mutually exclusive with `resize_height` and `auto_size`. ### `May 11` - Deprecated `symmetry_mode` parameter on [Text to 3D](/api/text-to-3d), [Image to 3D](/api/image-to-3d), and [Multi-Image to 3D](/api/multi-image-to-3d) endpoints. This parameter no longer affects output. ### `May 7` - New [Analyze Printability API](/api/analyze-printability): Analyze a succeeded Meshy task — or any 3D model URL — for FDM 3D printing readiness. Async create + stream pattern: POST returns a task_id, then GET / SSE stream return watertightness, volume, hole and non-manifold-edge metrics once SUCCEEDED. Free, no credits consumed. - New [Repair Printability API](/api/repair-printability): Repair a 3D model for FDM printability — fix non-manifold edges, degenerate faces, holes, and other topology issues. Accepts an existing Meshy `input_task_id` or a `model_url` (`.glb`, `.stl`, `.obj`). Output format matches the input. 10 credits per task. --- ## April 2026 ### `Apr 27` - Added `consumed_credits` field to all task responses across every API endpoint. Shows the number of credits consumed by each task. The field is present for tasks in `PENDING`, `IN_PROGRESS`, and `SUCCEEDED` statuses. Returns `0` for `FAILED` tasks (credits are automatically refunded on failure). See [Pricing](/api/pricing) for credit costs per endpoint. ### `Apr 24` - Added `model_url` parameter to the [Multi-Color Print](/api/multi-color-print#create-a-multi-color-3d-print-task) endpoint. Submit a textured 3D model directly (via URL or Data URI) instead of an `input_task_id` from a prior Meshy task. Supported formats: `.glb`, `.fbx`. When both `model_url` and `input_task_id` are provided, `input_task_id` takes priority. ### `Apr 21` - Added `input_task_id` parameter to the [Image to 3D](/api/image-to-3d#create-an-image-to-3d-task) and [Multi-Image to 3D](/api/multi-image-to-3d#create-a-multi-image-to-3d-task) endpoints. Reference a completed Text to Image or Image to Image task's output directly instead of providing `image_url` / `image_urls`. When both are supplied, `input_task_id` takes priority. ### `Apr 20` - Added `hd_texture` parameter to the [Image to 3D](/api/image-to-3d#create-an-image-to-3d-task), [Multi-Image to 3D](/api/multi-image-to-3d#create-a-multi-image-to-3d-task), [Text to 3D Refine](/api/text-to-3d#create-a-text-to-3d-refine-task), and [Retexture](/api/retexture#create-a-retexture-task) endpoints. When enabled, the base color texture is generated at 4K (4096×4096) resolution for higher detail. Only supported for `meshy-6` and `latest`. Defaults to `false`. - The PBR bundle returned when `enable_pbr` is `true` now includes an `emission` map under `texture_urls` for `meshy-6` and `latest` tasks across [Image to 3D](/api/image-to-3d), [Multi-Image to 3D](/api/multi-image-to-3d), [Text to 3D Refine](/api/text-to-3d#create-a-text-to-3d-refine-task), and [Retexture](/api/retexture). No request change is required. ### `Apr 14` - Added `decimation_mode` parameter to the [Image to 3D](/api/image-to-3d#create-an-image-to-3d-task), [Multi-Image to 3D](/api/multi-image-to-3d#create-a-multi-image-to-3d-task), [Text to 3D Preview](/api/text-to-3d#create-a-text-to-3d-preview-task), and [Remesh](/api/remesh#create-a-remesh-task) endpoints. Sets the adaptive decimation polycount level: `1` (ultra), `2` (high), `3` (medium), or `4` (low). ### `Apr 12` - Restructured API documentation: added parameter grouping with dependent fields, inline defaults, required/deprecated badges, expandable sub-navigation, and split Multi-Image, Rigging, and Animation into separate pages. --- ## March 2026 ### `Apr 2` - Added `3mf` format support to `target_formats` parameter across all endpoints ([Image to 3D](/api/image-to-3d), [Text to 3D](/api/text-to-3d), [Remesh](/api/remesh), [Retexture](/api/retexture)). Note: 3MF is opt-in only and must be explicitly requested. - New [Multi-Color Print API](/api/multi-color-print): Convert 3D models to multi-color 3MF format for 3D printing. Supports 1-16 color palettes with configurable precision. 10 credits per task. ### `Mar 20` - Retired the Meshy-4 AI model. All API requests using `meshy-4` are no longer supported. Please migrate to `meshy-6` or `latest`. - Added `auto_size` and `origin_at` parameters to the [Image to 3D](/api/image-to-3d#create-an-image-to-3d-task), [Multi-Image to 3D](/api/multi-image-to-3d#create-a-multi-image-to-3d-task), [Text to 3D](/api/text-to-3d), and [Remesh](/api/remesh#create-a-remesh-task) endpoints. When `auto_size` is enabled, the service uses AI vision to estimate real-world height and resize the model automatically. `origin_at` sets the origin position (`bottom` or `center`). In the Remesh API, `auto_size` is mutually exclusive with `resize_height`. ### `Mar 17` - Added optional `target_formats` parameter to [Image to 3D](/api/image-to-3d#create-an-image-to-3d-task), [Multi-Image to 3D](/api/multi-image-to-3d#create-a-multi-image-to-3d-task), [Text to 3D](/api/text-to-3d), and [Retexture](/api/retexture#create-a-retexture-task) endpoints. Specify which 3D formats to generate (e.g., `["glb", "fbx"]`) to reduce task completion time. --- ## February 2026 ### `Feb 28` - Added `remove_lighting` parameter to the [Image to 3D](/api/image-to-3d#create-an-image-to-3d-task), [Multi-Image to 3D](/api/multi-image-to-3d#create-a-multi-image-to-3d-task), [Text to 3D Refine](/api/text-to-3d#create-a-text-to-3d-refine-task), and [Retexture](/api/retexture#create-a-retexture-task) APIs. Removes highlights and shadows from the base color texture for cleaner results under custom lighting. Only supported for `meshy-6` and `latest`. Defaults to `true`. - The [Retexture](/api/retexture#create-a-retexture-task) and [Text to 3D Refine](/api/text-to-3d#create-a-text-to-3d-refine-task) APIs now support `meshy-6` as an `ai_model` value for full Meshy 6 texturing. ### `Feb 25` - Added `image_enhancement` parameter to the [Image to 3D](/api/image-to-3d#create-an-image-to-3d-task) and [Multi-Image to 3D](/api/multi-image-to-3d#create-a-multi-image-to-3d-task) APIs for users who want to opt out of input image optimization and preserve the exact appearance of their input. Only supported for `meshy-6` and `latest`. Defaults to `true`. ### `Feb 20` - Added `model_type` parameter to the [Text to 3D Preview](/api/text-to-3d#create-a-text-to-3d-preview-task) API for generating low-poly meshes optimized for cleaner polygons. --- ## January 2026 ### `Jan 27` - Added detailed [Failure Modes](/api/errors#task-errors) documentation for all API endpoints, including common HTTP error codes (400, 401, 402, 404, 422, 429) and task failure reasons. This helps developers better understand and handle API errors. ### `Jan 26` - The [Multi-Image to 3D](/api/multi-image-to-3d#create-a-multi-image-to-3d-task) API now supports Meshy-6 for full mesh generation. The `ai_model` parameter now accepts `meshy-6` and `latest` resolves to Meshy 6. ### `Jan 22` - Deprecated `art_style` for the [Text to 3D Preview](/api/text-to-3d#create-a-text-to-3d-preview-task) API (Meshy-6). The parameter was designed for legacy models (Meshy-4 / Meshy-5) and will be removed in a future release. - Deprecated `enable_pbr` for the [Text to 3D](/api/text-to-3d) and [Image to 3D](/api/image-to-3d) APIs when `ai_model` is `meshy-4`. This parameter will be removed in a future release. - Updated the default value of `should_remesh` parameter for Meshy-6 in the [Text to 3D](/api/text-to-3d) and [Image to 3D](/api/image-to-3d) APIs. The parameter now defaults to `false` for `meshy-6`, and `true` for other models if not specified. ### `Jan 19` - The `latest` option for `ai_model` in the [Text to 3D (Preview)](/api/text-to-3d#create-a-text-to-3d-preview-task) and [Image to 3D](/api/image-to-3d#create-an-image-to-3d-task) APIs now resolves to Meshy 6. ### `Jan 12` - Added a new `model_type` parameter to the [Image to 3D](/api/image-to-3d#create-an-image-to-3d-task) API for generating low-poly meshes optimized for cleaner polygons. --- ## December 2025 ### `Dec 31` - Launched the [API Playground](https://www.meshy.ai/api-playground), a dedicated space for developers to explore API parameters and test requests directly on the Meshy website. - Introduced the [Text to Image API](/api/text-to-image) and [Image to Image API](/api/image-to-image), enabling AI-powered image generation from text prompts and image editing from reference images. Both APIs support the `nano-banana` and `nano-banana-pro` models, with optional multi-view generation. ### `Dec 22` - The `video_url` field in the [Text to 3D](/api/text-to-3d) API response is now deprecated and will be removed in a future release. ### `Dec 04` - Added a new `pose_mode` parameter to the [Text to 3D Preview](/api/text-to-3d#create-a-text-to-3d-preview-task), [Image to 3D](/api/image-to-3d#create-an-image-to-3d-task), and [Multi-Image to 3D](/api/multi-image-to-3d#create-a-multi-image-to-3d-task) APIs. This parameter accepts `a-pose`, `t-pose`, or an empty string (default). The `is_a_t_pose` parameter is now deprecated in favor of `pose_mode`. --- ## November 2025 ### `Nov 24` - The [Image to 3D](/api/image-to-3d#create-an-image-to-3d-task) and [Multi-Image to 3D](/api/multi-image-to-3d#create-a-multi-image-to-3d-task) APIs add an optional `save_pre_remeshed_model` parameter and expose `model_urls.pre_remeshed_glb` when a pre-remesh backup is requested. ### `Nov 06` - The [Text to 3D Refine API](/api/text-to-3d#create-a-text-to-3d-refine-task) now supports `ai_model = latest`, which resolves to Meshy 6 Preview. - The [Image to 3D API](/api/image-to-3d#create-an-image-to-3d-task) now defaults to Meshy-6-preview texturing when `ai_model = latest` and `should_texture = true`. - The [Multi-Image to 3D API](/api/multi-image-to-3d#create-a-multi-image-to-3d-task) now supports `ai_model = latest`, running Meshy-6-preview for texturing by default while mesh generation remains Meshy-5. - The [Retexture API](/api/retexture) adds a `latest` option for `ai_model` (Meshy-6-preview) and now defaults to it when omitted. ### `Nov 04` - The [Remesh API](/api/remesh#create-a-remesh-task) now preserves textures for uploaded models. - The [Retexture API](/api/retexture) now preserves textures for uploaded models when the `enable_original_uv` option is enabled. --- ## October 2025 ### `Oct 28` - Added the `x-api-version` response header to indicate the current API server version. ### `Oct 20` - Added an optional `convert_format_only` boolean parameter to the [Remesh API](/api/remesh#create-a-remesh-task) to support converting the format of the input model file only. - Added `rigged_character_glb_url` to the response of [The Rigging Task Object](/api/rigging#the-rigging-task-object). ### `Oct 01` - Remove `text-to-voxel` APIs --- ## September 2025 ### `Sep 23` - Added a `latest` option for `ai_model` in the [Text to 3D](/api/text-to-3d#create-a-text-to-3d-preview-task) API to use Meshy 6 Preview. - Temporary 50% discount in place for Meshy-6-preview generation tasks to 10 credits that will last until Sep 30, 2025. After the discount period, the cost of Meshy-6-preview tasks will return to the normal 20 credits. ### `Sep 18` - Updated [API pricing](/api/pricing) for [Text to 3D](/api/text-to-3d) and [Image to 3D](/api/image-to-3d) to reflect different costs for Meshy 6 and other models. ### `Sep 16` - Added a `latest` option for `ai_model` in the [Image to 3D](/api/image-to-3d#create-an-image-to-3d-task) API to use Meshy 6 Preview. ### `Sep 4` - Expanded `model_url` input support to `.glb`, `.gltf`, `.obj`, `.fbx`, `.stl` for [Remesh](/api/remesh#create-a-remesh-task) and [Retexture](/api/retexture). --- ## August 2025 ### `Aug 18` - Added an optional `is_a_t_pose` parameter to the [Text to 3D Preview](/api/text-to-3d#create-a-text-to-3d-preview-task), [Image to 3D](/api/image-to-3d#create-an-image-to-3d-task), and [Multi-Image to 3D](/api/multi-image-to-3d#create-a-multi-image-to-3d-task) APIs to generate models in an A/T pose. ### `Aug 13` - Meshy 5 is now stable for [Text to 3D](/api/text-to-3d) and [Image to 3D](/api/image-to-3d) (`ai_model`: `meshy-5`), delivering improved quality and consistency. --- ## July 2025 ### `Jul 31` - Support PBR texture maps in API via `enable_pbr` parameter for latest `meshy-5` model for [Text to 3D](/api/text-to-3d), [Image to 3D](/api/image-to-3d), [Multi-Image to 3D](/api/multi-image-to-3d#create-a-multi-image-to-3d-task), and [Retexture](/api/retexture) endpoints. --- ## June 2025 ### `Jun 25 ` - Added the [Retexture API](/api/retexture), which allows users to retexture 3D models based on Meshy's latest foundation AI models. ### `Jun 19` - Added deletion APIs for [Text to 3D](/api/text-to-3d), [Image to 3D](/api/image-to-3d), [Remesh](/api/remesh), [Rigging](/api/rigging), and [Animation](/api/animation). - Added the `ai_model` parameter to the [Text to 3D Refine API](/api/text-to-3d#create-a-text-to-3d-refine-task). ### `Jun 17` - Added documentation for [Webhooks](/api/webhooks). ### `Jun 10` - The [Remesh API](/api/remesh#create-a-remesh-task) now supports base64-encoded GLB format models in the `model_url` parameter via Data URI. --- ## May 2025 ### `May 20` - Added an optional `moderation` parameter to the [Text to 3D Preview](/api/text-to-3d#create-a-text-to-3d-preview-task), [Text to 3D Refine](/api/text-to-3d#create-a-text-to-3d-refine-task), [Image to 3D](/api/image-to-3d#create-an-image-to-3d-task), and [Multi-Image to 3D](/api/multi-image-to-3d#create-a-multi-image-to-3d-task) APIs. When enabled, input content is automatically screened for potentially harmful content before generation. ### `May 15` - Introduced the Auto-rigging & Animation API, enabling users to automatically rig and animate 3D models. [Learn more about Rigging](/api/rigging) and [Animation](/api/animation). --- ## April 2025 ### `Apr 29` - Introduced the [Multi-Image to 3D API](/api/multi-image-to-3d#create-a-multi-image-to-3d-task), allowing generation of 3D models from 1 to 4 input images using the `meshy-5` AI model. - Added the `meshy-5` AI model option to the [Text to 3D](/api/text-to-3d) and [Image to 3D](/api/image-to-3d) APIs. The `latest` tag now also resolves to `meshy-5`. ### `Apr 17` - Added the `texture_image_url` parameter to the [Image to 3D](/api/image-to-3d#create-an-image-to-3d-task) and [Text to 3D Refine](/api/text-to-3d#create-a-text-to-3d-refine-task) APIs, allowing users to guide the texture generation process with an image. --- ## March 2025 ### `Mar 28` - Added the `latest` parameter to the [Text to 3D](/api/text-to-3d##create-a-text-to-3d-preview-task) and [Image to 3D](/api/image-to-3d#create-an-image-to-3d-task) APIs, enabling access to our upcoming advanced AI models for improved generation quality. ### `Mar 14` - The [Text to Texture API](/api/text-to-texture#create-a-text-to-texture-task) now supports base64-encoded models in the `model_url` parameter via Data URI, similar to the `image_url` in the [Image to 3D](/api/image-to-3d#create-an-image-to-3d-task) API. ### `Mar 06` - Updated pricing for API generation tasks: - Text to 3D (Preview): Increased from 2 to 5 credits per call - Text to 3D (Refine): Increased from 5 to 10 credits per call - Image to 3D: Now 5 credits without texture, 15 credits with texture - Text to Texture: Increased from 5 to 10 credits per call - Text to Voxel: Remains at 5 credits per call --- ## February 2025 ### `Feb 18` - Added a test mode API key `msy_dummy_api_key_for_test_mode_12345678` that allows developers to test API integration without consuming credits. All valid requests using this key will return the same sample task results. ### `Feb 13` - **Breaking Changes**: - Free tier task creation will end on `March 20, 2025`. After that, all API task requests will require a paid subscription. To keep your access smooth, we recommend upgrading before the deadline. - Use coupon code `APIACCESS` to enjoy a `40%` discount. Thank you for being with us! - Added Server-Sent Events (SSE) streaming endpoints for real-time task updates: - [Text to 3D Stream API](/api/text-to-3d#stream-a-text-to-3d-task) - [Image to 3D Stream API](/api/image-to-3d#stream-an-image-to-3d-task) - [Remesh Stream API](/api/remesh#stream-a-remesh-task) - [Text to Texture Stream API](/api/text-to-texture#stream-a-text-to-texture-task) ### `Feb 6` - Added the `texture_prompt` parameter to the [Image to 3D](/api/image-to-3d#create-an-image-to-3d-task) and [Text to 3D Refine](/api/text-to-3d#create-a-text-to-3d-refine-task) APIs, allowing users to guide the texture generation process with a text prompt. --- ## January 2025 ### `Jan 23` - Added endpoints for listing tasks to the [Text to 3D](/api/text-to-3d#list-text-to-3d-tasks), [Image to 3D](/api/image-to-3d#list-image-to-3d-tasks), [Remesh](/api/remesh#list-remesh-tasks) and [Text to Texture](/api/text-to-texture#list-text-to-texture-tasks) APIs. ### `Jan 14` - Deprecated the legacy Text to 3D and Image to 3D APIs powered by Meshy-3 AI models. ### `Jan 07` - Added the `symmetry_mode` parameter to the [Text to 3D Preview](/api/text-to-3d#create-a-text-to-3d-preview-task) and [Image to 3D](/api/image-to-3d#create-an-image-to-3d-task) APIs, allowing for configurable symmetry settings. --- ## December 2024 ### `Dec 19` - Added the [Remesh APIs](/api/remesh), which allow users to remesh and export existing 3D models generated by other Meshy APIs into various formats. - Updated the polycount limits for our APIs to a range of 100-300,000 for Premium users. ### `Dec 12` - Deprecated the `model_url` property in all response objects. - Separated legacy Meshy-3 API from the latest Meshy-4 API. ### `Dec 10` - Added an `enable_pbr` parameter to the [Image to 3D](/api/image-to-3d#create-an-image-to-3d-task) and [Text to 3D Refine](/api/text-to-3d#create-a-text-to-3d-refine-task) APIs. - Added a `should_texture` parameter to the [Image to 3D](/api/image-to-3d#create-an-image-to-3d-task) API. - Deprecated the `pbr` option in `art_style` parameter for the [Text to 3D Preview](/api/text-to-3d#create-a-text-to-3d-preview-task) API when using the `meshy-4` AI model. - Deprecated the `low-poly` option in `art_style` parameter for the [Text to 3D Preview](/api/text-to-3d#create-a-text-to-3d-preview-task) API. ### `Dec 5` - Added a [Get Balance API](/api/balance) to allow users to retrieve their credit balance. - Added a `should_remesh` parameter to the [Image to 3D](/api/image-to-3d#create-an-image-to-3d-task) and [Text to 3D Preview](/api/text-to-3d#create-a-text-to-3d-preview-task) APIs. ### `Dec 3` - External APIs now use the `/openapi` prefix. Legacy paths remain supported, but we recommend switching to the new paths. --- ## November 2024 ### `Nov 14` - The [Image to 3D API](/api/image-to-3d#create-an-image-to-3d-task) now supports base64-encoded images. --- --- # Text to 3D API Source: https://docs.meshy.ai/api/text-to-3d # Text to 3D API Text to 3D API is a feature that allows you to integrate Meshy's Text to 3D capabilities into your own application. In this section, you'll find all the information you need to get started with this API. Text to 3D uses a two-step workflow. First, create a **preview** task (`mode: "preview"`) to generate a 3D mesh without texture, so you can evaluate the shape. Then, pass the completed preview's task ID to a **refine** task (`mode: "refine"`) to apply texture to the mesh. Both steps share the same endpoint. --- ## POST /openapi/v2/text-to-3d -- Create a Text to 3D Preview Task This endpoint creates a Text to 3D preview task, which generates an untextured 3D mesh (geometry only) from a text prompt. This is the first step of the two-step workflow. Once the preview succeeds, use the returned task ID to [create a refine task](#create-a-text-to-3d-refine-task) for texturing. Refer to [The Text to 3D Task Object](#the-text-to-3d-task-object) for the full response schema. ### Parameters - `mode` · *string* · **required** This field should be set to "preview" when creating a preview task. - `prompt` · *string* · **required** Describe what kind of object the 3D model is. Maximum 600 characters. - `model_type` · *string* · default: `standard` Specify the type of 3D mesh generation. Available values: * `standard`: Regular high-detail 3D mesh generation. * `lowpoly`: Generates low-poly mesh optimized for cleaner polygons. > **Note:** When `lowpoly` is selected, `ai_model`, `topology`, `target_polycount`, `should_remesh` are ignored. - `ai_model` · *string* · default: `latest` ID of the model to use. Available values: `meshy-5`, `meshy-6`, `latest` (Meshy 6). - `should_remesh` · *boolean* · default: `false (meshy-6), true (others)` Controls whether to enable the remesh phase. When set to `false`, the API will directly return the highest-precision triangular mesh. **Only when `should_remesh` is set:** - `topology` · *string* · default: `triangle` Specify the topology of the generated model. Available values: * `quad`: Generate a quad-dominant mesh. * `triangle`: Generate a decimated triangle mesh. - `target_polycount` · *integer* · default: `30,000` Specify the target number of polygons in the generated model. The actual number of polygons may deviate from the target depending on the complexity of the geometry. The valid value range varies depending on the user tier: * 100 to 300,000 (inclusive) - `decimation_mode` · *integer* Enable adaptive decimation by setting a polycount level. When set, `target_polycount` is ignored. Available values: * `1`: Adaptive — ultra polycount. * `2`: Adaptive — high polycount. * `3`: Adaptive — medium polycount. * `4`: Adaptive — low polycount. - `symmetry_mode` · *string* · default: `auto` · **deprecated** Deprecated. This parameter no longer affects output. The `symmetry_mode` field controls symmetry behavior during the model generation process. The valid values are: * `off`: Disables symmetry. * `auto`: Automatically determines and applies symmetry based on input geometry. * `on`: Enforces symmetry during generation. - `pose_mode` · *string* · default: `""` Specify the pose mode for the generated model. Available values: * `a-pose`: Generate the model in an A pose. * `t-pose`: Generate the model in a T pose. * `""` (empty string): No specific pose applied. - `is_a_t_pose` · *boolean* · default: `false` · **deprecated** Use `pose_mode` instead. Whether to generate the model in an A/T pose. - `art_style` · *string* · default: `realistic` · **deprecated** Not supported by Meshy-6. Requests using Meshy-6 will ignore `art_style`, and some combinations may cause errors. Available values: `realistic`, `sculpture`. > **Note:** `enable_pbr` should be set to `false` when using Sculpture style, as Sculpture style generates its own set of PBR maps. - `moderation` · *boolean* · default: `false` When set to `true`, the input content will automatically be screened for potentially harmful content. If harmful content is detected, the task will not proceed to generation. The text from `prompt` will be screened. - `target_formats` · *string[]* Specifies which 3D file formats to include in the output. Only the requested formats will be generated and returned, which can reduce task completion time. When omitted, all supported formats are included. Available values: `glb`, `obj`, `fbx`, `stl`, `usdz`, `3mf` > **Note:** When omitted, all formats except `3mf` are generated. `3mf` is only included when explicitly specified. - `alpha_thumbnail` · *boolean* · default: `false` When set to `true`, the task additionally renders a transparent-background (RGBA) version of the preview and returns it as `alpha_thumbnail_url` on the GET response. The existing `thumbnail_url` field is unchanged. - `auto_size` · *boolean* · default: `false` When set to `true`, the service uses AI vision to automatically estimate the real-world height of the object and resize the model accordingly. The origin will default to `bottom` unless `origin_at` is explicitly set. **Only when `auto_size` is set:** - `origin_at` · *string* · default: `bottom` Position of the origin when `auto_size` is enabled. Available values: `bottom`, `center`. ### Returns The `result` property of the response contains the task `id` of the newly created Text to 3D task. ### Failure Modes - `400 - Bad Request` The request was unacceptable. Common causes: * **Missing parameter**: A required parameter (e.g., `prompt`, `mode`) is missing. * **Invalid parameter**: `art_style` is not one of the allowed values. * **Prompt too long**: The `prompt` exceeds the character limit. - `401 - Unauthorized` Authentication failed. Please check your API key. - `402 - Payment Required` Insufficient credits to perform this task. - `429 - Too Many Requests` You have exceeded your rate limit. **cURL** ```bash # Simple preview with required params only curl https://api.meshy.ai/openapi/v2/text-to-3d \ -H 'Authorization: Bearer ${YOUR_API_KEY}' \ -H 'Content-Type: application/json' \ -d '{ "mode": "preview", "prompt": "a monster mask" }' # Preview with remesh and A-pose curl https://api.meshy.ai/openapi/v2/text-to-3d \ -H 'Authorization: Bearer ${YOUR_API_KEY}' \ -H 'Content-Type: application/json' \ -d '{ "mode": "preview", "prompt": "a futuristic robot warrior", "should_remesh": true, "target_polycount": 100000, "pose_mode": "a-pose", "target_formats": ["glb"] }' ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; // Simple preview with required params only const payload = { mode: 'preview', prompt: 'a monster mask', }; try { const response = await axios.post( 'https://api.meshy.ai/openapi/v2/text-to-3d', payload, { headers } ); console.log(response.data); } catch (error) { console.error(error); } // Preview with remesh and A-pose const advancedPayload = { mode: 'preview', prompt: 'a futuristic robot warrior', should_remesh: true, target_polycount: 100000, pose_mode: 'a-pose', target_formats: ['glb'], }; try { const response = await axios.post( 'https://api.meshy.ai/openapi/v2/text-to-3d', advancedPayload, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } # Simple preview with required params only payload = { "mode": "preview", "prompt": "a monster mask", } response = requests.post( "https://api.meshy.ai/openapi/v2/text-to-3d", headers=headers, json=payload, ) response.raise_for_status() print(response.json()) # Preview with remesh and A-pose advanced_payload = { "mode": "preview", "prompt": "a futuristic robot warrior", "should_remesh": True, "target_polycount": 100000, "pose_mode": "a-pose", "target_formats": ["glb"], } response = requests.post( "https://api.meshy.ai/openapi/v2/text-to-3d", headers=headers, json=advanced_payload, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "result": "018a210d-8ba4-705c-b111-1f1776f7f578" } ``` --- ## POST /openapi/v2/text-to-3d -- Create a Text to 3D Refine Task This endpoint creates a Text to 3D refine task, which applies texture to a completed preview mesh. You must provide the `preview_task_id` from a [successful preview task](#create-a-text-to-3d-preview-task). This is the second step of the two-step workflow. ### Parameters - `mode` · *string* · **required** This field should be set to "refine" when creating a refine task. - `preview_task_id` · *string* · **required** The corresponding preview task id. The status of the given preview task must be `SUCCEEDED`. - `enable_pbr` · *boolean* · default: `false` Generate PBR Maps (metallic, roughness, normal) in addition to the base color. An emission map is also included when `ai_model` is `meshy-6` or `latest`. - `hd_texture` · *boolean* · default: `false` Generate the base color texture at 4K (4096×4096) resolution for higher detail. > **Note:** Only supported when `ai_model` is `meshy-6` or `latest`. PBR maps are always generated at 2K. - `texture_prompt` · *string* Provide an additional text prompt to guide the texturing process. Maximum 600 characters. - `texture_image_url` · *string* Provide a 2d image to guide the texturing process. We currently support `.jpg`, `.jpeg`, and `.png` formats. There are two ways to provide the image: - **Publicly accessible URL**: A URL that is accessible from the public internet - **Data URI**: A base64-encoded data URI of the image. Example of a data URI: `data:image/jpeg;base64,` > **Note:** Image texturing may not work optimally if there are substantial geometry differences between the original asset and uploaded image. Only one of `texture_image_url` or `texture_prompt` may be used to guide the texturing process. If both parameters are provided, then `texture_prompt` will be used to texture the model by default. - `ai_model` · *string* · default: `latest` ID of the model to use for refining. Available values: `meshy-5`, `meshy-6`, `latest` (Meshy 6). - `moderation` · *boolean* · default: `false` When set to `true`, the input content will automatically be screened for potentially harmful content. If harmful content is detected, the task will not proceed to generation. Both the text from `texture_prompt` and the image from `texture_image_url` will be screened. - `remove_lighting` · *boolean* · default: `true` Removes highlights and shadows from the base color texture, producing a cleaner result that works better under custom lighting setups. > **Note:** Only supported when `ai_model` is `meshy-6` or `latest`. - `target_formats` · *string[]* Specifies which 3D file formats to include in the output. Only the requested formats will be generated and returned, which can reduce task completion time. When omitted, all supported formats are included. Available values: `glb`, `obj`, `fbx`, `stl`, `usdz`, `3mf` > **Note:** When omitted, all formats except `3mf` are generated. `3mf` is only included when explicitly specified. - `alpha_thumbnail` · *boolean* · default: `false` When set to `true`, the task additionally renders a transparent-background (RGBA) version of the preview and returns it as `alpha_thumbnail_url` on the GET response. The existing `thumbnail_url` field is unchanged. - `auto_size` · *boolean* · default: `false` When set to `true`, the service uses AI vision to automatically estimate the real-world height of the object and resize the model accordingly. The origin will default to `bottom` unless `origin_at` is explicitly set. **Only when `auto_size` is set:** - `origin_at` · *string* · default: `bottom` Position of the origin when `auto_size` is enabled. Available values: `bottom`, `center`. ### Returns The `result` property of the response contains the task `id` of the newly created Text to 3D task. ### Failure Modes - `400 - Bad Request` The request was unacceptable. Common causes: * **Invalid task ID**: The `preview_task_id` is invalid or does not exist. * **Task not ready**: The preview task has not succeeded yet. * **Model mismatch**: The preview task's AI model is incompatible with the requested refine model. - `401 - Unauthorized` Authentication failed. Please check your API key. - `402 - Payment Required` Insufficient credits to perform this task. - `404 - Not Found` The preview task specified by `preview_task_id` was not found. - `429 - Too Many Requests` You have exceeded your rate limit. **cURL** ```bash # Basic refine task curl https://api.meshy.ai/openapi/v2/text-to-3d \ -H 'Authorization: Bearer ${YOUR_API_KEY}' \ -H 'Content-Type: application/json' \ -d '{ "mode": "refine", "preview_task_id": "018a210d-8ba4-705c-b111-1f1776f7f578", "enable_pbr": true }' # Refine with auto-size and GLB format curl https://api.meshy.ai/openapi/v2/text-to-3d \ -H 'Authorization: Bearer ${YOUR_API_KEY}' \ -H 'Content-Type: application/json' \ -d '{ "mode": "refine", "preview_task_id": "018a210d-8ba4-705c-b111-1f1776f7f578", "target_formats": ["glb"], "auto_size": true }' ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; // Basic refine task const payload = { mode: 'refine', preview_task_id: '018a210d-8ba4-705c-b111-1f1776f7f578', enable_pbr: true, }; try { const response = await axios.post( 'https://api.meshy.ai/openapi/v2/text-to-3d', payload, { headers } ); console.log(response.data); } catch (error) { console.error(error); } // Refine with auto-size and GLB format const advancedPayload = { mode: 'refine', preview_task_id: '018a210d-8ba4-705c-b111-1f1776f7f578', target_formats: ['glb'], auto_size: true, }; try { const response = await axios.post( 'https://api.meshy.ai/openapi/v2/text-to-3d', advancedPayload, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } # Basic refine task payload = { "mode": "refine", "preview_task_id": "018a210d-8ba4-705c-b111-1f1776f7f578", "enable_pbr": True, } response = requests.post( "https://api.meshy.ai/openapi/v2/text-to-3d", headers=headers, json=payload, ) response.raise_for_status() print(response.json()) # Refine with auto-size and GLB format advanced_payload = { "mode": "refine", "preview_task_id": "018a210d-8ba4-705c-b111-1f1776f7f578", "target_formats": ["glb"], "auto_size": True, } response = requests.post( "https://api.meshy.ai/openapi/v2/text-to-3d", headers=headers, json=advanced_payload, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "result": "018a210d-8ba4-705c-b111-1f1776f7f578" } ``` --- ## GET /openapi/v2/text-to-3d/:id -- Retrieve a Text to 3D Task This endpoint allows you to retrieve a Text to 3D task given a valid task `id`. Refer to [The Text to 3D Task Object](#the-text-to-3d-task-object) to see which properties are included with Text to 3D task object. This endpoint works for both preview and refine tasks. ### Parameters - `id` · *path* Unique identifier for the Text to 3D task to retrieve. ### Returns The response contains the Text to 3D task object. Check [The Text to 3D Task Object](#the-text-to-3d-task-object) section for details. ### Examples
Mode Sample Model
Preview Preview model
Refine Refined model
**cURL** ```bash curl https://api.meshy.ai/openapi/v2/text-to-3d/018a210d-8ba4-705c-b111-1f1776f7f578 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const taskId = '018a210d-8ba4-705c-b111-1f1776f7f578'; const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; try { const response = await axios.get( `https://api.meshy.ai/openapi/v2/text-to-3d/${taskId}`, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests task_id = "018a210d-8ba4-705c-b111-1f1776f7f578" headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.get( f"https://api.meshy.ai/openapi/v2/text-to-3d/{task_id}", headers=headers, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "text-to-3d-preview", "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=***", "obj": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.obj?Expires=***", "mtl": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.mtl?Expires=***", "usdz": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.usdz?Expires=***", "stl": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.stl?Expires=***" }, "thumbnail_url": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview.png?Expires=***", "prompt": "a monster mask", "progress": 100, "started_at": 1692771667037, "created_at": 1692771650657, "finished_at": 1692771669037, "status": "SUCCEEDED", "texture_urls": [ { "base_color": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0.png?Expires=***" } ], "preceding_tasks": 0, "task_error": { "message": "" }, "consumed_credits": 20 } ``` --- ## DELETE /openapi/v2/text-to-3d/:id -- Delete a Text to 3D Task This endpoint permanently deletes a Text to 3D task, including all associated models and data. This action is irreversible. ### Path Parameters - `id` · *path* The ID of the Text to 3D task to delete. ### Returns Returns `200 OK` on success. **cURL** ```bash curl --request DELETE \ --url https://api.meshy.ai/openapi/v2/text-to-3d/018a210d-8ba4-705c-b111-1f1776f7f578 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const taskId = '018a210d-8ba4-705c-b111-1f1776f7f578' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` } try { await axios.delete( `https://api.meshy.ai/openapi/v2/text-to-3d/${taskId}`, { headers } ) } catch (error) { console.error(error) } ``` ```python import requests task_id = "018a210d-8ba4-705c-b111-1f1776f7f578" headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.delete( f"https://api.meshy.ai/openapi/v2/text-to-3d/{task_id}", headers=headers, ) response.raise_for_status() ``` **Response** ```json // Returns 200 Ok on success. ``` --- ## GET /openapi/v2/text-to-3d -- List Text to 3D Tasks This endpoint allows you to retrieve a list of Text to 3D tasks. ### Parameters - `page_num` · *integer* · default: `1` Page number for pagination. - `page_size` · *integer* · default: `10` Page size limit. Maximum allowed is `50` items. - `sort_by` · *string* Field to sort by. Available values: * `+created_at`: Sort by creation time in ascending order. * `-created_at`: Sort by creation time in descending order. ### Returns Returns a paginated list of [The Text to 3D Task Objects](#the-text-to-3d-task-object). **cURL** ```bash curl https://api.meshy.ai/openapi/v2/text-to-3d?page_size=10 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; try { const response = await axios.get( `https://api.meshy.ai/openapi/v2/text-to-3d?page_size=10`, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.get( "https://api.meshy.ai/openapi/v2/text-to-3d", headers=headers, params={"page_size": 10} ) response.raise_for_status() print(response.json()) ``` **Response** ```json [ { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "text-to-3d-preview", "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=***", "obj": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.obj?Expires=***", "mtl": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.mtl?Expires=***", "usdz": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.usdz?Expires=***" }, "thumbnail_url": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview.png?Expires=***", "prompt": "a monster mask", "progress": 100, "started_at": 1692771667037, "created_at": 1692771650657, "finished_at": 1692771669037, "status": "SUCCEEDED", "texture_urls": [ { "base_color": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0.png?Expires=***" } ], "preceding_tasks": 0, "task_error": { "message": "" }, "consumed_credits": 20 } ] ``` --- ## GET /openapi/v2/text-to-3d/:id/stream -- Stream a Text to 3D Task This endpoint streams real-time updates for a Text to 3D task using Server-Sent Events (SSE). ### Parameters - `id` · *path* Unique identifier for the Text to 3D task to stream. ### Returns Returns a stream of [The Text to 3D Task Objects](#the-text-to-3d-task-object) as Server-Sent Events. For `PENDING` or `IN_PROGRESS` tasks, the response stream will only include necessary `progress` and `status` fields. **cURL** ```bash curl -N https://api.meshy.ai/openapi/v2/text-to-3d/018a210d-8ba4-705c-b111-1f1776f7f578/stream \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript const response = await fetch( 'https://api.meshy.ai/openapi/v2/text-to-3d/018a210d-8ba4-705c-b111-1f1776f7f578/stream', { headers: { Authorization: `Bearer ${YOUR_API_KEY}` } } ); const reader = response.body.getReader(); const decoder = new TextDecoder(); let buffer = ''; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const lines = buffer.split('\n'); buffer = lines.pop(); for (const line of lines) { if (line.startsWith('data:')) { const data = JSON.parse(line.slice(5)); console.log(data); if (['SUCCEEDED', 'FAILED', 'CANCELED'].includes(data.status)) { reader.cancel(); } } } } ``` ```python import requests import json headers = { "Authorization": f"Bearer {YOUR_API_KEY}", "Accept": "text/event-stream" } response = requests.get( 'https://api.meshy.ai/openapi/v2/text-to-3d/018a210d-8ba4-705c-b111-1f1776f7f578/stream', headers=headers, stream=True ) for line in response.iter_lines(): if line: if line.startswith(b'data:'): data = json.loads(line.decode('utf-8')[5:]) print(data) if data['status'] in ['SUCCEEDED', 'FAILED', 'CANCELED']: break response.close() ``` **Response Stream** ```javascript // Error event example event: error data: { "status_code": 404, "message": "Task not found" } // Message event examples illustrate task progress. // For PENDING or IN_PROGRESS tasks, the response stream will not include all fields. event: message data: { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "progress": 0, "status": "PENDING" } event: message data: { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "progress": 50, "status": "IN_PROGRESS" } event: message data: { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "text-to-3d-preview", "progress": 100, "status": "SUCCEEDED", "created_at": 1692771650657, "started_at": 1692771667037, "finished_at": 1692771669037, "model_urls": { "glb": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.glb?Expires=***" }, "texture_urls": [ { "base_color": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0.png?Expires=***", "metallic": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_metallic.png?Expires=XXX", "normal": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_normal.png?Expires=XXX", "roughness": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_roughness.png?Expires=XXX", "emission": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_emission.png?Expires=XXX" } ], "preceding_tasks": 0, "task_error": { "message": "" }, "consumed_credits": 20 } ``` --- ## The Text to 3D Task Object The Text to 3D Task object is a work unit that Meshy keeps track of to generate a 3D model from a **text** input. There are two stages of the Text to 3D API, `preview` and `refine`. Preview stage is for generating a mesh-only 3D model, and refine stage is for generating a textured 3D model based on the preview stage's result. The object has the following properties: ### Properties - `id` · *string* Unique identifier for the task. While we use a k-sortable UUID for task ids as the implementation detail, you should **not** make any assumptions about the format of the id. - `type` · *string* Type of the Text to 3D task. Possible values are `text-to-3d-preview` for preview stage tasks and `text-to-3d-refine` for refine stage tasks. - `model_urls` · *object* Downloadable URL to the textured 3D model file generated by Meshy. The property for a format will be omitted if the format is not generated instead of returning an empty string. - `glb` · *string* Downloadable URL to the GLB file. - `fbx` · *string* Downloadable URL to the FBX file. - `usdz` · *string* Downloadable URL to the USDZ file. - `obj` · *string* Downloadable URL to the OBJ file. - `mtl` · *string* Downloadable URL to the MTL file. - `stl` · *string* Downloadable URL to the STL file. - `3mf` · *string* Downloadable URL to the 3MF file. Only present when `3mf` was requested via `target_formats`. - `prompt` · *string* This is unmodified `prompt` that was used to create the task. - `negative_prompt` · *string* · **deprecated** Maintained for backward compatibility. This field has no functional impact on generated models. - `art_style` · *string* · **deprecated** The unmodified `art_style` that was used to create the preview task. Not supported by Meshy-6. - `texture_richness` · *string* · **deprecated** Maintained for backward compatibility. This field has no functional impact on generated models. - `texture_prompt` · *string* Additional text prompt provided to guide the texturing process during the refine stage. - `texture_image_url` · *string* Downloadable URL to the texture image that was used to guide the texturing process. - `thumbnail_url` · *string* Downloadable URL to the thumbnail image of the model file. - `alpha_thumbnail_url` · *string* Downloadable URL to a transparent-background (RGBA) version of `thumbnail_url`. Only present when the task was created with `alpha_thumbnail: true` and the transparent preview was successfully rendered; otherwise this field is omitted. - `video_url` · *string* · **deprecated** Downloadable URL to the preview video. Will be removed in a future release. - `progress` · *integer* Progress of the task. If the task is not started yet, this property will be `0`. Once the task has succeeded, this will become `100`. - `started_at` · *timestamp* Timestamp of when the task was started, in milliseconds. If the task is not started yet, this property will be `0`. > **Note:** A timestamp represents the number of milliseconds elapsed since January 1, 1970 UTC, following > the [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339) standard. > For example, Friday, September 1, 2023 12:00:00 PM GMT is represented as `1693569600000`. This applies > to **all** timestamps in Meshy API. - `created_at` · *timestamp* Timestamp of when the task was created, in milliseconds. - `finished_at` · *timestamp* Timestamp of when the task was finished, in milliseconds. If the task is not finished yet, this property will be `0`. - `status` · *string* Status of the task. Possible values are one of `PENDING`, `IN_PROGRESS`, `SUCCEEDED`, `FAILED`, `CANCELED`. - `texture_urls` · *array* An array of texture URL objects that are generated from the task. Normally this only contains **one** texture URL object. Each texture URL has the following properties: - `base_color` · *string* Downloadable URL to the base color map image. - `metallic` · *string* Downloadable URL to the metallic map image. > **Note:** If the task is created with `enable_pbr: false`, this property will be omitted. - `normal` · *string* Downloadable URL to the normal map image. > **Note:** If the task is created with `enable_pbr: false`, this property will be omitted. - `roughness` · *string* Downloadable URL to the roughness map image. > **Note:** If the task is created with `enable_pbr: false`, this property will be omitted. - `emission` · *string* Downloadable URL to the emission map image. > **Note:** If the task is created with `enable_pbr: false`, or `ai_model` is `meshy-5`, this property will be omitted. - `preceding_tasks` · *integer* The count of preceding tasks. > **Note:** The value of this field is meaningful only if the task status is `PENDING`. - `task_error` · *object* Error details for failed tasks. See [Errors](/api/errors#task-errors) for the full `task_error` object reference. - `consumed_credits` · *integer* The number of credits consumed by this task. Present when the task status is `PENDING`, `IN_PROGRESS`, or `SUCCEEDED`. Returns `0` for `FAILED` tasks (credits are refunded on failure). **Example Text to 3D Task Object** ```json { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "text-to-3d-preview", "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=***", "usdz": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.usdz?Expires=***", "obj": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.obj?Expires=***", "mtl": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.mtl?Expires=***", "stl": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.stl?Expires=***" }, "prompt": "a monster mask", "texture_prompt": "green slimy skin with scales and warts", "texture_image_url": "", "thumbnail_url": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview.png?Expires=***", "progress": 100, "seed": 1234, "started_at": 1692771667037, "created_at": 1692771650657, "finished_at": 1692771669037, "status": "SUCCEEDED", "texture_urls": [ { "base_color": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0.png?Expires=***", "metallic": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_metallic.png?Expires=XXX", "normal": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_normal.png?Expires=XXX", "roughness": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_roughness.png?Expires=XXX", "emission": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_emission.png?Expires=XXX" } ], "preceding_tasks": 0, "task_error": { "message": "" }, "consumed_credits": 20 } ``` --- # Image to 3D API Source: https://docs.meshy.ai/api/image-to-3d # Image to 3D API Image to 3D API is a feature that allows you to integrate Meshy's Image to 3D capabilities into your own application. In this section, you'll find all the information you need to get started with this API. --- ## POST /openapi/v1/image-to-3d -- Create an Image to 3D Task This endpoint allows you to create a new Image to 3D task. Refer to [The Image to 3D Task Object](#the-image-to-3d-task-object) to see which properties are included with Image to 3D task object. ### Parameters > **Note:** Only one of `input_task_id` or `image_url` is **required**. If both are provided, `input_task_id` takes priority. - `input_task_id` · *string* · **required** The ID of a completed image-generation task whose output should be used as the input image. This task must be one of the following tasks: Text to Image or Image to Image. In addition, it must have been run via the API, have a status of `SUCCEEDED`, and produce exactly one image. - `image_url` · *string* · **required** Provide an image for Meshy to use in model creation. We currently support `.jpg`, `.jpeg`, and `.png` formats. There are two ways to provide the image: - **Publicly accessible URL**: A URL that is accessible from the public internet. - **Data URI**: A base64-encoded data URI of the image. Example of a data URI: `data:image/jpeg;base64,`. - `model_type` · *string* · default: `standard` Specify the type of 3D mesh generation. Available values: * `standard`: Regular high-detail 3D mesh generation. * `lowpoly`: Generates low-poly mesh optimized for cleaner polygons. > **Note:** When `lowpoly` is selected, `ai_model`, `topology`, `target_polycount`, `should_remesh`, `save_pre_remeshed_model` are ignored. - `ai_model` · *string* · default: `latest` ID of the model to use. Available values: `meshy-5`, `meshy-6`, `latest` (Meshy 6). - `should_texture` · *boolean* · default: `true` Determines if textures are generated. Setting it to `false` skips the texture phase, providing a mesh without textures. **Only when `should_texture` is set:** - `enable_pbr` · *boolean* · default: `false` Generate PBR Maps (metallic, roughness, normal) in addition to the base color. An emission map is also included when `ai_model` is `meshy-6` or `latest`. - `hd_texture` · *boolean* · default: `false` Generate the base color texture at 4K (4096×4096) resolution for higher detail. > **Note:** Only supported when `ai_model` is `meshy-6` or `latest`. PBR maps are always generated at 2K. - `texture_prompt` · *string* Provide a text prompt to guide the texturing process. Maximum 600 characters. - `texture_image_url` · *string* Provide a 2d image to guide the texturing process. We currently support `.jpg`, `.jpeg`, and `.png` formats. There are two ways to provide the image: - **Publicly accessible URL**: A URL that is accessible from the public internet - **Data URI**: A base64-encoded data URI of the image. Example of a data URI: `data:image/jpeg;base64,` > **Note:** Image texturing may not work optimally if there are substantial geometry differences between the original asset and uploaded image. Only one of `texture_image_url` or `texture_prompt` may be used to guide the texturing process. If both parameters are provided, then `texture_prompt` will be used to texture the model by default. Texturing via either text or image will cost 10 credits per task. - `should_remesh` · *boolean* · default: `false (meshy-6), true (others)` Controls whether to enable the remesh phase. When set to `false`, the API returns the highest-precision triangular mesh. **Only when `should_remesh` is set:** - `topology` · *string* · default: `triangle` Specify the topology of the generated model. Available values: * `quad`: Generate a quad-dominant mesh. * `triangle`: Generate a decimated triangle mesh. - `target_polycount` · *integer* · default: `30,000` Specify the target number of polygons in the generated model. The actual number of polygons may deviate from the target depending on the complexity of the geometry. The valid value range varies depending on the user tier: * 100 to 300,000 (inclusive) - `decimation_mode` · *integer* Enable adaptive decimation by setting a polycount level. When set, `target_polycount` is ignored. Available values: * `1`: Adaptive — ultra polycount. * `2`: Adaptive — high polycount. * `3`: Adaptive — medium polycount. * `4`: Adaptive — low polycount. - `save_pre_remeshed_model` · *boolean* · default: `false` When set to `true`, Meshy also stores an extra GLB file before the remesh phase completes. - `symmetry_mode` · *string* · default: `auto` · **deprecated** Deprecated. This parameter no longer affects output. The `symmetry_mode` field controls symmetry behavior during the model generation process. The valid values are: * `off`: Disables symmetry. * `auto`: Automatically determines and applies symmetry based on input geometry. * `on`: Enforces symmetry during generation. - `pose_mode` · *string* · default: `""` Specify the pose mode for the generated model. Available values: * `a-pose`: Generate the model in an A pose. * `t-pose`: Generate the model in a T pose. * `""` (empty string): No specific pose applied. - `is_a_t_pose` · *boolean* · default: `false` · **deprecated** Use `pose_mode` instead. Whether to generate the model in an A/T pose. - `image_enhancement` · *boolean* · default: `true` Optimizes the input image for better results. Set to `false` to preserve the exact appearance of the input image without any style processing. > **Note:** Only supported when `ai_model` is `meshy-6` or `latest`. - `remove_lighting` · *boolean* · default: `true` Removes highlights and shadows from the base color texture, producing a cleaner result that works better under custom lighting setups. > **Note:** Only supported when `ai_model` is `meshy-6` or `latest`. - `moderation` · *boolean* · default: `false` When set to `true`, the input content will automatically be screened for potentially harmful content. If harmful content is detected, the task will not proceed to generation. The content from the `image_url`, `texture_image_url`, and `texture_prompt` inputs will be screened. - `target_formats` · *string[]* Specifies which 3D file formats to include in the output. Only the requested formats will be generated and returned, which can reduce task completion time. When omitted, all supported formats are included. Available values: `glb`, `obj`, `fbx`, `stl`, `usdz`, `3mf` > **Note:** When omitted, all formats except `3mf` are generated. `3mf` is only included when explicitly specified. - `auto_size` · *boolean* · default: `false` When set to `true`, the service uses AI vision to automatically estimate the real-world height of the object and resize the model accordingly. The origin will default to `bottom` unless `origin_at` is explicitly set. - `alpha_thumbnail` · *boolean* · default: `false` When set to `true`, the task additionally renders a transparent-background (RGBA) version of the preview and returns it as `alpha_thumbnail_url` on the GET response. The existing `thumbnail_url` field is unchanged. - `multi_view_thumbnails` · *boolean* · default: `false` When set to `true`, the task additionally renders four cardinal-view thumbnails (front, right, back, left) and returns them under `thumbnail_urls` on the GET response. The existing `thumbnail_url` field is unchanged and continues to point at the front view, so existing clients are unaffected. > **Note:** Adds approximately 3 seconds to task latency. **Only when `auto_size` is set:** - `origin_at` · *string* · default: `bottom` Position of the origin when `auto_size` is enabled. Available values: `bottom`, `center`. ### Returns The `result` property of the response contains the task `id` of the newly created Image to 3D task. ### Failure Modes - `400 - Bad Request` The request was unacceptable. Common causes: * **Missing parameter**: Either `image_url` or `input_task_id` must be provided. * **Invalid input task**: The `input_task_id` must refer to a `SUCCEEDED` Text to Image or Image to Image task that produces exactly one image. * **Invalid image format**: The provided `image_url` is not a supported format (.jpg, .jpeg, .png). * **Unreachable URL**: The `image_url` could not be downloaded (404 or timeout). * **Invalid Data URI**: The base64 string is malformed. * **Invalid parameter combination**: `enable_pbr` is only supported when `should_texture` is true. - `401 - Unauthorized` Authentication failed. Please check your API key. - `402 - Payment Required` Insufficient credits to perform this task. - `429 - Too Many Requests` You have exceeded your rate limit. **cURL** ```bash # Simple request with required params curl https://api.meshy.ai/openapi/v1/image-to-3d \ -X POST \ -H "Authorization: Bearer ${YOUR_API_KEY}" \ -H 'Content-Type: application/json' \ -d '{ "image_url": "" }' # With remesh, PBR, and A-pose curl https://api.meshy.ai/openapi/v1/image-to-3d \ -X POST \ -H "Authorization: Bearer ${YOUR_API_KEY}" \ -H 'Content-Type: application/json' \ -d '{ "image_url": "", "enable_pbr": true, "should_remesh": true, "target_polycount": 100000, "should_texture": true, "pose_mode": "a-pose", "target_formats": ["glb"] }' ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; // Simple request with required params const payload = { image_url: "", }; try { const response = await axios.post( 'https://api.meshy.ai/openapi/v1/image-to-3d', payload, { headers } ); console.log(response.data); } catch (error) { console.error(error); } // With remesh, PBR, and A-pose const advancedPayload = { image_url: "", enable_pbr: true, should_remesh: true, target_polycount: 100000, should_texture: true, pose_mode: "a-pose", target_formats: ["glb"], }; try { const response = await axios.post( 'https://api.meshy.ai/openapi/v1/image-to-3d', advancedPayload, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } # Simple request with required params payload = { "image_url": "", } response = requests.post( "https://api.meshy.ai/openapi/v1/image-to-3d", headers=headers, json=payload, ) response.raise_for_status() print(response.json()) # With remesh, PBR, and A-pose advanced_payload = { "image_url": "", "enable_pbr": True, "should_remesh": True, "target_polycount": 100000, "should_texture": True, "pose_mode": "a-pose", "target_formats": ["glb"], } response = requests.post( "https://api.meshy.ai/openapi/v1/image-to-3d", headers=headers, json=advanced_payload, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "result": "018a210d-8ba4-705c-b111-1f1776f7f578" } ``` --- ## GET /openapi/v1/image-to-3d/:id -- Retrieve an Image to 3D Task This endpoint allows you to retrieve an Image to 3D task given a valid task `id`. Refer to [The Image to 3D Task Object](#the-image-to-3d-task-object) to see which properties are included with Image to 3D task object. ### Parameters - `id` · *path* Unique identifier for the Image to 3D task to retrieve. ### Returns The response contains the Image to 3D task object. Check [The Image to 3D Task Object](#the-image-to-3d-task-object) section for details. **cURL** ```bash curl https://api.meshy.ai/openapi/v1/image-to-3d/018a210d-8ba4-705c-b111-1f1776f7f578 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const taskId = '018a210d-8ba4-705c-b111-1f1776f7f578'; const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; try { const response = await axios.get( `https://api.meshy.ai/openapi/v1/image-to-3d/${taskId}`, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests task_id = "018a210d-8ba4-705c-b111-1f1776f7f578" headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.get( f"https://api.meshy.ai/openapi/v1/image-to-3d/{task_id}", headers=headers, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "image-to-3d", "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=***", "obj": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.obj?Expires=***", "usdz": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.usdz?Expires=***", "stl": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.stl?Expires=***", "pre_remeshed_glb": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/pre_remeshed_model.glb?Expires=***" }, "thumbnail_url": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview.png?Expires=***", "thumbnail_urls": { "front": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview_front.png?Expires=***", "right": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview_right.png?Expires=***", "back": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview_back.png?Expires=***", "left": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview_left.png?Expires=***" }, "texture_prompt": "", "progress": 100, "started_at": 1692771667037, "created_at": 1692771650657, "expires_at": 1692771679037, "finished_at": 1692771669037, "status": "SUCCEEDED", "texture_urls": [ { "base_color": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0.png?Expires=***", "metallic": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_metallic.png?Expires=XXX", "normal": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_normal.png?Expires=XXX", "roughness": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_roughness.png?Expires=XXX", "emission": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_emission.png?Expires=XXX" } ], "preceding_tasks": 0, "task_error": { "message": "" }, "consumed_credits": 30 } ``` --- ## DELETE /openapi/v1/image-to-3d/:id -- Delete an Image to 3D Task This endpoint permanently deletes an Image to 3D task, including all associated models and data. This action is irreversible. ### Path Parameters - `id` · *path* The ID of the Image to 3D task to delete. ### Returns Returns `200 OK` on success. **cURL** ```bash curl --request DELETE \ --url https://api.meshy.ai/openapi/v1/image-to-3d/018a210d-8ba4-705c-b111-1f1776f7f578 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const taskId = '018a210d-8ba4-705c-b111-1f1776f7f578' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` } try { await axios.delete( `https://api.meshy.ai/openapi/v1/image-to-3d/${taskId}`, { headers } ) } catch (error) { console.error(error) } ``` ```python import requests task_id = "018a210d-8ba4-705c-b111-1f1776f7f578" headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.delete( f"https://api.meshy.ai/openapi/v1/image-to-3d/{task_id}", headers=headers, ) response.raise_for_status() ``` **Response** ```json // Returns 200 Ok on success. ``` --- ## GET /openapi/v1/image-to-3d -- List Image to 3D Tasks This endpoint allows you to retrieve a list of Image to 3D tasks. ### Parameters #### Optional attributes - `page_num` · *integer* Page number for pagination. Starts and defaults to `1`. - `page_size` · *integer* Page size limit. Defaults to `10` items. Maximum allowed is `50` items. - `sort_by` · *string* Field to sort by. Available values: * `+created_at`: Sort by creation time in ascending order. * `-created_at`: Sort by creation time in descending order. ### Returns Returns a paginated list of [The Image to 3D Task Objects](#the-image-to-3d-task-object). **cURL** ```bash curl https://api.meshy.ai/openapi/v1/image-to-3d?page_size=10 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; try { const response = await axios.get( `https://api.meshy.ai/openapi/v1/image-to-3d?page_size=10`, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.get( "https://api.meshy.ai/openapi/v1/image-to-3d", headers=headers, params={"page_size": 10} ) response.raise_for_status() print(response.json()) ``` **Response** ```json [ { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "image-to-3d", "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=***", "obj": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.obj?Expires=***", "usdz": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.usdz?Expires=***", "pre_remeshed_glb": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/pre_remeshed_model.glb?Expires=***" }, "thumbnail_url": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview.png?Expires=***", "thumbnail_urls": { "front": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview_front.png?Expires=***", "right": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview_right.png?Expires=***", "back": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview_back.png?Expires=***", "left": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview_left.png?Expires=***" }, "texture_prompt": "", "progress": 100, "started_at": 1692771667037, "created_at": 1692771650657, "expires_at": 1692771679037, "finished_at": 1692771669037, "status": "SUCCEEDED", "texture_urls": [ { "base_color": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0.png?Expires=***", "metallic": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_metallic.png?Expires=XXX", "normal": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_normal.png?Expires=XXX", "roughness": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_roughness.png?Expires=XXX", "emission": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_emission.png?Expires=XXX" } ], "preceding_tasks": 0, "task_error": { "message": "" }, "consumed_credits": 30 } ] ``` --- ## GET /openapi/v1/image-to-3d/:id/stream -- Stream an Image to 3D Task This endpoint streams real-time updates for an Image to 3D task using Server-Sent Events (SSE). ### Parameters - `id` · *path* Unique identifier for the Image to 3D task to stream. ### Returns Returns a stream of [The Image to 3D Task Objects](#the-image-to-3d-task-object) as Server-Sent Events. For `PENDING` or `IN_PROGRESS` tasks, the response stream will only include necessary `progress` and `status` fields. **cURL** ```bash curl -N https://api.meshy.ai/openapi/v1/image-to-3d/018a210d-8ba4-705c-b111-1f1776f7f578/stream \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript const response = await fetch( 'https://api.meshy.ai/openapi/v1/image-to-3d/018a210d-8ba4-705c-b111-1f1776f7f578/stream', { headers: { Authorization: `Bearer ${YOUR_API_KEY}` } } ); const reader = response.body.getReader(); const decoder = new TextDecoder(); let buffer = ''; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const lines = buffer.split('\n'); buffer = lines.pop(); for (const line of lines) { if (line.startsWith('data:')) { const data = JSON.parse(line.slice(5)); console.log(data); if (['SUCCEEDED', 'FAILED', 'CANCELED'].includes(data.status)) { reader.cancel(); } } } } ``` ```python import requests import json headers = { "Authorization": f"Bearer {YOUR_API_KEY}", "Accept": "text/event-stream" } response = requests.get( 'https://api.meshy.ai/openapi/v1/image-to-3d/018a210d-8ba4-705c-b111-1f1776f7f578/stream', headers=headers, stream=True ) for line in response.iter_lines(): if line: if line.startswith(b'data:'): data = json.loads(line.decode('utf-8')[5:]) print(data) if data['status'] in ['SUCCEEDED', 'FAILED', 'CANCELED']: break response.close() ``` **Response Stream** ```javascript // Error event example event: error data: { "status_code": 404, "message": "Task not found" } // Message event examples illustrate task progress. // For PENDING or IN_PROGRESS tasks, the response stream will not include all fields. event: message data: { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "progress": 0, "status": "PENDING" } event: message data: { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "image-to-3d", "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=***", "obj": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.obj?Expires=***", "usdz": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.usdz?Expires=***", "stl": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.stl?Expires=***", "pre_remeshed_glb": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/pre_remeshed_model.glb?Expires=***" }, "thumbnail_url": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview.png?Expires=***", "thumbnail_urls": { "front": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview_front.png?Expires=***", "right": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview_right.png?Expires=***", "back": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview_back.png?Expires=***", "left": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview_left.png?Expires=***" }, "texture_prompt": "", "progress": 100, "started_at": 1692771667037, "created_at": 1692771650657, "expires_at": 1692771679037, "finished_at": 1692771669037, "status": "SUCCEEDED", "texture_urls": [ { "base_color": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0.png?Expires=***", "metallic": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_metallic.png?Expires=XXX", "normal": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_normal.png?Expires=XXX", "roughness": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_roughness.png?Expires=XXX", "emission": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_emission.png?Expires=XXX" } ], "preceding_tasks": 0, "task_error": { "message": "" }, "consumed_credits": 30 } ``` --- ## The Image to 3D Task Object The Image to 3D Task object is a work unit that Meshy keeps track of to generate a 3D model from an **image** input. The object has the following properties: ### Properties - `id` · *string* Unique identifier for the task. While we use a k-sortable UUID for task ids as the implementation detail, you should **not** make any assumptions about the format of the id. - `type` · *string* Type of the Image to 3D task. The value is `image-to-3d`. - `model_urls` · *object* Downloadable URL to the textured 3D model file generated by Meshy. The property for a format will be omitted if the format is not generated instead of returning an empty string. - `glb` · *string* Downloadable URL to the GLB file. - `fbx` · *string* Downloadable URL to the FBX file. - `obj` · *string* Downloadable URL to the OBJ file. - `usdz` · *string* Downloadable URL to the USDZ file. - `mtl` · *string* Downloadable URL to the MTL file, returned alongside OBJ exports when textures are present. - `stl` · *string* Downloadable URL to the STL file. - `3mf` · *string* Downloadable URL to the 3MF file. Only present when `3mf` was requested via `target_formats`. - `pre_remeshed_glb` · *string* Downloadable URL to the original GLB output before remeshing. > **Note:** Available only when the task was created with both `should_remesh: true` and `save_pre_remeshed_model: true`. - `thumbnail_url` · *string* Downloadable URL to the thumbnail image of the model file. Equivalent to `thumbnail_urls.front` when present, kept for backwards compatibility. - `alpha_thumbnail_url` · *string* Downloadable URL to a transparent-background (RGBA) version of `thumbnail_url`. Only present when the task was created with `alpha_thumbnail: true` and the transparent preview was successfully rendered; otherwise this field is omitted. - `thumbnail_urls` · *object* Downloadable URLs for four cardinal-view thumbnails of the generated 3D model. Each value is a signed URL to a 512×512 PNG rendered with the same materials and lighting as `thumbnail_url`. Useful for previewing the model from multiple angles in batch pipelines without downloading the GLB. > **Note:** Only present when the task was created with `multi_view_thumbnails: true` and has reached `SUCCEEDED`. Older tasks and tasks created without the opt-in will not include this field. - `front` · *string* Front view, 0° rotation around the vertical axis (matches `thumbnail_url`). - `right` · *string* Right view, 90° rotation. - `back` · *string* Back view, 180° rotation. - `left` · *string* Left view, 270° rotation. - `texture_prompt` · *string* The text prompt that was used to guide the texturing process. - `texture_image_url` · *string* Downloadable URL to the texture image that was used to guide the texturing process. - `progress` · *integer* Progress of the task. If the task is not started yet, this property will be `0`. Once the task has succeeded, this will become `100`. - `started_at` · *timestamp* Timestamp of when the task was started, in milliseconds. If the task is not started yet, this property will be `0`. > **Note:** A timestamp represents the number of milliseconds elapsed since January 1, 1970 UTC, following > the [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339) standard. > For example, Friday, September 1, 2023 12:00:00 PM GMT is represented as `1693569600000`. This applies > to **all** timestamps in Meshy API. - `created_at` · *timestamp* Timestamp of when the task was created, in milliseconds. - `expires_at` · *timestamp* Timestamp of when the task result expires, in milliseconds. - `finished_at` · *timestamp* Timestamp of when the task was finished, in milliseconds. If the task is not finished yet, this property will be `0`. - `status` · *string* Status of the task. Possible values are one of `PENDING`, `IN_PROGRESS`, `SUCCEEDED`, `FAILED`, `CANCELED`. - `texture_urls` · *array* An array of texture URL objects that are generated from the task. Normally this only contains **one** texture URL object. Each texture URL has the following properties: - `base_color` · *string* Downloadable URL to the base color map image. - `metallic` · *string* Downloadable URL to the metallic map image. > **Note:** If the task is created with `enable_pbr: false`, this property will be omitted. - `normal` · *string* Downloadable URL to the normal map image. > **Note:** If the task is created with `enable_pbr: false`, this property will be omitted. - `roughness` · *string* Downloadable URL to the roughness map image. > **Note:** If the task is created with `enable_pbr: false`, this property will be omitted. - `emission` · *string* Downloadable URL to the emission map image. > **Note:** If the task is created with `enable_pbr: false`, or `ai_model` is `meshy-5`, this property will be omitted. - `preceding_tasks` · *integer* The count of preceding tasks. > **Note:** The value of this field is meaningful only if the task status is `PENDING`. - `task_error` · *object* Error details for failed tasks. See [Errors](/api/errors#task-errors) for the full `task_error` object reference. - `consumed_credits` · *integer* The number of credits consumed by this task. Present when the task status is `PENDING`, `IN_PROGRESS`, or `SUCCEEDED`. Returns `0` for `FAILED` tasks (credits are refunded on failure). **Example Image to 3D Task Object** ```json { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "image-to-3d", "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=***", "obj": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.obj?Expires=***", "usdz": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.usdz?Expires=***", "stl": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.stl?Expires=***", "pre_remeshed_glb": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/pre_remeshed_model.glb?Expires=***" }, "thumbnail_url": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview.png?Expires=***", "thumbnail_urls": { "front": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview_front.png?Expires=***", "right": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview_right.png?Expires=***", "back": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview_back.png?Expires=***", "left": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview_left.png?Expires=***" }, "texture_prompt": "", "texture_image_url": "", "progress": 100, "started_at": 1692771667037, "created_at": 1692771650657, "expires_at": 1692771679037, "finished_at": 1692771669037, "status": "SUCCEEDED", "texture_urls": [ { "base_color": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0.png?Expires=***", "metallic": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_metallic.png?Expires=XXX", "normal": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_normal.png?Expires=XXX", "roughness": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_roughness.png?Expires=XXX", "emission": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_emission.png?Expires=XXX" } ], "preceding_tasks": 0, "task_error": { "message": "" }, "consumed_credits": 30 } ``` --- # Multi-Image to 3D API Source: https://docs.meshy.ai/api/multi-image-to-3d # Multi-Image to 3D API Multi-Image to 3D API is a feature that allows you to integrate Meshy's Multi-Image to 3D capabilities into your own application. In this section, you'll find all the information you need to get started with this API. --- ## POST /openapi/v1/multi-image-to-3d -- Create a Multi-Image to 3D Task This endpoint allows you to create a new Multi-Image to 3D task. Refer to [The Multi-Image to 3D Task Object](#the-multi-image-to-3d-task-object) to see which properties are included with Multi-Image to 3D task object. ### Parameters > **Note:** Only one of `input_task_id` or `image_urls` is **required**. If both are provided, `input_task_id` takes priority. - `input_task_id` · *string* · **required** The ID of a completed image-generation task whose output (1-4 images) should be used as the input. This task must be one of the following tasks: Text to Image, Image to Image, Text to Image Multi-View, or Image to Image Multi-View. In addition, it must have been run via the API and have a status of `SUCCEEDED`. - `image_urls` · *array* · **required** Provide 1 to 4 images for Meshy to use in model creation. We currently support `.jpg`, `.jpeg`, and `.png` formats. All images should depict the same object from different angles for best results. There are two ways to provide each image: - **Publicly accessible URL**: A URL that is accessible from the public internet. - **Data URI**: A base64-encoded data URI of the image. Example of a data URI: `data:image/jpeg;base64,`. - `ai_model` · *string* · default: `latest` ID of the model to use. Available values: `meshy-5`, `meshy-6`, `latest` (Meshy 6). - `should_texture` · *boolean* · default: `true` Determines if textures are generated. Setting it to `false` skips the texture phase, providing a mesh without textures. **Only when `should_texture` is set:** - `enable_pbr` · *boolean* · default: `false` Generate PBR Maps (metallic, roughness, normal) in addition to the base color. An emission map is also included when `ai_model` is `meshy-6` or `latest`. - `hd_texture` · *boolean* · default: `false` Generate the base color texture at 4K (4096×4096) resolution for higher detail. > **Note:** Only supported when `ai_model` is `meshy-6` or `latest`. PBR maps are always generated at 2K. - `texture_prompt` · *string* Provide a text prompt to guide the texturing process. Maximum 600 characters. - `texture_image_url` · *string* Provide a 2d image to guide the texturing process. We currently support `.jpg`, `.jpeg`, and `.png` formats. There are two ways to provide the image: - **Publicly accessible URL**: A URL that is accessible from the public internet - **Data URI**: A base64-encoded data URI of the image. Example of a data URI: `data:image/jpeg;base64,` > **Note:** Image texturing may not work optimally if there are substantial geometry differences between the original asset and uploaded image. Only one of `texture_image_url` or `texture_prompt` may be used to guide the texturing process. If both parameters are provided, then `texture_prompt` will be used to texture the model by default. - `should_remesh` · *boolean* · default: `false (meshy-6), true (others)` Controls whether to enable the remesh phase. When set to `false`, the API returns the highest-precision triangular mesh. **Only when `should_remesh` is set:** - `topology` · *string* · default: `triangle` Specify the topology of the generated model. Available values: * `quad`: Generate a quad-dominant mesh. * `triangle`: Generate a decimated triangle mesh. - `target_polycount` · *integer* · default: `30,000` Specify the target number of polygons in the generated model. The actual number of polygons may deviate from the target depending on the complexity of the geometry. The valid value range varies depending on the user tier: * 100 to 300,000 (inclusive) - `decimation_mode` · *integer* Enable adaptive decimation by setting a polycount level. When set, `target_polycount` is ignored. Available values: * `1`: Adaptive — ultra polycount. * `2`: Adaptive — high polycount. * `3`: Adaptive — medium polycount. * `4`: Adaptive — low polycount. - `save_pre_remeshed_model` · *boolean* · default: `false` When set to `true`, Meshy also stores an extra GLB file before the remesh phase completes. - `symmetry_mode` · *string* · default: `auto` · **deprecated** Deprecated. This parameter no longer affects output. The `symmetry_mode` field controls symmetry behavior during the model generation process. The valid values are: * `off`: Disables symmetry. * `auto`: Automatically determines and applies symmetry based on input geometry. * `on`: Enforces symmetry during generation. - `pose_mode` · *string* · default: `""` Specify the pose mode for the generated model. Available values: * `a-pose`: Generate the model in an A pose. * `t-pose`: Generate the model in a T pose. * `""` (empty string): No specific pose applied. - `is_a_t_pose` · *boolean* · default: `false` · **deprecated** Use `pose_mode` instead. Whether to generate the model in an A/T pose. - `image_enhancement` · *boolean* · default: `true` Optimizes the input images for better results. Set to `false` to preserve the exact appearance of the input images without any style processing. > **Note:** Only supported when `ai_model` is `meshy-6` or `latest`. - `remove_lighting` · *boolean* · default: `true` Removes highlights and shadows from the base color texture, producing a cleaner result that works better under custom lighting setups. > **Note:** Only supported when `ai_model` is `meshy-6` or `latest`. - `moderation` · *boolean* · default: `false` When set to `true`, the input content will automatically be screened for potentially harmful content. If harmful content is detected, the task will not proceed to generation. Each image from `image_urls` and the text from `texture_prompt` will be screened. - `target_formats` · *string[]* Specifies which 3D file formats to include in the output. Only the requested formats will be generated and returned, which can reduce task completion time. Available values: `glb`, `obj`, `fbx`, `stl`, `usdz`, `3mf` > **Note:** When omitted, all formats except `3mf` are generated. `3mf` is only included when explicitly specified. - `auto_size` · *boolean* · default: `false` When set to `true`, the service uses AI vision to automatically estimate the real-world height of the object and resize the model accordingly. The origin will default to `bottom` unless `origin_at` is explicitly set. - `alpha_thumbnail` · *boolean* · default: `false` When set to `true`, the task additionally renders a transparent-background (RGBA) version of the preview and returns it as `alpha_thumbnail_url` on the GET response. The existing `thumbnail_url` field is unchanged. - `multi_view_thumbnails` · *boolean* · default: `false` When set to `true`, the task additionally renders four cardinal-view thumbnails (front, right, back, left) and returns them under `thumbnail_urls` on the GET response. The existing `thumbnail_url` field is unchanged and continues to point at the front view, so existing clients are unaffected. > **Note:** Adds approximately 3 seconds to task latency. **Only when `auto_size` is set:** - `origin_at` · *string* · default: `bottom` Position of the origin when `auto_size` is enabled. Available values: `bottom`, `center`. ### Returns The `result` property of the response contains the task `id` of the newly created Multi-Image to 3D task. ### Failure Modes - `400 - Bad Request` The request was unacceptable. Common causes: * **Missing parameter**: Either `image_urls` or `input_task_id` must be provided. * **Invalid input task**: The `input_task_id` must refer to a `SUCCEEDED` Text to Image, Image to Image, or multi-view variant task. * **Invalid image count**: `image_urls` must contain between 1 and 4 images. * **Invalid image format**: One or more images in `image_urls` are not supported formats. * **Unreachable URL**: One or more `image_urls` could not be downloaded. - `401 - Unauthorized` Authentication failed. Please check your API key. - `402 - Payment Required` Insufficient credits to perform this task. - `429 - Too Many Requests` You have exceeded your rate limit. **cURL** ```bash # Simple request curl https://api.meshy.ai/openapi/v1/multi-image-to-3d \ -X POST \ -H "Authorization: Bearer ${YOUR_API_KEY}" \ -H 'Content-Type: application/json' \ -d '{ "image_urls": [ "", "" ] }' # With PBR texturing and GLB format curl https://api.meshy.ai/openapi/v1/multi-image-to-3d \ -X POST \ -H "Authorization: Bearer ${YOUR_API_KEY}" \ -H 'Content-Type: application/json' \ -d '{ "image_urls": [ "", "" ], "should_texture": true, "enable_pbr": true, "target_formats": ["glb"] }' ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; // Simple request const payload = { image_urls: [ "", "" ], }; try { const response = await axios.post( 'https://api.meshy.ai/openapi/v1/multi-image-to-3d', payload, { headers } ); console.log(response.data); } catch (error) { console.error(error); } // With PBR texturing and GLB format const advancedPayload = { image_urls: [ "", "" ], should_texture: true, enable_pbr: true, target_formats: ["glb"], }; try { const response = await axios.post( 'https://api.meshy.ai/openapi/v1/multi-image-to-3d', advancedPayload, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests # Simple request payload = { "image_urls": [ "", "" ], } headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } # Simple request response = requests.post( "https://api.meshy.ai/openapi/v1/multi-image-to-3d", headers=headers, json=payload, ) response.raise_for_status() print(response.json()) # With PBR texturing and GLB format advanced_payload = { "image_urls": [ "", "" ], "should_texture": True, "enable_pbr": True, "target_formats": ["glb"], } response = requests.post( "https://api.meshy.ai/openapi/v1/multi-image-to-3d", headers=headers, json=payload, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "result": "018a210d-8ba4-705c-b111-1f1776f7f578" } ``` --- ## GET /openapi/v1/multi-image-to-3d/:id -- Retrieve a Multi-Image to 3D Task This endpoint allows you to retrieve a Multi-Image to 3D task given a valid task `id`. Refer to [The Multi-Image to 3D Task Object](#the-multi-image-to-3d-task-object) to see which properties are included with Multi-Image to 3D task object. ### Parameters - `id` · *path* Unique identifier for the Multi-Image to 3D task to retrieve. ### Returns The response contains the Multi-Image to 3D task object. Check [The Multi-Image to 3D Task Object](#the-multi-image-to-3d-task-object) section for details. **cURL** ```bash curl https://api.meshy.ai/openapi/v1/multi-image-to-3d/018a210d-8ba4-705c-b111-1f1776f7f578 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const taskId = '018a210d-8ba4-705c-b111-1f1776f7f578'; const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; try { const response = await axios.get( `https://api.meshy.ai/openapi/v1/multi-image-to-3d/${taskId}`, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests task_id = "018a210d-8ba4-705c-b111-1f1776f7f578" headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.get( f"https://api.meshy.ai/openapi/v1/multi-image-to-3d/{task_id}", headers=headers, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "multi-image-to-3d", "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=***", "obj": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.obj?Expires=***", "usdz": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.usdz?Expires=***", "stl": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.stl?Expires=***", "pre_remeshed_glb": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/pre_remeshed_model.glb?Expires=***" }, "thumbnail_url": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview.png?Expires=***", "thumbnail_urls": { "front": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview_front.png?Expires=***", "right": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview_right.png?Expires=***", "back": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview_back.png?Expires=***", "left": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview_left.png?Expires=***" }, "texture_prompt": "", "progress": 100, "started_at": 1692771667037, "created_at": 1692771650657, "expires_at": 1692771679037, "finished_at": 1692771669037, "status": "SUCCEEDED", "texture_urls": [ { "base_color": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0.png?Expires=***", "metallic": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_metallic.png?Expires=XXX", "normal": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_normal.png?Expires=XXX", "roughness": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_roughness.png?Expires=XXX", "emission": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_emission.png?Expires=XXX" } ], "preceding_tasks": 0, "task_error": { "message": "" }, "consumed_credits": 30 } ``` --- ## DELETE /openapi/v1/multi-image-to-3d/:id -- Delete a Multi-Image to 3D Task This endpoint permanently deletes a Multi-Image to 3D task, including all associated models and data. This action is irreversible. ### Path Parameters - `id` · *path* The ID of the Multi-Image to 3D task to delete. ### Returns Returns `200 OK` on success. **cURL** ```bash curl --request DELETE \ --url https://api.meshy.ai/openapi/v1/multi-image-to-3d/018a210d-8ba4-705c-b111-1f1776f7f578 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const taskId = '018a210d-8ba4-705c-b111-1f1776f7f578' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` } try { await axios.delete( `https://api.meshy.ai/openapi/v1/multi-image-to-3d/${taskId}`, { headers } ) } catch (error) { console.error(error) } ``` ```python import requests task_id = "018a210d-8ba4-705c-b111-1f1776f7f578" headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.delete( f"https://api.meshy.ai/openapi/v1/multi-image-to-3d/{task_id}", headers=headers, ) response.raise_for_status() ``` **Response** ```json // Returns 200 Ok on success. ``` --- ## GET /openapi/v1/multi-image-to-3d -- List Multi-Image to 3D Tasks This endpoint allows you to retrieve a list of Multi-Image to 3D tasks. ### Parameters #### Optional attributes - `page_num` · *integer* Page number for pagination. Starts and defaults to `1`. - `page_size` · *integer* Page size limit. Defaults to `10` items. Maximum allowed is `50` items. - `sort_by` · *string* Field to sort by. Available values: * `+created_at`: Sort by creation time in ascending order. * `-created_at`: Sort by creation time in descending order. ### Returns Returns a paginated list of [The Multi-Image to 3D Task Objects](#the-multi-image-to-3d-task-object). **cURL** ```bash curl https://api.meshy.ai/openapi/v1/multi-image-to-3d?page_size=10 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; try { const response = await axios.get( `https://api.meshy.ai/openapi/v1/multi-image-to-3d?page_size=10`, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.get( "https://api.meshy.ai/openapi/v1/multi-image-to-3d", headers=headers, params={"page_size": 10} ) response.raise_for_status() print(response.json()) ``` **Response** ```json [ { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "multi-image-to-3d", "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=***", "obj": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.obj?Expires=***", "usdz": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.usdz?Expires=***", "pre_remeshed_glb": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/pre_remeshed_model.glb?Expires=***" }, "thumbnail_url": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview.png?Expires=***", "thumbnail_urls": { "front": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview_front.png?Expires=***", "right": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview_right.png?Expires=***", "back": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview_back.png?Expires=***", "left": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview_left.png?Expires=***" }, "texture_prompt": "", "progress": 100, "started_at": 1692771667037, "created_at": 1692771650657, "expires_at": 1692771679037, "finished_at": 1692771669037, "status": "SUCCEEDED", "texture_urls": [ { "base_color": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0.png?Expires=***", "metallic": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_metallic.png?Expires=XXX", "normal": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_normal.png?Expires=XXX", "roughness": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_roughness.png?Expires=XXX", "emission": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_emission.png?Expires=XXX" } ], "preceding_tasks": 0, "task_error": { "message": "" }, "consumed_credits": 30 } ] ``` --- ## GET /openapi/v1/multi-image-to-3d/:id/stream -- Stream a Multi-Image to 3D Task This endpoint streams real-time updates for a Multi-Image to 3D task using Server-Sent Events (SSE). ### Parameters - `id` · *path* Unique identifier for the Multi-Image to 3D task to stream. ### Returns Returns a stream of [The Multi-Image to 3D Task Objects](#the-multi-image-to-3d-task-object) as Server-Sent Events. For `PENDING` or `IN_PROGRESS` tasks, the response stream will only include necessary `progress` and `status` fields. **cURL** ```bash curl -N https://api.meshy.ai/openapi/v1/multi-image-to-3d/018a210d-8ba4-705c-b111-1f1776f7f578/stream \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript const response = await fetch( 'https://api.meshy.ai/openapi/v1/multi-image-to-3d/018a210d-8ba4-705c-b111-1f1776f7f578/stream', { headers: { Authorization: `Bearer ${YOUR_API_KEY}` } } ); const reader = response.body.getReader(); const decoder = new TextDecoder(); let buffer = ''; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const lines = buffer.split('\n'); buffer = lines.pop(); for (const line of lines) { if (line.startsWith('data:')) { const data = JSON.parse(line.slice(5)); console.log(data); if (['SUCCEEDED', 'FAILED', 'CANCELED'].includes(data.status)) { reader.cancel(); } } } } ``` ```python import requests import json headers = { "Authorization": f"Bearer {YOUR_API_KEY}", "Accept": "text/event-stream" } response = requests.get( 'https://api.meshy.ai/openapi/v1/multi-image-to-3d/018a210d-8ba4-705c-b111-1f1776f7f578/stream', headers=headers, stream=True ) for line in response.iter_lines(): if line: if line.startswith(b'data:'): data = json.loads(line.decode('utf-8')[5:]) print(data) if data['status'] in ['SUCCEEDED', 'FAILED', 'CANCELED']: break response.close() ``` **Response Stream** ```text // Error event example event: error data: { "status_code": 404, "message": "Task not found" } // Message event examples illustrate task progress. // For PENDING or IN_PROGRESS tasks, the response stream will not include all fields. event: message data: { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "progress": 0, "status": "PENDING" } event: message data: { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "multi-image-to-3d", "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=***", "obj": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.obj?Expires=***", "usdz": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.usdz?Expires=***", "stl": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.stl?Expires=***", "pre_remeshed_glb": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/pre_remeshed_model.glb?Expires=***" }, "thumbnail_url": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview.png?Expires=***", "thumbnail_urls": { "front": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview_front.png?Expires=***", "right": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview_right.png?Expires=***", "back": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview_back.png?Expires=***", "left": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview_left.png?Expires=***" }, "texture_prompt": "", "progress": 100, "started_at": 1692771667037, "created_at": 1692771650657, "expires_at": 1692771679037, "finished_at": 1692771669037, "status": "SUCCEEDED", "texture_urls": [ { "base_color": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0.png?Expires=***", "metallic": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_metallic.png?Expires=XXX", "normal": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_normal.png?Expires=XXX", "roughness": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_roughness.png?Expires=XXX", "emission": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_emission.png?Expires=XXX" } ], "preceding_tasks": 0, "task_error": { "message": "" }, "consumed_credits": 30 } ``` --- ## The Multi-Image to 3D Task Object The Multi-Image to 3D Task object is a work unit that Meshy keeps track of to generate a 3d model from multiple images (between 1 to 4 inclusive). The images should be of the same object, ideally from different views or angles. The object has the following properties: ### Properties - `id` · *string* Unique identifier for the task. While we use a k-sortable UUID for task ids as the implementation detail, you should **not** make any assumptions about the format of the id. - `type` · *string* Type of the Multi-Image to 3D task. The value is `multi-image-to-3d`. - `model_urls` · *object* Downloadable URL to the textured 3D model file generated by Meshy. The property for a format will be omitted if the format is not generated instead of returning an empty string. - `glb` · *string* Downloadable URL to the GLB file. - `fbx` · *string* Downloadable URL to the FBX file. - `obj` · *string* Downloadable URL to the OBJ file. - `usdz` · *string* Downloadable URL to the USDZ file. - `mtl` · *string* Downloadable URL to the MTL file, returned alongside OBJ exports when textures are present. - `stl` · *string* Downloadable URL to the STL file. - `3mf` · *string* Downloadable URL to the 3MF file. Only present when `3mf` was requested via `target_formats`. - `pre_remeshed_glb` · *string* Downloadable URL to the original GLB output before remeshing. > **Note:** Available only when the task was created with both `should_remesh: true` and `save_pre_remeshed_model: true`. - `thumbnail_url` · *string* Downloadable URL to the thumbnail image of the model file. Equivalent to `thumbnail_urls.front` when present, kept for backwards compatibility. - `alpha_thumbnail_url` · *string* Downloadable URL to a transparent-background (RGBA) version of `thumbnail_url`. Only present when the task was created with `alpha_thumbnail: true` and the transparent preview was successfully rendered; otherwise this field is omitted. - `thumbnail_urls` · *object* Downloadable URLs for four cardinal-view thumbnails of the generated 3D model. Each value is a signed URL to a 512×512 PNG rendered with the same materials and lighting as `thumbnail_url`. Useful for previewing the model from multiple angles in batch pipelines without downloading the GLB. > **Note:** Only present when the task was created with `multi_view_thumbnails: true` and has reached `SUCCEEDED`. Older tasks and tasks created without the opt-in will not include this field. - `front` · *string* Front view, 0° rotation around the vertical axis (matches `thumbnail_url`). - `right` · *string* Right view, 90° rotation. - `back` · *string* Back view, 180° rotation. - `left` · *string* Left view, 270° rotation. - `texture_prompt` · *string* The text prompt that was used to guide the texturing process. - `progress` · *integer* Progress of the task. If the task is not started yet, this property will be `0`. Once the task has succeeded, this will become `100`. - `started_at` · *timestamp* Timestamp of when the task was started, in milliseconds. If the task is not started yet, this property will be `0`. > **Note:** A timestamp represents the number of milliseconds elapsed since January 1, 1970 UTC, following > the [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339) standard. > For example, Friday, September 1, 2023 12:00:00 PM GMT is represented as `1693569600000`. This applies > to **all** timestamps in Meshy API. - `created_at` · *timestamp* Timestamp of when the task was created, in milliseconds. - `expires_at` · *timestamp* Timestamp of when the task result expires, in milliseconds. - `finished_at` · *timestamp* Timestamp of when the task was finished, in milliseconds. If the task is not finished yet, this property will be `0`. - `status` · *string* Status of the task. Possible values are one of `PENDING`, `IN_PROGRESS`, `SUCCEEDED`, `FAILED`, `CANCELED`. - `texture_urls` · *array* An array of texture URL objects that are generated from the task. Normally this only contains **one** texture URL object. Each texture URL has the following properties: - `base_color` · *string* Downloadable URL to the base color map image. - `metallic` · *string* Downloadable URL to the metallic map image. > **Note:** If the task is created with `enable_pbr: false`, this property will be omitted. - `normal` · *string* Downloadable URL to the normal map image. > **Note:** If the task is created with `enable_pbr: false`, this property will be omitted. - `roughness` · *string* Downloadable URL to the roughness map image. > **Note:** If the task is created with `enable_pbr: false`, this property will be omitted. - `emission` · *string* Downloadable URL to the emission map image. > **Note:** If the task is created with `enable_pbr: false`, or `ai_model` is `meshy-5`, this property will be omitted. - `preceding_tasks` · *integer* The count of preceding tasks. > **Note:** The value of this field is meaningful only if the task status is `PENDING`. - `task_error` · *object* Error details for failed tasks. See [Errors](/api/errors#task-errors) for the full `task_error` object reference. - `consumed_credits` · *integer* The number of credits consumed by this task. Present when the task status is `PENDING`, `IN_PROGRESS`, or `SUCCEEDED`. Returns `0` for `FAILED` tasks (credits are refunded on failure). **Example Multi-Image to 3D Task Object** ```json { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "multi-image-to-3d", "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=***", "obj": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.obj?Expires=***", "usdz": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.usdz?Expires=***", "stl": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.stl?Expires=***", "pre_remeshed_glb": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/pre_remeshed_model.glb?Expires=***" }, "thumbnail_url": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview.png?Expires=***", "thumbnail_urls": { "front": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview_front.png?Expires=***", "right": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview_right.png?Expires=***", "back": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview_back.png?Expires=***", "left": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview_left.png?Expires=***" }, "texture_prompt": "", "progress": 100, "started_at": 1692771667037, "created_at": 1692771650657, "expires_at": 1692771679037, "finished_at": 1692771669037, "status": "SUCCEEDED", "texture_urls": [ { "base_color": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0.png?Expires=***", "metallic": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_metallic.png?Expires=XXX", "normal": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_normal.png?Expires=XXX", "roughness": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_roughness.png?Expires=XXX", "emission": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_emission.png?Expires=XXX" } ], "preceding_tasks": 0, "task_error": { "message": "" }, "consumed_credits": 30, } ``` --- # Remesh API Source: https://docs.meshy.ai/api/remesh # Remesh API The Remesh API allows you to remesh and export existing 3D models generated by other Meshy APIs (like Image to 3D or Text to 3D) into various formats. This section provides details on how to use the Remesh API. --- ## POST /openapi/v1/remesh -- Create a Remesh Task This endpoint creates a new remesh task. > **Note:** For format conversion and resizing, use the dedicated [Convert API](/api/convert) and [Resize API](/api/resize). The deprecated parameters below will continue to work, but we recommend the new endpoints for new integrations. ### Parameters > **Note:** Only one of `input_task_id` or `model_url` is **required**. If both are provided, `input_task_id` takes priority. - `input_task_id` · *string* · **required** The ID of the completed Image to 3D or Text to 3D task you wish to remesh. This task must be one of the following tasks: Text to 3D Preview, Text to 3D Refine, Image to 3D or Retexture. In addition, it must have a status of `SUCCEEDED`. - `model_url` · *string* · **required** Please provide a 3D model for Meshy to remesh via a publicly accessible URL or data URI. Supported formats: `.glb`, `.gltf`, `.obj`, `.fbx`, `.stl`. For Data URIs, use the MIME type: `application/octet-stream`. - `target_formats` · *string[]* · default: `["glb"]` A list of target formats for the remeshed model. When omitted, only GLB is generated. Available values: `glb`, `fbx`, `obj`, `usdz`, `blend`, `stl`, `3mf`. - `topology` · *string* · default: `triangle` Specify the topology of the generated model. Available values: * `quad`: Generate a quad-dominant mesh. * `triangle`: Generate a decimated triangle mesh. - `target_polycount` · *integer* · default: `30,000` Specify the target number of polygons in the generated model. The actual number of polygons may deviate from the target depending on the complexity of the geometry. The valid value range varies depending on the user tier: * 100 to 300,000 (inclusive) - `decimation_mode` · *integer* Enable adaptive decimation by setting a polycount level. When set, `target_polycount` is ignored. Available values: * `1`: Adaptive — ultra polycount. * `2`: Adaptive — high polycount. * `3`: Adaptive — medium polycount. * `4`: Adaptive — low polycount. - `resize_height` · *number* · default: `0` · **deprecated** Resize the model to a certain height measured in meters. We recommend using the dedicated [Resize API](/api/resize) instead. > **Note:** `auto_size`, `resize_height`, and `resize_longest_side` are mutually exclusive. - `resize_longest_side` · *number* · default: `0` · **deprecated** Resize the model so the longest bounding-box dimension equals the specified value in meters. We recommend using the dedicated [Resize API](/api/resize) instead. > **Note:** `auto_size`, `resize_height`, and `resize_longest_side` are mutually exclusive. - `auto_size` · *boolean* · default: `false` · **deprecated** When set to `true`, the service uses AI vision to automatically estimate the real-world height of the object and resize the model accordingly. We recommend using the dedicated [Resize API](/api/resize) instead. > **Note:** `auto_size`, `resize_height`, and `resize_longest_side` are mutually exclusive. **Only when `auto_size` is set:** - `origin_at` · *string* · default: `bottom` · **deprecated** Position of the origin. We recommend using the dedicated [Resize API](/api/resize) instead. Available values: `bottom`, `center`. - `convert_format_only` · *boolean* · **deprecated** If `true`, the service will only change the format of the input model file, ignoring other inputs like `topology`, `resize_height`, and `target_polycount`. We recommend using the dedicated [Convert API](/api/convert) instead. > **Note:** `target_formats` must be provided if `convert_format_only` is set to `true`. - `alpha_thumbnail` · *boolean* · default: `false` When set to `true`, the task additionally renders a transparent-background (RGBA) version of the preview and returns it as `alpha_thumbnail_url` on the GET response. The existing `thumbnail_url` field is unchanged. ### Returns The `result` property of the response contains the `id` of the newly created remesh task. ### Failure Modes - `400 - Bad Request` The request was unacceptable. Common causes: * **Missing parameter**: Either `model_url` or `input_task_id` must be provided. * **Invalid input task**: The `input_task_id` must refer to a successful task from a supported model. * **Invalid model format**: The `model_url` points to a file with an unsupported extension. * **Unreachable URL**: The `model_url` could not be downloaded. * **Invalid topology**: The `topology` parameter is invalid. * **Mutually exclusive parameters**: `auto_size` and `resize_height` cannot both be set. - `401 - Unauthorized` Authentication failed. Please check your API key. - `402 - Payment Required` Insufficient credits to perform this task. - `429 - Too Many Requests` You have exceeded your rate limit. **cURL** ```bash # Basic remesh with custom formats and resize curl https://api.meshy.ai/openapi/v1/remesh \ -X POST \ -H "Authorization: Bearer ${YOUR_API_KEY}" \ -H 'Content-Type: application/json' \ -d '{ "input_task_id": "018a210d-8ba4-705c-b111-1f1776f7f578", "target_formats": ["glb", "fbx"], "topology": "quad", "target_polycount": 50000, "resize_height": 1.0, "origin_at": "bottom" }' # Quad remesh with auto-size curl https://api.meshy.ai/openapi/v1/remesh \ -X POST \ -H "Authorization: Bearer ${YOUR_API_KEY}" \ -H 'Content-Type: application/json' \ -d '{ "input_task_id": "018a210d-8ba4-705c-b111-1f1776f7f578", "target_formats": ["glb", "fbx"], "topology": "quad", "target_polycount": 50000, "auto_size": true }' ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; // Basic remesh with custom formats and resize const payload = { input_task_id: "018a210d-8ba4-705c-b111-1f1776f7f578", target_formats: ["glb", "fbx"], topology: "quad", target_polycount: 50000, resize_height: 1.0, origin_at: "bottom" }; try { const response = await axios.post( 'https://api.meshy.ai/openapi/v1/remesh', payload, { headers } ); console.log(response.data); } catch (error) { console.error(error); } // Quad remesh with auto-size const autoSizePayload = { input_task_id: "018a210d-8ba4-705c-b111-1f1776f7f578", target_formats: ["glb", "fbx"], topology: "quad", target_polycount: 50000, auto_size: true }; try { const response = await axios.post( 'https://api.meshy.ai/openapi/v1/remesh', autoSizePayload, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } # Basic remesh with custom formats and resize payload = { "input_task_id": "018a210d-8ba4-705c-b111-1f1776f7f578", "target_formats": ["glb", "fbx"], "topology": "quad", "target_polycount": 50000, "resize_height": 1.0, "origin_at": "bottom" } response = requests.post( "https://api.meshy.ai/openapi/v1/remesh", headers=headers, json=payload, ) response.raise_for_status() print(response.json()) # Quad remesh with auto-size auto_size_payload = { "input_task_id": "018a210d-8ba4-705c-b111-1f1776f7f578", "target_formats": ["glb", "fbx"], "topology": "quad", "target_polycount": 50000, "auto_size": True } response = requests.post( "https://api.meshy.ai/openapi/v1/remesh", headers=headers, json=auto_size_payload, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "result": "0193bfc5-ee4f-73f8-8525-44b398884ce9" } ``` --- ## GET /openapi/v1/remesh/:id -- Retrieve a Remesh Task This endpoint retrieves a remesh task by its ID. ### Parameters - `id` · *path* The ID of the remesh task to retrieve. ### Returns The Remesh Task object. **cURL** ```bash curl https://api.meshy.ai/openapi/v1/remesh/a43b5c6d-7e8f-901a-234b-567c890d1e2f \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const taskId = 'a43b5c6d-7e8f-901a-234b-567c890d1e2f'; const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; try { const response = await axios.get( `https://api.meshy.ai/openapi/v1/remesh/${taskId}`, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests task_id = "a43b5c6d-7e8f-901a-234b-567c890d1e2f" headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.get( f"https://api.meshy.ai/openapi/v1/remesh/{task_id}", headers=headers, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "id": "0193bfc5-ee4f-73f8-8525-44b398884ce9", "type": "remesh", "model_urls": { "glb": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.glb?Expires=***", "fbx": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.fbx?Expires=***", "obj": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.obj?Expires=***", "usdz": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.usdz?Expires=***", "blend": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.blend?Expires=***", "stl": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.stl?Expires=***" }, "progress": 100, "status": "SUCCEEDED", "created_at": 1699999999000, "started_at": 1700000000000, "finished_at": 1700000001000, "task_error": null, } ``` --- ## DELETE /openapi/v1/remesh/:id -- Delete a Remesh Task This endpoint permanently deletes a remesh task, including all associated models and data. This action is irreversible. ### Path Parameters - `id` · *path* The ID of the remesh task to delete. ### Returns Returns `200 OK` on success. **cURL** ```bash curl --request DELETE \ --url https://api.meshy.ai/openapi/v1/remesh/a43b5c6d-7e8f-901a-234b-567c890d1e2f \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const taskId = 'a43b5c6d-7e8f-901a-234b-567c890d1e2f' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` } try { await axios.delete( `https://api.meshy.ai/openapi/v1/remesh/${taskId}`, { headers } ) } catch (error) { console.error(error) } ``` ```python import requests task_id = "a43b5c6d-7e8f-901a-234b-567c890d1e2f" headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.delete( f"https://api.meshy.ai/openapi/v1/remesh/{task_id}", headers=headers, ) response.raise_for_status() ``` **Response** ```json // Returns 200 Ok on success. ``` --- ## GET /openapi/v1/remesh -- List Remesh Tasks This endpoint allows you to retrieve a list of Remesh tasks. ### Parameters - `page_num` · *integer* · default: `1` Page number for pagination. - `page_size` · *integer* · default: `10` Page size limit. Maximum allowed is `50` items. - `sort_by` · *string* Field to sort by. Available values: * `+created_at`: Sort by creation time in ascending order. * `-created_at`: Sort by creation time in descending order. ### Returns Returns a paginated list of [The Remesh Task Objects](#the-remesh-task-object). **cURL** ```bash curl https://api.meshy.ai/openapi/v1/remesh?page_size=10 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; try { const response = await axios.get( `https://api.meshy.ai/openapi/v1/remesh?page_size=10`, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.get( "https://api.meshy.ai/openapi/v1/remesh", headers=headers, params={"page_size": 10} ) response.raise_for_status() print(response.json()) ``` **Response** ```json [ { "id": "0193bfc5-ee4f-73f8-8525-44b398884ce9", "type": "remesh", "model_urls": { "glb": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.glb?Expires=***", "fbx": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.fbx?Expires=***", "obj": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.obj?Expires=***", "usdz": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.usdz?Expires=***", "blend": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.blend?Expires=***", "stl": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.stl?Expires=***" }, "progress": 100, "status": "SUCCEEDED", "created_at": 1699999999000, "started_at": 1700000000000, "finished_at": 1700000001000, "task_error": null } ] ``` --- ## GET /openapi/v1/remesh/:id/stream -- Stream a Remesh Task This endpoint streams real-time updates for a Remesh task using Server-Sent Events (SSE). ### Parameters - `id` · *path* Unique identifier for the Remesh task to stream. ### Returns Returns a stream of [The Remesh Task Objects](#the-remesh-task-object) as Server-Sent Events. For `PENDING` or `IN_PROGRESS` tasks, the response stream will only include necessary `progress` and `status` fields. **cURL** ```bash curl -N https://api.meshy.ai/openapi/v1/remesh/a43b5c6d-7e8f-901a-234b-567c890d1e2f/stream \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript const response = await fetch( 'https://api.meshy.ai/openapi/v1/remesh/a43b5c6d-7e8f-901a-234b-567c890d1e2f/stream', { headers: { Authorization: `Bearer ${YOUR_API_KEY}` } } ); const reader = response.body.getReader(); const decoder = new TextDecoder(); let buffer = ''; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const lines = buffer.split('\n'); buffer = lines.pop(); for (const line of lines) { if (line.startsWith('data:')) { const data = JSON.parse(line.slice(5)); console.log(data); if (['SUCCEEDED', 'FAILED', 'CANCELED'].includes(data.status)) { reader.cancel(); } } } } ``` ```python import requests import json headers = { "Authorization": f"Bearer {YOUR_API_KEY}", "Accept": "text/event-stream" } response = requests.get( 'https://api.meshy.ai/openapi/v1/remesh/a43b5c6d-7e8f-901a-234b-567c890d1e2f/stream', headers=headers, stream=True ) for line in response.iter_lines(): if line: if line.startswith(b'data:'): data = json.loads(line.decode('utf-8')[5:]) print(data) if data['status'] in ['SUCCEEDED', 'FAILED', 'CANCELED']: break response.close() ``` **Response Stream** ```javascript // Error event example event: error data: { "status_code": 404, "message": "Task not found" } // Message event examples illustrate task progress. // For PENDING or IN_PROGRESS tasks, the response stream will not include all fields. event: message data: { "id": "0193bfc5-ee4f-73f8-8525-44b398884ce9", "progress": 0, "status": "PENDING" } event: message data: { "id": "0193bfc5-ee4f-73f8-8525-44b398884ce9", "type": "remesh", "model_urls": { "glb": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.glb?Expires=***", "fbx": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.fbx?Expires=***", "obj": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.obj?Expires=***", "usdz": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.usdz?Expires=***", "blend": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.blend?Expires=***", "stl": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.stl?Expires=***" }, "progress": 100, "status": "SUCCEEDED", "created_at": 1699999999000, "started_at": 1700000000000, "finished_at": 1700000001000, "task_error": null, } ``` --- ## The Remesh Task Object The Remesh Task object represents a work unit that Meshy uses to remesh and export an existing 3D model into various formats. The object has the following properties: ### Properties - `id` · *string* Unique identifier for the task. While we use a k-sortable UUID for task ids as the implementation detail, you should **not** make any assumptions about the format of the id. - `type` · *string* Type of the Remesh task. The value is `remesh`. - `model_urls` · *object* Downloadable URL to the textured 3D model file generated by Meshy. The property for a format will be omitted if the format is not generated instead of returning an empty string. - `glb` · *string* Downloadable URL to the GLB file. - `fbx` · *string* Downloadable URL to the FBX file. - `obj` · *string* Downloadable URL to the OBJ file. - `usdz` · *string* Downloadable URL to the USDZ file. - `blend` · *string* Downloadable URL to the Blender file. - `stl` · *string* Downloadable URL to the STL file. - `3mf` · *string* Downloadable URL to the 3MF file. Only present when `3mf` was requested via `target_formats`. - `thumbnail_url` · *string* Downloadable URL to a preview image rendered from the remeshed model. - `alpha_thumbnail_url` · *string* Downloadable URL to a transparent-background (RGBA) version of `thumbnail_url`. Only present when the task was created with `alpha_thumbnail: true` and the transparent preview was successfully rendered; otherwise this field is omitted. - `progress` · *integer* Progress of the task. If the task is not started yet, this property will be `0`. Once the task has succeeded, this will become `100`. - `status` · *string* Status of the task. Possible values are one of `PENDING`, `IN_PROGRESS`, `SUCCEEDED`, `FAILED`. - `preceding_tasks` · *integer* The count of preceding tasks. > **Note:** The value of this field is meaningful only if the task status is `PENDING`. - `created_at` · *timestamp* Timestamp of when the task was created, in milliseconds. - `started_at` · *timestamp* Timestamp of when the task was started, in milliseconds. If the task is not started yet, this property will be `0`. - `finished_at` · *timestamp* Timestamp of when the task was finished, in milliseconds. If the task is not finished yet, this property will be `0`. - `task_error` · *object* Error details for failed tasks. See [Errors](/api/errors#task-errors) for the full `task_error` object reference. - `consumed_credits` · *integer* The number of credits consumed by this task. Present when the task status is `PENDING`, `IN_PROGRESS`, or `SUCCEEDED`. Returns `0` for `FAILED` tasks (credits are refunded on failure). **Example Remesh Task Object** ```json { "id": "0193bfc5-ee4f-73f8-8525-44b398884ce9", "type": "remesh", "model_urls": { "glb": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.glb?Expires=***", "fbx": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.fbx?Expires=***", "obj": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.obj?Expires=***", "usdz": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.usdz?Expires=***", "blend": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.blend?Expires=***", "stl": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.stl?Expires=***" }, "progress": 100, "status": "SUCCEEDED", "preceding_tasks": 0, "created_at": 1699999999000, "started_at": 1700000000000, "finished_at": 1700000001000, "task_error": { "message": "" }, "consumed_credits": 5 } ``` --- # Convert API Source: https://docs.meshy.ai/api/convert # Convert API The Convert API allows you to convert existing 3D models into different file formats. --- ## POST /openapi/v1/convert -- Create a Convert Task This endpoint creates a new format conversion task. ### Parameters > **Note:** Only one of `input_task_id` or `model_url` is **required**. If both are provided, `input_task_id` takes priority. - `input_task_id` · *string* · **required** The ID of a completed Meshy task whose model you wish to convert. The task must have a status of `SUCCEEDED`. - `model_url` · *string* · **required** A publicly accessible URL or data URI pointing to a 3D model file. Supported formats: `.glb`, `.gltf`, `.obj`, `.fbx`, `.stl`. For Data URIs, use the MIME type: `application/octet-stream`. - `target_formats` · *string[]* · **required** A list of output formats for the converted model. Available values: `glb`, `fbx`, `obj`, `usdz`, `blend`, `stl`, `3mf`. ### Returns The `result` property of the response contains the `id` of the newly created convert task. ### Failure Modes - `400 - Bad Request` The request was unacceptable. Common causes: * **Missing parameter**: Either `model_url` or `input_task_id` must be provided. * **Missing target_formats**: At least one target format must be specified. * **Invalid input task**: The `input_task_id` must refer to a successful task. * **Invalid model format**: The `model_url` points to a file with an unsupported extension. * **Unreachable URL**: The `model_url` could not be downloaded. - `401 - Unauthorized` Authentication failed. Please check your API key. - `402 - Payment Required` Insufficient credits to perform this task. - `429 - Too Many Requests` You have exceeded your rate limit. ```bash curl https://api.meshy.ai/openapi/v1/convert \ -X POST \ -H "Authorization: Bearer ${YOUR_API_KEY}" \ -H 'Content-Type: application/json' \ -d '{ "input_task_id": "018a210d-8ba4-705c-b111-1f1776f7f578", "target_formats": ["fbx", "stl"] }' ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; const payload = { input_task_id: "018a210d-8ba4-705c-b111-1f1776f7f578", target_formats: ["fbx", "stl"] }; try { const response = await axios.post( 'https://api.meshy.ai/openapi/v1/convert', payload, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } payload = { "input_task_id": "018a210d-8ba4-705c-b111-1f1776f7f578", "target_formats": ["fbx", "stl"] } response = requests.post( "https://api.meshy.ai/openapi/v1/convert", headers=headers, json=payload, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "result": "0193bfc5-ee4f-73f8-8525-44b398884ce9" } ``` --- ## GET /openapi/v1/convert/:id -- Retrieve a Convert Task This endpoint retrieves a convert task by its ID. ### Parameters - `id` · *path* The ID of the convert task to retrieve. ### Returns The Convert Task object. ```bash curl https://api.meshy.ai/openapi/v1/convert/a43b5c6d-7e8f-901a-234b-567c890d1e2f \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const taskId = 'a43b5c6d-7e8f-901a-234b-567c890d1e2f'; const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; try { const response = await axios.get( `https://api.meshy.ai/openapi/v1/convert/${taskId}`, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests task_id = "a43b5c6d-7e8f-901a-234b-567c890d1e2f" headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.get( f"https://api.meshy.ai/openapi/v1/convert/{task_id}", headers=headers, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "id": "0193bfc5-ee4f-73f8-8525-44b398884ce9", "type": "convert", "model_urls": { "glb": "", "fbx": "https://assets.meshy.ai/.../model.fbx?Expires=...", "obj": "", "usdz": "", "stl": "https://assets.meshy.ai/.../model.stl?Expires=..." }, "progress": 100, "status": "SUCCEEDED", "created_at": 1699999999000, "started_at": 1700000000000, "finished_at": 1700000001000, "task_error": null, "consumed_credits": 1 } ``` --- ## DELETE /openapi/v1/convert/:id -- Delete a Convert Task This endpoint permanently deletes a convert task, including all associated models and data. This action is irreversible. ### Path Parameters - `id` · *path* The ID of the convert task to delete. ### Returns Returns `200 OK` on success. ```bash curl --request DELETE \ --url https://api.meshy.ai/openapi/v1/convert/a43b5c6d-7e8f-901a-234b-567c890d1e2f \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const taskId = 'a43b5c6d-7e8f-901a-234b-567c890d1e2f' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` } try { await axios.delete( `https://api.meshy.ai/openapi/v1/convert/${taskId}`, { headers } ) } catch (error) { console.error(error) } ``` ```python import requests task_id = "a43b5c6d-7e8f-901a-234b-567c890d1e2f" headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.delete( f"https://api.meshy.ai/openapi/v1/convert/{task_id}", headers=headers, ) response.raise_for_status() ``` **Response** ```json // Returns 200 Ok on success. ``` --- ## GET /openapi/v1/convert -- List Convert Tasks This endpoint allows you to retrieve a list of convert tasks. ### Parameters - `page_num` · *integer* · default: `1` Page number for pagination. - `page_size` · *integer* · default: `10` Page size limit. Maximum allowed is `50` items. - `sort_by` · *string* Field to sort by. Available values: * `+created_at`: Sort by creation time in ascending order. * `-created_at`: Sort by creation time in descending order. ### Returns Returns a paginated list of [The Convert Task Objects](#the-convert-task-object). ```bash curl https://api.meshy.ai/openapi/v1/convert?page_size=10 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; try { const response = await axios.get( `https://api.meshy.ai/openapi/v1/convert?page_size=10`, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.get( "https://api.meshy.ai/openapi/v1/convert", headers=headers, params={"page_size": 10} ) response.raise_for_status() print(response.json()) ``` **Response** ```json [ { "id": "0193bfc5-ee4f-73f8-8525-44b398884ce9", "type": "convert", "model_urls": { "fbx": "https://assets.meshy.ai/.../model.fbx?Expires=...", "stl": "https://assets.meshy.ai/.../model.stl?Expires=..." }, "progress": 100, "status": "SUCCEEDED", "created_at": 1699999999000, "started_at": 1700000000000, "finished_at": 1700000001000, "task_error": null, "consumed_credits": 1 } ] ``` --- ## GET /openapi/v1/convert/:id/stream -- Stream a Convert Task This endpoint streams real-time updates for a convert task using Server-Sent Events (SSE). ### Parameters - `id` · *path* Unique identifier for the convert task to stream. ### Returns Returns a stream of [The Convert Task Objects](#the-convert-task-object) as Server-Sent Events. For `PENDING` or `IN_PROGRESS` tasks, the response stream will only include necessary `progress` and `status` fields. ```bash curl -N https://api.meshy.ai/openapi/v1/convert/a43b5c6d-7e8f-901a-234b-567c890d1e2f/stream \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript const response = await fetch( 'https://api.meshy.ai/openapi/v1/convert/a43b5c6d-7e8f-901a-234b-567c890d1e2f/stream', { headers: { Authorization: `Bearer ${YOUR_API_KEY}` } } ); const reader = response.body.getReader(); const decoder = new TextDecoder(); let buffer = ''; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const lines = buffer.split('\n'); buffer = lines.pop(); for (const line of lines) { if (line.startsWith('data:')) { const data = JSON.parse(line.slice(5)); console.log(data); if (['SUCCEEDED', 'FAILED', 'CANCELED'].includes(data.status)) { reader.cancel(); } } } } ``` ```python import requests import json headers = { "Authorization": f"Bearer {YOUR_API_KEY}", "Accept": "text/event-stream" } response = requests.get( 'https://api.meshy.ai/openapi/v1/convert/a43b5c6d-7e8f-901a-234b-567c890d1e2f/stream', headers=headers, stream=True ) for line in response.iter_lines(): if line: if line.startswith(b'data:'): data = json.loads(line.decode('utf-8')[5:]) print(data) if data['status'] in ['SUCCEEDED', 'FAILED', 'CANCELED']: break response.close() ``` **Response Stream** ```javascript // Message event examples illustrate task progress. event: message data: { "id": "0193bfc5-ee4f-73f8-8525-44b398884ce9", "progress": 0, "status": "PENDING" } event: message data: { "id": "0193bfc5-ee4f-73f8-8525-44b398884ce9", "type": "convert", "model_urls": { "fbx": "https://assets.meshy.ai/.../model.fbx?Expires=...", "stl": "https://assets.meshy.ai/.../model.stl?Expires=..." }, "progress": 100, "status": "SUCCEEDED", "created_at": 1699999999000, "started_at": 1700000000000, "finished_at": 1700000001000, "task_error": null, "consumed_credits": 1 } ``` --- ## The Convert Task Object The Convert Task object represents a format conversion job. ### Properties - `id` · *string* Unique identifier for the task. - `type` · *string* Type of the task. The value is `convert`. - `model_urls` · *object* Downloadable URLs for the converted model files. Only the formats specified in `target_formats` will have URLs. Other format properties will be empty strings. - `progress` · *integer* Progress of the task (0-100). - `status` · *string* Status of the task. Possible values: `PENDING`, `IN_PROGRESS`, `SUCCEEDED`, `FAILED`, `CANCELED`. - `preceding_tasks` · *integer* The count of preceding tasks. Meaningful only when status is `PENDING`. - `created_at` · *timestamp* Timestamp of when the task was created, in milliseconds. - `started_at` · *timestamp* Timestamp of when the task was started, in milliseconds. `0` if not started. - `finished_at` · *timestamp* Timestamp of when the task was finished, in milliseconds. `0` if not finished. - `task_error` · *object* Error object if the task failed. See [Errors](/api/errors) for more details. - `consumed_credits` · *integer* The number of credits consumed by this task (1 credit per convert task). Returns `0` for `FAILED` tasks. --- # Resize API Source: https://docs.meshy.ai/api/resize # Resize API The Resize API allows you to resize existing 3D models to real-world dimensions. You can specify an exact height, a longest-side constraint, or let AI automatically estimate the appropriate size. --- ## POST /openapi/v1/resize -- Create a Resize Task This endpoint creates a new resize task. ### Parameters > **Note:** Only one of `input_task_id` or `model_url` is **required**. If both are provided, `input_task_id` takes priority. - `input_task_id` · *string* · **required** The ID of a completed Meshy task whose model you wish to resize. The task must have a status of `SUCCEEDED`. The output format will be GLB. - `model_url` · *string* · **required** A publicly accessible URL or data URI pointing to a 3D model file. Supported formats: `.glb`, `.gltf`, `.obj`, `.fbx`, `.stl`. For Data URIs, use the MIME type: `application/octet-stream`. The output format will preserve the original format of the input model. > **Note:** Exactly one resize mode is **required**: `resize_height`, `resize_longest_side`, or `auto_size`. These three parameters are mutually exclusive. - `resize_height` · *number* Resize the model to a specific height measured in meters. - `resize_longest_side` · *number* Resize the model so that its longest side matches this value, measured in meters. The aspect ratio is preserved. - `auto_size` · *boolean* When set to `true`, the service uses AI vision to automatically estimate the real-world height of the object and resize the model accordingly. The origin will default to `bottom` unless `origin_at` is explicitly set. - `origin_at` · *string* · default: `bottom` Position of the origin after resizing. Available values: `bottom`, `center`. ### Returns The `result` property of the response contains the `id` of the newly created resize task. ### Failure Modes - `400 - Bad Request` The request was unacceptable. Common causes: * **Missing parameter**: Either `model_url` or `input_task_id` must be provided. * **Missing resize mode**: At least one of `resize_height`, `resize_longest_side`, or `auto_size` must be specified. * **Mutually exclusive parameters**: `resize_height`, `resize_longest_side`, and `auto_size` cannot be combined. * **Invalid input task**: The `input_task_id` must refer to a successful task. * **Invalid model format**: The `model_url` points to a file with an unsupported extension. * **Unreachable URL**: The `model_url` could not be downloaded. - `401 - Unauthorized` Authentication failed. Please check your API key. - `402 - Payment Required` Insufficient credits to perform this task. - `429 - Too Many Requests` You have exceeded your rate limit. **cURL** ```bash # Simple: resize to a specific height curl https://api.meshy.ai/openapi/v1/resize \ -X POST \ -H "Authorization: Bearer ${YOUR_API_KEY}" \ -H 'Content-Type: application/json' \ -d '{ "input_task_id": "018a210d-8ba4-705c-b111-1f1776f7f578", "resize_height": 1.8 }' # Advanced: resize longest side with custom origin curl https://api.meshy.ai/openapi/v1/resize \ -X POST \ -H "Authorization: Bearer ${YOUR_API_KEY}" \ -H 'Content-Type: application/json' \ -d '{ "model_url": "https://example.com/model.glb", "resize_longest_side": 2.0, "origin_at": "center" }' ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; // Simple: resize to a specific height const payload = { input_task_id: "018a210d-8ba4-705c-b111-1f1776f7f578", resize_height: 1.8 }; try { const response = await axios.post( 'https://api.meshy.ai/openapi/v1/resize', payload, { headers } ); console.log(response.data); } catch (error) { console.error(error); } // Advanced: resize longest side with custom origin const advancedPayload = { model_url: "https://example.com/model.glb", resize_longest_side: 2.0, origin_at: "center" }; try { const response = await axios.post( 'https://api.meshy.ai/openapi/v1/resize', advancedPayload, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } # Simple: resize to a specific height payload = { "input_task_id": "018a210d-8ba4-705c-b111-1f1776f7f578", "resize_height": 1.8 } response = requests.post( "https://api.meshy.ai/openapi/v1/resize", headers=headers, json=payload, ) response.raise_for_status() print(response.json()) # Advanced: resize longest side with custom origin advanced_payload = { "model_url": "https://example.com/model.glb", "resize_longest_side": 2.0, "origin_at": "center" } response = requests.post( "https://api.meshy.ai/openapi/v1/resize", headers=headers, json=advanced_payload, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "result": "0193bfc5-ee4f-73f8-8525-44b398884ce9" } ``` --- ## GET /openapi/v1/resize/:id -- Retrieve a Resize Task This endpoint retrieves a resize task by its ID. ### Parameters - `id` · *path* The ID of the resize task to retrieve. ### Returns The Resize Task object. ```bash curl https://api.meshy.ai/openapi/v1/resize/a43b5c6d-7e8f-901a-234b-567c890d1e2f \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const taskId = 'a43b5c6d-7e8f-901a-234b-567c890d1e2f'; const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; try { const response = await axios.get( `https://api.meshy.ai/openapi/v1/resize/${taskId}`, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests task_id = "a43b5c6d-7e8f-901a-234b-567c890d1e2f" headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.get( f"https://api.meshy.ai/openapi/v1/resize/{task_id}", headers=headers, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "id": "0193bfc5-ee4f-73f8-8525-44b398884ce9", "type": "resize", "model_urls": { "glb": "https://assets.meshy.ai/.../model.glb?Expires=..." }, "progress": 100, "status": "SUCCEEDED", "created_at": 1699999999000, "started_at": 1700000000000, "finished_at": 1700000001000, "task_error": null, "consumed_credits": 1 } ``` --- ## DELETE /openapi/v1/resize/:id -- Delete a Resize Task This endpoint permanently deletes a resize task, including all associated models and data. This action is irreversible. ### Path Parameters - `id` · *path* The ID of the resize task to delete. ### Returns Returns `200 OK` on success. ```bash curl --request DELETE \ --url https://api.meshy.ai/openapi/v1/resize/a43b5c6d-7e8f-901a-234b-567c890d1e2f \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const taskId = 'a43b5c6d-7e8f-901a-234b-567c890d1e2f' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` } try { await axios.delete( `https://api.meshy.ai/openapi/v1/resize/${taskId}`, { headers } ) } catch (error) { console.error(error) } ``` ```python import requests task_id = "a43b5c6d-7e8f-901a-234b-567c890d1e2f" headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.delete( f"https://api.meshy.ai/openapi/v1/resize/{task_id}", headers=headers, ) response.raise_for_status() ``` **Response** ```json // Returns 200 Ok on success. ``` --- ## GET /openapi/v1/resize -- List Resize Tasks This endpoint allows you to retrieve a list of resize tasks. ### Parameters - `page_num` · *integer* · default: `1` Page number for pagination. - `page_size` · *integer* · default: `10` Page size limit. Maximum allowed is `50` items. - `sort_by` · *string* Field to sort by. Available values: * `+created_at`: Sort by creation time in ascending order. * `-created_at`: Sort by creation time in descending order. ### Returns Returns a paginated list of [The Resize Task Objects](#the-resize-task-object). ```bash curl https://api.meshy.ai/openapi/v1/resize?page_size=10 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; try { const response = await axios.get( `https://api.meshy.ai/openapi/v1/resize?page_size=10`, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.get( "https://api.meshy.ai/openapi/v1/resize", headers=headers, params={"page_size": 10} ) response.raise_for_status() print(response.json()) ``` **Response** ```json [ { "id": "0193bfc5-ee4f-73f8-8525-44b398884ce9", "type": "resize", "model_urls": { "glb": "https://assets.meshy.ai/.../model.glb?Expires=..." }, "progress": 100, "status": "SUCCEEDED", "created_at": 1699999999000, "started_at": 1700000000000, "finished_at": 1700000001000, "task_error": null, "consumed_credits": 1 } ] ``` --- ## GET /openapi/v1/resize/:id/stream -- Stream a Resize Task This endpoint streams real-time updates for a resize task using Server-Sent Events (SSE). ### Parameters - `id` · *path* Unique identifier for the resize task to stream. ### Returns Returns a stream of [The Resize Task Objects](#the-resize-task-object) as Server-Sent Events. For `PENDING` or `IN_PROGRESS` tasks, the response stream will only include necessary `progress` and `status` fields. ```bash curl -N https://api.meshy.ai/openapi/v1/resize/a43b5c6d-7e8f-901a-234b-567c890d1e2f/stream \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript const response = await fetch( 'https://api.meshy.ai/openapi/v1/resize/a43b5c6d-7e8f-901a-234b-567c890d1e2f/stream', { headers: { Authorization: `Bearer ${YOUR_API_KEY}` } } ); const reader = response.body.getReader(); const decoder = new TextDecoder(); let buffer = ''; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const lines = buffer.split('\n'); buffer = lines.pop(); for (const line of lines) { if (line.startsWith('data:')) { const data = JSON.parse(line.slice(5)); console.log(data); if (['SUCCEEDED', 'FAILED', 'CANCELED'].includes(data.status)) { reader.cancel(); } } } } ``` ```python import requests import json headers = { "Authorization": f"Bearer {YOUR_API_KEY}", "Accept": "text/event-stream" } response = requests.get( 'https://api.meshy.ai/openapi/v1/resize/a43b5c6d-7e8f-901a-234b-567c890d1e2f/stream', headers=headers, stream=True ) for line in response.iter_lines(): if line: if line.startswith(b'data:'): data = json.loads(line.decode('utf-8')[5:]) print(data) if data['status'] in ['SUCCEEDED', 'FAILED', 'CANCELED']: break response.close() ``` **Response Stream** ```javascript // Message event examples illustrate task progress. event: message data: { "id": "0193bfc5-ee4f-73f8-8525-44b398884ce9", "progress": 0, "status": "PENDING" } event: message data: { "id": "0193bfc5-ee4f-73f8-8525-44b398884ce9", "type": "resize", "model_urls": { "glb": "https://assets.meshy.ai/.../model.glb?Expires=..." }, "progress": 100, "status": "SUCCEEDED", "created_at": 1699999999000, "started_at": 1700000000000, "finished_at": 1700000001000, "task_error": null, "consumed_credits": 1 } ``` --- ## The Resize Task Object The Resize Task object represents a resize job. ### Properties - `id` · *string* Unique identifier for the task. - `type` · *string* Type of the task. The value is `resize`. - `model_urls` · *object* Downloadable URL for the resized model file. When using `input_task_id`, the output is always GLB. When using `model_url`, the output preserves the original format. - `progress` · *integer* Progress of the task (0-100). - `status` · *string* Status of the task. Possible values: `PENDING`, `IN_PROGRESS`, `SUCCEEDED`, `FAILED`, `CANCELED`. - `preceding_tasks` · *integer* The count of preceding tasks. Meaningful only when status is `PENDING`. - `created_at` · *timestamp* Timestamp of when the task was created, in milliseconds. - `started_at` · *timestamp* Timestamp of when the task was started, in milliseconds. `0` if not started. - `finished_at` · *timestamp* Timestamp of when the task was finished, in milliseconds. `0` if not finished. - `task_error` · *object* Error object if the task failed. See [Errors](/api/errors) for more details. - `consumed_credits` · *integer* The number of credits consumed by this task (1 credit per resize task). Returns `0` for `FAILED` tasks. --- # Rigging API Source: https://docs.meshy.ai/api/rigging # Rigging API The Rigging API allows you to programmatically add a skeleton (armature) to 3D humanoid models, binding the mesh to it so they are ready for animation. For applying animations to a rigged character, see the [Animation API](/api/animation). Please note that programmatic rigging currently only works well with standard humanoid (bipedal) assets with clearly defined limbs and body structure at this time. --- ## POST /openapi/v1/rigging -- Create a Rigging Task This endpoint allows you to create a new rigging task for a given 3D model. Upon successful completion, it provides a rigged character in standard formats and optionally basic walking/running animations. Currently, auto-rigging is not suitable for the following models: - Untextured meshes - Non-humanoid assets - Humanoid assets with unclear limb and body structure > **Note:** When using `input_task_id`, models with more than **300,000 faces** are not supported for rigging. Please use the [Remesh API](/api/remesh) to reduce the face count before rigging. > **Note:** When using `model_url`, the character's face must point toward the +Z axis (the standard glTF forward direction). Models facing other axes will fail pose estimation. ### Parameters > **Note:** Only one of `input_task_id` or `model_url` is **required**. If both are provided, `input_task_id` takes priority. - `input_task_id` · *string* · **required** The input task that needs to be rigged. We currently support textured humanoid models. - `model_url` · *string* · **required** Please provide a 3D model for Meshy to rig via a publicly accessible URL or Data URI. We currently support textured humanoid GLB files (`.glb` format). - `height_meters` · *number* · default: `1.7` The approximate height of the character model in meters. This aids in scaling and rigging accuracy. It must be a positive number. - `texture_image_url` · *string* The model's UV-unwrapped base color texture image. Publicly accessible URL or Data URI. We currently support `.png` formats. ### Returns The `result` property of the response contains the task `id` of the newly created rigging task. ### Failure Modes - `400 - Bad Request` The request was unacceptable. Common causes: * **Missing parameter**: Either `model_url` or `input_task_id` must be provided. * **Invalid model format**: The `model_url` points to a file with an unsupported extension (only .glb supported). * **Unreachable URL**: The `model_url` could not be downloaded. * **Invalid input task**: The `input_task_id` does not refer to a valid API task. * **Face count exceeded**: The input model has more than 300,000 faces. Please use the [Remesh API](/api/remesh) to reduce the face count before rigging. - `401 - Unauthorized` Authentication failed. Please check your API key. - `402 - Payment Required` Insufficient credits to perform this task. - `422 - Unprocessable Entity` Pose estimation failed. The provided model may not be a valid humanoid character. - `429 - Too Many Requests` You have exceeded your rate limit. **cURL** ```bash # Rig a model from a URL curl https://api.meshy.ai/openapi/v1/rigging \ -X POST \ -H "Authorization: Bearer ${YOUR_API_KEY}" \ -H 'Content-Type: application/json' \ -d '{ "model_url": "YOUR_MODEL_URL_OR_DATA_URI", "height_meters": 1.8 }' ``` ```javascript import axios from 'axios' // Rig a model from a URL const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; const payload = { model_url: "YOUR_MODEL_URL_OR_DATA_URI", height_meters: 1.8 }; try { const response = await axios.post( 'https://api.meshy.ai/openapi/v1/rigging', payload, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests # Rig a model from a URL payload = { "model_url": "YOUR_MODEL_URL_OR_DATA_URI", "height_meters": 1.8 } headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.post( "https://api.meshy.ai/openapi/v1/rigging", headers=headers, json=payload, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "result": "018b314a-a1b5-716d-c222-2f1776f7f579" } ``` --- ## GET /openapi/v1/rigging/:id -- Retrieve a Rigging Task This endpoint allows you to retrieve a rigging task given a valid task `id`. Refer to [The Rigging Task Object](#the-rigging-task-object) to see which properties are included. ### Parameters - `id` · *path* Unique identifier for the rigging task to retrieve. ### Returns The response contains the Rigging Task object. Check [The Rigging Task Object](#the-rigging-task-object) section for details. **cURL** ```bash curl https://api.meshy.ai/openapi/v1/rigging/018b314a-a1b5-716d-c222-2f1776f7f579 -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const taskId = '018b314a-a1b5-716d-c222-2f1776f7f579'; const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; try { const response = await axios.get( `https://api.meshy.ai/openapi/v1/rigging/${taskId}`, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests task_id = "018b314a-a1b5-716d-c222-2f1776f7f579" headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.get( f"https://api.meshy.ai/openapi/v1/rigging/{task_id}", headers=headers, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "id": "018b314a-a1b5-716d-c222-2f1776f7f579", "type": "rig", "status": "SUCCEEDED", "created_at": 1747032400453, "progress": 100, "started_at": 1747032401314, "finished_at": 1747032418417, "expires_at": 1747291618417, "task_error": { "message": "" }, "consumed_credits": 5, "result": { "rigged_character_fbx_url": "https://assets.meshy.ai/0630d47c-84b8-4d37-bc02-69e45d9272c1/tasks/018b314a-a1b5-716d-c222-2f1776f7f579/output/Character_output.fbx?Expires=...", "rigged_character_glb_url": "https://assets.meshy.ai/0630d47c-84b8-4d37-bc02-69e45d9272c1/tasks/018b314a-a1b5-716d-c222-2f1776f7f579/output/Character_output.glb?Expires=...", "basic_animations": { "walking_glb_url": "https://assets.meshy.ai/0630d47c-84b8-4d37-bc02-69e45d9272c1/tasks/018b314a-a1b5-716d-c222-2f1776f7f579/output/Animation_Walking_withSkin.glb?Expires=...", "walking_fbx_url": "https://assets.meshy.ai/0630d47c-84b8-4d37-bc02-69e45d9272c1/tasks/018b314a-a1b5-716d-c222-2f1776f7f579/output/Animation_Walking_withSkin.fbx?Expires=...", "walking_armature_glb_url": "https://assets.meshy.ai/0630d47c-84b8-4d37-bc02-69e45d9272c1/tasks/018b314a-a1b5-716d-c222-2f1776f7f579/output/Animation_Walking_withSkin_armature.glb?Expires=...", "running_glb_url": "https://assets.meshy.ai/0630d47c-84b8-4d37-bc02-69e45d9272c1/tasks/018b314a-a1b5-716d-c222-2f1776f7f579/output/Animation_Running_withSkin.glb?Expires=...", "running_fbx_url": "https://assets.meshy.ai/0630d47c-84b8-4d37-bc02-69e45d9272c1/tasks/018b314a-a1b5-716d-c222-2f1776f7f579/output/Animation_Running_withSkin.fbx?Expires=...", "running_armature_glb_url": "https://assets.meshy.ai/0630d47c-84b8-4d37-bc02-69e45d9272c1/tasks/018b314a-a1b5-716d-c222-2f1776f7f579/output/Animation_Running_withSkin_armature.glb?Expires=..." } }, "preceding_tasks": 0 } ``` --- ## DELETE /openapi/v1/rigging/:id -- Delete a Rigging Task This endpoint permanently deletes a rigging task, including all associated models and data. This action is irreversible. ### Path Parameters - `id` · *path* The ID of the rigging task to delete. ### Returns Returns `200 OK` on success. **cURL** ```bash curl --request DELETE \ --url https://api.meshy.ai/openapi/v1/rigging/018b314a-a1b5-716d-c222-2f1776f7f579 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const taskId = '018b314a-a1b5-716d-c222-2f1776f7f579' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` } try { await axios.delete( `https://api.meshy.ai/openapi/v1/rigging/${taskId}`, { headers } ) } catch (error) { console.error(error) } ``` ```python import requests task_id = "018b314a-a1b5-716d-c222-2f1776f7f579" headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.delete( f"https://api.meshy.ai/openapi/v1/rigging/{task_id}", headers=headers, ) response.raise_for_status() ``` **Response** ```json // Returns 200 Ok on success. ``` --- ## GET /openapi/v1/rigging/:id/stream -- Stream a Rigging Task This endpoint streams real-time updates for a Rigging task using Server-Sent Events (SSE). ### Parameters - `id` · *path* Unique identifier for the Rigging task to stream. ### Returns Returns a stream of [The Rigging Task Objects](#the-rigging-task-object) as Server-Sent Events. For `PENDING` or `IN_PROGRESS` tasks, the response stream will only include necessary `progress` and `status` fields. **cURL** ```bash curl -N https://api.meshy.ai/openapi/v1/rigging/018b314a-a1b5-716d-c222-2f1776f7f579/stream -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript const response = await fetch( 'https://api.meshy.ai/openapi/v1/rigging/018b314a-a1b5-716d-c222-2f1776f7f579/stream', { headers: { Authorization: `Bearer ${YOUR_API_KEY}` } } ); const reader = response.body.getReader(); const decoder = new TextDecoder(); let buffer = ''; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const lines = buffer.split('\n'); buffer = lines.pop(); for (const line of lines) { if (line.startsWith('data:')) { const data = JSON.parse(line.slice(5)); console.log(data); if (['SUCCEEDED', 'FAILED', 'CANCELED'].includes(data.status)) { reader.cancel(); } } } } ``` ```python import requests import json headers = { "Authorization": f"Bearer {YOUR_API_KEY}", "Accept": "text/event-stream" } task_id = "018b314a-a1b5-716d-c222-2f1776f7f579" response = requests.get( f'https://api.meshy.ai/openapi/v1/rigging/{task_id}/stream', headers=headers, stream=True ) for line in response.iter_lines(): if line: if line.startswith(b'data:'): data_str = line.decode('utf-8')[5:] try: data = json.loads(data_str) print(data) if data.get('status') in ['SUCCEEDED', 'FAILED', 'CANCELED']: break except json.JSONDecodeError: print(f"Failed to decode JSON: {data_str}") response.close() ``` **Response Stream** ```javascript // Error event example event: error data: { "status_code": 404, "message": "Task not found" } // Message event examples illustrate task progress. // For PENDING or IN_PROGRESS tasks, the response stream will not include all fields. event: message data: { "id": "018b314a-a1b5-716d-c222-2f1776f7f579", "progress": 0, "status": "PENDING" } event: message data: { "id": "018b314a-a1b5-716d-c222-2f1776f7f579", "progress": 50, "status": "IN_PROGRESS" } event: message data: { // Example of a SUCCEEDED task stream item, mirroring The Rigging Task Object structure "id": "018b314a-a1b5-716d-c222-2f1776f7f579", "type": "rig", "status": "SUCCEEDED", "created_at": 1747032400453, "progress": 100, "started_at": 1747032401314, "finished_at": 1747032418417, "expires_at": 1747291618417, "task_error": { "message": "" }, "consumed_credits": 5, "result": { "rigged_character_fbx_url": "https://assets.meshy.ai/.../Character_output.fbx?...", "rigged_character_glb_url": "https://assets.meshy.ai/.../Character_output.glb?...", "basic_animations": { "walking_glb_url": "https://assets.meshy.ai/.../Animation_Walking_withSkin.glb?...", "walking_fbx_url": "https://assets.meshy.ai/.../Animation_Walking_withSkin.fbx?...", "walking_armature_glb_url": "https://assets.meshy.ai/.../Animation_Walking_withSkin_armature.glb?...", "running_glb_url": "https://assets.meshy.ai/.../Animation_Running_withSkin.glb?...", "running_fbx_url": "https://assets.meshy.ai/.../Animation_Running_withSkin.fbx?...", "running_armature_glb_url": "https://assets.meshy.ai/.../Animation_Running_withSkin_armature.glb?..." } }, "preceding_tasks": 0 } ``` --- ## The Rigging Task Object The Rigging Task object represents the work unit for rigging a character. ### Properties - `id` · *string* Unique identifier for the task. - `type` · *string* Type of the Rigging task. The value is `rig`. - `status` · *string* Status of the task. Possible values: `PENDING`, `IN_PROGRESS`, `SUCCEEDED`, `FAILED`, `CANCELED`. - `progress` · *integer* Progress of the task (0-100). `0` if not started, `100` if succeeded. - `created_at` · *timestamp* Timestamp (milliseconds since epoch) when the task was created. > **Note:** A timestamp represents the number of milliseconds elapsed since January 1, 1970 UTC, following > the [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339) standard. > For example, Friday, September 1, 2023 12:00:00 PM GMT is represented as `1693569600000`. This applies > to **all** timestamps in Meshy API. - `started_at` · *timestamp* Timestamp (milliseconds since epoch) when the task started processing. `0` if not started. - `finished_at` · *timestamp* Timestamp (milliseconds since epoch) when the task finished. `0` if not finished. - `expires_at` · *timestamp* Timestamp (milliseconds since epoch) when the task result assets expire and may be deleted. - `task_error` · *object* Error details for failed tasks. See [Errors](/api/errors#task-errors) for the full `task_error` object reference. - `consumed_credits` · *integer* The number of credits consumed by this task. Present when the task status is `PENDING`, `IN_PROGRESS`, or `SUCCEEDED`. Returns `0` for `FAILED` tasks (credits are refunded on failure). - `result` · *object* Contains the output asset URLs if the task `SUCCEEDED`, `null` otherwise. - `rigged_character_fbx_url` · *string* Downloadable URL for the rigged character in FBX format. - `rigged_character_glb_url` · *string* Downloadable URL for the rigged character in GLB format. - `basic_animations` · *object (optional)* Contains URLs for default animations. (e.g. if `generate_basic_animations` was implicitly true or enabled by default). - `walking_glb_url` · *string* Downloadable URL for walking animation in GLB format (with skin). - `walking_fbx_url` · *string* Downloadable URL for walking animation in FBX format (with skin). - `walking_armature_glb_url` · *string* Downloadable URL for walking animation armature in GLB format. - `running_glb_url` · *string* Downloadable URL for running animation in GLB format (with skin). - `running_fbx_url` · *string* Downloadable URL for running animation in FBX format (with skin). - `running_armature_glb_url` · *string* Downloadable URL for running animation armature in GLB format. - `preceding_tasks` · *integer* The count of preceding tasks in the queue. Meaningful only if status is `PENDING`. **Example Rigging Task Object** ```json { "id": "018b314a-a1b5-716d-c222-2f1776f7f579", "type": "rig", "status": "SUCCEEDED", "created_at": 1747032400453, "progress": 100, "started_at": 1747032401314, "finished_at": 1747032418417, "expires_at": 1747291618417, "task_error": { "message": "" }, "consumed_credits": 5, "result": { "rigged_character_fbx_url": "https://assets.meshy.ai/0630d47c-84b8-4d37-bc02-69e45d9272c1/tasks/018b314a-a1b5-716d-c222-2f1776f7f579/output/Character_output.fbx?Expires=...", "rigged_character_glb_url": "https://assets.meshy.ai/0630d47c-84b8-4d37-bc02-69e45d9272c1/tasks/018b314a-a1b5-716d-c222-2f1776f7f579/output/Character_output.glb?Expires=...", "basic_animations": { "walking_glb_url": "https://assets.meshy.ai/0630d47c-84b8-4d37-bc02-69e45d9272c1/tasks/018b314a-a1b5-716d-c222-2f1776f7f579/output/Animation_Walking_withSkin.glb?Expires=...", "walking_fbx_url": "https://assets.meshy.ai/0630d47c-84b8-4d37-bc02-69e45d9272c1/tasks/018b314a-a1b5-716d-c222-2f1776f7f579/output/Animation_Walking_withSkin.fbx?Expires=...", "walking_armature_glb_url": "https://assets.meshy.ai/0630d47c-84b8-4d37-bc02-69e45d9272c1/tasks/018b314a-a1b5-716d-c222-2f1776f7f579/output/Animation_Walking_withSkin_armature.glb?Expires=...", "running_glb_url": "https://assets.meshy.ai/0630d47c-84b8-4d37-bc02-69e45d9272c1/tasks/018b314a-a1b5-716d-c222-2f1776f7f579/output/Animation_Running_withSkin.glb?Expires=...", "running_fbx_url": "https://assets.meshy.ai/0630d47c-84b8-4d37-bc02-69e45d9272c1/tasks/018b314a-a1b5-716d-c222-2f1776f7f579/output/Animation_Running_withSkin.fbx?Expires=...", "running_armature_glb_url": "https://assets.meshy.ai/0630d47c-84b8-4d37-bc02-69e45d9272c1/tasks/018b314a-a1b5-716d-c222-2f1776f7f579/output/Animation_Running_withSkin_armature.glb?Expires=..." } }, "preceding_tasks": 0 } ``` --- # Animation API Source: https://docs.meshy.ai/api/animation # Animation API Endpoints for discovering available animations and applying them to rigged characters. --- ## POST /openapi/v1/animations -- Create an Animation Task This endpoint allows you to create a new task to apply a specific animation action to a previously rigged character. Includes post-processing options. ### Parameters - `rig_task_id` · *string* · **required** The `id` of a successfully completed rigging task (from `POST /openapi/v1/rigging`). The character from this task will be animated. - `action_id` · *integer* · **required** The identifier of the animation action to apply. See the [Animation Library Reference](/api/animation-library) for a complete list of available animations. - `post_process` · *object* Parameters for post-processing animation files. - `operation_type` · *string* · **required** The type of operation to perform. Available values: `change_fps`, `fbx2usdz`, `extract_armature`. - `fps` · *integer* · default: `30` The target frame rate. Applicable only when `operation_type` is `change_fps`. Allowed values: `24`, `25`, `30`, `60`. ### Returns The `result` property of the response contains the task `id` of the newly created animation task. ### Failure Modes - `400 - Bad Request` The request was unacceptable. Common causes: * **Missing parameter**: `rig_task_id` or `action_id` is missing. * **Invalid rig task**: The `rig_task_id` is invalid or refers to a failed/non-existent task. * **Invalid action ID**: The `action_id` does not correspond to a valid animation. - `401 - Unauthorized` Authentication failed. Please check your API key. - `402 - Payment Required` Insufficient credits to perform this task. - `404 - Not Found` The rigging task specified by `rig_task_id` was not found. - `429 - Too Many Requests` You have exceeded your rate limit. **cURL** ```bash # Animate a rigged model with required params only curl https://api.meshy.ai/openapi/v1/animations \ -X POST \ -H "Authorization: Bearer ${YOUR_API_KEY}" \ -H 'Content-Type: application/json' \ -d '{ "rig_task_id": "018b314a-a1b5-716d-c222-2f1776f7f579", "action_id": 92 }' # With post-processing to change FPS curl https://api.meshy.ai/openapi/v1/animations \ -X POST \ -H "Authorization: Bearer ${YOUR_API_KEY}" \ -H 'Content-Type: application/json' \ -d '{ "rig_task_id": "018b314a-a1b5-716d-c222-2f1776f7f579", "action_id": 92, "post_process": { "operation_type": "change_fps", "fps": 24 } }' ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; // Animate a rigged model with required params only const payload = { rig_task_id: "018b314a-a1b5-716d-c222-2f1776f7f579", action_id: 92 }; try { const response = await axios.post( 'https://api.meshy.ai/openapi/v1/animations', payload, { headers } ); console.log(response.data); } catch (error) { console.error(error); } // With post-processing to change FPS const advancedPayload = { rig_task_id: "018b314a-a1b5-716d-c222-2f1776f7f579", action_id: 92, post_process: { operation_type: "change_fps", fps: 24 } }; try { const response = await axios.post( 'https://api.meshy.ai/openapi/v1/animations', advancedPayload, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } # Animate a rigged model with required params only payload = { "rig_task_id": "018b314a-a1b5-716d-c222-2f1776f7f579", "action_id": 92 } response = requests.post( "https://api.meshy.ai/openapi/v1/animations", headers=headers, json=payload, ) response.raise_for_status() print(response.json()) # With post-processing to change FPS advanced_payload = { "rig_task_id": "018b314a-a1b5-716d-c222-2f1776f7f579", "action_id": 92, "post_process": { "operation_type": "change_fps", "fps": 24 } } response = requests.post( "https://api.meshy.ai/openapi/v1/animations", headers=headers, json=advanced_payload, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "result": "018c425b-b2c6-727e-d333-3c1887i9h791" } ``` --- ## GET /openapi/v1/animations/:id -- Retrieve an Animation Task This endpoint allows you to retrieve an animation task given a valid task `id`. Refer to [The Animation Task Object](#the-animation-task-object) to see which properties are included. ### Parameters - `id` · *path* Unique identifier for the animation task to retrieve. ### Returns The response contains the Animation Task object. Check [The Animation Task Object](#the-animation-task-object) section for details. **cURL** ```bash curl https://api.meshy.ai/openapi/v1/animations/018c425b-b2c6-727e-d333-3c1887i9h791 -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const taskId = '018c425b-b2c6-727e-d333-3c1887i9h791'; const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; try { const response = await axios.get( `https://api.meshy.ai/openapi/v1/animations/${taskId}`, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests task_id = "018c425b-b2c6-727e-d333-3c1887i9h791" headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.get( f"https://api.meshy.ai/openapi/v1/animations/{task_id}", headers=headers, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "id": "018c425b-b2c6-727e-d333-3c1887i9h791", "type": "animate", "status": "SUCCEEDED", "created_at": 1747032440896, "progress": 100, "started_at": 1747032441210, "finished_at": 1747032457530, "expires_at": 1747291657530, "task_error": { "message": "" }, "consumed_credits": 3, "result": { "animation_glb_url": "https://assets.meshy.ai/0630d47c-84b8-4d37-bc02-69e45d9272c1/tasks/018c425b-b2c6-727e-d333-3c1887i9h791/output/Animation_Reaping_Swing_withSkin.glb?Expires=...", "animation_fbx_url": "https://assets.meshy.ai/0630d47c-84b8-4d37-bc02-69e45d9272c1/tasks/018c425b-b2c6-727e-d333-3c1887i9h791/output/Animation_Reaping_Swing_withSkin.fbx?Expires=...", "processed_usdz_url": "https://assets.meshy.ai/0630d47c-84b8-4d37-bc02-69e45d9272c1/tasks/018c425b-b2c6-727e-d333-3c1887i9h791/output/processed.usdz?Expires=...", "processed_armature_fbx_url": "https://assets.meshy.ai/0630d47c-84b8-4d37-bc02-69e45d9272c1/tasks/018c425b-b2c6-727e-d333-3c1887i9h791/output/processed_armature.fbx?Expires=...", "processed_animation_fps_fbx_url": "https://assets.meshy.ai/0630d47c-84b8-4d37-bc02-69e45d9272c1/tasks/018c425b-b2c6-727e-d333-3c1887i9h791/output/processed_60fps.fbx?Expires=..." }, "preceding_tasks": 0 } ``` --- ## DELETE /openapi/v1/animations/:id -- Delete an Animation Task This endpoint permanently deletes an animation task, including all associated models and data. This action is irreversible. ### Path Parameters - `id` · *path* The ID of the animation task to delete. ### Returns Returns `200 OK` on success. **cURL** ```bash curl --request DELETE \ --url https://api.meshy.ai/openapi/v1/animations/018b314a-a1b5-716d-c222-2f1776f7f579 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const taskId = '018b314a-a1b5-716d-c222-2f1776f7f579' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` } try { await axios.delete( `https://api.meshy.ai/openapi/v1/animations/${taskId}`, { headers } ) } catch (error) { console.error(error) } ``` ```python import requests task_id = "018b314a-a1b5-716d-c222-2f1776f7f579" headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.delete( f"https://api.meshy.ai/openapi/v1/animations/{task_id}", headers=headers, ) response.raise_for_status() ``` **Response** ```json // Returns 200 Ok on success. ``` --- ## GET /openapi/v1/animations/:id/stream -- Stream an Animation Task This endpoint streams real-time updates for an Animation task using Server-Sent Events (SSE). ### Parameters - `id` · *path* Unique identifier for the Animation task to stream. ### Returns Returns a stream of [The Animation Task Objects](#the-animation-task-object) as Server-Sent Events. For `PENDING` or `IN_PROGRESS` tasks, the response stream will only include necessary `progress` and `status` fields. **cURL** ```bash curl -N https://api.meshy.ai/openapi/v1/animations/018c425b-b2c6-727e-d333-3c1887i9h791/stream -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript const response = await fetch( 'https://api.meshy.ai/openapi/v1/animations/018c425b-b2c6-727e-d333-3c1887i9h791/stream', { headers: { Authorization: `Bearer ${YOUR_API_KEY}` } } ); const reader = response.body.getReader(); const decoder = new TextDecoder(); let buffer = ''; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const lines = buffer.split('\n'); buffer = lines.pop(); for (const line of lines) { if (line.startsWith('data:')) { const data = JSON.parse(line.slice(5)); console.log(data); if (['SUCCEEDED', 'FAILED', 'CANCELED'].includes(data.status)) { reader.cancel(); } } } } ``` ```python import requests import json headers = { "Authorization": f"Bearer {YOUR_API_KEY}", "Accept": "text/event-stream" } task_id = "018c425b-b2c6-727e-d333-3c1887i9h791" response = requests.get( f'https://api.meshy.ai/openapi/v1/animations/{task_id}/stream', headers=headers, stream=True ) for line in response.iter_lines(): if line: if line.startswith(b'data:'): data_str = line.decode('utf-8')[5:] try: data = json.loads(data_str) print(data) if data.get('status') in ['SUCCEEDED', 'FAILED', 'CANCELED']: break except json.JSONDecodeError: print(f"Failed to decode JSON: {data_str}") response.close() ``` **Response Stream** ```javascript // Error event example event: error data: { "status_code": 404, "message": "Task not found" } // Message event examples illustrate task progress. // For PENDING or IN_PROGRESS tasks, the response stream will not include all fields. event: message data: { "id": "018c425b-b2c6-727e-d333-3c1887i9h791", "progress": 0, "status": "PENDING" } event: message data: { "id": "018c425b-b2c6-727e-d333-3c1887i9h791", "progress": 50, "status": "IN_PROGRESS" } event: message data: { // Example of a SUCCEEDED task stream item, mirroring The Animation Task Object structure "id": "018c425b-b2c6-727e-d333-3c1887i9h791", "type": "animate", "status": "SUCCEEDED", "created_at": 1747032440896, "progress": 100, "started_at": 1747032441210, "finished_at": 1747032457530, "expires_at": 1747291657530, "task_error": { "message": "" }, "consumed_credits": 3, "result": { "animation_glb_url": "https://assets.meshy.ai/.../Animation_Reaping_Swing_withSkin.glb?...", "animation_fbx_url": "https://assets.meshy.ai/.../Animation_Reaping_Swing_withSkin.fbx?...", "processed_usdz_url": "https://assets.meshy.ai/.../processed.usdz?...", "processed_armature_fbx_url": "https://assets.meshy.ai/.../processed_armature.fbx?...", "processed_animation_fps_fbx_url": "https://assets.meshy.ai/.../processed_60fps.fbx?..." }, "preceding_tasks": 0 } ``` --- ## The Animation Task Object The Animation Task object represents the work unit for applying an animation to a rigged character. ### Properties - `id` · *string* Unique identifier for the task. - `type` · *string* Type of the Animation task. The value is `animate`. - `status` · *string* Status of the task. Possible values: `PENDING`, `IN_PROGRESS`, `SUCCEEDED`, `FAILED`, `CANCELED`. - `progress` · *integer* Progress of the task (0-100). - `created_at` · *timestamp* Timestamp (milliseconds since epoch) when the task was created. > **Note:** A timestamp represents the number of milliseconds elapsed since January 1, 1970 UTC, following > the [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339) standard. > For example, Friday, September 1, 2023 12:00:00 PM GMT is represented as `1693569600000`. This applies > to **all** timestamps in Meshy API. - `started_at` · *timestamp* Timestamp (milliseconds since epoch) when the task started processing. `0` if not started. - `finished_at` · *timestamp* Timestamp (milliseconds since epoch) when the task finished. `0` if not finished. - `expires_at` · *timestamp* Timestamp (milliseconds since epoch) when the task result assets expire. - `task_error` · *object* Error details for failed tasks. See [Errors](/api/errors#task-errors) for the full `task_error` object reference. - `consumed_credits` · *integer* The number of credits consumed by this task. Present when the task status is `PENDING`, `IN_PROGRESS`, or `SUCCEEDED`. Returns `0` for `FAILED` tasks (credits are refunded on failure). - `result` · *object* Contains the output animation URLs if the task `SUCCEEDED`. - `animation_glb_url` · *string* Downloadable URL for the animation in GLB format. - `animation_fbx_url` · *string* Downloadable URL for the animation in FBX format. - `processed_usdz_url` · *string* Downloadable URL for the processed animation in USDZ format. - `processed_armature_fbx_url` · *string* Downloadable URL for the processed armature in FBX format. - `processed_animation_fps_fbx_url` · *string* Downloadable URL for the animation with changed FPS in FBX format (e.g., if `change_fps` operation was used). - `preceding_tasks` · *integer* The count of preceding tasks in the queue. Meaningful only if status is `PENDING`. **Example Animation Task Object** ```json { "id": "018c425b-b2c6-727e-d333-3c1887i9h791", "type": "animate", "status": "SUCCEEDED", "created_at": 1747032440896, "progress": 100, "started_at": 1747032441210, "finished_at": 1747032457530, "expires_at": 1747291657530, "task_error": { "message": "" }, "consumed_credits": 3, "result": { "animation_glb_url": "https://assets.meshy.ai/.../Animation_Reaping_Swing_withSkin.glb?...", "animation_fbx_url": "https://assets.meshy.ai/.../Animation_Reaping_Swing_withSkin.fbx?...", "processed_usdz_url": "https://assets.meshy.ai/.../processed.usdz?...", "processed_armature_fbx_url": "https://assets.meshy.ai/.../processed_armature.fbx?...", "processed_animation_fps_fbx_url": "https://assets.meshy.ai/.../processed_60fps.fbx?..." }, "preceding_tasks": 0 } ``` --- # Retexture API Source: https://docs.meshy.ai/api/retexture export const sections = [ { title: "Create a Task", id: "create-a-retexture-task", }, { title: "Get a Task", id: "retrieve-a-retexture-task", }, { title: "List Tasks", id: "list-retexture-tasks", }, { title: "Stream a Task", id: "stream-a-retexture-task", }, { title: "Task Object", id: "the-retexture-task-object" }, ]; # Retexture API Retexture API is a feature that allows you to integrate Meshy's AI retexturing capabilities into your own application. In this section, you'll find all the information you need to get started with this API. --- ## POST /openapi/v1/retexture -- Create a Retexture Task This endpoint allows you to create a new Retexture task. Refer to [The Retexture Task Object](#the-retexture-task-object) to see which properties are included with Retexture task object. ### Parameters > **Note:** Only one of `input_task_id` or `model_url` is **required**. If both are provided, `input_task_id` takes priority. - `input_task_id` · *string* · **required** The ID of the completed Image to 3D or Text to 3D task you wish to retexture. This task must be one of the following tasks: Text to 3D Preview, Text to 3D Refine, Image to 3D or Remesh. In addition, it must have a status of `SUCCEEDED`. - `model_url` · *string* · **required** Provide a 3D model for Meshy to texture. Supported formats: `.glb`, `.gltf`, `.obj`, `.fbx`, `.stl`. There are two ways to provide the model: - **Publicly accessible URL**: A URL that is accessible from the public internet. - **Data URI**: A base64-encoded data URI of the model. Use MIME type `application/octet-stream`. Example: `data:application/octet-stream;base64,`. > **Note:** Only one of `text_style_prompt` or `image_style_url` is **required**. If both are provided, `image_style_url` takes priority. - `text_style_prompt` · *string* · **required** Describe your desired texture style of the object using text. Maximum 600 characters. - `image_style_url` · *string* · **required** Provide a 2d image to guide the texturing process. We currently support `.jpg`, `.jpeg`, and `.png` formats. There are two ways to provide the image: - **Publicly accessible URL**: A URL that is accessible from the public internet - **Data URI**: A base64-encoded data URI of the image. Example of a data URI: `data:image/jpeg;base64,` > **Note:** Image texturing may not work optimally if there are substantial geometry differences between the original asset and uploaded image. - `ai_model` · *string* · default: `latest` ID of the AI model to use for retexturing. Available values: `meshy-5`, `meshy-6`, `latest` (Meshy 6). - `enable_original_uv` · *boolean* · default: `false` Use the original UV of the model instead of generating new UVs. When enabled, Meshy preserves existing textures from the uploaded model. If the model has no original UV, the quality of the output might not be as good. - `enable_pbr` · *boolean* · default: `false` Generate PBR Maps (metallic, roughness, normal) in addition to the base color. An emission map is also included when `ai_model` is `meshy-6` or `latest`. - `hd_texture` · *boolean* · default: `false` Generate the base color texture at 4K (4096×4096) resolution for higher detail. > **Note:** Only supported when `ai_model` is `meshy-6` or `latest`. PBR maps are always generated at 2K. - `remove_lighting` · *boolean* · default: `true` Removes highlights and shadows from the base color texture, producing a cleaner result that works better under custom lighting setups. > **Note:** Only supported when `ai_model` is `meshy-6` or `latest`. - `target_formats` · *string[]* Specifies which 3D file formats to include in the output. Only the requested formats will be generated and returned, which can reduce task completion time. When omitted, all supported formats are included. Available values: `glb`, `obj`, `fbx`, `stl`, `usdz`, `3mf` > **Note:** When omitted, all formats except `3mf` are generated. `3mf` is only included when explicitly specified. - `alpha_thumbnail` · *boolean* · default: `false` When set to `true`, the task additionally renders a transparent-background (RGBA) version of the preview and returns it as `alpha_thumbnail_url` on the GET response. The existing `thumbnail_url` field is unchanged. ### Returns The `result` property of the response contains the task `id` of the newly created Retexture task. ### Failure Modes - `400 - Bad Request` The request was unacceptable. Common causes: * **Missing parameter**: Either `model_url` or `input_task_id` must be provided. * **Missing style**: Either `text_style_prompt` or `image_style_url` must be provided. * **Invalid input task**: The `input_task_id` must refer to a successful task from a supported model. * **Invalid model format**: The `model_url` points to a file with an unsupported extension. * **Unreachable URL**: The `model_url` or `image_style_url` could not be downloaded. - `401 - Unauthorized` Authentication failed. Please check your API key. - `402 - Payment Required` Insufficient credits to perform this task. - `429 - Too Many Requests` You have exceeded your rate limit. **cURL** ```bash # Retexture with text prompt curl https://api.meshy.ai/openapi/v1/retexture \ -H "Authorization: Bearer ${YOUR_API_KEY}" \ -H 'Content-Type: application/json' \ -d '{ "model_url": "https://cdn.meshy.ai/model/example_model_2.glb", "text_style_prompt": "red fangs, Samurai outfit that fused with japanese batik style", "enable_original_uv": true, "enable_pbr": true }' # Retexture with image style and PBR curl https://api.meshy.ai/openapi/v1/retexture \ -H "Authorization: Bearer ${YOUR_API_KEY}" \ -H 'Content-Type: application/json' \ -d '{ "model_url": "https://cdn.meshy.ai/model/example_model_2.glb", "image_style_url": "https://cdn.meshy.ai/image/example_image.jpg", "ai_model": "latest", "enable_pbr": true, "enable_original_uv": true }' ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; // Retexture with text prompt const payload = { model_url: 'https://cdn.meshy.ai/model/example_model_2.glb', text_style_prompt: 'red fangs, Samurai outfit that fused with japanese batik style', enable_original_uv: true, enable_pbr: true, }; try { const response = await axios.post( 'https://api.meshy.ai/openapi/v1/retexture', payload, { headers } ); console.log(response.data); } catch (error) { console.error(error); } // Retexture with image style and PBR const imageStylePayload = { model_url: 'https://cdn.meshy.ai/model/example_model_2.glb', image_style_url: 'https://cdn.meshy.ai/image/example_image.jpg', ai_model: 'latest', enable_pbr: true, enable_original_uv: true, }; try { const response = await axios.post( 'https://api.meshy.ai/openapi/v1/retexture', imageStylePayload, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } # Retexture with text prompt payload = { "model_url": "https://cdn.meshy.ai/model/example_model_2.glb", "text_style_prompt": "red fangs, Samurai outfit that fused with japanese batik style", "enable_original_uv": True, "enable_pbr": True } response = requests.post( "https://api.meshy.ai/openapi/v1/retexture", headers=headers, json=payload, ) response.raise_for_status() print(response.json()) # Retexture with image style and PBR image_style_payload = { "model_url": "https://cdn.meshy.ai/model/example_model_2.glb", "image_style_url": "https://cdn.meshy.ai/image/example_image.jpg", "ai_model": "latest", "enable_pbr": True, "enable_original_uv": True } response = requests.post( "https://api.meshy.ai/openapi/v1/retexture", headers=headers, json=image_style_payload, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "result": "018a210d-8ba4-705c-b111-1f1776f7f578" } ``` --- ## GET /openapi/v1/retexture/:id -- Retrieve a Retexture Task This endpoint allows you to retrieve a Retexture task given a valid task `id`. Refer to [The Retexture Task Object](#the-retexture-task-object) to see which properties are included with Retexture task object. ### Parameters - `id` · *path* Unique identifier for the Retexture task to retrieve. ### Returns The response contains the Retexture task object. Check [The Retexture Task Object](#the-retexture-task-object) section for details. **cURL** ```bash curl https://api.meshy.ai/openapi/v1/retexture/018a210d-8ba4-705c-b111-1f1776f7f578 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const taskId = '018a210d-8ba4-705c-b111-1f1776f7f578'; const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; try { const response = await axios.get( `https://api.meshy.ai/openapi/v1/retexture/${taskId}`, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests task_id = "018a210d-8ba4-705c-b111-1f1776f7f578" headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.get( f"https://api.meshy.ai/openapi/v1/retexture/{task_id}", headers=headers, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "retexture", "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=***", "obj": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.obj?Expires=***", "usdz": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.usdz?Expires=***", "mtl": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.mtl?Expires=***", "stl": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.stl?Expires=***" }, "thumbnail_url": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview.png?Expires=***", "text_style_prompt": "red fangs, Samurai outfit that fused with japanese batik style", "texture_image_url": "", "progress": 100, "started_at": 1692771667037, "created_at": 1692771650657, "expires_at": 1692771679037, "finished_at": 1692771669037, "status": "SUCCEEDED", "texture_urls": [ { "base_color": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0.png?Expires=***", "metallic": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_metallic.png?Expires=XXX", "normal": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_normal.png?Expires=XXX", "roughness": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_roughness.png?Expires=XXX", "emission": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_emission.png?Expires=XXX" } ], "task_error": { "message": "" }, "consumed_credits": 10 } ``` --- ## DELETE /openapi/v1/retexture/:id -- Delete a Retexture Task This endpoint permanently deletes a retexture task, including all associated models and data. This action is irreversible. ### Path Parameters - `id` · *path* The ID of the retexture task to delete. ### Returns Returns `200 OK` on success. **cURL** ```bash curl --request DELETE \ --url https://api.meshy.ai/openapi/v1/retexture/a43b5c6d-7e8f-901a-234b-567c890d1e2f \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const taskId = 'a43b5c6d-7e8f-901a-234b-567c890d1e2f' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` } try { await axios.delete( `https://api.meshy.ai/openapi/v1/retexture/${taskId}`, { headers } ) } catch (error) { console.error(error) } ``` ```python import requests task_id = "a43b5c6d-7e8f-901a-234b-567c890d1e2f" headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.delete( f"https://api.meshy.ai/openapi/v1/retexture/{task_id}", headers=headers, ) response.raise_for_status() ``` **Response** ```json // Returns 200 Ok on success. ``` --- ## GET /openapi/v1/retexture -- List Retexture Tasks This endpoint allows you to retrieve a list of Retexture tasks. ### Parameters - `page_num` · *integer* · default: `1` Page number for pagination. - `page_size` · *integer* · default: `10` Page size limit. Maximum allowed is `50` items. - `sort_by` · *string* Field to sort by. Available values: * `+created_at`: Sort by creation time in ascending order. * `-created_at`: Sort by creation time in descending order. ### Returns Returns a paginated list of [The Retexture Task Objects](#the-retexture-task-object). **cURL** ```bash curl https://api.meshy.ai/openapi/v1/retexture?page_size=10 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; try { const response = await axios.get( `https://api.meshy.ai/openapi/v1/retexture?page_size=10`, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.get( "https://api.meshy.ai/openapi/v1/retexture", headers=headers, params={"page_size": 10} ) response.raise_for_status() print(response.json()) ``` **Response** ```json [ { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "retexture", "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=***", "usdz": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.usdz?Expires=***" }, "thumbnail_url": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview.png?Expires=***", "text_style_prompt": "red fangs, Samurai outfit that fused with japanese batik style", "progress": 100, "started_at": 1692771667037, "created_at": 1692771650657, "expires_at": 1692771679037, "finished_at": 1692771669037, "status": "SUCCEEDED", "texture_urls": [ { "base_color": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0.png?Expires=***", "metallic": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_metallic.png?Expires=XXX", "normal": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_normal.png?Expires=XXX", "roughness": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_roughness.png?Expires=XXX", "emission": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_emission.png?Expires=XXX" } ], "preceding_tasks": 0, "task_error": { "message": "" }, "consumed_credits": 10 } ] ``` --- ## GET /openapi/v1/retexture/:id/stream -- Stream a Retexture Task This endpoint streams real-time updates for a Retexture task using Server-Sent Events (SSE). ### Parameters - `id` · *path* Unique identifier for the Retexture task to stream. ### Returns Returns a stream of [The Retexture Task Objects](#the-retexture-task-object) as Server-Sent Events. For `PENDING` or `IN_PROGRESS` tasks, the response stream will only include necessary `progress` and `status` fields. **cURL** ```bash curl -N https://api.meshy.ai/openapi/v1/retexture/018a210d-8ba4-705c-b111-1f1776f7f578/stream \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript const response = await fetch( 'https://api.meshy.ai/openapi/v1/retexture/018a210d-8ba4-705c-b111-1f1776f7f578/stream', { headers: { Authorization: `Bearer ${YOUR_API_KEY}` } } ); const reader = response.body.getReader(); const decoder = new TextDecoder(); let buffer = ''; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const lines = buffer.split('\n'); buffer = lines.pop(); for (const line of lines) { if (line.startsWith('data:')) { const data = JSON.parse(line.slice(5)); console.log(data); if (['SUCCEEDED', 'FAILED', 'CANCELED'].includes(data.status)) { reader.cancel(); } } } } ``` ```python import requests import json headers = { "Authorization": f"Bearer {YOUR_API_KEY}", "Accept": "text/event-stream" } response = requests.get( 'https://api.meshy.ai/openapi/v1/retexture/018a210d-8ba4-705c-b111-1f1776f7f578/stream', headers=headers, stream=True ) for line in response.iter_lines(): if line: if line.startswith(b'data:'): data = json.loads(line.decode('utf-8')[5:]) print(data) if data['status'] in ['SUCCEEDED', 'FAILED', 'CANCELED']: break response.close() ``` **Response Stream** ```javascript // Error event example event: error data: { "status_code": 404, "message": "Task not found" } // Message event examples illustrate task progress. // For PENDING or IN_PROGRESS tasks, the response stream will not include all fields. event: message data: { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "progress": 0, "status": "PENDING" } event: message data: { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "progress": 50, "status": "IN_PROGRESS" } event: message data: { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "retexture", "progress": 100, "status": "SUCCEEDED", "created_at": 1692771650657, "started_at": 1692771667037, "finished_at": 1692771669037, "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=***", "obj": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.obj?Expires=***", "usdz": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.usdz?Expires=***", "mtl": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.mtl?Expires=***", "stl": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.stl?Expires=***" }, "texture_urls": [ { "base_color": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0.png?Expires=***", "metallic": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_metallic.png?Expires=XXX", "normal": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_normal.png?Expires=XXX", "roughness": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_roughness.png?Expires=XXX", "emission": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_emission.png?Expires=XXX" } ], "preceding_tasks": 0, "task_error": { "message": "" }, "consumed_credits": 10 } ``` --- ## The Retexture Task Object The Retexture Task object is a work unit that Meshy uses to generate a 3D texture from a either text or image inputs. The model has the following properties: ### Properties - `id` · *string* Unique identifier for the task. While we use a k-sortable UUID for task ids as the implementation detail, you should **not** make any assumptions about the format of the id. - `type` · *string* Type of the Retexture task. The value is `retexture`. - `model_urls` · *object* Downloadable URL to the textured 3D model file generated by Meshy. - `glb` · *string* Downloadable URL to the GLB file. - `fbx` · *string* Downloadable URL to the FBX file. - `obj` · *string* Downloadable URL to the OBJ file. - `usdz` · *string* Downloadable URL to the USDZ file. - `mtl` · *string* Downloadable URL to the MTL file, returned alongside OBJ exports when textures are present. - `stl` · *string* Downloadable URL to the STL file. - `3mf` · *string* Downloadable URL to the 3MF file. Only present when `3mf` was requested via `target_formats`. - `text_style_prompt` · *string* This is the text prompt that was used to create the texturing task. - `image_style_url` · *string* This is the image input that was used to create the texturing task. - `thumbnail_url` · *string* Downloadable URL to the thumbnail image of the model file. - `alpha_thumbnail_url` · *string* Downloadable URL to a transparent-background (RGBA) version of `thumbnail_url`. Only present when the task was created with `alpha_thumbnail: true` and the transparent preview was successfully rendered; otherwise this field is omitted. - `progress` · *integer* Progress of the task. If the task is not started yet, this property will be `0`. Once the task has succeeded, this will become `100`. - `started_at` · *timestamp* Timestamp of when the task was started, in milliseconds. If the task is not started yet, this property will be `0`. > **Note:** A timestamp represents the number of milliseconds elapsed since January 1, 1970 UTC, following > the [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339) standard. > For example, Friday, September 1, 2023 12:00:00 PM GMT is represented as `1693569600000`. This applies > to **all** timestamps in Meshy API. - `created_at` · *timestamp* Timestamp of when the task was created, in milliseconds. - `expires_at` · *timestamp* Timestamp of when the task result expires, in milliseconds. - `finished_at` · *timestamp* Timestamp of when the task was finished, in milliseconds. If the task is not finished yet, this property will be `0`. - `status` · *string* Status of the task. Possible values are one of `PENDING`, `IN_PROGRESS`, `SUCCEEDED`, `FAILED`, `CANCELED`. - `texture_urls` · *array* An array of texture URL objects that are generated from the task. Normally this only contains **one** texture URL object. Each texture URL has the following properties: - `base_color` · *string* Downloadable URL to the base color map image. - `metallic` · *string* Downloadable URL to the metallic map image. > **Note:** If the task is created with `enable_pbr: false`, this property will be omitted. - `normal` · *string* Downloadable URL to the normal map image. > **Note:** If the task is created with `enable_pbr: false`, this property will be omitted. - `roughness` · *string* Downloadable URL to the roughness map image. > **Note:** If the task is created with `enable_pbr: false`, this property will be omitted. - `emission` · *string* Downloadable URL to the emission map image. > **Note:** If the task is created with `enable_pbr: false`, or `ai_model` is `meshy-5`, this property will be omitted. - `preceding_tasks` · *integer* The count of preceding tasks. > **Note:** This property only presents when the task status is `PENDING`. - `task_error` · *object* Error details for failed tasks. See [Errors](/api/errors#task-errors) for the full `task_error` object reference. - `consumed_credits` · *integer* The number of credits consumed by this task. Present when the task status is `PENDING`, `IN_PROGRESS`, or `SUCCEEDED`. Returns `0` for `FAILED` tasks (credits are refunded on failure). **Example Retexture Task Model** ```json { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "retexture", "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=***", "usdz": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/model.usdz?Expires=***" }, "text_style_prompt": "red fangs, Samurai outfit that fused with japanese batik style", "image_style_url": "https://assets.meshy.ai/***/image/example_image.jpg?Expires=***", "thumbnail_url": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/preview.png?Expires=***", "progress": 100, "started_at": 1692771667037, "created_at": 1692771650657, "expires_at": 1692771679037, "finished_at": 1692771669037, "status": "SUCCEEDED", "texture_urls": [ { "base_color": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0.png?Expires=***", "metallic": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_metallic.png?Expires=XXX", "normal": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_normal.png?Expires=XXX", "roughness": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_roughness.png?Expires=XXX", "emission": "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/texture_0_emission.png?Expires=XXX" } ], "preceding_tasks": 0, "task_error": { "message": "" }, "consumed_credits": 10 } ``` --- # Text to Image API Source: https://docs.meshy.ai/api/text-to-image # Text to Image API Text to Image API is a feature that allows you to integrate Meshy's AI image generation capabilities into your own application. Generate high-quality images from text prompts using our powerful AI models. --- ## POST /openapi/v1/text-to-image -- Create a Text to Image Task This endpoint allows you to create a new Text to Image task. Refer to [The Text to Image Task Object](#the-text-to-image-task-object) to see which properties are included with Text to Image task object. ### Parameters - `ai_model` · *string* · **required** ID of the model to use for image generation. Available values: * `nano-banana`: Standard model (3 credits per image) * `nano-banana-2`: Balanced model with stronger capability than standard (6 credits per image) * `nano-banana-pro`: Pro model with enhanced quality (9 credits per image) * `gpt-image-2`: OpenAI GPT Image 2, a high-fidelity image model with restricted aspect-ratio support (9 credits per image) - `prompt` · *string* · **required** A text description of the image you want to generate. Be descriptive for best results. - `generate_multi_view` · *boolean* · default: `false` When set to `true`, generates a multi-view image showing the subject from multiple angles. > **Note:** When `generate_multi_view` is `true`, the `aspect_ratio` parameter cannot be set. - `pose_mode` · *string* Specify the pose mode for character generation. When omitted, the image is generated without any pose presets. Available values: `a-pose`, `t-pose` - `aspect_ratio` · *string* · default: `1:1` Specify the aspect ratio of the generated image. Allowed values depend on the selected `ai_model`: * `nano-banana`, `nano-banana-2`, `nano-banana-pro`: `1:1`, `16:9`, `9:16`, `4:3`, `3:4` * `gpt-image-2`: `1:1`, `3:2`, `2:3` only Available values: * `1:1`: Square format * `16:9`: Widescreen landscape (not supported by `gpt-image-2`) * `9:16`: Widescreen portrait (not supported by `gpt-image-2`) * `4:3`: Standard landscape (not supported by `gpt-image-2`) * `3:4`: Standard portrait (not supported by `gpt-image-2`) * `3:2`: Landscape (only supported by `gpt-image-2`) * `2:3`: Portrait (only supported by `gpt-image-2`) ### Returns The `result` property of the response contains the task `id` of the newly created Text to Image task. ### Failure Modes - `400 - Bad Request` The request was unacceptable. Common causes: * **Missing parameter**: A required parameter (e.g., `ai_model`, `prompt`) is missing. * **Invalid parameter**: `ai_model` or `aspect_ratio` is not one of the allowed values. * **Conflict**: `generate_multi_view` and `aspect_ratio` cannot be used simultaneously. - `401 - Unauthorized` Authentication failed. Please check your API key. - `402 - Payment Required` Insufficient credits to perform this task. - `429 - Too Many Requests` You have exceeded your rate limit. **cURL** ```bash # Generate an image from a text prompt curl https://api.meshy.ai/openapi/v1/text-to-image \ -X POST \ -H "Authorization: Bearer ${YOUR_API_KEY}" \ -H 'Content-Type: application/json' \ -d '{ "ai_model": "nano-banana", "prompt": "A majestic dragon soaring through clouds at sunset", "aspect_ratio": "16:9" }' ``` ```javascript import axios from 'axios' // Generate an image from a text prompt const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; const payload = { ai_model: "nano-banana", prompt: "A majestic dragon soaring through clouds at sunset", aspect_ratio: "16:9" }; try { const response = await axios.post( 'https://api.meshy.ai/openapi/v1/text-to-image', payload, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests # Generate an image from a text prompt payload = { "ai_model": "nano-banana", "prompt": "A majestic dragon soaring through clouds at sunset", "aspect_ratio": "16:9" } headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.post( "https://api.meshy.ai/openapi/v1/text-to-image", headers=headers, json=payload, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "result": "018a210d-8ba4-705c-b111-1f1776f7f578" } ``` --- ## GET /openapi/v1/text-to-image/:id -- Retrieve a Text to Image Task This endpoint allows you to retrieve a Text to Image task given a valid task `id`. Refer to [The Text to Image Task Object](#the-text-to-image-task-object) to see which properties are included with Text to Image task object. ### Parameters - `id` · *path* Unique identifier for the Text to Image task to retrieve. ### Returns The response contains the Text to Image task object. Check [The Text to Image Task Object](#the-text-to-image-task-object) section for details. **cURL** ```bash curl https://api.meshy.ai/openapi/v1/text-to-image/018a210d-8ba4-705c-b111-1f1776f7f578 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const taskId = '018a210d-8ba4-705c-b111-1f1776f7f578'; const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; try { const response = await axios.get( `https://api.meshy.ai/openapi/v1/text-to-image/${taskId}`, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests task_id = "018a210d-8ba4-705c-b111-1f1776f7f578" headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.get( f"https://api.meshy.ai/openapi/v1/text-to-image/{task_id}", headers=headers, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "text-to-image", "ai_model": "nano-banana", "prompt": "A majestic dragon soaring through clouds at sunset", "status": "SUCCEEDED", "progress": 100, "created_at": 1692771650657, "started_at": 1692771667037, "finished_at": 1692771669037, "expires_at": 1692771679037, "image_urls": [ "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/image.png?Expires=***" ] } ``` --- ## DELETE /openapi/v1/text-to-image/:id -- Delete a Text to Image Task This endpoint permanently deletes a Text to Image task, including all associated images and data. This action is irreversible. ### Path Parameters - `id` · *path* The ID of the Text to Image task to delete. ### Returns Returns `200 OK` on success. **cURL** ```bash curl --request DELETE \ --url https://api.meshy.ai/openapi/v1/text-to-image/018a210d-8ba4-705c-b111-1f1776f7f578 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const taskId = '018a210d-8ba4-705c-b111-1f1776f7f578' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` } try { await axios.delete( `https://api.meshy.ai/openapi/v1/text-to-image/${taskId}`, { headers } ) } catch (error) { console.error(error) } ``` ```python import requests task_id = "018a210d-8ba4-705c-b111-1f1776f7f578" headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.delete( f"https://api.meshy.ai/openapi/v1/text-to-image/{task_id}", headers=headers, ) response.raise_for_status() ``` **Response** ```json // Returns 200 Ok on success. ``` --- ## GET /openapi/v1/text-to-image -- List Text to Image Tasks This endpoint allows you to retrieve a list of Text to Image tasks. ### Parameters - `page_num` · *integer* Page number for pagination. Starts and defaults to `1`. - `page_size` · *integer* Page size limit. Defaults to `10` items. Maximum allowed is `50` items. - `sort_by` · *string* Field to sort by. Available values: * `+created_at`: Sort by creation time in ascending order. * `-created_at`: Sort by creation time in descending order. ### Returns Returns a paginated list of [The Text to Image Task Objects](#the-text-to-image-task-object). **cURL** ```bash curl https://api.meshy.ai/openapi/v1/text-to-image?page_size=10 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; try { const response = await axios.get( `https://api.meshy.ai/openapi/v1/text-to-image?page_size=10`, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.get( "https://api.meshy.ai/openapi/v1/text-to-image", headers=headers, params={"page_size": 10} ) response.raise_for_status() print(response.json()) ``` **Response** ```json [ { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "text-to-image", "ai_model": "nano-banana", "prompt": "A majestic dragon soaring through clouds at sunset", "status": "SUCCEEDED", "progress": 100, "created_at": 1692771650657, "started_at": 1692771667037, "finished_at": 1692771669037, "expires_at": 1692771679037, "image_urls": [ "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/image.png?Expires=***" ] } ] ``` --- ## GET /openapi/v1/text-to-image/:id/stream -- Stream a Text to Image Task This endpoint streams real-time updates for a Text to Image task using Server-Sent Events (SSE). ### Parameters - `id` · *path* Unique identifier for the Text to Image task to stream. ### Returns Returns a stream of [The Text to Image Task Objects](#the-text-to-image-task-object) as Server-Sent Events. For `PENDING` or `IN_PROGRESS` tasks, the response stream will only include necessary `progress` and `status` fields. **cURL** ```bash curl -N https://api.meshy.ai/openapi/v1/text-to-image/018a210d-8ba4-705c-b111-1f1776f7f578/stream \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript const response = await fetch( 'https://api.meshy.ai/openapi/v1/text-to-image/018a210d-8ba4-705c-b111-1f1776f7f578/stream', { headers: { Authorization: `Bearer ${YOUR_API_KEY}` } } ); const reader = response.body.getReader(); const decoder = new TextDecoder(); let buffer = ''; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const lines = buffer.split('\n'); buffer = lines.pop(); for (const line of lines) { if (line.startsWith('data:')) { const data = JSON.parse(line.slice(5)); console.log(data); if (['SUCCEEDED', 'FAILED', 'CANCELED'].includes(data.status)) { reader.cancel(); } } } } ``` ```python import requests import json headers = { "Authorization": f"Bearer {YOUR_API_KEY}", "Accept": "text/event-stream" } response = requests.get( 'https://api.meshy.ai/openapi/v1/text-to-image/018a210d-8ba4-705c-b111-1f1776f7f578/stream', headers=headers, stream=True ) for line in response.iter_lines(): if line: if line.startswith(b'data:'): data = json.loads(line.decode('utf-8')[5:]) print(data) if data['status'] in ['SUCCEEDED', 'FAILED', 'CANCELED']: break response.close() ``` **Response Stream** ```text // Error event example event: error data: { "status_code": 404, "message": "Task not found" } // Message event examples illustrate task progress. // For PENDING or IN_PROGRESS tasks, the response stream will not include all fields. event: message data: { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "progress": 0, "status": "PENDING" } event: message data: { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "text-to-image", "ai_model": "nano-banana", "prompt": "A majestic dragon soaring through clouds at sunset", "status": "SUCCEEDED", "progress": 100, "created_at": 1692771650657, "started_at": 1692771667037, "finished_at": 1692771669037, "expires_at": 1692771679037, "image_urls": [ "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/image.png?Expires=***" ] } ``` --- ## The Text to Image Task Object The Text to Image Task object is a work unit that Meshy keeps track of to generate an image from a **text prompt** input. The object has the following properties: ### Properties - `id` · *string* Unique identifier for the task. While we use a k-sortable UUID for task ids as the implementation detail, you should **not** make any assumptions about the format of the id. - `type` · *string* The type of image generation task. For Text to Image tasks, this will always be `text-to-image`. - `ai_model` · *string* The AI model used for this task. Possible values are `nano-banana`, `nano-banana-2`, `nano-banana-pro`, or `gpt-image-2`. - `prompt` · *string* The text prompt that was used to generate the image. - `status` · *string* Status of the task. Possible values are one of `PENDING`, `IN_PROGRESS`, `SUCCEEDED`, `FAILED`, `CANCELED`. - `progress` · *integer* Progress of the task. If the task is not started yet, this property will be `0`. Once the task has succeeded, this will become `100`. - `created_at` · *timestamp* Timestamp of when the task was created, in milliseconds. > **Note:** A timestamp represents the number of milliseconds elapsed since January 1, 1970 UTC, following > the [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339) standard. > For example, Friday, September 1, 2023 12:00:00 PM GMT is represented as `1693569600000`. This applies > to **all** timestamps in Meshy API. - `started_at` · *timestamp* Timestamp of when the task was started, in milliseconds. If the task is not started yet, this property will be `0`. - `finished_at` · *timestamp* Timestamp of when the task was finished, in milliseconds. If the task is not finished yet, this property will be `0`. - `expires_at` · *timestamp* Timestamp of when the task result expires, in milliseconds. - `preceding_tasks` · *integer* The count of preceding tasks. > **Note:** The value of this field is meaningful only if the task status is `PENDING`. - `image_urls` · *array* An array of downloadable URLs to the generated images. When `generate_multi_view` is enabled, this array contains three image URLs representing different viewing angles. Otherwise, it contains a single image URL. - `task_error` · *object* Error details for failed tasks. See [Errors](/api/errors#task-errors) for the full `task_error` object reference. - `consumed_credits` · *integer* The number of credits consumed by this task. Present when the task status is `PENDING`, `IN_PROGRESS`, or `SUCCEEDED`. Returns `0` for `FAILED` tasks (credits are refunded on failure). **Example Text to Image Task Object** ```json { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "text-to-image", "ai_model": "nano-banana", "prompt": "A majestic dragon soaring through clouds at sunset", "status": "SUCCEEDED", "progress": 100, "created_at": 1692771650657, "started_at": 1692771667037, "finished_at": 1692771669037, "expires_at": 1692771679037, "preceding_tasks": 0, "image_urls": [ "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/image.png?Expires=***" ], "task_error": { "message": "" }, "consumed_credits": 3 } ``` --- # Image to Image API Source: https://docs.meshy.ai/api/image-to-image # Image to Image API Image to Image API is a feature that allows you to integrate Meshy's AI image editing capabilities into your own application. Transform and edit existing images using reference images and text prompts with our powerful AI models. --- ## POST /openapi/v1/image-to-image -- Create an Image to Image Task This endpoint allows you to create a new Image to Image task. Refer to [The Image to Image Task Object](#the-image-to-image-task-object) to see which properties are included with Image to Image task object. ### Parameters - `ai_model` · *string* · **required** ID of the model to use for image generation. Available values: * `nano-banana`: Standard model (3 credits per image) * `nano-banana-2`: Balanced model with stronger capability than standard (6 credits per image) * `nano-banana-pro`: Pro model with enhanced quality (9 credits per image) * `gpt-image-2`: OpenAI GPT Image 2, a high-fidelity image edit model (12 credits per image) - `prompt` · *string* · **required** A text description of the transformation or edit you want to apply to the reference images. - `reference_image_urls` · *array* · **required** An array of 1 to 5 reference images to use for the image editing task. We currently support `.jpg`, `.jpeg`, and `.png` formats. There are two ways to provide each image: - **Publicly accessible URL**: A URL that is accessible from the public internet. - **Data URI**: A base64-encoded data URI of the image. Example of a data URI: `data:image/jpeg;base64,`. - `generate_multi_view` · *boolean* · default: `false` When set to `true`, generates a multi-view image showing the subject from multiple angles. ### Returns The `result` property of the response contains the task `id` of the newly created Image to Image task. ### Failure Modes - `400 - Bad Request` The request was unacceptable. Common causes: * **Missing parameter**: A required parameter (e.g., `ai_model`, `prompt`, `reference_image_urls`) is missing. * **Invalid image format**: One or more reference images are not supported formats. * **Unreachable URL**: One or more `reference_image_urls` could not be downloaded. - `401 - Unauthorized` Authentication failed. Please check your API key. - `402 - Payment Required` Insufficient credits to perform this task. - `429 - Too Many Requests` You have exceeded your rate limit. **cURL** ```bash # Transform a reference image with a text prompt curl https://api.meshy.ai/openapi/v1/image-to-image \ -X POST \ -H "Authorization: Bearer ${YOUR_API_KEY}" \ -H 'Content-Type: application/json' \ -d '{ "ai_model": "nano-banana", "prompt": "Transform this into a cyberpunk style artwork", "reference_image_urls": [ "" ] }' ## Using Data URI example curl https://api.meshy.ai/openapi/v1/image-to-image \ -X POST \ -H "Authorization: Bearer ${YOUR_API_KEY}" \ -H 'Content-Type: application/json' \ -d '{ "ai_model": "nano-banana", "prompt": "Transform this into a cyberpunk style artwork", "reference_image_urls": [ "data:image/png;base64,${YOUR_BASE64_ENCODED_IMAGE_DATA}" ] }' ``` ```javascript import axios from 'axios' // Transform a reference image with a text prompt const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; const payload = { ai_model: "nano-banana", prompt: "Transform this into a cyberpunk style artwork", // Using data URI example // reference_image_urls: ['data:image/png;base64,${YOUR_BASE64_ENCODED_IMAGE_DATA}'], reference_image_urls: [ "" ] }; try { const response = await axios.post( 'https://api.meshy.ai/openapi/v1/image-to-image', payload, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests # Transform a reference image with a text prompt payload = { "ai_model": "nano-banana", "prompt": "Transform this into a cyberpunk style artwork", # Using data URI example # "reference_image_urls": [f"data:image/png;base64,{YOUR_BASE64_ENCODED_IMAGE_DATA}"], "reference_image_urls": [ "" ] } headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.post( "https://api.meshy.ai/openapi/v1/image-to-image", headers=headers, json=payload, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "result": "018a210d-8ba4-705c-b111-1f1776f7f578" } ``` --- ## GET /openapi/v1/image-to-image/:id -- Retrieve an Image to Image Task This endpoint allows you to retrieve an Image to Image task given a valid task `id`. Refer to [The Image to Image Task Object](#the-image-to-image-task-object) to see which properties are included with Image to Image task object. ### Parameters - `id` · *path* Unique identifier for the Image to Image task to retrieve. ### Returns The response contains the Image to Image task object. Check [The Image to Image Task Object](#the-image-to-image-task-object) section for details. **cURL** ```bash curl https://api.meshy.ai/openapi/v1/image-to-image/018a210d-8ba4-705c-b111-1f1776f7f578 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const taskId = '018a210d-8ba4-705c-b111-1f1776f7f578'; const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; try { const response = await axios.get( `https://api.meshy.ai/openapi/v1/image-to-image/${taskId}`, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests task_id = "018a210d-8ba4-705c-b111-1f1776f7f578" headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.get( f"https://api.meshy.ai/openapi/v1/image-to-image/{task_id}", headers=headers, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "image-to-image", "ai_model": "nano-banana", "prompt": "Transform this into a cyberpunk style artwork", "status": "SUCCEEDED", "progress": 100, "created_at": 1692771650657, "started_at": 1692771667037, "finished_at": 1692771669037, "expires_at": 1692771679037, "image_urls": [ "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/image.png?Expires=***" ] } ``` --- ## DELETE /openapi/v1/image-to-image/:id -- Delete an Image to Image Task This endpoint permanently deletes an Image to Image task, including all associated images and data. This action is irreversible. ### Path Parameters - `id` · *path* The ID of the Image to Image task to delete. ### Returns Returns `200 OK` on success. **cURL** ```bash curl --request DELETE \ --url https://api.meshy.ai/openapi/v1/image-to-image/018a210d-8ba4-705c-b111-1f1776f7f578 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const taskId = '018a210d-8ba4-705c-b111-1f1776f7f578' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` } try { await axios.delete( `https://api.meshy.ai/openapi/v1/image-to-image/${taskId}`, { headers } ) } catch (error) { console.error(error) } ``` ```python import requests task_id = "018a210d-8ba4-705c-b111-1f1776f7f578" headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.delete( f"https://api.meshy.ai/openapi/v1/image-to-image/{task_id}", headers=headers, ) response.raise_for_status() ``` **Response** ```json // Returns 200 Ok on success. ``` --- ## GET /openapi/v1/image-to-image -- List Image to Image Tasks This endpoint allows you to retrieve a list of Image to Image tasks. ### Parameters - `page_num` · *integer* Page number for pagination. Starts and defaults to `1`. - `page_size` · *integer* Page size limit. Defaults to `10` items. Maximum allowed is `50` items. - `sort_by` · *string* Field to sort by. Available values: * `+created_at`: Sort by creation time in ascending order. * `-created_at`: Sort by creation time in descending order. ### Returns Returns a paginated list of [The Image to Image Task Objects](#the-image-to-image-task-object). **cURL** ```bash curl https://api.meshy.ai/openapi/v1/image-to-image?page_size=10 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; try { const response = await axios.get( `https://api.meshy.ai/openapi/v1/image-to-image?page_size=10`, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.get( "https://api.meshy.ai/openapi/v1/image-to-image", headers=headers, params={"page_size": 10} ) response.raise_for_status() print(response.json()) ``` **Response** ```json [ { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "image-to-image", "ai_model": "nano-banana", "prompt": "Transform this into a cyberpunk style artwork", "status": "SUCCEEDED", "progress": 100, "created_at": 1692771650657, "started_at": 1692771667037, "finished_at": 1692771669037, "expires_at": 1692771679037, "image_urls": [ "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/image.png?Expires=***" ] } ] ``` --- ## GET /openapi/v1/image-to-image/:id/stream -- Stream an Image to Image Task This endpoint streams real-time updates for an Image to Image task using Server-Sent Events (SSE). ### Parameters - `id` · *path* Unique identifier for the Image to Image task to stream. ### Returns Returns a stream of [The Image to Image Task Objects](#the-image-to-image-task-object) as Server-Sent Events. For `PENDING` or `IN_PROGRESS` tasks, the response stream will only include necessary `progress` and `status` fields. **cURL** ```bash curl -N https://api.meshy.ai/openapi/v1/image-to-image/018a210d-8ba4-705c-b111-1f1776f7f578/stream \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript const response = await fetch( 'https://api.meshy.ai/openapi/v1/image-to-image/018a210d-8ba4-705c-b111-1f1776f7f578/stream', { headers: { Authorization: `Bearer ${YOUR_API_KEY}` } } ); const reader = response.body.getReader(); const decoder = new TextDecoder(); let buffer = ''; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const lines = buffer.split('\n'); buffer = lines.pop(); for (const line of lines) { if (line.startsWith('data:')) { const data = JSON.parse(line.slice(5)); console.log(data); if (['SUCCEEDED', 'FAILED', 'CANCELED'].includes(data.status)) { reader.cancel(); } } } } ``` ```python import requests import json headers = { "Authorization": f"Bearer {YOUR_API_KEY}", "Accept": "text/event-stream" } response = requests.get( 'https://api.meshy.ai/openapi/v1/image-to-image/018a210d-8ba4-705c-b111-1f1776f7f578/stream', headers=headers, stream=True ) for line in response.iter_lines(): if line: if line.startswith(b'data:'): data = json.loads(line.decode('utf-8')[5:]) print(data) if data['status'] in ['SUCCEEDED', 'FAILED', 'CANCELED']: break response.close() ``` **Response Stream** ```text // Error event example event: error data: { "status_code": 404, "message": "Task not found" } // Message event examples illustrate task progress. // For PENDING or IN_PROGRESS tasks, the response stream will not include all fields. event: message data: { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "progress": 0, "status": "PENDING" } event: message data: { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "image-to-image", "ai_model": "nano-banana", "prompt": "Transform this into a cyberpunk style artwork", "status": "SUCCEEDED", "progress": 100, "created_at": 1692771650657, "started_at": 1692771667037, "finished_at": 1692771669037, "expires_at": 1692771679037, "image_urls": [ "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/image.png?Expires=***" ] } ``` --- ## The Image to Image Task Object The Image to Image Task object is a work unit that Meshy keeps track of to generate an image from **reference images** and a **text prompt** input. The object has the following properties: ### Properties - `id` · *string* Unique identifier for the task. While we use a k-sortable UUID for task ids as the implementation detail, you should **not** make any assumptions about the format of the id. - `type` · *string* The type of image generation task. For Image to Image tasks, this will always be `image-to-image`. - `ai_model` · *string* The AI model used for this task. Possible values are `nano-banana`, `nano-banana-2`, `nano-banana-pro`, or `gpt-image-2`. - `prompt` · *string* The text prompt that was used to guide the image transformation. - `status` · *string* Status of the task. Possible values are one of `PENDING`, `IN_PROGRESS`, `SUCCEEDED`, `FAILED`, `CANCELED`. - `progress` · *integer* Progress of the task. If the task is not started yet, this property will be `0`. Once the task has succeeded, this will become `100`. - `created_at` · *timestamp* Timestamp of when the task was created, in milliseconds. > **Note:** A timestamp represents the number of milliseconds elapsed since January 1, 1970 UTC, following > the [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339) standard. > For example, Friday, September 1, 2023 12:00:00 PM GMT is represented as `1693569600000`. This applies > to **all** timestamps in Meshy API. - `started_at` · *timestamp* Timestamp of when the task was started, in milliseconds. If the task is not started yet, this property will be `0`. - `finished_at` · *timestamp* Timestamp of when the task was finished, in milliseconds. If the task is not finished yet, this property will be `0`. - `expires_at` · *timestamp* Timestamp of when the task result expires, in milliseconds. - `preceding_tasks` · *integer* The count of preceding tasks. > **Note:** The value of this field is meaningful only if the task status is `PENDING`. - `image_urls` · *array* An array of downloadable URLs to the generated images. When `generate_multi_view` is enabled, this array contains three image URLs representing different viewing angles. Otherwise, it contains a single image URL. - `task_error` · *object* Error details for failed tasks. See [Errors](/api/errors#task-errors) for the full `task_error` object reference. - `consumed_credits` · *integer* The number of credits consumed by this task. Present when the task status is `PENDING`, `IN_PROGRESS`, or `SUCCEEDED`. Returns `0` for `FAILED` tasks (credits are refunded on failure). **Example Image to Image Task Object** ```json { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "image-to-image", "ai_model": "nano-banana", "prompt": "Transform this into a cyberpunk style artwork", "status": "SUCCEEDED", "progress": 100, "created_at": 1692771650657, "started_at": 1692771667037, "finished_at": 1692771669037, "expires_at": 1692771679037, "preceding_tasks": 0, "image_urls": [ "https://assets.meshy.ai/***/tasks/018a210d-8ba4-705c-b111-1f1776f7f578/output/image.png?Expires=***" ], "task_error": { "message": "" }, "consumed_credits": 3 } ``` --- # Multi-Color Print API Source: https://docs.meshy.ai/api/multi-color-print # Multi-Color Print API Convert 3D models into multi-color 3MF format for 3D printing, with a configurable color palette of up to 16 colors. --- ## POST /openapi/v1/print/multi-color -- Create a Multi-Color 3D Print Task This endpoint creates a new multi-color 3D print task. The task converts a 3D model into a multi-color 3MF file suitable for 3D printing. ### Parameters > **Note:** Only one of `input_task_id` or `model_url` is **required**. If both are provided, `input_task_id` takes priority. - `input_task_id` · *string* · **required** The ID of a succeeded task to use as input. Supported task types: [Image to 3D](/api/image-to-3d), [Multi-Image to 3D](/api/multi-image-to-3d#create-a-multi-image-to-3d-task), [Text to 3D](/api/text-to-3d), [Remesh](/api/remesh), and [Retexture](/api/retexture). The task must have a status of `SUCCEEDED`. - `model_url` · *string* · **required** Publicly accessible URL or Data URI of a 3D model. We currently support `.glb` and `.fbx` formats. - `max_colors` · *integer* · default: `4` Maximum number of colors in the output palette. Valid range: `1` to `16`. - `max_depth` · *integer* · default: `4` Quadtree depth for color precision. Higher values produce finer color boundaries but increase file size. Valid range: `3` to `6`. ### Returns The `result` property of the response contains the `id` of the newly created 3D print task. ### Failure Modes - `400 - Bad Request` The request was unacceptable. Common causes: * **Missing parameter**: Either `model_url` or `input_task_id` must be provided. * **Invalid model format**: The `model_url` points to a file with an unsupported extension (only `.glb` and `.fbx` are supported). * **Unreachable URL**: The `model_url` could not be downloaded. * **Invalid input task**: The `input_task_id` must refer to a successful task. * **Invalid max_colors**: Value must be between 1 and 16. * **Invalid max_depth**: Value must be between 3 and 6. - `401 - Unauthorized` Authentication failed. Please check your API key. - `402 - Payment Required` Insufficient credits to perform this task. - `429 - Too Many Requests` You have exceeded your rate limit. **cURL** ```bash # Convert a 3D model to multi-color 3MF for printing curl https://api.meshy.ai/openapi/v1/print/multi-color \ -X POST \ -H "Authorization: Bearer ${YOUR_API_KEY}" \ -H 'Content-Type: application/json' \ -d '{ "input_task_id": "018a210d-8ba4-705c-b111-1f1776f7f578", "max_colors": 8, "max_depth": 5 }' ``` ```javascript import axios from 'axios' // Convert a 3D model to multi-color 3MF for printing const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; const payload = { input_task_id: "018a210d-8ba4-705c-b111-1f1776f7f578", max_colors: 8, max_depth: 5 }; try { const response = await axios.post( 'https://api.meshy.ai/openapi/v1/print/multi-color', payload, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests # Convert a 3D model to multi-color 3MF for printing payload = { "input_task_id": "018a210d-8ba4-705c-b111-1f1776f7f578", "max_colors": 8, "max_depth": 5 } headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.post( "https://api.meshy.ai/openapi/v1/print/multi-color", headers=headers, json=payload, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "result": "0193bfc5-ee4f-73f8-8525-44b398884ce9" } ``` --- ## GET /openapi/v1/print/multi-color/:id -- Retrieve a Multi-Color 3D Print Task This endpoint retrieves a multi-color 3D print task by its ID. ### Parameters - `id` · *path* The ID of the 3D print task to retrieve. ### Returns The 3D Print Task object. **cURL** ```bash curl https://api.meshy.ai/openapi/v1/print/multi-color/a43b5c6d-7e8f-901a-234b-567c890d1e2f \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const taskId = 'a43b5c6d-7e8f-901a-234b-567c890d1e2f'; const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; try { const response = await axios.get( `https://api.meshy.ai/openapi/v1/print/multi-color/${taskId}`, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests task_id = "a43b5c6d-7e8f-901a-234b-567c890d1e2f" headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.get( f"https://api.meshy.ai/openapi/v1/print/multi-color/{task_id}", headers=headers, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "id": "0193bfc5-ee4f-73f8-8525-44b398884ce9", "type": "print-multi-color", "model_urls": { "3mf": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.3mf?Expires=***" }, "progress": 100, "status": "SUCCEEDED", "created_at": 1699999999000, "started_at": 1700000000000, "finished_at": 1700000001000, "task_error": null, "consumed_credits": 10 } ``` --- ## DELETE /openapi/v1/print/multi-color/:id -- Delete a Multi-Color 3D Print Task This endpoint permanently deletes a multi-color 3D print task, including all associated models and data. This action is irreversible. ### Path Parameters - `id` · *path* The ID of the multi-color 3D print task to delete. ### Returns Returns `200 OK` on success. **cURL** ```bash curl --request DELETE \ --url https://api.meshy.ai/openapi/v1/print/multi-color/a43b5c6d-7e8f-901a-234b-567c890d1e2f \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const taskId = 'a43b5c6d-7e8f-901a-234b-567c890d1e2f' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` } try { await axios.delete( `https://api.meshy.ai/openapi/v1/print/multi-color/${taskId}`, { headers } ) } catch (error) { console.error(error) } ``` ```python import requests task_id = "a43b5c6d-7e8f-901a-234b-567c890d1e2f" headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.delete( f"https://api.meshy.ai/openapi/v1/print/multi-color/{task_id}", headers=headers, ) response.raise_for_status() ``` **Response** ```json // Returns 200 Ok on success. ``` --- ## GET /openapi/v1/print/multi-color -- List Multi-Color 3D Print Tasks This endpoint allows you to retrieve a list of multi-color 3D print tasks. ### Parameters #### Optional attributes - `page_num` · *integer* Page number for pagination. Starts and defaults to `1`. - `page_size` · *integer* Page size limit. Defaults to `10` items. Maximum allowed is `50` items. - `sort_by` · *string* Field to sort by. Available values: * `+created_at`: Sort by creation time in ascending order. * `-created_at`: Sort by creation time in descending order. ### Returns Returns a paginated list of [The 3D Print Task Objects](#the-3d-print-task-object). **cURL** ```bash curl https://api.meshy.ai/openapi/v1/print/multi-color?page_size=10 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; try { const response = await axios.get( `https://api.meshy.ai/openapi/v1/print/multi-color?page_size=10`, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.get( "https://api.meshy.ai/openapi/v1/print/multi-color", headers=headers, params={"page_size": 10} ) response.raise_for_status() print(response.json()) ``` **Response** ```json [ { "id": "0193bfc5-ee4f-73f8-8525-44b398884ce9", "type": "print-multi-color", "model_urls": { "3mf": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.3mf?Expires=***" }, "progress": 100, "status": "SUCCEEDED", "preceding_tasks": 0, "created_at": 1699999999000, "started_at": 1700000000000, "finished_at": 1700000001000, "task_error": null, "consumed_credits": 10 } ] ``` --- ## GET /openapi/v1/print/multi-color/:id/stream -- Stream a Multi-Color 3D Print Task This endpoint streams real-time updates for a multi-color 3D print task using Server-Sent Events (SSE). ### Parameters - `id` · *path* Unique identifier for the multi-color 3D print task to stream. ### Returns Returns a stream of [The 3D Print Task Objects](#the-3d-print-task-object) as Server-Sent Events. For `PENDING` or `IN_PROGRESS` tasks, the response stream will only include necessary `progress` and `status` fields. **cURL** ```bash curl -N https://api.meshy.ai/openapi/v1/print/multi-color/a43b5c6d-7e8f-901a-234b-567c890d1e2f/stream \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript const response = await fetch( 'https://api.meshy.ai/openapi/v1/print/multi-color/a43b5c6d-7e8f-901a-234b-567c890d1e2f/stream', { headers: { Authorization: `Bearer ${YOUR_API_KEY}` } } ); const reader = response.body.getReader(); const decoder = new TextDecoder(); let buffer = ''; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const lines = buffer.split('\n'); buffer = lines.pop(); for (const line of lines) { if (line.startsWith('data:')) { const data = JSON.parse(line.slice(5)); console.log(data); if (['SUCCEEDED', 'FAILED', 'CANCELED'].includes(data.status)) { reader.cancel(); } } } } ``` ```python import requests import json headers = { "Authorization": f"Bearer {YOUR_API_KEY}", "Accept": "text/event-stream" } response = requests.get( 'https://api.meshy.ai/openapi/v1/print/multi-color/a43b5c6d-7e8f-901a-234b-567c890d1e2f/stream', headers=headers, stream=True ) for line in response.iter_lines(): if line: if line.startswith(b'data:'): data = json.loads(line.decode('utf-8')[5:]) print(data) if data['status'] in ['SUCCEEDED', 'FAILED', 'CANCELED']: break response.close() ``` **Response Stream** ```javascript // Error event example event: error data: { "status_code": 404, "message": "Task not found" } // Message event examples illustrate task progress. // For PENDING or IN_PROGRESS tasks, the response stream will not include all fields. event: message data: { "id": "a43b5c6d-7e8f-901a-234b-567c890d1e2f", "progress": 0, "status": "PENDING" } event: message data: { "id": "a43b5c6d-7e8f-901a-234b-567c890d1e2f", "type": "print-multi-color", "model_urls": { "3mf": "https://assets.meshy.ai/***/tasks/a43b5c6d-7e8f-901a-234b-567c890d1e2f/output/model.3mf?Expires=***" }, "progress": 100, "status": "SUCCEEDED", "preceding_tasks": 0, "created_at": 1699999999000, "started_at": 1700000000000, "finished_at": 1700000001000, "task_error": null, "consumed_credits": 10 } ``` --- ## The 3D Print Task Object - `id` · *string* Unique identifier for the task. While we use a k-sortable UUID for task ids as the implementation detail, you should **not** make any assumptions about the format of the id. - `type` · *string* Type of the 3D Print task. The value is `print-multi-color`. - `model_urls` · *object* Downloadable URL to the 3D model file generated by Meshy. The property for a format will be omitted if the format is not generated instead of returning an empty string. - `3mf` · *string* Downloadable URL to the multi-color 3MF file. - `progress` · *integer* Progress of the task. If the task is not started yet, this property will be `0`. Once the task has succeeded, this will become `100`. - `status` · *string* Status of the task. Possible values are one of `PENDING`, `IN_PROGRESS`, `SUCCEEDED`, `FAILED`. - `preceding_tasks` · *integer* The count of preceding tasks. > **Note:** The value of this field is meaningful only if the task status is `PENDING`. - `created_at` · *timestamp* Timestamp of when the task was created, in milliseconds. - `started_at` · *timestamp* Timestamp of when the task was started, in milliseconds. If the task is not started yet, this property will be `0`. - `finished_at` · *timestamp* Timestamp of when the task was finished, in milliseconds. If the task is not finished yet, this property will be `0`. - `task_error` · *object* Error details for failed tasks. See [Errors](/api/errors#task-errors) for the full `task_error` object reference. - `consumed_credits` · *integer* The number of credits consumed by this task. Present when the task status is `PENDING`, `IN_PROGRESS`, or `SUCCEEDED`. Returns `0` for `FAILED` tasks (credits are refunded on failure). **The 3D Print Task Object** ```json { "id": "0193bfc5-ee4f-73f8-8525-44b398884ce9", "type": "print-multi-color", "model_urls": { "3mf": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.3mf?Expires=***" }, "progress": 100, "status": "SUCCEEDED", "preceding_tasks": 0, "created_at": 1699999999000, "started_at": 1700000000000, "finished_at": 1700000001000, "task_error": null, "consumed_credits": 10 } ``` --- # Analyze Printability API Source: https://docs.meshy.ai/api/analyze-printability # Analyze Printability API Analyze a 3D model for FDM printability — watertightness, volume, holes, non-manifold edges, and degenerate faces. --- ## POST /openapi/v1/print/analyze -- Create an Analyze Printability Task This endpoint creates a new analyze-printability task. The task evaluates a 3D model and reports its printability metrics. If the input task already has cached printability, the returned task is immediately ready and the first `GET` on it will return the analysis result without going through the worker. ### Parameters > **Note:** Only one of `input_task_id` or `model_url` is **required**. If both are provided, `input_task_id` takes priority. - `input_task_id` · *string* · **required** The ID of a succeeded task you own. Supported task types: [Image to 3D](/api/image-to-3d), [Multi-Image to 3D](/api/multi-image-to-3d), [Text to 3D](/api/text-to-3d), [Remesh](/api/remesh), and [Retexture](/api/retexture). The task must use Meshy 6 (or any Preview model) and must have a status of `SUCCEEDED`. - `model_url` · *string* · **required** URL of a 3D model to analyze. Supported formats: `.glb`, `.gltf`, `.obj`, `.fbx`, `.stl`. Maximum file size: 100 MB. Must use `http`, `https`, or a `data:` URL (data URLs bypass extension checks). ### Returns The `result` property of the response contains the `id` of the newly created analyze-printability task. ### Failure Modes - `400 - Bad Request` The request was unacceptable. Common causes: * **Missing parameter**: neither `input_task_id` nor `model_url` was provided. * **Invalid UUID**: `input_task_id` is not a valid UUID. * **Invalid model URL**: `model_url` is malformed, uses an unsupported scheme, or has an unsupported file extension. * **Model file too large**: `model_url` body exceeded 100 MB. * **Task not succeeded**: the referenced task is still pending, in progress, or failed. - `401 - Unauthorized` Authentication failed. Please check your API key. - `403 - Forbidden` The task exists but is owned by a different user. - `404 - Not Found` Common causes: * The task does not exist or has been deleted. * The task uses a model older than Meshy 6, or its mode does not produce a 3D asset. * The underlying model file is no longer available in storage. - `429 - Too Many Requests` You have exceeded your pending-task quota or rate limit. **cURL** ```bash # Analyze an existing task curl https://api.meshy.ai/openapi/v1/print/analyze \ -X POST \ -H "Authorization: Bearer ${YOUR_API_KEY}" \ -H 'Content-Type: application/json' \ -d '{ "input_task_id": "018a210d-8ba4-705c-b111-1f1776f7f578" }' # Or analyze a model URL directly curl https://api.meshy.ai/openapi/v1/print/analyze \ -X POST \ -H "Authorization: Bearer ${YOUR_API_KEY}" \ -H 'Content-Type: application/json' \ -d '{ "model_url": "https://example.com/model.glb" }' ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; const payload = { input_task_id: "018a210d-8ba4-705c-b111-1f1776f7f578" }; try { const response = await axios.post( 'https://api.meshy.ai/openapi/v1/print/analyze', payload, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests payload = { "input_task_id": "018a210d-8ba4-705c-b111-1f1776f7f578" } headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.post( "https://api.meshy.ai/openapi/v1/print/analyze", headers=headers, json=payload, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "result": "0193bfc5-ee4f-73f8-8525-44b398884ce9" } ``` --- ## GET /openapi/v1/print/analyze/:id -- Retrieve an Analyze Printability Task This endpoint retrieves an analyze-printability task by its ID. ### Parameters - `id` · *path* The ID of the analyze-printability task to retrieve. ### Returns The [Analyze Printability Task Object](#the-analyze-printability-task-object). The `printability` field is `null` until the task reaches `SUCCEEDED`. **cURL** ```bash curl https://api.meshy.ai/openapi/v1/print/analyze/a43b5c6d-7e8f-901a-234b-567c890d1e2f \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const taskId = 'a43b5c6d-7e8f-901a-234b-567c890d1e2f'; const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; try { const response = await axios.get( `https://api.meshy.ai/openapi/v1/print/analyze/${taskId}`, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests task_id = "a43b5c6d-7e8f-901a-234b-567c890d1e2f" headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.get( f"https://api.meshy.ai/openapi/v1/print/analyze/{task_id}", headers=headers, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "id": "0193bfc5-ee4f-73f8-8525-44b398884ce9", "type": "print-analyze", "status": "SUCCEEDED", "progress": 100, "created_at": 1699999999000, "started_at": 1700000000000, "finished_at": 1700000001000, "expires_at": 1715725401000, "task_error": null, "printability": { "_version": "v1", "status": "warning", "issue_count": 1, "error_count": 0, "warning_count": 1, "metrics": { "is_watertight": true, "volume": 1.316167354292668, "non_manifold_edges": 0, "degenerate_faces": 43242, "holes": 0 }, "evaluated_at": 1700000001000 }, "consumed_credits": 0 } ``` --- ## DELETE /openapi/v1/print/analyze/:id -- Delete an Analyze Printability Task This endpoint permanently deletes an analyze-printability task and its cached result. This action is irreversible. ### Path Parameters - `id` · *path* The ID of the analyze-printability task to delete. ### Returns Returns `200 OK` on success. **cURL** ```bash curl --request DELETE \ --url https://api.meshy.ai/openapi/v1/print/analyze/a43b5c6d-7e8f-901a-234b-567c890d1e2f \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const taskId = 'a43b5c6d-7e8f-901a-234b-567c890d1e2f' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` } try { await axios.delete( `https://api.meshy.ai/openapi/v1/print/analyze/${taskId}`, { headers } ) } catch (error) { console.error(error) } ``` ```python import requests task_id = "a43b5c6d-7e8f-901a-234b-567c890d1e2f" headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.delete( f"https://api.meshy.ai/openapi/v1/print/analyze/{task_id}", headers=headers, ) response.raise_for_status() ``` **Response** ```json // Returns 200 Ok on success. ``` --- ## GET /openapi/v1/print/analyze -- List Analyze Printability Tasks This endpoint allows you to retrieve a list of analyze-printability tasks. ### Parameters #### Optional attributes - `page_num` · *integer* Page number for pagination. Starts and defaults to `1`. - `page_size` · *integer* Page size limit. Defaults to `10` items. Maximum allowed is `50` items. - `sort_by` · *string* Field to sort by. Available values: * `+created_at`: Sort by creation time in ascending order. * `-created_at`: Sort by creation time in descending order. ### Returns Returns a paginated list of [Analyze Printability Task Objects](#the-analyze-printability-task-object). **cURL** ```bash curl https://api.meshy.ai/openapi/v1/print/analyze?page_size=10 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; try { const response = await axios.get( `https://api.meshy.ai/openapi/v1/print/analyze?page_size=10`, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.get( "https://api.meshy.ai/openapi/v1/print/analyze", headers=headers, params={"page_size": 10} ) response.raise_for_status() print(response.json()) ``` **Response** ```json [ { "id": "0193bfc5-ee4f-73f8-8525-44b398884ce9", "type": "print-analyze", "status": "SUCCEEDED", "progress": 100, "preceding_tasks": 0, "created_at": 1699999999000, "started_at": 1700000000000, "finished_at": 1700000001000, "expires_at": 1715725401000, "task_error": null, "printability": { "_version": "v1", "status": "warning", "issue_count": 1, "error_count": 0, "warning_count": 1, "metrics": { "is_watertight": true, "volume": 1.316167354292668, "non_manifold_edges": 0, "degenerate_faces": 43242, "holes": 0 }, "evaluated_at": 1700000001000 }, "consumed_credits": 0 } ] ``` --- ## GET /openapi/v1/print/analyze/:id/stream -- Stream an Analyze Printability Task This endpoint streams real-time updates for an analyze-printability task using Server-Sent Events (SSE). ### Parameters - `id` · *path* Unique identifier for the analyze-printability task to stream. ### Returns Returns a stream of [Analyze Printability Task Objects](#the-analyze-printability-task-object) as Server-Sent Events. For `PENDING` or `IN_PROGRESS` tasks, the response stream will only include the necessary `progress` and `status` fields. The `printability` block is sent only once the task reaches `SUCCEEDED`. **cURL** ```bash curl -N https://api.meshy.ai/openapi/v1/print/analyze/a43b5c6d-7e8f-901a-234b-567c890d1e2f/stream \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript const response = await fetch( 'https://api.meshy.ai/openapi/v1/print/analyze/a43b5c6d-7e8f-901a-234b-567c890d1e2f/stream', { headers: { Authorization: `Bearer ${YOUR_API_KEY}` } } ); const reader = response.body.getReader(); const decoder = new TextDecoder(); let buffer = ''; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const lines = buffer.split('\n'); buffer = lines.pop(); for (const line of lines) { if (line.startsWith('data:')) { const data = JSON.parse(line.slice(5)); console.log(data); if (['SUCCEEDED', 'FAILED', 'CANCELED'].includes(data.status)) { reader.cancel(); } } } } ``` ```python import requests import json headers = { "Authorization": f"Bearer {YOUR_API_KEY}", "Accept": "text/event-stream" } response = requests.get( 'https://api.meshy.ai/openapi/v1/print/analyze/a43b5c6d-7e8f-901a-234b-567c890d1e2f/stream', headers=headers, stream=True ) for line in response.iter_lines(): if line: if line.startswith(b'data:'): data = json.loads(line.decode('utf-8')[5:]) print(data) if data['status'] in ['SUCCEEDED', 'FAILED', 'CANCELED']: break response.close() ``` **Response Stream** ```javascript // Error event example event: error data: { "status_code": 404, "message": "Task not found" } // Message event examples illustrate task progress. // For PENDING or IN_PROGRESS tasks, the response stream will not include all fields. event: message data: { "id": "a43b5c6d-7e8f-901a-234b-567c890d1e2f", "progress": 0, "status": "PENDING" } event: message data: { "id": "a43b5c6d-7e8f-901a-234b-567c890d1e2f", "type": "print-analyze", "status": "SUCCEEDED", "progress": 100, "preceding_tasks": 0, "created_at": 1699999999000, "started_at": 1700000000000, "finished_at": 1700000001000, "expires_at": 1715725401000, "task_error": null, "printability": { "_version": "v1", "status": "warning", "issue_count": 1, "error_count": 0, "warning_count": 1, "metrics": { "is_watertight": true, "volume": 1.316167354292668, "non_manifold_edges": 0, "degenerate_faces": 43242, "holes": 0 }, "evaluated_at": 1700000001000 }, "consumed_credits": 0 } ``` --- ## The Analyze Printability Task Object - `id` · *string* Unique identifier for the task. While we use a k-sortable UUID for task ids as the implementation detail, you should **not** make any assumptions about the format of the id. - `type` · *string* Type of the analyze-printability task. The value is `print-analyze`. - `status` · *string* Status of the task. Possible values are one of `PENDING`, `IN_PROGRESS`, `SUCCEEDED`, `FAILED`, `CANCELED`. - `progress` · *integer* Progress of the task. If the task is not started yet, this property will be `0`. Once the task has succeeded, this will become `100`. - `preceding_tasks` · *integer* The count of preceding tasks. > **Note:** The value of this field is meaningful only if the task status is `PENDING`. - `created_at` · *timestamp* Timestamp of when the task was created, in milliseconds. - `started_at` · *timestamp* Timestamp of when the task was started, in milliseconds. If the task is not started yet, this property will be `0`. - `finished_at` · *timestamp* Timestamp of when the task was finished, in milliseconds. If the task is not finished yet, this property will be `0`. - `expires_at` · *timestamp* Timestamp of when the task result will expire from the system, in milliseconds. `0` if the task has not yet finished. - `task_error` · *object* Error information if the task has failed. This property is `null` if the task has not failed. See [Errors](/api/errors) for more details. - `message` · *string* Error message describing what went wrong. - `printability` · *object* Printability evaluation result. `null` until the task reaches `SUCCEEDED`. - `_version` · *string* Schema version of the printability result. Currently `v1`. - `status` · *string* Overall status. One of: * `healthy`: no errors and no warnings. * `warning`: at least one warning, no errors. * `error`: at least one error. * `unknown`: the model could not be analyzed. - `issue_count` · *integer* Total count of issues, equal to `error_count + warning_count`. - `error_count` · *integer* Number of error-level issues. Errors are raised when the model is **not watertight**, has **non-positive volume**, or has **non-manifold edges**. - `warning_count` · *integer* Number of warning-level issues. Warnings are raised when the model contains **degenerate faces** or **holes**. - `metrics` · *object* Raw geometry metrics returned by the evaluator. - `is_watertight` · *boolean* `true` when the mesh has no boundary edges (i.e., is closed). - `volume` · *number* Volume of the model in cubic meters. - `non_manifold_edges` · *integer* Count of non-manifold edges. - `degenerate_faces` · *integer* Count of degenerate faces (zero-area or invalid faces). - `holes` · *integer* Count of holes (boundary loops) in the mesh. - `evaluated_at` · *timestamp* Timestamp of when the analysis was computed, in milliseconds since epoch. - `consumed_credits` · *integer* Always `0`. This endpoint is free. **The Analyze Printability Task Object** ```json { "id": "0193bfc5-ee4f-73f8-8525-44b398884ce9", "type": "print-analyze", "status": "SUCCEEDED", "progress": 100, "preceding_tasks": 0, "created_at": 1699999999000, "started_at": 1700000000000, "finished_at": 1700000001000, "expires_at": 1715725401000, "task_error": null, "printability": { "_version": "v1", "status": "warning", "issue_count": 1, "error_count": 0, "warning_count": 1, "metrics": { "is_watertight": true, "volume": 1.316167354292668, "non_manifold_edges": 0, "degenerate_faces": 43242, "holes": 0 }, "evaluated_at": 1700000001000 }, "consumed_credits": 0 } ``` --- # Repair Printability API Source: https://docs.meshy.ai/api/repair-printability # Repair Printability API Repair a 3D model for FDM printability — fix non-manifold edges, degenerate faces, holes, and other topology issues so the mesh is print-ready. --- ## POST /openapi/v1/print/repair -- Create a Repair Printability Task This endpoint creates a new repair-printability task. The task runs topology repair on a 3D model and returns a watertight, print-ready version. The output format matches the input format. If you submit an `.stl` via `model_url`, the response's `model_urls.stl` will hold the repaired mesh and the other format fields will be empty. The `input_task_id` path always reads the source task's GLB, so the output is `.glb`. ### Parameters > **Note:** Only one of `input_task_id` or `model_url` is **required**. If both are provided, `input_task_id` takes priority. > **Note:** Existing textures are removed during repair due to geometry changes. To add textures back, use the [Retexture API](/api/retexture) on the repaired model. - `input_task_id` · *string* · **required** The ID of a succeeded task you own. Supported task types: [Image to 3D](/api/image-to-3d), [Multi-Image to 3D](/api/multi-image-to-3d), [Text to 3D](/api/text-to-3d), [Remesh](/api/remesh), and [Retexture](/api/retexture). The task must have a status of `SUCCEEDED` and must have produced a GLB asset. - `model_url` · *string* · **required** URL of a 3D model to repair. Supported formats: `.glb`, `.stl`, `.obj`. Maximum file size: 100 MB. Must use `http`, `https`, or a `data:` URL (data URLs bypass extension checks). - `alpha_thumbnail` · *boolean* · default: `false` When set to `true`, the task additionally renders a transparent-background (RGBA) version of the preview and returns it as `alpha_thumbnail_url` on the GET response. The existing `thumbnail_url` field is unchanged. ### Returns The `result` property of the response contains the `id` of the newly created repair-printability task. ### Failure Modes - `400 - Bad Request` The request was unacceptable. Common causes: * **Missing parameter**: neither `input_task_id` nor `model_url` was provided. * **Invalid UUID**: `input_task_id` is not a valid UUID. * **Invalid model URL**: `model_url` is malformed, uses an unsupported scheme, or has an unsupported file extension. * **Model file too large**: `model_url` body exceeded 100 MB. * **Task not succeeded**: the referenced task is still pending, in progress, or failed. * **Missing GLB**: the referenced task has no GLB asset to repair. - `401 - Unauthorized` Authentication failed. Please check your API key. - `402 - Payment Required` Common causes: * **Free plan**: task creation requires a paid plan. Upgrade at the [subscription page](https://www.meshy.ai/settings/subscription). * **Insufficient credits**: the workspace credit limit was reached. - `404 - Not Found` The referenced task does not exist or is owned by a different user. - `429 - Too Many Requests` You have exceeded your pending-task quota or rate limit. **cURL** ```bash # Repair an existing task curl https://api.meshy.ai/openapi/v1/print/repair \ -X POST \ -H "Authorization: Bearer ${YOUR_API_KEY}" \ -H 'Content-Type: application/json' \ -d '{ "input_task_id": "018a210d-8ba4-705c-b111-1f1776f7f578" }' # Or repair a model URL directly curl https://api.meshy.ai/openapi/v1/print/repair \ -X POST \ -H "Authorization: Bearer ${YOUR_API_KEY}" \ -H 'Content-Type: application/json' \ -d '{ "model_url": "https://example.com/model.stl" }' ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; const payload = { input_task_id: "018a210d-8ba4-705c-b111-1f1776f7f578" }; try { const response = await axios.post( 'https://api.meshy.ai/openapi/v1/print/repair', payload, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests payload = { "input_task_id": "018a210d-8ba4-705c-b111-1f1776f7f578" } headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.post( "https://api.meshy.ai/openapi/v1/print/repair", headers=headers, json=payload, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "result": "0193bfc5-ee4f-73f8-8525-44b398884ce9" } ``` --- ## GET /openapi/v1/print/repair/:id -- Retrieve a Repair Printability Task This endpoint retrieves a repair-printability task by its ID. ### Parameters - `id` · *path* The ID of the repair-printability task to retrieve. ### Returns The [Repair Printability Task Object](#the-repair-printability-task-object). The `model_urls` block is empty until the task reaches `SUCCEEDED`. Only the `model_urls` field matching the input format is populated. **cURL** ```bash curl https://api.meshy.ai/openapi/v1/print/repair/a43b5c6d-7e8f-901a-234b-567c890d1e2f \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const taskId = 'a43b5c6d-7e8f-901a-234b-567c890d1e2f'; const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; try { const response = await axios.get( `https://api.meshy.ai/openapi/v1/print/repair/${taskId}`, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests task_id = "a43b5c6d-7e8f-901a-234b-567c890d1e2f" headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.get( f"https://api.meshy.ai/openapi/v1/print/repair/{task_id}", headers=headers, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "id": "0193bfc5-ee4f-73f8-8525-44b398884ce9", "type": "print-repair", "status": "SUCCEEDED", "progress": 100, "created_at": 1699999999000, "started_at": 1700000000000, "finished_at": 1700000030000, "expires_at": 1715725401000, "task_error": null, "model_urls": { "glb": "", "fbx": "", "obj": "", "stl": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.stl?Expires=***", "usdz": "", "3mf": "", "mtl": "" }, "thumbnail_url": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/preview.png?Expires=***", "texture_urls": [], "consumed_credits": 10 } ``` --- ## DELETE /openapi/v1/print/repair/:id -- Delete a Repair Printability Task This endpoint permanently deletes a repair-printability task and its repaired output. This action is irreversible. ### Path Parameters - `id` · *path* The ID of the repair-printability task to delete. ### Returns Returns `200 OK` on success. **cURL** ```bash curl --request DELETE \ --url https://api.meshy.ai/openapi/v1/print/repair/a43b5c6d-7e8f-901a-234b-567c890d1e2f \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const taskId = 'a43b5c6d-7e8f-901a-234b-567c890d1e2f' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` } try { await axios.delete( `https://api.meshy.ai/openapi/v1/print/repair/${taskId}`, { headers } ) } catch (error) { console.error(error) } ``` ```python import requests task_id = "a43b5c6d-7e8f-901a-234b-567c890d1e2f" headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.delete( f"https://api.meshy.ai/openapi/v1/print/repair/{task_id}", headers=headers, ) response.raise_for_status() ``` **Response** ```json // Returns 200 Ok on success. ``` --- ## GET /openapi/v1/print/repair -- List Repair Printability Tasks This endpoint allows you to retrieve a list of repair-printability tasks. ### Parameters #### Optional attributes - `page_num` · *integer* Page number for pagination. Starts and defaults to `1`. - `page_size` · *integer* Page size limit. Defaults to `10` items. Maximum allowed is `50` items. - `sort_by` · *string* Field to sort by. Available values: * `+created_at`: Sort by creation time in ascending order. * `-created_at`: Sort by creation time in descending order. ### Returns Returns a paginated list of [Repair Printability Task Objects](#the-repair-printability-task-object). **cURL** ```bash curl https://api.meshy.ai/openapi/v1/print/repair?page_size=10 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; try { const response = await axios.get( `https://api.meshy.ai/openapi/v1/print/repair?page_size=10`, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.get( "https://api.meshy.ai/openapi/v1/print/repair", headers=headers, params={"page_size": 10} ) response.raise_for_status() print(response.json()) ``` **Response** ```json [ { "id": "0193bfc5-ee4f-73f8-8525-44b398884ce9", "type": "print-repair", "status": "SUCCEEDED", "progress": 100, "preceding_tasks": 0, "created_at": 1699999999000, "started_at": 1700000000000, "finished_at": 1700000030000, "expires_at": 1715725401000, "task_error": null, "model_urls": { "glb": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.glb?Expires=***", "fbx": "", "obj": "", "stl": "", "usdz": "", "3mf": "", "mtl": "" }, "thumbnail_url": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/preview.png?Expires=***", "texture_urls": [], "consumed_credits": 10 } ] ``` --- ## GET /openapi/v1/print/repair/:id/stream -- Stream a Repair Printability Task This endpoint streams real-time updates for a repair-printability task using Server-Sent Events (SSE). ### Parameters - `id` · *path* Unique identifier for the repair-printability task to stream. ### Returns Returns a stream of [Repair Printability Task Objects](#the-repair-printability-task-object) as Server-Sent Events. For `PENDING` or `IN_PROGRESS` tasks, the response stream will only include the necessary `progress` and `status` fields. The `model_urls` block is sent only once the task reaches `SUCCEEDED`. **cURL** ```bash curl -N https://api.meshy.ai/openapi/v1/print/repair/a43b5c6d-7e8f-901a-234b-567c890d1e2f/stream \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript const response = await fetch( 'https://api.meshy.ai/openapi/v1/print/repair/a43b5c6d-7e8f-901a-234b-567c890d1e2f/stream', { headers: { Authorization: `Bearer ${YOUR_API_KEY}` } } ); const reader = response.body.getReader(); const decoder = new TextDecoder(); let buffer = ''; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const lines = buffer.split('\n'); buffer = lines.pop(); for (const line of lines) { if (line.startsWith('data:')) { const data = JSON.parse(line.slice(5)); console.log(data); if (['SUCCEEDED', 'FAILED', 'CANCELED'].includes(data.status)) { reader.cancel(); } } } } ``` ```python import requests import json headers = { "Authorization": f"Bearer {YOUR_API_KEY}", "Accept": "text/event-stream" } response = requests.get( 'https://api.meshy.ai/openapi/v1/print/repair/a43b5c6d-7e8f-901a-234b-567c890d1e2f/stream', headers=headers, stream=True ) for line in response.iter_lines(): if line: if line.startswith(b'data:'): data = json.loads(line.decode('utf-8')[5:]) print(data) if data['status'] in ['SUCCEEDED', 'FAILED', 'CANCELED']: break response.close() ``` **Response Stream** ```javascript // Error event example event: error data: { "status_code": 404, "message": "Task not found" } // Message event examples illustrate task progress. // For PENDING or IN_PROGRESS tasks, the response stream will not include all fields. event: message data: { "id": "a43b5c6d-7e8f-901a-234b-567c890d1e2f", "progress": 0, "status": "PENDING" } event: message data: { "id": "a43b5c6d-7e8f-901a-234b-567c890d1e2f", "type": "print-repair", "status": "SUCCEEDED", "progress": 100, "preceding_tasks": 0, "created_at": 1699999999000, "started_at": 1700000000000, "finished_at": 1700000030000, "expires_at": 1715725401000, "task_error": null, "model_urls": { "glb": "https://assets.meshy.ai/***/tasks/a43b5c6d-7e8f-901a-234b-567c890d1e2f/output/model.glb?Expires=***", "fbx": "", "obj": "", "stl": "", "usdz": "", "3mf": "", "mtl": "" }, "thumbnail_url": "https://assets.meshy.ai/***/tasks/a43b5c6d-7e8f-901a-234b-567c890d1e2f/output/preview.png?Expires=***", "texture_urls": [], "consumed_credits": 10 } ``` --- ## The Repair Printability Task Object - `id` · *string* Unique identifier for the task. While we use a k-sortable UUID for task ids as the implementation detail, you should **not** make any assumptions about the format of the id. - `type` · *string* Type of the repair-printability task. The value is `print-repair`. - `status` · *string* Status of the task. Possible values are one of `PENDING`, `IN_PROGRESS`, `SUCCEEDED`, `FAILED`, `CANCELED`. - `progress` · *integer* Progress of the task. If the task is not started yet, this property will be `0`. Once the task has succeeded, this will become `100`. - `preceding_tasks` · *integer* The count of preceding tasks. > **Note:** The value of this field is meaningful only if the task status is `PENDING`. - `created_at` · *timestamp* Timestamp of when the task was created, in milliseconds. - `started_at` · *timestamp* Timestamp of when the task was started, in milliseconds. If the task is not started yet, this property will be `0`. - `finished_at` · *timestamp* Timestamp of when the task was finished, in milliseconds. If the task is not finished yet, this property will be `0`. - `expires_at` · *timestamp* Timestamp of when the task result will expire from the system, in milliseconds. `0` if the task has not yet finished. - `task_error` · *object* Error information if the task has failed. This property is `null` if the task has not failed. See [Errors](/api/errors) for more details. - `message` · *string* Error message describing what went wrong. - `model_urls` · *object* Downloadable URLs to the repaired 3D model. **Only the field matching the input format is populated**; the other format fields are empty strings. - `glb` · *string* Downloadable URL to the repaired GLB. Populated when the input was a GLB or when `input_task_id` was used. - `fbx` · *string* Reserved for FBX output. Always an empty string for repair-printability tasks. - `obj` · *string* Downloadable URL to the repaired OBJ. Populated when the input was an OBJ upload. - `stl` · *string* Downloadable URL to the repaired STL. Populated when the input was an STL upload. - `usdz` · *string* Reserved for USDZ output. Always an empty string for repair-printability tasks. - `3mf` · *string* Reserved for 3MF output. Always an empty string for repair-printability tasks. - `mtl` · *string* Reserved for MTL output. Always an empty string for repair-printability tasks. - `thumbnail_url` · *string* URL of a preview image rendered from the repaired model. - `alpha_thumbnail_url` · *string* Downloadable URL to a transparent-background (RGBA) version of `thumbnail_url`. Only present when the task was created with `alpha_thumbnail: true` and the transparent preview was successfully rendered; otherwise this field is omitted. - `texture_urls` · *array* Always an empty array. Repair preserves the input geometry only and does not re-bake textures. - `consumed_credits` · *integer* The number of credits consumed by this task. `10` once the task has reached `SUCCEEDED`. Returns `0` for `FAILED` tasks (credits are refunded on failure). **The Repair Printability Task Object** ```json { "id": "0193bfc5-ee4f-73f8-8525-44b398884ce9", "type": "print-repair", "status": "SUCCEEDED", "progress": 100, "preceding_tasks": 0, "created_at": 1699999999000, "started_at": 1700000000000, "finished_at": 1700000030000, "expires_at": 1715725401000, "task_error": null, "model_urls": { "glb": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.glb?Expires=***", "fbx": "", "obj": "", "stl": "", "usdz": "", "3mf": "", "mtl": "" }, "thumbnail_url": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/preview.png?Expires=***", "texture_urls": [], "consumed_credits": 10 } ``` --- # Creative Lab — Keychain API Source: https://docs.meshy.ai/api/creative-lab-keychain # Creative Lab — Keychain API Turn a source photo into a 3D-printable keychain medallion — a badge-shaped colorized depth relief — in two stages: **prototype** generates a colorized concept image from your input photo, then **build** turns that concept image into a relief 3D model. The two stages are linked via `input_task_id`. - `POST /openapi/creative-lab/keychain/v1/prototype` - `POST /openapi/creative-lab/keychain/v1/build` --- ## POST /openapi/creative-lab/keychain/v1/prototype -- Create a Keychain Prototype Task Generate a single colorized concept image from the source photo. The returned task ID is what you pass as `input_task_id` to the build endpoint. Refer to [The Keychain Prototype Task Object](#the-keychain-prototype-task-object) for the response shape. ### Parameters - `image_url` · *string* · **required** Source photo for Meshy to colorize into a keychain-ready concept image. We currently support `.jpg`, `.jpeg`, `.png`, and `.webp` formats. There are two ways to provide the image: - **Publicly accessible URL**: A URL that is accessible from the public internet. - **Data URI**: A base64-encoded data URI of the image. Example of a data URI: `data:image/jpeg;base64,`. - `name` · *string* Optional task name for display purposes. Maximum 100 characters. ### Returns The `result` property of the response contains the task `id` of the newly created keychain prototype task. Poll the [Get a Task](#retrieve-a-keychain-task) endpoint or subscribe to the [stream](#stream-a-keychain-task) until the task reaches `SUCCEEDED`, then pass that ID to the [build endpoint](#create-a-keychain-build-task) as `input_task_id`. ### Failure Modes - `400 - Bad Request` The request was unacceptable. Common causes: * **Missing parameter**: `image_url` is required. * **Invalid image format**: The provided `image_url` is not a supported format (`.jpg`, `.jpeg`, `.png`, `.webp`). * **Image dimensions out of range**: The image is too small, exceeds the maximum file size, or exceeds the maximum pixel count. * **Unreachable URL**: The `image_url` could not be downloaded (404 or timeout). * **Invalid Data URI**: The base64 string is malformed. * **Content flagged**: The input image was flagged by NSFW or intellectual property moderation. - `401 - Unauthorized` Authentication failed. Please check your API key. - `402 - Payment Required` Insufficient credits to perform this task. - `429 - Too Many Requests` You have exceeded your rate limit. **cURL** ```bash # Stage 1: generate a colorized keychain concept image curl https://api.meshy.ai/openapi/creative-lab/keychain/v1/prototype \ -X POST \ -H "Authorization: Bearer ${YOUR_API_KEY}" \ -H 'Content-Type: application/json' \ -d '{ "image_url": "" }' ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; // Stage 1: generate a colorized keychain concept image const payload = { image_url: "", }; try { const response = await axios.post( 'https://api.meshy.ai/openapi/creative-lab/keychain/v1/prototype', payload, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } # Stage 1: generate a colorized keychain concept image payload = { "image_url": "", } response = requests.post( "https://api.meshy.ai/openapi/creative-lab/keychain/v1/prototype", headers=headers, json=payload, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "result": "018a210d-8ba4-705c-b111-1f1776f7f578" } ``` --- ## POST /openapi/creative-lab/keychain/v1/build -- Create a Keychain Build Task Generate the final 3D-printable keychain medallion from a succeeded prototype task. The build runs a depth-map relief pipeline on the prototype's colorized concept image and ships a single mesh artifact in the format you ask for. Refer to [The Keychain Build Task Object](#the-keychain-build-task-object) for the response shape. ### Parameters - `input_task_id` · *string* · **required** The task ID of a prototype task created via this same OpenAPI endpoint. The prototype must have been created with the same API key, must have reached `SUCCEEDED`, and must have produced exactly one candidate image. Prototype tasks created through the webapp are **not** accepted — the build endpoint accepts only prototype tasks produced by `POST /openapi/creative-lab/keychain/v1/prototype` and refuses any other source with `404`. - `name` · *string* Optional task name for display purposes. Maximum 100 characters. #### `options` Optional tuning parameters for the relief geometry. Every field has a sensible default — send only the ones you want to override. - `badge_shape` · *string* · default: `circle` Outline silhouette of the keychain medallion. Available values: * `circle` (default) * `rounded-rect` * `hexagon` * `shield` * `star` - `size_mm` · *number* · default: `40` Bounding square edge length of the keychain, in millimeters. Range: `(0, 400]`. - `relief_height_mm` · *number* · default: `2.2` Maximum relief height above the base, in millimeters. Range: `[0, 20]`. - `relief_offset_mm` · *number* · default: `0` Vertical offset applied to the relief before extrusion, in millimeters. Range: `[0, 20]`. - `base_thickness_mm` · *number* · default: `0.1` Thickness of the flat base plate behind the relief, in millimeters. Range: `[0, 20]`. - `has_closed_back` · *boolean* · default: `true` Whether the back of the medallion is sealed as a closed surface. Set to `false` for an open shell. - `relief_curve` · *string* · default: `linear` Transfer curve mapping depth-map values to relief height. Available values: * `linear` (default) * `gamma` * `s-curve` - `curve_param` · *number* · default: `1.0` Shape parameter for the transfer curve (only meaningful when `relief_curve` is `gamma`). Range: `(0, 10]`. - `invert_depth` · *boolean* · default: `false` Invert the depth-map interpretation so darker regions become higher relief. - `smoothing` · *number* · default: `0.24` Smoothing strength applied to the depth map before relief extraction. Range: `[0, 10]`. - `relief_scale` · *number* · default: `1.0` Vertical scale multiplier applied on top of `relief_height_mm`. Range: `(0, 10]`. - `depth_threshold` · *number* · default: `0.1` Low-pass threshold for depth-map values; anything below this is clamped to zero. Range: `[0, 1]`. - `remove_background` · *boolean* · default: `true` Automatically remove the background of the prototype's concept image before reliefing. - `export_resolution` · *integer* · default: `512` Mesh resolution used for export. Range: `[64, 2048]`. #### `output` Optional wire-format selector. Defaults to `glb`. - `format` · *string* · default: `glb` Artifact bundle returned by the build. Available values: * `glb` (default) — returns a single `model.glb` under `model_urls.glb`. * `obj` — zips `model.obj` + `model.mtl` + `texture.png` and returns the bundle under `model_urls.obj`. * `zip` — zips every artifact the generator emits and returns the bundle under `model_urls.bundle_zip`. ### Returns The `result` property of the response contains the task `id` of the newly created keychain build task. Poll the [Get a Task](#retrieve-a-keychain-task) endpoint or subscribe to the [stream](#stream-a-keychain-task) until the task reaches `SUCCEEDED`, then download the artifact from the single entry in `model_urls`. ### Failure Modes - `400 - Bad Request` The request was unacceptable. Common causes: * **Missing parameter**: `input_task_id` is required. * **Invalid UUID**: The `input_task_id` is not a valid UUID. * **Parent not succeeded**: The referenced prototype task has not reached `SUCCEEDED` yet. * **No candidate**: The prototype task succeeded but produced no candidate image. * **Options out of range**: One of the `options` fields fell outside its allowed range or enum set. - `401 - Unauthorized` Authentication failed. Please check your API key. - `402 - Payment Required` Insufficient credits to perform this task. - `404 - Not Found` The referenced prototype task does not exist, belongs to a different user, or was created through the webapp (only API-mode prototype tasks chain into build). - `429 - Too Many Requests` You have exceeded your rate limit. **cURL** ```bash # Stage 2: chain build off a succeeded prototype task curl https://api.meshy.ai/openapi/creative-lab/keychain/v1/build \ -X POST \ -H "Authorization: Bearer ${YOUR_API_KEY}" \ -H 'Content-Type: application/json' \ -d '{ "input_task_id": "018a210d-8ba4-705c-b111-1f1776f7f578", "options": { "badge_shape": "circle", "size_mm": 40, "relief_height_mm": 2.5 }, "output": { "format": "glb" } }' ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; // Stage 2: chain build off a succeeded prototype task const payload = { input_task_id: "018a210d-8ba4-705c-b111-1f1776f7f578", options: { badge_shape: "circle", size_mm: 40, relief_height_mm: 2.5, }, output: { format: "glb" }, }; try { const response = await axios.post( 'https://api.meshy.ai/openapi/creative-lab/keychain/v1/build', payload, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } # Stage 2: chain build off a succeeded prototype task payload = { "input_task_id": "018a210d-8ba4-705c-b111-1f1776f7f578", "options": { "badge_shape": "circle", "size_mm": 40, "relief_height_mm": 2.5, }, "output": {"format": "glb"}, } response = requests.post( "https://api.meshy.ai/openapi/creative-lab/keychain/v1/build", headers=headers, json=payload, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "result": "019c320e-9a8f-7a1c-9c11-2a1876f8a9bb" } ``` --- ## GET /openapi/creative-lab/keychain/v1/(prototype|build)/:id -- Retrieve a Keychain Task Retrieve a prototype or build task given a valid task `id`. The URL path must match the task's stage — a build task fetched through `/prototype/:id` returns `404`, and vice versa. Refer to [The Keychain Prototype Task Object](#the-keychain-prototype-task-object) and [The Keychain Build Task Object](#the-keychain-build-task-object) for response shapes. ### Parameters - `id` · *path* Unique identifier for the keychain task to retrieve. ### Returns The response contains the keychain task object. The shape depends on which stage was requested. **cURL** ```bash # Prototype curl https://api.meshy.ai/openapi/creative-lab/keychain/v1/prototype/018a210d-8ba4-705c-b111-1f1776f7f578 \ -H "Authorization: Bearer ${YOUR_API_KEY}" # Build curl https://api.meshy.ai/openapi/creative-lab/keychain/v1/build/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; // Prototype const prototypeId = '018a210d-8ba4-705c-b111-1f1776f7f578'; const proto = await axios.get( `https://api.meshy.ai/openapi/creative-lab/keychain/v1/prototype/${prototypeId}`, { headers } ); console.log(proto.data); // Build const buildId = '019c320e-9a8f-7a1c-9c11-2a1876f8a9bb'; const build = await axios.get( `https://api.meshy.ai/openapi/creative-lab/keychain/v1/build/${buildId}`, { headers } ); console.log(build.data); ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } # Prototype prototype_id = "018a210d-8ba4-705c-b111-1f1776f7f578" proto = requests.get( f"https://api.meshy.ai/openapi/creative-lab/keychain/v1/prototype/{prototype_id}", headers=headers, ) proto.raise_for_status() print(proto.json()) # Build build_id = "019c320e-9a8f-7a1c-9c11-2a1876f8a9bb" build = requests.get( f"https://api.meshy.ai/openapi/creative-lab/keychain/v1/build/{build_id}", headers=headers, ) build.raise_for_status() print(build.json()) ``` **Prototype Response** ```json { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "creative-lab-keychain-prototype", "name": "", "status": "SUCCEEDED", "progress": 100, "created_at": 1729123456000, "started_at": 1729123460000, "finished_at": 1729123486000, "expires_at": 1729382686000, "preceding_tasks": 0, "task_error": null, "consumed_credits": 6, "image_urls": [ "https://assets.meshy.ai/***/concept.png?Expires=***" ] } ``` **Build Response** ```json { "id": "019c320e-9a8f-7a1c-9c11-2a1876f8a9bb", "type": "creative-lab-keychain-build", "name": "", "status": "SUCCEEDED", "progress": 100, "created_at": 1729123500000, "started_at": 1729123510000, "finished_at": 1729123535000, "expires_at": 1729382735000, "preceding_tasks": 0, "task_error": null, "consumed_credits": 20, "model_urls": { "glb": "https://assets.meshy.ai/***/tasks/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/output/model.glb?Expires=***" } } ``` --- ## DELETE /openapi/creative-lab/keychain/v1/(prototype|build)/:id -- Delete a Keychain Task Cancel a keychain task. If the task is still `PENDING`, the credits consumed at create-time are refunded. Tasks that are already `IN_PROGRESS` are cancelled without a refund (the worker may already be burning resources). Tasks that have already reached a terminal state (`SUCCEEDED`, `FAILED`, `CANCELED`) cannot be cancelled. The URL path must match the task's stage — `DELETE` on `/prototype/:buildId` returns `404`. ### Path Parameters - `id` · *path* Unique identifier for the keychain task to cancel. ### Returns Returns `204 No Content` on success with an empty body. ### Failure Modes - `400 - Bad Request` The task is already in a terminal state and cannot be cancelled. - `404 - Not Found` The task does not exist, belongs to a different user, or its stage does not match the URL path. **cURL** ```bash curl --request DELETE \ --url https://api.meshy.ai/openapi/creative-lab/keychain/v1/prototype/018a210d-8ba4-705c-b111-1f1776f7f578 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const taskId = '018a210d-8ba4-705c-b111-1f1776f7f578' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` } try { await axios.delete( `https://api.meshy.ai/openapi/creative-lab/keychain/v1/prototype/${taskId}`, { headers } ) } catch (error) { console.error(error) } ``` ```python import requests task_id = "018a210d-8ba4-705c-b111-1f1776f7f578" headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.delete( f"https://api.meshy.ai/openapi/creative-lab/keychain/v1/prototype/{task_id}", headers=headers, ) response.raise_for_status() ``` **Response** ```json // Returns 204 No Content on success (empty body). ``` --- ## GET /openapi/creative-lab/keychain/v1/(prototype|build)/:id/stream -- Stream a Keychain Task Stream real-time updates for a keychain task via Server-Sent Events (SSE). The URL path must match the task's stage — opening a stream at `/prototype/:buildId/stream` emits a single `event: error` payload with `status_code: 404` and closes the stream. ### Parameters - `id` · *path* Unique identifier for the keychain task to stream. ### Returns Returns a stream of [Keychain Prototype](#the-keychain-prototype-task-object) or [Keychain Build](#the-keychain-build-task-object) task objects as Server-Sent Events. For `PENDING` or `IN_PROGRESS` tasks, the response stream will only include the necessary `progress` and `status` fields. **cURL** ```bash curl -N https://api.meshy.ai/openapi/creative-lab/keychain/v1/build/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/stream \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript const response = await fetch( 'https://api.meshy.ai/openapi/creative-lab/keychain/v1/build/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/stream', { headers: { Authorization: `Bearer ${YOUR_API_KEY}` } } ); const reader = response.body.getReader(); const decoder = new TextDecoder(); let buffer = ''; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const lines = buffer.split('\n'); buffer = lines.pop(); for (const line of lines) { if (line.startsWith('data:')) { const data = JSON.parse(line.slice(5)); console.log(data); if (['SUCCEEDED', 'FAILED', 'CANCELED'].includes(data.status)) { reader.cancel(); } } } } ``` ```python import requests import json headers = { "Authorization": f"Bearer {YOUR_API_KEY}", "Accept": "text/event-stream" } response = requests.get( 'https://api.meshy.ai/openapi/creative-lab/keychain/v1/build/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/stream', headers=headers, stream=True ) for line in response.iter_lines(): if line: if line.startswith(b'data:'): data = json.loads(line.decode('utf-8')[5:]) print(data) if data['status'] in ['SUCCEEDED', 'FAILED', 'CANCELED']: break response.close() ``` **Response Stream** ```javascript // Error event example (wrong stage or task not found) event: error data: { "status_code": 404, "message": "Task not found" } // Message event examples illustrate task progress. // For PENDING or IN_PROGRESS tasks, the response stream will not include all fields. event: message data: { "id": "019c320e-9a8f-7a1c-9c11-2a1876f8a9bb", "progress": 0, "status": "PENDING" } event: message data: { "id": "019c320e-9a8f-7a1c-9c11-2a1876f8a9bb", "type": "creative-lab-keychain-build", "status": "SUCCEEDED", "progress": 100, "created_at": 1729123500000, "started_at": 1729123510000, "finished_at": 1729123535000, "expires_at": 1729382735000, "task_error": null, "consumed_credits": 20, "model_urls": { "glb": "https://assets.meshy.ai/***/tasks/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/output/model.glb?Expires=***" } } ``` --- ## GET /openapi/creative-lab/keychain/v1/(prototype|build) -- List Keychain Tasks Retrieve a paginated list of your keychain tasks for a single stage. The URL path selects the stage — `/prototype` returns prototype tasks; `/build` returns build tasks. Tasks from the other stage are not included in either response. ### Path Parameters - `stage` · *path* · **required** Either `prototype` or `build`. The collection returns only tasks whose stage matches the URL — fetching `/prototype` never returns build tasks and vice versa. ### Query Parameters - `page_num` · *integer* · default: `1` Page number for pagination. - `page_size` · *integer* · default: `10` Page size limit. Maximum allowed is `50` items. - `sort_by` · *string* · default: `-created_at` Field to sort by. Available values: * `+created_at`: Sort by creation time in ascending order. * `-created_at`: Sort by creation time in descending order. ### Returns Returns a paginated list of the per-stage task object — either [the keychain prototype task object](#the-keychain-prototype-task-object) when listing `/prototype` or [the keychain build task object](#the-keychain-build-task-object) when listing `/build`. **cURL** ```bash # List prototype tasks curl https://api.meshy.ai/openapi/creative-lab/keychain/v1/prototype?page_size=10 \ -H "Authorization: Bearer ${YOUR_API_KEY}" # List build tasks curl https://api.meshy.ai/openapi/creative-lab/keychain/v1/build?page_size=10 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` } try { const { data } = await axios.get( 'https://api.meshy.ai/openapi/creative-lab/keychain/v1/prototype', { headers, params: { page_size: 10 } } ) console.log(data) } catch (error) { console.error(error) } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.get( "https://api.meshy.ai/openapi/creative-lab/keychain/v1/prototype", headers=headers, params={"page_size": 10}, ) response.raise_for_status() print(response.json()) ``` **Response (List Prototype Tasks)** ```json [ { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "creative-lab-keychain-prototype", "name": "", "status": "SUCCEEDED", "progress": 100, "created_at": 1729123456000, "started_at": 1729123460000, "finished_at": 1729123486000, "expires_at": 1729382686000, "preceding_tasks": 0, "task_error": null, "consumed_credits": 6, "image_urls": [ "https://assets.meshy.ai/***/concept.png?Expires=***" ] } ] ``` --- ## The Keychain Prototype Task Object The Keychain Prototype Task object is a work unit that Meshy keeps track of to generate a colorized **concept image** from a source photo. The output of this stage is chained into [the build stage](#create-a-keychain-build-task) via `input_task_id`. ### Properties - `id` · *string* Unique identifier for the task. While we use a k-sortable UUID for task ids as the implementation detail, you should **not** make any assumptions about the format of the id. - `type` · *string* Type of the task. The value is `creative-lab-keychain-prototype`. - `name` · *string* The task name supplied when the task was created. Empty string if no name was provided. - `status` · *string* Status of the task. Possible values are one of `PENDING`, `IN_PROGRESS`, `SUCCEEDED`, `FAILED`, `CANCELED`. - `progress` · *integer* Progress of the task. If the task is not started yet, this property will be `0`. Once the task has succeeded, this will become `100`. - `created_at` · *timestamp* Timestamp of when the task was created, in milliseconds. > **Note:** A timestamp represents the number of milliseconds elapsed since January 1, 1970 UTC, following > the [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339) standard. > For example, Friday, September 1, 2023 12:00:00 PM GMT is represented as `1693569600000`. This applies > to **all** timestamps in Meshy API. - `started_at` · *timestamp* Timestamp of when the task was started, in milliseconds. If the task is not started yet, this property will be `0`. - `finished_at` · *timestamp* Timestamp of when the task was finished, in milliseconds. If the task is not finished yet, this property will be `0`. - `expires_at` · *timestamp* Timestamp of when the task result expires, in milliseconds. - `preceding_tasks` · *integer* The count of preceding tasks. > **Note:** The value of this field is meaningful only if the task status is `PENDING`. - `task_error` · *object* Error details for failed tasks. See [Errors](/api/errors#task-errors) for the full `task_error` object reference. - `consumed_credits` · *integer* The number of credits consumed by this task. Present when the task status is `PENDING`, `IN_PROGRESS`, or `SUCCEEDED`. Returns `0` for `FAILED` tasks (credits are refunded on failure). - `image_urls` · *array of strings* Downloadable URLs for the concept image candidates generated by this prototype task. Currently the API always returns exactly one candidate; the field is an array so future revisions can surface multiple candidates without a breaking change. **Example Keychain Prototype Task Object** ```json { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "creative-lab-keychain-prototype", "name": "", "status": "SUCCEEDED", "progress": 100, "created_at": 1729123456000, "started_at": 1729123460000, "finished_at": 1729123486000, "expires_at": 1729382686000, "preceding_tasks": 0, "task_error": null, "consumed_credits": 6, "image_urls": [ "https://assets.meshy.ai/***/concept.png?Expires=***" ] } ``` --- ## The Keychain Build Task Object The Keychain Build Task object is a work unit that Meshy keeps track of to generate the final 3D keychain mesh from a succeeded prototype task. The build runs a depth-map relief pipeline on the prototype's concept image and publishes a single mesh artifact in the format the caller requested. ### Properties - `id` · *string* Unique identifier for the task. - `type` · *string* Type of the task. The value is `creative-lab-keychain-build`. - `name` · *string* The task name supplied when the task was created. Empty string if no name was provided. - `status` · *string* Status of the task. Possible values are one of `PENDING`, `IN_PROGRESS`, `SUCCEEDED`, `FAILED`, `CANCELED`. - `progress` · *integer* Progress of the task. If the task is not started yet, this property will be `0`. Once the task has succeeded, this will become `100`. - `created_at` · *timestamp* Timestamp of when the task was created, in milliseconds. - `started_at` · *timestamp* Timestamp of when the task was started, in milliseconds. - `finished_at` · *timestamp* Timestamp of when the task was finished, in milliseconds. - `expires_at` · *timestamp* Timestamp of when the task result expires, in milliseconds. - `preceding_tasks` · *integer* The count of preceding tasks. Meaningful only when status is `PENDING`. - `task_error` · *object* Error details for failed tasks. See [Errors](/api/errors#task-errors) for the full `task_error` object reference. - `consumed_credits` · *integer* The number of credits consumed by this task. Returns `0` for `FAILED` tasks (credits are refunded on failure). - `model_urls` · *object* Downloadable URLs for the generated artifact, keyed by artifact name. Always contains exactly one entry — the format requested via the build request's `output.format`. The key matches the requested format: - `glb` · *string* Downloadable URL to the GLB file. Present when `output.format` was `glb` (the default). - `obj` · *string* Downloadable URL to a zip bundle containing `model.obj`, `model.mtl`, and `texture.png`. Present when `output.format` was `obj`. - `bundle_zip` · *string* Downloadable URL to a zip bundle of every artifact the generator emits. Present when `output.format` was `zip`. **Example Keychain Build Task Object** ```json { "id": "019c320e-9a8f-7a1c-9c11-2a1876f8a9bb", "type": "creative-lab-keychain-build", "name": "", "status": "SUCCEEDED", "progress": 100, "created_at": 1729123500000, "started_at": 1729123510000, "finished_at": 1729123535000, "expires_at": 1729382735000, "preceding_tasks": 0, "task_error": null, "consumed_credits": 20, "model_urls": { "glb": "https://assets.meshy.ai/***/tasks/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/output/model.glb?Expires=***" } } ``` --- # Creative Lab — Fridge Magnet API Source: https://docs.meshy.ai/api/creative-lab-fridge-magnet # Creative Lab — Fridge Magnet API Turn your photos into custom fridge magnets — a rounded-rectangle colorized depth relief with a flat magnetic back, sized for the fridge — in two stages: **prototype** generates a colorized concept image from your input photo, then **build** turns that concept image into a relief 3D model. The two stages are linked via `input_task_id`. - `POST /openapi/creative-lab/fridge-magnet/v1/prototype` - `POST /openapi/creative-lab/fridge-magnet/v1/build` --- ## POST /openapi/creative-lab/fridge-magnet/v1/prototype -- Create a Fridge Magnet Prototype Task Generate a single colorized concept image from the source photo. The returned task ID is what you pass as `input_task_id` to the build endpoint. Refer to [The Fridge Magnet Prototype Task Object](#the-fridge-magnet-prototype-task-object) for the response shape. ### Parameters - `image_url` · *string* · **required** Source photo for Meshy to colorize into a fridge-magnet-ready concept image. We currently support `.jpg`, `.jpeg`, `.png`, and `.webp` formats. There are two ways to provide the image: - **Publicly accessible URL**: A URL that is accessible from the public internet. - **Data URI**: A base64-encoded data URI of the image. Example of a data URI: `data:image/jpeg;base64,`. - `name` · *string* Optional task name for display purposes. Maximum 100 characters. ### Returns The `result` property of the response contains the task `id` of the newly created fridge magnet prototype task. Poll the [Get a Task](#retrieve-a-fridge-magnet-task) endpoint or subscribe to the [stream](#stream-a-fridge-magnet-task) until the task reaches `SUCCEEDED`, then pass that ID to the [build endpoint](#create-a-fridge-magnet-build-task) as `input_task_id`. ### Failure Modes - `400 - Bad Request` The request was unacceptable. Common causes: * **Missing parameter**: `image_url` is required. * **Invalid image format**: The provided `image_url` is not a supported format (`.jpg`, `.jpeg`, `.png`, `.webp`). * **Image dimensions out of range**: The image is too small, exceeds the maximum file size, or exceeds the maximum pixel count. * **Unreachable URL**: The `image_url` could not be downloaded (404 or timeout). * **Invalid Data URI**: The base64 string is malformed. * **Content flagged**: The input image was flagged by NSFW or intellectual property moderation. - `401 - Unauthorized` Authentication failed. Please check your API key. - `402 - Payment Required` Insufficient credits to perform this task. - `429 - Too Many Requests` You have exceeded your rate limit. **cURL** ```bash # Stage 1: generate a colorized fridge magnet concept image curl https://api.meshy.ai/openapi/creative-lab/fridge-magnet/v1/prototype \ -X POST \ -H "Authorization: Bearer ${YOUR_API_KEY}" \ -H 'Content-Type: application/json' \ -d '{ "image_url": "" }' ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; // Stage 1: generate a colorized fridge magnet concept image const payload = { image_url: "", }; try { const response = await axios.post( 'https://api.meshy.ai/openapi/creative-lab/fridge-magnet/v1/prototype', payload, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } # Stage 1: generate a colorized fridge magnet concept image payload = { "image_url": "", } response = requests.post( "https://api.meshy.ai/openapi/creative-lab/fridge-magnet/v1/prototype", headers=headers, json=payload, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "result": "01a3d8f1-8c2e-7d04-b223-3f3776a1c8c9" } ``` --- ## POST /openapi/creative-lab/fridge-magnet/v1/build -- Create a Fridge Magnet Build Task Generate the final 3D-printable fridge magnet from a succeeded prototype task. The build runs a depth-map relief pipeline on the prototype's colorized concept image and ships a single mesh artifact in the format you ask for. Refer to [The Fridge Magnet Build Task Object](#the-fridge-magnet-build-task-object) for the response shape. ### Parameters - `input_task_id` · *string* · **required** The task ID of a prototype task created via this same OpenAPI endpoint. The prototype must have been created with the same API key, must have reached `SUCCEEDED`, and must have produced exactly one candidate image. Prototype tasks created through the webapp are **not** accepted — the build endpoint accepts only prototype tasks produced by `POST /openapi/creative-lab/fridge-magnet/v1/prototype` and refuses any other source with `404`. - `name` · *string* Optional task name for display purposes. Maximum 100 characters. #### `options` Optional tuning parameters for the relief geometry. Every field has a sensible default — send only the ones you want to override. - `badge_shape` · *string* · default: `rounded-rect` Outline silhouette of the fridge magnet. Available values: * `circle` * `rounded-rect` (default) * `hexagon` * `shield` * `star` - `size_mm` · *number* · default: `60` Bounding square edge length of the fridge magnet, in millimeters. Range: `(0, 400]`. - `relief_height_mm` · *number* · default: `3.3` Maximum relief height above the base, in millimeters. Range: `[0, 20]`. - `relief_offset_mm` · *number* · default: `0` Vertical offset applied to the relief before extrusion, in millimeters. Range: `[0, 20]`. - `base_thickness_mm` · *number* · default: `2.0` Thickness of the flat base plate behind the relief, in millimeters. The fridge-magnet default is a chunkier 2 mm base — gives the magnet enough body to grip the fridge without the relief feeling fragile. Range: `[0, 20]`. - `has_closed_back` · *boolean* · default: `true` Whether the back of the fridge magnet is sealed as a closed surface (the side you glue the magnet to). Set to `false` for an open shell. - `relief_curve` · *string* · default: `linear` Transfer curve mapping depth-map values to relief height. Available values: * `linear` (default) * `gamma` * `s-curve` - `curve_param` · *number* · default: `1.0` Shape parameter for the transfer curve (only meaningful when `relief_curve` is `gamma`). Range: `(0, 10]`. - `invert_depth` · *boolean* · default: `false` Invert the depth-map interpretation so darker regions become higher relief. - `smoothing` · *number* · default: `0.24` Smoothing strength applied to the depth map before relief extraction. Range: `[0, 10]`. - `relief_scale` · *number* · default: `1.0` Vertical scale multiplier applied on top of `relief_height_mm`. Range: `(0, 10]`. - `depth_threshold` · *number* · default: `0.1` Low-pass threshold for depth-map values; anything below this is clamped to zero. Range: `[0, 1]`. - `remove_background` · *boolean* · default: `true` Automatically remove the background of the prototype's concept image before reliefing. - `export_resolution` · *integer* · default: `512` Mesh resolution used for export. Range: `[64, 2048]`. #### `output` Optional wire-format selector. Defaults to `glb`. - `format` · *string* · default: `glb` Artifact bundle returned by the build. Available values: * `glb` (default) — returns a single `model.glb` under `model_urls.glb`. * `obj` — zips `model.obj` + `model.mtl` + `texture.png` and returns the bundle under `model_urls.obj`. * `zip` — zips every artifact the generator emits and returns the bundle under `model_urls.bundle_zip`. ### Returns The `result` property of the response contains the task `id` of the newly created fridge magnet build task. Poll the [Get a Task](#retrieve-a-fridge-magnet-task) endpoint or subscribe to the [stream](#stream-a-fridge-magnet-task) until the task reaches `SUCCEEDED`, then download the artifact from the single entry in `model_urls`. ### Failure Modes - `400 - Bad Request` The request was unacceptable. Common causes: * **Missing parameter**: `input_task_id` is required. * **Invalid UUID**: The `input_task_id` is not a valid UUID. * **Parent not succeeded**: The referenced prototype task has not reached `SUCCEEDED` yet. * **No candidate**: The prototype task succeeded but produced no candidate image. * **Options out of range**: One of the `options` fields fell outside its allowed range or enum set. - `401 - Unauthorized` Authentication failed. Please check your API key. - `402 - Payment Required` Insufficient credits to perform this task. - `404 - Not Found` The referenced prototype task does not exist, belongs to a different user, or was created through the webapp (only API-mode prototype tasks chain into build). - `429 - Too Many Requests` You have exceeded your rate limit. **cURL** ```bash # Stage 2: chain build off a succeeded prototype task curl https://api.meshy.ai/openapi/creative-lab/fridge-magnet/v1/build \ -X POST \ -H "Authorization: Bearer ${YOUR_API_KEY}" \ -H 'Content-Type: application/json' \ -d '{ "input_task_id": "01a3d8f1-8c2e-7d04-b223-3f3776a1c8c9", "options": { "badge_shape": "rounded-rect", "size_mm": 60, "relief_height_mm": 3.3 }, "output": { "format": "glb" } }' ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; // Stage 2: chain build off a succeeded prototype task const payload = { input_task_id: "01a3d8f1-8c2e-7d04-b223-3f3776a1c8c9", options: { badge_shape: "rounded-rect", size_mm: 60, relief_height_mm: 3.3, }, output: { format: "glb" }, }; try { const response = await axios.post( 'https://api.meshy.ai/openapi/creative-lab/fridge-magnet/v1/build', payload, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } # Stage 2: chain build off a succeeded prototype task payload = { "input_task_id": "01a3d8f1-8c2e-7d04-b223-3f3776a1c8c9", "options": { "badge_shape": "rounded-rect", "size_mm": 60, "relief_height_mm": 3.3, }, "output": {"format": "glb"}, } response = requests.post( "https://api.meshy.ai/openapi/creative-lab/fridge-magnet/v1/build", headers=headers, json=payload, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "result": "01b4e9a2-9d3f-8e15-c334-4f4887b2d9d0" } ``` --- ## GET /openapi/creative-lab/fridge-magnet/v1/(prototype|build)/:id -- Retrieve a Fridge Magnet Task Retrieve a prototype or build task given a valid task `id`. The URL path must match the task's stage — a build task fetched through `/prototype/:id` returns `404`, and vice versa. Refer to [The Fridge Magnet Prototype Task Object](#the-fridge-magnet-prototype-task-object) and [The Fridge Magnet Build Task Object](#the-fridge-magnet-build-task-object) for response shapes. ### Parameters - `id` · *path* Unique identifier for the fridge magnet task to retrieve. ### Returns The response contains the fridge magnet task object. The shape depends on which stage was requested. **cURL** ```bash # Prototype curl https://api.meshy.ai/openapi/creative-lab/fridge-magnet/v1/prototype/01a3d8f1-8c2e-7d04-b223-3f3776a1c8c9 \ -H "Authorization: Bearer ${YOUR_API_KEY}" # Build curl https://api.meshy.ai/openapi/creative-lab/fridge-magnet/v1/build/01b4e9a2-9d3f-8e15-c334-4f4887b2d9d0 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; // Prototype const prototypeId = '01a3d8f1-8c2e-7d04-b223-3f3776a1c8c9'; const proto = await axios.get( `https://api.meshy.ai/openapi/creative-lab/fridge-magnet/v1/prototype/${prototypeId}`, { headers } ); console.log(proto.data); // Build const buildId = '01b4e9a2-9d3f-8e15-c334-4f4887b2d9d0'; const build = await axios.get( `https://api.meshy.ai/openapi/creative-lab/fridge-magnet/v1/build/${buildId}`, { headers } ); console.log(build.data); ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } # Prototype prototype_id = "01a3d8f1-8c2e-7d04-b223-3f3776a1c8c9" proto = requests.get( f"https://api.meshy.ai/openapi/creative-lab/fridge-magnet/v1/prototype/{prototype_id}", headers=headers, ) proto.raise_for_status() print(proto.json()) # Build build_id = "01b4e9a2-9d3f-8e15-c334-4f4887b2d9d0" build = requests.get( f"https://api.meshy.ai/openapi/creative-lab/fridge-magnet/v1/build/{build_id}", headers=headers, ) build.raise_for_status() print(build.json()) ``` **Prototype Response** ```json { "id": "01a3d8f1-8c2e-7d04-b223-3f3776a1c8c9", "type": "creative-lab-fridge-magnet-prototype", "name": "", "status": "SUCCEEDED", "progress": 100, "created_at": 1729543210000, "started_at": 1729543215000, "finished_at": 1729543242000, "expires_at": 1729802442000, "preceding_tasks": 0, "task_error": null, "consumed_credits": 6, "image_urls": [ "https://assets.meshy.ai/***/concept.png?Expires=***" ] } ``` **Build Response** ```json { "id": "01b4e9a2-9d3f-8e15-c334-4f4887b2d9d0", "type": "creative-lab-fridge-magnet-build", "name": "", "status": "SUCCEEDED", "progress": 100, "created_at": 1729543250000, "started_at": 1729543258000, "finished_at": 1729543285000, "expires_at": 1729802485000, "preceding_tasks": 0, "task_error": null, "consumed_credits": 20, "model_urls": { "glb": "https://assets.meshy.ai/***/tasks/01b4e9a2-9d3f-8e15-c334-4f4887b2d9d0/output/model.glb?Expires=***" } } ``` --- ## DELETE /openapi/creative-lab/fridge-magnet/v1/(prototype|build)/:id -- Delete a Fridge Magnet Task Cancel a fridge magnet task. If the task is still `PENDING`, the credits consumed at create-time are refunded. Tasks that are already `IN_PROGRESS` are cancelled without a refund (the worker may already be burning resources). Tasks that have already reached a terminal state (`SUCCEEDED`, `FAILED`, `CANCELED`) cannot be cancelled. The URL path must match the task's stage — `DELETE` on `/prototype/:buildId` returns `404`. ### Path Parameters - `id` · *path* Unique identifier for the fridge magnet task to cancel. ### Returns Returns `204 No Content` on success with an empty body. ### Failure Modes - `400 - Bad Request` The task is already in a terminal state and cannot be cancelled. - `404 - Not Found` The task does not exist, belongs to a different user, or its stage does not match the URL path. **cURL** ```bash curl --request DELETE \ --url https://api.meshy.ai/openapi/creative-lab/fridge-magnet/v1/prototype/01a3d8f1-8c2e-7d04-b223-3f3776a1c8c9 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const taskId = '01a3d8f1-8c2e-7d04-b223-3f3776a1c8c9' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` } try { await axios.delete( `https://api.meshy.ai/openapi/creative-lab/fridge-magnet/v1/prototype/${taskId}`, { headers } ) } catch (error) { console.error(error) } ``` ```python import requests task_id = "01a3d8f1-8c2e-7d04-b223-3f3776a1c8c9" headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.delete( f"https://api.meshy.ai/openapi/creative-lab/fridge-magnet/v1/prototype/{task_id}", headers=headers, ) response.raise_for_status() ``` **Response** ```json // Returns 204 No Content on success (empty body). ``` --- ## GET /openapi/creative-lab/fridge-magnet/v1/(prototype|build)/:id/stream -- Stream a Fridge Magnet Task Stream real-time updates for a fridge magnet task via Server-Sent Events (SSE). The URL path must match the task's stage — opening a stream at `/prototype/:buildId/stream` emits a single `event: error` payload with `status_code: 404` and closes the stream. ### Parameters - `id` · *path* Unique identifier for the fridge magnet task to stream. ### Returns Returns a stream of [Fridge Magnet Prototype](#the-fridge-magnet-prototype-task-object) or [Fridge Magnet Build](#the-fridge-magnet-build-task-object) task objects as Server-Sent Events. For `PENDING` or `IN_PROGRESS` tasks, the response stream will only include the necessary `progress` and `status` fields. **cURL** ```bash curl -N https://api.meshy.ai/openapi/creative-lab/fridge-magnet/v1/build/01b4e9a2-9d3f-8e15-c334-4f4887b2d9d0/stream \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript const response = await fetch( 'https://api.meshy.ai/openapi/creative-lab/fridge-magnet/v1/build/01b4e9a2-9d3f-8e15-c334-4f4887b2d9d0/stream', { headers: { Authorization: `Bearer ${YOUR_API_KEY}` } } ); const reader = response.body.getReader(); const decoder = new TextDecoder(); let buffer = ''; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const lines = buffer.split('\n'); buffer = lines.pop(); for (const line of lines) { if (line.startsWith('data:')) { const data = JSON.parse(line.slice(5)); console.log(data); if (['SUCCEEDED', 'FAILED', 'CANCELED'].includes(data.status)) { reader.cancel(); } } } } ``` ```python import requests import json headers = { "Authorization": f"Bearer {YOUR_API_KEY}", "Accept": "text/event-stream" } response = requests.get( 'https://api.meshy.ai/openapi/creative-lab/fridge-magnet/v1/build/01b4e9a2-9d3f-8e15-c334-4f4887b2d9d0/stream', headers=headers, stream=True ) for line in response.iter_lines(): if line: if line.startswith(b'data:'): data = json.loads(line.decode('utf-8')[5:]) print(data) if data['status'] in ['SUCCEEDED', 'FAILED', 'CANCELED']: break response.close() ``` **Response Stream** ```javascript // Error event example (wrong stage or task not found) event: error data: { "status_code": 404, "message": "Task not found" } // Message event examples illustrate task progress. // For PENDING or IN_PROGRESS tasks, the response stream will not include all fields. event: message data: { "id": "01b4e9a2-9d3f-8e15-c334-4f4887b2d9d0", "progress": 0, "status": "PENDING" } event: message data: { "id": "01b4e9a2-9d3f-8e15-c334-4f4887b2d9d0", "type": "creative-lab-fridge-magnet-build", "status": "SUCCEEDED", "progress": 100, "created_at": 1729543250000, "started_at": 1729543258000, "finished_at": 1729543285000, "expires_at": 1729802485000, "task_error": null, "consumed_credits": 20, "model_urls": { "glb": "https://assets.meshy.ai/***/tasks/01b4e9a2-9d3f-8e15-c334-4f4887b2d9d0/output/model.glb?Expires=***" } } ``` --- ## GET /openapi/creative-lab/fridge-magnet/v1/(prototype|build) -- List Fridge Magnet Tasks Retrieve a paginated list of your fridge magnet tasks for a single stage. The URL path selects the stage — `/prototype` returns prototype tasks; `/build` returns build tasks. Tasks from the other stage are not included in either response. ### Path Parameters - `stage` · *path* · **required** Either `prototype` or `build`. The collection returns only tasks whose stage matches the URL — fetching `/prototype` never returns build tasks and vice versa. ### Query Parameters - `page_num` · *integer* · default: `1` Page number for pagination. - `page_size` · *integer* · default: `10` Page size limit. Maximum allowed is `50` items. - `sort_by` · *string* · default: `-created_at` Field to sort by. Available values: * `+created_at`: Sort by creation time in ascending order. * `-created_at`: Sort by creation time in descending order. ### Returns Returns a paginated list of the per-stage task object — either [the fridge magnet prototype task object](#the-fridge-magnet-prototype-task-object) when listing `/prototype` or [the fridge magnet build task object](#the-fridge-magnet-build-task-object) when listing `/build`. **cURL** ```bash # List prototype tasks curl https://api.meshy.ai/openapi/creative-lab/fridge-magnet/v1/prototype?page_size=10 \ -H "Authorization: Bearer ${YOUR_API_KEY}" # List build tasks curl https://api.meshy.ai/openapi/creative-lab/fridge-magnet/v1/build?page_size=10 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` } try { const { data } = await axios.get( 'https://api.meshy.ai/openapi/creative-lab/fridge-magnet/v1/prototype', { headers, params: { page_size: 10 } } ) console.log(data) } catch (error) { console.error(error) } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.get( "https://api.meshy.ai/openapi/creative-lab/fridge-magnet/v1/prototype", headers=headers, params={"page_size": 10}, ) response.raise_for_status() print(response.json()) ``` **Response (List Prototype Tasks)** ```json [ { "id": "01a3d8f1-8c2e-7d04-b223-3f3776a1c8c9", "type": "creative-lab-fridge-magnet-prototype", "name": "", "status": "SUCCEEDED", "progress": 100, "created_at": 1729543210000, "started_at": 1729543215000, "finished_at": 1729543242000, "expires_at": 1729802442000, "preceding_tasks": 0, "task_error": null, "consumed_credits": 6, "image_urls": [ "https://assets.meshy.ai/***/concept.png?Expires=***" ] } ] ``` --- ## The Fridge Magnet Prototype Task Object The Fridge Magnet Prototype Task object is a work unit that Meshy keeps track of to generate a colorized **concept image** from a source photo. The output of this stage is chained into [the build stage](#create-a-fridge-magnet-build-task) via `input_task_id`. ### Properties - `id` · *string* Unique identifier for the task. While we use a k-sortable UUID for task ids as the implementation detail, you should **not** make any assumptions about the format of the id. - `type` · *string* Type of the task. The value is `creative-lab-fridge-magnet-prototype`. - `name` · *string* The task name supplied when the task was created. Empty string if no name was provided. - `status` · *string* Status of the task. Possible values are one of `PENDING`, `IN_PROGRESS`, `SUCCEEDED`, `FAILED`, `CANCELED`. - `progress` · *integer* Progress of the task. If the task is not started yet, this property will be `0`. Once the task has succeeded, this will become `100`. - `created_at` · *timestamp* Timestamp of when the task was created, in milliseconds. > **Note:** A timestamp represents the number of milliseconds elapsed since January 1, 1970 UTC, following > the [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339) standard. > For example, Friday, September 1, 2023 12:00:00 PM GMT is represented as `1693569600000`. This applies > to **all** timestamps in Meshy API. - `started_at` · *timestamp* Timestamp of when the task was started, in milliseconds. If the task is not started yet, this property will be `0`. - `finished_at` · *timestamp* Timestamp of when the task was finished, in milliseconds. If the task is not finished yet, this property will be `0`. - `expires_at` · *timestamp* Timestamp of when the task result expires, in milliseconds. - `preceding_tasks` · *integer* The count of preceding tasks. > **Note:** The value of this field is meaningful only if the task status is `PENDING`. - `task_error` · *object* Error details for failed tasks. See [Errors](/api/errors#task-errors) for the full `task_error` object reference. - `consumed_credits` · *integer* The number of credits consumed by this task. Present when the task status is `PENDING`, `IN_PROGRESS`, or `SUCCEEDED`. Returns `0` for `FAILED` tasks (credits are refunded on failure). - `image_urls` · *array of strings* Downloadable URLs for the concept image candidates generated by this prototype task. Currently the API always returns exactly one candidate; the field is an array so future revisions can surface multiple candidates without a breaking change. **Example Fridge Magnet Prototype Task Object** ```json { "id": "01a3d8f1-8c2e-7d04-b223-3f3776a1c8c9", "type": "creative-lab-fridge-magnet-prototype", "name": "", "status": "SUCCEEDED", "progress": 100, "created_at": 1729543210000, "started_at": 1729543215000, "finished_at": 1729543242000, "expires_at": 1729802442000, "preceding_tasks": 0, "task_error": null, "consumed_credits": 6, "image_urls": [ "https://assets.meshy.ai/***/concept.png?Expires=***" ] } ``` --- ## The Fridge Magnet Build Task Object The Fridge Magnet Build Task object is a work unit that Meshy keeps track of to generate the final 3D fridge magnet mesh from a succeeded prototype task. The build runs a depth-map relief pipeline on the prototype's concept image and publishes a single mesh artifact in the format the caller requested. ### Properties - `id` · *string* Unique identifier for the task. - `type` · *string* Type of the task. The value is `creative-lab-fridge-magnet-build`. - `name` · *string* The task name supplied when the task was created. Empty string if no name was provided. - `status` · *string* Status of the task. Possible values are one of `PENDING`, `IN_PROGRESS`, `SUCCEEDED`, `FAILED`, `CANCELED`. - `progress` · *integer* Progress of the task. If the task is not started yet, this property will be `0`. Once the task has succeeded, this will become `100`. - `created_at` · *timestamp* Timestamp of when the task was created, in milliseconds. - `started_at` · *timestamp* Timestamp of when the task was started, in milliseconds. - `finished_at` · *timestamp* Timestamp of when the task was finished, in milliseconds. - `expires_at` · *timestamp* Timestamp of when the task result expires, in milliseconds. - `preceding_tasks` · *integer* The count of preceding tasks. Meaningful only when status is `PENDING`. - `task_error` · *object* Error details for failed tasks. See [Errors](/api/errors#task-errors) for the full `task_error` object reference. - `consumed_credits` · *integer* The number of credits consumed by this task. Returns `0` for `FAILED` tasks (credits are refunded on failure). - `model_urls` · *object* Downloadable URLs for the generated artifact, keyed by artifact name. Always contains exactly one entry — the format requested via the build request's `output.format`. The key matches the requested format: - `glb` · *string* Downloadable URL to the GLB file. Present when `output.format` was `glb` (the default). - `obj` · *string* Downloadable URL to a zip bundle containing `model.obj`, `model.mtl`, and `texture.png`. Present when `output.format` was `obj`. - `bundle_zip` · *string* Downloadable URL to a zip bundle of every artifact the generator emits. Present when `output.format` was `zip`. **Example Fridge Magnet Build Task Object** ```json { "id": "01b4e9a2-9d3f-8e15-c334-4f4887b2d9d0", "type": "creative-lab-fridge-magnet-build", "name": "", "status": "SUCCEEDED", "progress": 100, "created_at": 1729543250000, "started_at": 1729543258000, "finished_at": 1729543285000, "expires_at": 1729802485000, "preceding_tasks": 0, "task_error": null, "consumed_credits": 20, "model_urls": { "glb": "https://assets.meshy.ai/***/tasks/01b4e9a2-9d3f-8e15-c334-4f4887b2d9d0/output/model.glb?Expires=***" } } ``` --- # Creative Lab — Figure API Source: https://docs.meshy.ai/api/creative-lab-figure # Creative Lab — Figure API Turn a source photo into a chibi-style collectible 3D figure in two stages: **prototype** generates a styled concept image from your input photo, then **build** turns that concept image into a textured 3D model. The two stages are linked via `input_task_id`. - `POST /openapi/creative-lab/figure/v1/prototype` - `POST /openapi/creative-lab/figure/v1/build` --- ## POST /openapi/creative-lab/figure/v1/prototype -- Create a Figure Prototype Task Generate a single chibi-style concept image from the source photo. The returned task ID is what you pass as `input_task_id` to the build endpoint. Refer to [The Figure Prototype Task Object](#the-figure-prototype-task-object) for the response shape. ### Parameters - `image_url` · *string* · **required** Source photo for Meshy to stylize as a chibi figure. We currently support `.jpg`, `.jpeg`, `.png`, and `.webp` formats. There are two ways to provide the image: - **Publicly accessible URL**: A URL that is accessible from the public internet. - **Data URI**: A base64-encoded data URI of the image. Example of a data URI: `data:image/jpeg;base64,`. - `name` · *string* Optional task name for display purposes. Maximum 100 characters. ### Returns The `result` property of the response contains the task `id` of the newly created figure prototype task. Poll the [Get a Task](#retrieve-a-figure-task) endpoint or subscribe to the [stream](#stream-a-figure-task) until the task reaches `SUCCEEDED`, then pass that ID to the [build endpoint](#create-a-figure-build-task) as `input_task_id`. ### Failure Modes - `400 - Bad Request` The request was unacceptable. Common causes: * **Missing parameter**: `image_url` is required. * **Invalid image format**: The provided `image_url` is not a supported format (`.jpg`, `.jpeg`, `.png`, `.webp`). * **Image dimensions out of range**: The image is too small, exceeds the maximum file size, or exceeds the maximum pixel count. * **Unreachable URL**: The `image_url` could not be downloaded (404 or timeout). * **Invalid Data URI**: The base64 string is malformed. * **Content flagged**: The input image was flagged by NSFW or intellectual property moderation. - `401 - Unauthorized` Authentication failed. Please check your API key. - `402 - Payment Required` Insufficient credits to perform this task. - `429 - Too Many Requests` You have exceeded your rate limit. **cURL** ```bash # Stage 1: generate a chibi-style concept image curl https://api.meshy.ai/openapi/creative-lab/figure/v1/prototype \ -X POST \ -H "Authorization: Bearer ${YOUR_API_KEY}" \ -H 'Content-Type: application/json' \ -d '{ "image_url": "" }' ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; // Stage 1: generate a chibi-style concept image const payload = { image_url: "", }; try { const response = await axios.post( 'https://api.meshy.ai/openapi/creative-lab/figure/v1/prototype', payload, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } # Stage 1: generate a chibi-style concept image payload = { "image_url": "", } response = requests.post( "https://api.meshy.ai/openapi/creative-lab/figure/v1/prototype", headers=headers, json=payload, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "result": "018a210d-8ba4-705c-b111-1f1776f7f578" } ``` --- ## POST /openapi/creative-lab/figure/v1/build -- Create a Figure Build Task Generate the final textured 3D figure from a succeeded prototype task. The build runs the same image-to-3D pipeline as [Image to 3D](/api/image-to-3d), so the response object format and the list of output URLs match exactly. Refer to [The Figure Build Task Object](#the-figure-build-task-object) for the response shape. ### Parameters - `input_task_id` · *string* · **required** The task ID of a prototype task created via this same OpenAPI endpoint. The prototype must have been created with the same API key, must have reached `SUCCEEDED`, and must have produced exactly one candidate image. Prototype tasks created through the webapp are **not** accepted — the build endpoint accepts only prototype tasks produced by `POST /openapi/creative-lab/figure/v1/prototype` and refuses any other source with `404`. - `name` · *string* Optional task name for display purposes. Maximum 100 characters. ### Returns The `result` property of the response contains the task `id` of the newly created figure build task. Poll the [Get a Task](#retrieve-a-figure-task) endpoint or subscribe to the [stream](#stream-a-figure-task) until the task reaches `SUCCEEDED`, then download the textured GLB from `model_urls.glb` (or the OBJ + MTL pair from `model_urls.obj` and `model_urls.mtl` if your downstream pipeline prefers OBJ). ### Failure Modes - `400 - Bad Request` The request was unacceptable. Common causes: * **Missing parameter**: `input_task_id` is required. * **Invalid UUID**: The `input_task_id` is not a valid UUID. * **Parent not succeeded**: The referenced prototype task has not reached `SUCCEEDED` yet. * **No candidate**: The prototype task succeeded but produced no candidate image. - `401 - Unauthorized` Authentication failed. Please check your API key. - `402 - Payment Required` Insufficient credits to perform this task. - `404 - Not Found` The referenced prototype task does not exist, belongs to a different user, or was created through the webapp (only API-mode prototype tasks chain into build). - `429 - Too Many Requests` You have exceeded your rate limit. **cURL** ```bash # Stage 2: chain build off a succeeded prototype task curl https://api.meshy.ai/openapi/creative-lab/figure/v1/build \ -X POST \ -H "Authorization: Bearer ${YOUR_API_KEY}" \ -H 'Content-Type: application/json' \ -d '{ "input_task_id": "018a210d-8ba4-705c-b111-1f1776f7f578" }' ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; // Stage 2: chain build off a succeeded prototype task const payload = { input_task_id: "018a210d-8ba4-705c-b111-1f1776f7f578", }; try { const response = await axios.post( 'https://api.meshy.ai/openapi/creative-lab/figure/v1/build', payload, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } # Stage 2: chain build off a succeeded prototype task payload = { "input_task_id": "018a210d-8ba4-705c-b111-1f1776f7f578", } response = requests.post( "https://api.meshy.ai/openapi/creative-lab/figure/v1/build", headers=headers, json=payload, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "result": "019c320e-9a8f-7a1c-9c11-2a1876f8a9bb" } ``` --- ## GET /openapi/creative-lab/figure/v1/(prototype|build)/:id -- Retrieve a Figure Task Retrieve a prototype or build task given a valid task `id`. The URL path must match the task's stage — a build task fetched through `/prototype/:id` returns `404`, and vice versa. Refer to [The Figure Prototype Task Object](#the-figure-prototype-task-object) and [The Figure Build Task Object](#the-figure-build-task-object) for response shapes. ### Parameters - `id` · *path* Unique identifier for the figure task to retrieve. ### Returns The response contains the figure task object. The shape depends on which stage was requested. **cURL** ```bash # Prototype curl https://api.meshy.ai/openapi/creative-lab/figure/v1/prototype/018a210d-8ba4-705c-b111-1f1776f7f578 \ -H "Authorization: Bearer ${YOUR_API_KEY}" # Build curl https://api.meshy.ai/openapi/creative-lab/figure/v1/build/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; // Prototype const prototypeId = '018a210d-8ba4-705c-b111-1f1776f7f578'; const proto = await axios.get( `https://api.meshy.ai/openapi/creative-lab/figure/v1/prototype/${prototypeId}`, { headers } ); console.log(proto.data); // Build const buildId = '019c320e-9a8f-7a1c-9c11-2a1876f8a9bb'; const build = await axios.get( `https://api.meshy.ai/openapi/creative-lab/figure/v1/build/${buildId}`, { headers } ); console.log(build.data); ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } # Prototype prototype_id = "018a210d-8ba4-705c-b111-1f1776f7f578" proto = requests.get( f"https://api.meshy.ai/openapi/creative-lab/figure/v1/prototype/{prototype_id}", headers=headers, ) proto.raise_for_status() print(proto.json()) # Build build_id = "019c320e-9a8f-7a1c-9c11-2a1876f8a9bb" build = requests.get( f"https://api.meshy.ai/openapi/creative-lab/figure/v1/build/{build_id}", headers=headers, ) build.raise_for_status() print(build.json()) ``` **Prototype Response** ```json { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "creative-lab-figure-prototype", "name": "", "status": "SUCCEEDED", "progress": 100, "created_at": 1729123456000, "started_at": 1729123460000, "finished_at": 1729123486000, "expires_at": 1729382686000, "preceding_tasks": 0, "task_error": null, "consumed_credits": 6, "image_urls": [ "https://assets.meshy.ai/***/concept.png?Expires=***" ] } ``` **Build Response** ```json { "id": "019c320e-9a8f-7a1c-9c11-2a1876f8a9bb", "type": "creative-lab-figure-build", "name": "", "status": "SUCCEEDED", "progress": 100, "created_at": 1729123500000, "started_at": 1729123510000, "finished_at": 1729123535000, "expires_at": 1729382735000, "preceding_tasks": 0, "task_error": null, "consumed_credits": 20, "prompt": "", "negative_prompt": "", "texture_prompt": "", "texture_image_url": "", "model_urls": { "glb": "https://assets.meshy.ai/***/tasks/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/output/model.glb?Expires=***", "obj": "https://assets.meshy.ai/***/tasks/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/output/model.obj?Expires=***", "mtl": "https://assets.meshy.ai/***/tasks/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/output/model.mtl?Expires=***" }, "thumbnail_url": "https://assets.meshy.ai/***/tasks/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/output/preview.png?Expires=***", "texture_urls": [ { "base_color": "https://assets.meshy.ai/***/tasks/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/output/texture_0.png?Expires=***" } ] } ``` --- ## DELETE /openapi/creative-lab/figure/v1/(prototype|build)/:id -- Delete a Figure Task Cancel a figure task. If the task is still `PENDING`, the credits consumed at create-time are refunded. Tasks that are already `IN_PROGRESS` are cancelled without a refund (the worker may already be burning resources). Tasks that have already reached a terminal state (`SUCCEEDED`, `FAILED`, `CANCELED`) cannot be cancelled. The URL path must match the task's stage — `DELETE` on `/prototype/:buildId` returns `404`. ### Path Parameters - `id` · *path* Unique identifier for the figure task to cancel. ### Returns Returns `204 No Content` on success with an empty body. ### Failure Modes - `400 - Bad Request` The task is already in a terminal state and cannot be cancelled. - `404 - Not Found` The task does not exist, belongs to a different user, or its stage does not match the URL path. **cURL** ```bash curl --request DELETE \ --url https://api.meshy.ai/openapi/creative-lab/figure/v1/prototype/018a210d-8ba4-705c-b111-1f1776f7f578 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const taskId = '018a210d-8ba4-705c-b111-1f1776f7f578' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` } try { await axios.delete( `https://api.meshy.ai/openapi/creative-lab/figure/v1/prototype/${taskId}`, { headers } ) } catch (error) { console.error(error) } ``` ```python import requests task_id = "018a210d-8ba4-705c-b111-1f1776f7f578" headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.delete( f"https://api.meshy.ai/openapi/creative-lab/figure/v1/prototype/{task_id}", headers=headers, ) response.raise_for_status() ``` **Response** ```json // Returns 204 No Content on success (empty body). ``` --- ## GET /openapi/creative-lab/figure/v1/(prototype|build)/:id/stream -- Stream a Figure Task Stream real-time updates for a figure task via Server-Sent Events (SSE). The URL path must match the task's stage — opening a stream at `/prototype/:buildId/stream` emits a single `event: error` payload with `status_code: 404` and closes the stream. ### Parameters - `id` · *path* Unique identifier for the figure task to stream. ### Returns Returns a stream of [Figure Prototype](#the-figure-prototype-task-object) or [Figure Build](#the-figure-build-task-object) task objects as Server-Sent Events. For `PENDING` or `IN_PROGRESS` tasks, the response stream will only include the necessary `progress` and `status` fields. **cURL** ```bash curl -N https://api.meshy.ai/openapi/creative-lab/figure/v1/build/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/stream \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript const response = await fetch( 'https://api.meshy.ai/openapi/creative-lab/figure/v1/build/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/stream', { headers: { Authorization: `Bearer ${YOUR_API_KEY}` } } ); const reader = response.body.getReader(); const decoder = new TextDecoder(); let buffer = ''; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const lines = buffer.split('\n'); buffer = lines.pop(); for (const line of lines) { if (line.startsWith('data:')) { const data = JSON.parse(line.slice(5)); console.log(data); if (['SUCCEEDED', 'FAILED', 'CANCELED'].includes(data.status)) { reader.cancel(); } } } } ``` ```python import requests import json headers = { "Authorization": f"Bearer {YOUR_API_KEY}", "Accept": "text/event-stream" } response = requests.get( 'https://api.meshy.ai/openapi/creative-lab/figure/v1/build/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/stream', headers=headers, stream=True ) for line in response.iter_lines(): if line: if line.startswith(b'data:'): data = json.loads(line.decode('utf-8')[5:]) print(data) if data['status'] in ['SUCCEEDED', 'FAILED', 'CANCELED']: break response.close() ``` **Response Stream** ```javascript // Error event example (wrong stage or task not found) event: error data: { "status_code": 404, "message": "Task not found" } // Message event examples illustrate task progress. // For PENDING or IN_PROGRESS tasks, the response stream will not include all fields. event: message data: { "id": "019c320e-9a8f-7a1c-9c11-2a1876f8a9bb", "progress": 0, "status": "PENDING" } event: message data: { "id": "019c320e-9a8f-7a1c-9c11-2a1876f8a9bb", "type": "creative-lab-figure-build", "status": "SUCCEEDED", "progress": 100, "created_at": 1729123500000, "started_at": 1729123510000, "finished_at": 1729123535000, "expires_at": 1729382735000, "task_error": null, "consumed_credits": 20, "prompt": "", "negative_prompt": "", "texture_prompt": "", "texture_image_url": "", "model_urls": { "glb": "https://assets.meshy.ai/***/tasks/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/output/model.glb?Expires=***", "obj": "https://assets.meshy.ai/***/tasks/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/output/model.obj?Expires=***", "mtl": "https://assets.meshy.ai/***/tasks/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/output/model.mtl?Expires=***" }, "thumbnail_url": "https://assets.meshy.ai/***/tasks/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/output/preview.png?Expires=***", "texture_urls": [ { "base_color": "https://assets.meshy.ai/***/tasks/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/output/texture_0.png?Expires=***" } ] } ``` --- ## GET /openapi/creative-lab/figure/v1/(prototype|build) -- List Figure Tasks Retrieve a paginated list of your figure tasks for a single stage. The URL path selects the stage — `/prototype` returns prototype tasks; `/build` returns build tasks. Tasks from the other stage are not included in either response. ### Path Parameters - `stage` · *path* · **required** Either `prototype` or `build`. The collection returns only tasks whose stage matches the URL — fetching `/prototype` never returns build tasks and vice versa. ### Query Parameters - `page_num` · *integer* · default: `1` Page number for pagination. - `page_size` · *integer* · default: `10` Page size limit. Maximum allowed is `50` items. - `sort_by` · *string* · default: `-created_at` Field to sort by. Available values: * `+created_at`: Sort by creation time in ascending order. * `-created_at`: Sort by creation time in descending order. ### Returns Returns a paginated list of the per-stage task object — either [the figure prototype task object](#the-figure-prototype-task-object) when listing `/prototype` or [the figure build task object](#the-figure-build-task-object) when listing `/build`. **cURL** ```bash # List prototype tasks curl https://api.meshy.ai/openapi/creative-lab/figure/v1/prototype?page_size=10 \ -H "Authorization: Bearer ${YOUR_API_KEY}" # List build tasks curl https://api.meshy.ai/openapi/creative-lab/figure/v1/build?page_size=10 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` } try { const { data } = await axios.get( 'https://api.meshy.ai/openapi/creative-lab/figure/v1/prototype', { headers, params: { page_size: 10 } } ) console.log(data) } catch (error) { console.error(error) } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.get( "https://api.meshy.ai/openapi/creative-lab/figure/v1/prototype", headers=headers, params={"page_size": 10}, ) response.raise_for_status() print(response.json()) ``` **Response (List Prototype Tasks)** ```json [ { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "creative-lab-figure-prototype", "name": "", "status": "SUCCEEDED", "progress": 100, "created_at": 1729123456000, "started_at": 1729123460000, "finished_at": 1729123486000, "expires_at": 1729382686000, "preceding_tasks": 0, "task_error": null, "consumed_credits": 6, "image_urls": [ "https://assets.meshy.ai/***/concept.png?Expires=***" ] } ] ``` --- ## The Figure Prototype Task Object The Figure Prototype Task object is a work unit that Meshy keeps track of to generate a chibi-style **concept image** from a source photo. The output of this stage is chained into [the build stage](#create-a-figure-build-task) via `input_task_id`. ### Properties - `id` · *string* Unique identifier for the task. While we use a k-sortable UUID for task ids as the implementation detail, you should **not** make any assumptions about the format of the id. - `type` · *string* Type of the task. The value is `creative-lab-figure-prototype`. - `name` · *string* The task name supplied when the task was created. Empty string if no name was provided. - `status` · *string* Status of the task. Possible values are one of `PENDING`, `IN_PROGRESS`, `SUCCEEDED`, `FAILED`, `CANCELED`. - `progress` · *integer* Progress of the task. If the task is not started yet, this property will be `0`. Once the task has succeeded, this will become `100`. - `created_at` · *timestamp* Timestamp of when the task was created, in milliseconds. > **Note:** A timestamp represents the number of milliseconds elapsed since January 1, 1970 UTC, following > the [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339) standard. > For example, Friday, September 1, 2023 12:00:00 PM GMT is represented as `1693569600000`. This applies > to **all** timestamps in Meshy API. - `started_at` · *timestamp* Timestamp of when the task was started, in milliseconds. If the task is not started yet, this property will be `0`. - `finished_at` · *timestamp* Timestamp of when the task was finished, in milliseconds. If the task is not finished yet, this property will be `0`. - `expires_at` · *timestamp* Timestamp of when the task result expires, in milliseconds. - `preceding_tasks` · *integer* The count of preceding tasks. > **Note:** The value of this field is meaningful only if the task status is `PENDING`. - `task_error` · *object* Error details for failed tasks. See [Errors](/api/errors#task-errors) for the full `task_error` object reference. - `consumed_credits` · *integer* The number of credits consumed by this task. Present when the task status is `PENDING`, `IN_PROGRESS`, or `SUCCEEDED`. Returns `0` for `FAILED` tasks (credits are refunded on failure). - `image_urls` · *array of strings* Downloadable URLs for the concept image candidates generated by this prototype task. Currently the API always returns exactly one candidate; the field is an array so future revisions can surface multiple candidates without a breaking change. **Example Figure Prototype Task Object** ```json { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "creative-lab-figure-prototype", "name": "", "status": "SUCCEEDED", "progress": 100, "created_at": 1729123456000, "started_at": 1729123460000, "finished_at": 1729123486000, "expires_at": 1729382686000, "preceding_tasks": 0, "task_error": null, "consumed_credits": 6, "image_urls": [ "https://assets.meshy.ai/***/concept.png?Expires=***" ] } ``` --- ## The Figure Build Task Object The Figure Build Task object is a work unit that Meshy keeps track of to generate a textured **3D figure** from a succeeded prototype task. It runs the same image-to-3D pipeline used by [Image to 3D](/api/image-to-3d), so the output fields mirror that endpoint's [task object](/api/image-to-3d#the-image-to-3d-task-object). ### Properties - `id` · *string* Unique identifier for the task. - `type` · *string* Type of the task. The value is `creative-lab-figure-build`. - `name` · *string* The task name supplied when the task was created. Empty string if no name was provided. - `status` · *string* Status of the task. Possible values are one of `PENDING`, `IN_PROGRESS`, `SUCCEEDED`, `FAILED`, `CANCELED`. - `progress` · *integer* Progress of the task. If the task is not started yet, this property will be `0`. Once the task has succeeded, this will become `100`. - `created_at` · *timestamp* Timestamp of when the task was created, in milliseconds. - `started_at` · *timestamp* Timestamp of when the task was started, in milliseconds. - `finished_at` · *timestamp* Timestamp of when the task was finished, in milliseconds. - `expires_at` · *timestamp* Timestamp of when the task result expires, in milliseconds. - `preceding_tasks` · *integer* The count of preceding tasks. Meaningful only when status is `PENDING`. - `task_error` · *object* Error details for failed tasks. See [Errors](/api/errors#task-errors) for the full `task_error` object reference. - `consumed_credits` · *integer* The number of credits consumed by this task. Returns `0` for `FAILED` tasks (credits are refunded on failure). - `prompt` · *string* Always empty for figure build. Present for cross-endpoint compatibility with the shared `V2ImageTo3DTaskResponse` shape used by [Image to 3D](/api/image-to-3d). - `negative_prompt` · *string* Always empty for figure build. Present for cross-endpoint compatibility. - `texture_prompt` · *string* Always empty for figure build. Present for cross-endpoint compatibility. - `texture_image_url` · *string* Always empty for figure build. Present for cross-endpoint compatibility. - `model_urls` · *object* Downloadable URLs for the generated 3D model. The figure build emits a textured GLB plus the OBJ + MTL pair for pipelines that prefer Wavefront OBJ. The field shape matches the [Image to 3D model_urls](/api/image-to-3d#the-image-to-3d-task-object) object so future format additions slot in without a breaking change. - `glb` · *string* Downloadable URL to the textured GLB file. - `obj` · *string* Downloadable URL to the Wavefront OBJ file (geometry + UV). - `mtl` · *string* Downloadable URL to the OBJ companion MTL material file. Pair with `obj` and the entry from `texture_urls[0].base_color`. - `thumbnail_url` · *string* Downloadable URL to the thumbnail image of the model file. - `texture_urls` · *array* An array of texture URL objects generated by this task. Currently contains a single object with the base color map. - `base_color` · *string* Downloadable URL to the base color map image. **Example Figure Build Task Object** ```json { "id": "019c320e-9a8f-7a1c-9c11-2a1876f8a9bb", "type": "creative-lab-figure-build", "name": "", "status": "SUCCEEDED", "progress": 100, "created_at": 1729123500000, "started_at": 1729123510000, "finished_at": 1729123535000, "expires_at": 1729382735000, "preceding_tasks": 0, "task_error": null, "consumed_credits": 20, "prompt": "", "negative_prompt": "", "texture_prompt": "", "texture_image_url": "", "model_urls": { "glb": "https://assets.meshy.ai/***/tasks/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/output/model.glb?Expires=***", "obj": "https://assets.meshy.ai/***/tasks/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/output/model.obj?Expires=***", "mtl": "https://assets.meshy.ai/***/tasks/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/output/model.mtl?Expires=***" }, "thumbnail_url": "https://assets.meshy.ai/***/tasks/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/output/preview.png?Expires=***", "texture_urls": [ { "base_color": "https://assets.meshy.ai/***/tasks/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/output/texture_0.png?Expires=***" } ] } ``` --- # Creative Lab — Lamp API Source: https://docs.meshy.ai/api/creative-lab-lamp # Creative Lab — Lamp API Turn a text prompt or a source photo into a 3D-printable lampshade in two stages: **prototype** generates a stylized matte-white concept image, then **build** turns that concept image into a hollow STL lampshade (optionally paired with a base disk for a light-source fixture). The two stages are linked via `input_task_id`. - `POST /openapi/creative-lab/lamp/v1/prototype` - `POST /openapi/creative-lab/lamp/v1/build` --- ## POST /openapi/creative-lab/lamp/v1/prototype -- Create a Lamp Prototype Task Generate a single matte-white concept image for the lampshade — either from a text prompt (text-to-3D) or from a reference photo (image-to-3D). The returned task ID is what you pass as `input_task_id` to the build endpoint. Refer to [The Lamp Prototype Task Object](#the-lamp-prototype-task-object) for the response shape. ### Parameters > **Note:** Exactly one of `text` or `image_url` is **required**. Passing both, or neither, returns `400`. - `text` · *string* · **required** Text prompt describing the desired lampshade subject. Required when `image_url` is omitted. Maximum 800 characters. - `image_url` · *string* · **required** Source photo Meshy uses as the visual reference for the lampshade. Required when `text` is omitted. We currently support `.jpg`, `.jpeg`, `.png`, and `.webp` formats. There are two ways to provide the image: - **Publicly accessible URL**: A URL that is accessible from the public internet. - **Data URI**: A base64-encoded data URI of the image. Example of a data URI: `data:image/jpeg;base64,`. - `image_subject` · *string* · default: `character` Subject category hint for the image-to-3D path. Available values: * `character` (default) — single character / object subject (figurine, animal, mascot, etc.). * `landscape` — outdoor scene / panorama subject (mountain, cityscape, forest, etc.). Ignored on the text-to-3D path. - `name` · *string* Optional task name for display purposes. Maximum 100 characters. ### Returns The `result` property of the response contains the task `id` of the newly created lamp prototype task. Poll the [Get a Task](#retrieve-a-lamp-task) endpoint or subscribe to the [stream](#stream-a-lamp-task) until the task reaches `SUCCEEDED`, then pass that ID to the [build endpoint](#create-a-lamp-build-task) as `input_task_id`. ### Failure Modes - `400 - Bad Request` The request was unacceptable. Common causes: * **Missing parameter**: Exactly one of `text` or `image_url` is required. * **Both provided**: Passing both `text` and `image_url` is rejected — they are mutually exclusive. * **Invalid image format**: The provided `image_url` is not a supported format (`.jpg`, `.jpeg`, `.png`, `.webp`). * **Image dimensions out of range**: The image is too small, exceeds the maximum file size, or exceeds the maximum pixel count. * **Unreachable URL**: The `image_url` could not be downloaded (404 or timeout). * **Invalid Data URI**: The base64 string is malformed. * **Content flagged**: The input image was flagged by NSFW or intellectual property moderation. * **Text too long**: `text` exceeds 800 characters. * **Invalid `image_subject`**: Not one of `character` / `landscape`. - `401 - Unauthorized` Authentication failed. Please check your API key. - `402 - Payment Required` Insufficient credits to perform this task. - `429 - Too Many Requests` You have exceeded your rate limit. **cURL** ```bash # Stage 1 (image-to-3D): generate a matte-white lampshade concept image curl https://api.meshy.ai/openapi/creative-lab/lamp/v1/prototype \ -X POST \ -H "Authorization: Bearer ${YOUR_API_KEY}" \ -H 'Content-Type: application/json' \ -d '{ "image_url": "", "image_subject": "character" }' # Stage 1 (text-to-3D): generate from a text prompt curl https://api.meshy.ai/openapi/creative-lab/lamp/v1/prototype \ -X POST \ -H "Authorization: Bearer ${YOUR_API_KEY}" \ -H 'Content-Type: application/json' \ -d '{ "text": "a stylized owl perched on a tree branch under moonlight" }' ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; // Stage 1 (image-to-3D): generate a matte-white lampshade concept image const payload = { image_url: "", image_subject: "character", }; try { const response = await axios.post( 'https://api.meshy.ai/openapi/creative-lab/lamp/v1/prototype', payload, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } # Stage 1 (image-to-3D): generate a matte-white lampshade concept image payload = { "image_url": "", "image_subject": "character", } response = requests.post( "https://api.meshy.ai/openapi/creative-lab/lamp/v1/prototype", headers=headers, json=payload, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "result": "018a210d-8ba4-705c-b111-1f1776f7f578" } ``` --- ## POST /openapi/creative-lab/lamp/v1/build -- Create a Lamp Build Task Generate the final 3D-printable lampshade from a succeeded prototype task. The build runs an image-to-3D pipeline on the prototype's concept image, then post-processes the mesh through the lamp processor to hollow it, flatten the top, optionally cut a base, and (when a fixture preset is chosen) emit a separate base disk for the light source. Refer to [The Lamp Build Task Object](#the-lamp-build-task-object) for the response shape. ### Parameters - `input_task_id` · *string* · **required** The task ID of a prototype task created via this same OpenAPI endpoint. The prototype must have been created with the same API key, must have reached `SUCCEEDED`, and must have produced exactly one candidate image. Prototype tasks created through the webapp are **not** accepted — the build endpoint accepts only prototype tasks produced by `POST /openapi/creative-lab/lamp/v1/prototype` and refuses any other source with `404`. - `name` · *string* Optional task name for display purposes. Maximum 100 characters. #### `options` Optional tuning parameters for the lampshade geometry. Every field has a sensible default — send only the ones you want to override. - `diameter_mm` · *number* · default: `80` Target maximum dimension of the lampshade bounding box, in millimeters. The mesh is uniformly scaled to fit. Range: `[50, 400]`. - `thickness_mm` · *number* · default: `1.5` Wall thickness of the hollow lampshade, in millimeters. Range: `(0, 10]`. - `cut_amount_percent` · *number* · default: `35` Percentage of the lampshade height to flatten at the top so the print can sit on the bed. Range: `[1, 100]`. - `light_source_preset` · *string* · default: `bambu_mh001_60mm` Light-source fixture preset that determines whether (and what) base disk to emit alongside the lampshade. Available values: * `bambu_mh001_60mm` (default) — emit a 60 mm base disk sized for a compatible light-source fixture. Result includes `model_urls.base_stl`. * `none` — no fixture, no base disk. `model_urls.base_stl` is omitted. - `fixture_offset_x_mm` · *number* · default: `0` Horizontal X-axis offset of the fixture cutout relative to the lampshade center, in millimeters. Only meaningful when `light_source_preset` ≠ `none`. Range: `[-80, 80]`. - `fixture_offset_z_mm` · *number* · default: `0` Vertical Z-axis offset of the fixture cutout relative to the lampshade bottom, in millimeters. Range: `[-80, 80]`. - `rotate_x_deg` · *number* · default: `0` Rotation around the X axis applied to the imported mesh before processing, in degrees. Range: `[-360, 360]`. - `rotate_y_deg` · *number* · default: `0` Rotation around the Y axis applied to the imported mesh before processing, in degrees. Range: `[-360, 360]`. - `rotate_z_deg` · *number* · default: `0` Rotation around the Z axis applied to the imported mesh before processing, in degrees. Range: `[-360, 360]`. - `include_result_json` · *boolean* · default: `false` When `true` and `output.format` is `zip`, includes the lamp processor's `result.json` (containing measured mesh metrics + the resolved option set) inside the bundle. Ignored when `output.format` is `stl`. #### `output` Optional wire-format selector. Defaults to `stl`. - `format` · *string* · default: `stl` Artifact bundle returned by the build. Available values: * `stl` (default) — returns the lampshade as `model_urls.lamp_stl`, plus `model_urls.base_stl` when `light_source_preset` ≠ `none`. * `zip` — packages every artifact the processor emits (`lamp.stl`, optional `base.stl`, optional `result.json`) into a single zip and returns it under `model_urls.bundle_zip`. ### Returns The `result` property of the response contains the task `id` of the newly created lamp build task. Poll the [Get a Task](#retrieve-a-lamp-task) endpoint or subscribe to the [stream](#stream-a-lamp-task) until the task reaches `SUCCEEDED`, then download the artifacts from `model_urls`. ### Failure Modes - `400 - Bad Request` The request was unacceptable. Common causes: * **Missing parameter**: `input_task_id` is required. * **Invalid UUID**: The `input_task_id` is not a valid UUID. * **Parent not succeeded**: The referenced prototype task has not reached `SUCCEEDED` yet. * **No candidate**: The prototype task succeeded but produced no candidate image. * **Options out of range**: One of the `options` fields fell outside its allowed range or enum set. - `401 - Unauthorized` Authentication failed. Please check your API key. - `402 - Payment Required` Insufficient credits to perform this task. - `404 - Not Found` The referenced prototype task does not exist, belongs to a different user, or was created through the webapp (only API-mode prototype tasks chain into build). - `429 - Too Many Requests` You have exceeded your rate limit. **cURL** ```bash # Stage 2: chain build off a succeeded prototype task curl https://api.meshy.ai/openapi/creative-lab/lamp/v1/build \ -X POST \ -H "Authorization: Bearer ${YOUR_API_KEY}" \ -H 'Content-Type: application/json' \ -d '{ "input_task_id": "018a210d-8ba4-705c-b111-1f1776f7f578", "options": { "diameter_mm": 120, "thickness_mm": 2, "light_source_preset": "bambu_mh001_60mm", "cut_amount_percent": 30 }, "output": { "format": "stl" } }' ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; // Stage 2: chain build off a succeeded prototype task const payload = { input_task_id: "018a210d-8ba4-705c-b111-1f1776f7f578", options: { diameter_mm: 120, thickness_mm: 2, light_source_preset: "bambu_mh001_60mm", cut_amount_percent: 30, }, output: { format: "stl" }, }; try { const response = await axios.post( 'https://api.meshy.ai/openapi/creative-lab/lamp/v1/build', payload, { headers } ); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } # Stage 2: chain build off a succeeded prototype task payload = { "input_task_id": "018a210d-8ba4-705c-b111-1f1776f7f578", "options": { "diameter_mm": 120, "thickness_mm": 2, "light_source_preset": "bambu_mh001_60mm", "cut_amount_percent": 30, }, "output": {"format": "stl"}, } response = requests.post( "https://api.meshy.ai/openapi/creative-lab/lamp/v1/build", headers=headers, json=payload, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "result": "019c320e-9a8f-7a1c-9c11-2a1876f8a9bb" } ``` --- ## GET /openapi/creative-lab/lamp/v1/(prototype|build)/:id -- Retrieve a Lamp Task Retrieve a prototype or build task given a valid task `id`. The URL path must match the task's stage — a build task fetched through `/prototype/:id` returns `404`, and vice versa. Refer to [The Lamp Prototype Task Object](#the-lamp-prototype-task-object) and [The Lamp Build Task Object](#the-lamp-build-task-object) for response shapes. ### Parameters - `id` · *path* Unique identifier for the lamp task to retrieve. ### Returns The response contains the lamp task object. The shape depends on which stage was requested. **cURL** ```bash # Prototype curl https://api.meshy.ai/openapi/creative-lab/lamp/v1/prototype/018a210d-8ba4-705c-b111-1f1776f7f578 \ -H "Authorization: Bearer ${YOUR_API_KEY}" # Build curl https://api.meshy.ai/openapi/creative-lab/lamp/v1/build/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }; // Prototype const prototypeId = '018a210d-8ba4-705c-b111-1f1776f7f578'; const proto = await axios.get( `https://api.meshy.ai/openapi/creative-lab/lamp/v1/prototype/${prototypeId}`, { headers } ); console.log(proto.data); // Build const buildId = '019c320e-9a8f-7a1c-9c11-2a1876f8a9bb'; const build = await axios.get( `https://api.meshy.ai/openapi/creative-lab/lamp/v1/build/${buildId}`, { headers } ); console.log(build.data); ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } # Prototype prototype_id = "018a210d-8ba4-705c-b111-1f1776f7f578" proto = requests.get( f"https://api.meshy.ai/openapi/creative-lab/lamp/v1/prototype/{prototype_id}", headers=headers, ) proto.raise_for_status() print(proto.json()) # Build build_id = "019c320e-9a8f-7a1c-9c11-2a1876f8a9bb" build = requests.get( f"https://api.meshy.ai/openapi/creative-lab/lamp/v1/build/{build_id}", headers=headers, ) build.raise_for_status() print(build.json()) ``` **Prototype Response** ```json { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "creative-lab-lamp-prototype", "name": "", "status": "SUCCEEDED", "progress": 100, "created_at": 1729123456000, "started_at": 1729123460000, "finished_at": 1729123486000, "expires_at": 1729382686000, "preceding_tasks": 0, "task_error": null, "consumed_credits": 6, "image_urls": [ "https://assets.meshy.ai/***/concept.png?Expires=***" ] } ``` **Build Response** ```json { "id": "019c320e-9a8f-7a1c-9c11-2a1876f8a9bb", "type": "creative-lab-lamp-build", "name": "", "status": "SUCCEEDED", "progress": 100, "created_at": 1729123500000, "started_at": 1729123510000, "finished_at": 1729123535000, "expires_at": 1729382735000, "preceding_tasks": 0, "task_error": null, "consumed_credits": 30, "model_urls": { "lamp_stl": "https://assets.meshy.ai/***/tasks/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/output/lamp.stl?Expires=***", "base_stl": "https://assets.meshy.ai/***/tasks/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/output/base.stl?Expires=***" } } ``` --- ## DELETE /openapi/creative-lab/lamp/v1/(prototype|build)/:id -- Delete a Lamp Task Cancel a lamp task. If the task is still `PENDING`, the credits consumed at create-time are refunded. Tasks that are already `IN_PROGRESS` are cancelled without a refund (the worker may already be burning resources). Tasks that have already reached a terminal state (`SUCCEEDED`, `FAILED`, `CANCELED`) cannot be cancelled. The URL path must match the task's stage — `DELETE` on `/prototype/:buildId` returns `404`. ### Path Parameters - `id` · *path* Unique identifier for the lamp task to cancel. ### Returns Returns `204 No Content` on success with an empty body. ### Failure Modes - `400 - Bad Request` The task is already in a terminal state and cannot be cancelled. - `404 - Not Found` The task does not exist, belongs to a different user, or its stage does not match the URL path. **cURL** ```bash curl --request DELETE \ --url https://api.meshy.ai/openapi/creative-lab/lamp/v1/prototype/018a210d-8ba4-705c-b111-1f1776f7f578 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const taskId = '018a210d-8ba4-705c-b111-1f1776f7f578' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` } try { await axios.delete( `https://api.meshy.ai/openapi/creative-lab/lamp/v1/prototype/${taskId}`, { headers } ) } catch (error) { console.error(error) } ``` ```python import requests task_id = "018a210d-8ba4-705c-b111-1f1776f7f578" headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.delete( f"https://api.meshy.ai/openapi/creative-lab/lamp/v1/prototype/{task_id}", headers=headers, ) response.raise_for_status() ``` **Response** ```json // Returns 204 No Content on success (empty body). ``` --- ## GET /openapi/creative-lab/lamp/v1/(prototype|build)/:id/stream -- Stream a Lamp Task Stream real-time updates for a lamp task via Server-Sent Events (SSE). The URL path must match the task's stage — opening a stream at `/prototype/:buildId/stream` emits a single `event: error` payload with `status_code: 404` and closes the stream. ### Parameters - `id` · *path* Unique identifier for the lamp task to stream. ### Returns Returns a stream of [Lamp Prototype](#the-lamp-prototype-task-object) or [Lamp Build](#the-lamp-build-task-object) task objects as Server-Sent Events. For `PENDING` or `IN_PROGRESS` tasks, the response stream will only include the necessary `progress` and `status` fields. **cURL** ```bash curl -N https://api.meshy.ai/openapi/creative-lab/lamp/v1/build/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/stream \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript const response = await fetch( 'https://api.meshy.ai/openapi/creative-lab/lamp/v1/build/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/stream', { headers: { Authorization: `Bearer ${YOUR_API_KEY}` } } ); const reader = response.body.getReader(); const decoder = new TextDecoder(); let buffer = ''; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const lines = buffer.split('\n'); buffer = lines.pop(); for (const line of lines) { if (line.startsWith('data:')) { const data = JSON.parse(line.slice(5)); console.log(data); if (['SUCCEEDED', 'FAILED', 'CANCELED'].includes(data.status)) { reader.cancel(); } } } } ``` ```python import requests import json headers = { "Authorization": f"Bearer {YOUR_API_KEY}", "Accept": "text/event-stream" } response = requests.get( 'https://api.meshy.ai/openapi/creative-lab/lamp/v1/build/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/stream', headers=headers, stream=True ) for line in response.iter_lines(): if line: if line.startswith(b'data:'): data = json.loads(line.decode('utf-8')[5:]) print(data) if data['status'] in ['SUCCEEDED', 'FAILED', 'CANCELED']: break response.close() ``` **Response Stream** ```javascript // Error event example (wrong stage or task not found) event: error data: { "status_code": 404, "message": "Task not found" } // Message event examples illustrate task progress. // For PENDING or IN_PROGRESS tasks, the response stream will not include all fields. event: message data: { "id": "019c320e-9a8f-7a1c-9c11-2a1876f8a9bb", "progress": 0, "status": "PENDING" } event: message data: { "id": "019c320e-9a8f-7a1c-9c11-2a1876f8a9bb", "type": "creative-lab-lamp-build", "status": "SUCCEEDED", "progress": 100, "created_at": 1729123500000, "started_at": 1729123510000, "finished_at": 1729123535000, "expires_at": 1729382735000, "task_error": null, "consumed_credits": 30, "model_urls": { "lamp_stl": "https://assets.meshy.ai/***/tasks/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/output/lamp.stl?Expires=***", "base_stl": "https://assets.meshy.ai/***/tasks/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/output/base.stl?Expires=***" } } ``` --- ## GET /openapi/creative-lab/lamp/v1/(prototype|build) -- List Lamp Tasks Retrieve a paginated list of your lamp tasks for a single stage. The URL path selects the stage — `/prototype` returns prototype tasks; `/build` returns build tasks. Tasks from the other stage are not included in either response. ### Path Parameters - `stage` · *path* · **required** Either `prototype` or `build`. The collection returns only tasks whose stage matches the URL — fetching `/prototype` never returns build tasks and vice versa. ### Query Parameters - `page_num` · *integer* · default: `1` Page number for pagination. - `page_size` · *integer* · default: `10` Page size limit. Maximum allowed is `50` items. - `sort_by` · *string* · default: `-created_at` Field to sort by. Available values: * `+created_at`: Sort by creation time in ascending order. * `-created_at`: Sort by creation time in descending order. ### Returns Returns a paginated list of the per-stage task object — either [the lamp prototype task object](#the-lamp-prototype-task-object) when listing `/prototype` or [the lamp build task object](#the-lamp-build-task-object) when listing `/build`. **cURL** ```bash # List prototype tasks curl https://api.meshy.ai/openapi/creative-lab/lamp/v1/prototype?page_size=10 \ -H "Authorization: Bearer ${YOUR_API_KEY}" # List build tasks curl https://api.meshy.ai/openapi/creative-lab/lamp/v1/build?page_size=10 \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios' const headers = { Authorization: `Bearer ${YOUR_API_KEY}` } try { const { data } = await axios.get( 'https://api.meshy.ai/openapi/creative-lab/lamp/v1/prototype', { headers, params: { page_size: 10 } } ) console.log(data) } catch (error) { console.error(error) } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.get( "https://api.meshy.ai/openapi/creative-lab/lamp/v1/prototype", headers=headers, params={"page_size": 10}, ) response.raise_for_status() print(response.json()) ``` **Response (List Prototype Tasks)** ```json [ { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "creative-lab-lamp-prototype", "name": "", "status": "SUCCEEDED", "progress": 100, "created_at": 1729123456000, "started_at": 1729123460000, "finished_at": 1729123486000, "expires_at": 1729382686000, "preceding_tasks": 0, "task_error": null, "consumed_credits": 6, "image_urls": [ "https://assets.meshy.ai/***/concept.png?Expires=***" ] } ] ``` --- ## The Lamp Prototype Task Object The Lamp Prototype Task object is a work unit that Meshy keeps track of to generate a stylized matte-white **concept image** from either a text prompt or a source photo. The output of this stage is chained into [the build stage](#create-a-lamp-build-task) via `input_task_id`. ### Properties - `id` · *string* Unique identifier for the task. While we use a k-sortable UUID for task ids as the implementation detail, you should **not** make any assumptions about the format of the id. - `type` · *string* Type of the task. The value is `creative-lab-lamp-prototype`. - `name` · *string* The task name supplied when the task was created. Empty string if no name was provided. - `status` · *string* Status of the task. Possible values are one of `PENDING`, `IN_PROGRESS`, `SUCCEEDED`, `FAILED`, `CANCELED`. - `progress` · *integer* Progress of the task. If the task is not started yet, this property will be `0`. Once the task has succeeded, this will become `100`. - `created_at` · *timestamp* Timestamp of when the task was created, in milliseconds. > **Note:** A timestamp represents the number of milliseconds elapsed since January 1, 1970 UTC, following > the [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339) standard. > For example, Friday, September 1, 2023 12:00:00 PM GMT is represented as `1693569600000`. This applies > to **all** timestamps in Meshy API. - `started_at` · *timestamp* Timestamp of when the task was started, in milliseconds. If the task is not started yet, this property will be `0`. - `finished_at` · *timestamp* Timestamp of when the task was finished, in milliseconds. If the task is not finished yet, this property will be `0`. - `expires_at` · *timestamp* Timestamp of when the task result expires, in milliseconds. - `preceding_tasks` · *integer* The count of preceding tasks. > **Note:** The value of this field is meaningful only if the task status is `PENDING`. - `task_error` · *object* Error details for failed tasks. See [Errors](/api/errors#task-errors) for the full `task_error` object reference. - `consumed_credits` · *integer* The number of credits consumed by this task. Present when the task status is `PENDING`, `IN_PROGRESS`, or `SUCCEEDED`. Returns `0` for `FAILED` tasks (credits are refunded on failure). - `image_urls` · *array of strings* Downloadable URLs for the concept image candidates generated by this prototype task. Currently the API always returns exactly one candidate; the field is an array so future revisions can surface multiple candidates without a breaking change. **Example Lamp Prototype Task Object** ```json { "id": "018a210d-8ba4-705c-b111-1f1776f7f578", "type": "creative-lab-lamp-prototype", "name": "", "status": "SUCCEEDED", "progress": 100, "created_at": 1729123456000, "started_at": 1729123460000, "finished_at": 1729123486000, "expires_at": 1729382686000, "preceding_tasks": 0, "task_error": null, "consumed_credits": 6, "image_urls": [ "https://assets.meshy.ai/***/concept.png?Expires=***" ] } ``` --- ## The Lamp Build Task Object The Lamp Build Task object is a work unit that Meshy keeps track of to generate the final 3D-printable lampshade from a succeeded prototype task. The build runs an image-to-3D draft + texture pipeline on the prototype's concept image, then post-processes the mesh through the lamp processor to hollow, flatten, and (optionally) cut a fixture base. ### Properties - `id` · *string* Unique identifier for the task. - `type` · *string* Type of the task. The value is `creative-lab-lamp-build`. - `name` · *string* The task name supplied when the task was created. Empty string if no name was provided. - `status` · *string* Status of the task. Possible values are one of `PENDING`, `IN_PROGRESS`, `SUCCEEDED`, `FAILED`, `CANCELED`. - `progress` · *integer* Progress of the task. If the task is not started yet, this property will be `0`. Once the task has succeeded, this will become `100`. - `created_at` · *timestamp* Timestamp of when the task was created, in milliseconds. - `started_at` · *timestamp* Timestamp of when the task was started, in milliseconds. - `finished_at` · *timestamp* Timestamp of when the task was finished, in milliseconds. - `expires_at` · *timestamp* Timestamp of when the task result expires, in milliseconds. - `preceding_tasks` · *integer* The count of preceding tasks. Meaningful only when status is `PENDING`. - `task_error` · *object* Error details for failed tasks. See [Errors](/api/errors#task-errors) for the full `task_error` object reference. - `consumed_credits` · *integer* The number of credits consumed by this task. Returns `0` for `FAILED` tasks (credits are refunded on failure). - `model_urls` · *object* Downloadable URLs for the generated artifacts, keyed by artifact name. The set of keys depends on `output.format` and `options.light_source_preset`: - `lamp_stl` · *string* Downloadable URL to the lampshade `lamp.stl`. Present when `output.format` was `stl` (the default). - `base_stl` · *string* Downloadable URL to the fixture-base `base.stl`. Present when `output.format` was `stl` **and** `options.light_source_preset` was not `none`. Omitted when the fixture preset was `none`. - `bundle_zip` · *string* Downloadable URL to a zip bundle of every artifact the processor emits (`lamp.stl`, optional `base.stl`, and — when `options.include_result_json` is `true` — `result.json`). Present when `output.format` was `zip`. When `bundle_zip` is present, `lamp_stl` / `base_stl` are omitted. **Example Lamp Build Task Object** ```json { "id": "019c320e-9a8f-7a1c-9c11-2a1876f8a9bb", "type": "creative-lab-lamp-build", "name": "", "status": "SUCCEEDED", "progress": 100, "created_at": 1729123500000, "started_at": 1729123510000, "finished_at": 1729123535000, "expires_at": 1729382735000, "preceding_tasks": 0, "task_error": null, "consumed_credits": 30, "model_urls": { "lamp_stl": "https://assets.meshy.ai/***/tasks/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/output/lamp.stl?Expires=***", "base_stl": "https://assets.meshy.ai/***/tasks/019c320e-9a8f-7a1c-9c11-2a1876f8a9bb/output/base.stl?Expires=***" } } ``` --- # Balance API Source: https://docs.meshy.ai/api/balance # Balance API The Balance API allows you to retrieve the current credit balance for your account. This endpoint provides a simple way to check your available credits, which are used for various Meshy services. --- ## GET /openapi/v1/balance -- Get Balance This endpoint retrieves the current credit balance for the authenticated user. ### Returns Returns an object containing the current balance of credits. **cURL** ```bash curl https://api.meshy.ai/openapi/v1/balance \ -H "Authorization: Bearer ${YOUR_API_KEY}" ``` ```javascript import axios from 'axios'; const headers = {Authorization: `Bearer ${YOUR_API_KEY}`}; try { const response = await axios.get('https://api.meshy.ai/openapi/v1/balance', {headers}); console.log(response.data); } catch (error) { console.error(error); } ``` ```python import requests headers = { "Authorization": f"Bearer {YOUR_API_KEY}" } response = requests.get( "https://api.meshy.ai/openapi/v1/balance", headers=headers, ) response.raise_for_status() print(response.json()) ``` **Response** ```json { "balance": 1000 } ``` --- # Animation Library Source: https://docs.meshy.ai/api/animation-library # Animation Library Reference This page provides a comprehensive reference of all available animations in Meshy's [Animation API](/api/animation). Each animation is identified by a unique `action_id` that can be used when creating animation tasks. ## Available Animations Below is a complete list of animations available for use with the [Animation API](/api/animation). Use the `action_id` value when creating an animation task with the [`POST /openapi/v1/animations`](/api/animation#create-an-animation-task) endpoint. > The full list of available animations (with `action_id`, name, category, preview URL) is served as JSON at https://api.meshy.ai/web/public/animations/resources — fetch it directly to retrieve the current catalog. ## Usage Example To apply an animation to your rigged character, use the action_id in your API request: ```javascript const payload = { rig_task_id: "YOUR_RIGGING_TASK_ID", action_id: 92, // Double Combo Attack animation }; // Send this payload to the POST /openapi/v1/animations endpoint ``` For more details on how to create animation tasks, see the [Animation API documentation](/api/animation#create-an-animation-task). ---