> **Reading as an AI agent?** This is the Markdown version of https://docs.meshy.ai/api/auto-split.
>
> - Full docs index: https://docs.meshy.ai/llms.txt
> - Single-fetch full content: https://docs.meshy.ai/llms-full.txt
> - Tool-calling access via MCP server: https://docs.meshy.ai/api/ai

---
# Auto Split API

Split a 3D model into separately printable parts — automatically, by the parts you name, or by color region — with optional connectors; thin regions left by a cut are always reinforced so every part prints solid.

> **Note:** **The split result does not preserve the input texture.** Auto Split accepts textured inputs, so you do not need to regenerate the model with `should_texture: false`. It rebuilds the cut parts and assigns each one a flat vertex color; no input texture map is carried into any exported format.

---

## POST /openapi/v1/print/split -- Create an Auto Split Task

This endpoint creates a new Auto Split task. The task cuts the model of a previous task into separately printable parts and returns the segmented model, with every part as its own object in the file.

The task runs in the background. For how long it usually takes, see [Processing Times](/api/task-lifecycle#processing-times).

### Parameters

  - `input_task_id` · *string* · **required**

  The ID of a succeeded task whose model to split. 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) (preview), [Remesh](/api/remesh), [Convert](/api/convert), and [Resize](/api/resize). The task must have a status of `SUCCEEDED`, and its model must be generated with Meshy 6 or Meshy 7 (`ai_model` `meshy-6`, `meshy-7`, `meshy-7.1`, or `latest`). Low-poly and Smart Topology (`meshy-t2`, `meshy-t2.5`) models are not supported. A textured model is accepted, and its texture is not carried into the result.

  - `mode` · *string* · default: `auto`

  How the model is divided into parts.

  Available values:
  * `auto`: Meshy chooses the cuts. `prompt` is ignored.
  * `by_parts`: Cut along the structural parts you name in `prompt`, such as head, arms, and torso.
  * `by_color`: Cut along the color regions you name in `prompt`. Requires an input generated from an uploaded image ([Image to 3D](/api/image-to-3d) or [Multi-Image to 3D](/api/multi-image-to-3d)); other inputs are rejected with `400`. The color-region boundaries come from the source image, not from the input model's texture. For Multi-Image to 3D, Auto Split uses the first source image.

**Only when `mode` is set:**
  - `prompt` · *string* · **required**

  Describes the parts to split into, in any language. Meshy reads 1 to 10 part names from it, so name the pieces rather than describing the model, for example `split into the figure and the base`, or `head, torso, left arm, right arm, legs`. Naming a single part is fine: everything you did not name becomes one remaining part, so `the head` splits the model into the head and the rest, as in the web app. Up to 600 characters. A description that asks for no split at all, or names more than 10 parts, is rejected with `400` and nothing is charged. If Meshy cannot read any part names from the description, it splits along the parts it identifies in the model's reference image instead, in the mode you chose: the task still runs and is charged, and it carries `prompt_ignored: true`. If the model has no reference image, or Meshy finds fewer than two parts in it, that request is rejected with `400` instead and nothing is charged.

  - `target_formats` · *array* · default: `["glb"]`

  Formats to export the split model in. Formats that support scene objects (`glb`, `obj`, `fbx`, `usdz`, `blend`, `3mf`) carry each part as a separate object; `stl` has no notion of separate objects, so it fuses every part into one solid arranged by `layout` (request `3mf` for separately selectable parts in a slicer). `glb` is always produced and returned in `model_urls`; list any other formats you want in addition.

  Available values: `glb`, `obj`, `fbx`, `stl`, `usdz`, `blend`, `3mf`.

  - `layout` · *string* · default: `assembled`

  How the parts are arranged in every output format, and in the thumbnail.

  Available values:
  * `assembled`: Parts stay where the source model had them.
  * `on_plate`: Parts are laid flat and spread out on the build plate, ready to slice — the same arrangement as the web app's On Plate view.

  In both layouts a collapsed sliver or point-like piece left over from a cut is removed before export, so every part you get is printable. Formats that support scene objects hold one object per part; `stl` fuses them into a single solid.

  - `connectors` · *boolean* · default: `false`

  Adds mortise-and-tenon connectors at each cut so the printed parts fit together.

**Only when `connectors` is set:**
  - `connector_type` · *string* · default: `cube`

  The shape of the connector at each cut surface.

  Available values: `cube`, `cylinder`.

  - `connector_size` · *number* · default: `0.5`

  Connector size relative to the cut surface.

  Valid range: `0.1` to `0.8`.

  - `connector_height` · *number* · default: `0.1`

  How far the connector extends from the cut surface, relative to the cut surface.

  Valid range: `0.1` to `0.8`.

### Returns

The `result` property of the response contains the `id` of the newly created Auto Split task.

### Failure Modes

  - `400 - Bad Request`

  The request was unacceptable. Common causes:
  * **Missing prompt**: `prompt` is required when `mode` is `by_parts` or `by_color`.
  * **Prompt describes no split, or too many parts**: `by_parts` / `by_color` accepts 1 to 10 named pieces. A description that asks to keep the model in one piece, or names more than 10 parts, is rejected. Nothing is charged.
  * **Unsupported input task**: The `input_task_id` must refer to a succeeded task of a supported type, generated with Meshy 6 or Meshy 7.
  * **No reference image**: `by_color` requires an input generated from an uploaded image.
  * **Out-of-range connector**: `connector_size` or `connector_height` is outside `0.1` to `0.8`.

  - `401 - Unauthorized`

  Authentication failed. Please check your API key.

  - `402 - Payment Required`

  Insufficient credits to perform this task.

  - `404 - Not Found`

  The `input_task_id` does not exist or does not belong to your account.

  - `429 - Too Many Requests`

  You have exceeded your rate limit. `by_parts` and `by_color` requests also share a prompt-parsing limit of 12 requests per minute per account.

  - `503 - Service Unavailable`

  Prompt-based splitting (`by_parts` and `by_color`) is temporarily unavailable. Retry later, or use `mode: "auto"`, which is unaffected. Nothing is charged.

  **cURL**

  ```bash
  # Simple request: let Meshy choose the cuts
  curl https://api.meshy.ai/openapi/v1/print/split \
  -X POST \
  -H "Authorization: Bearer ${YOUR_API_KEY}" \
  -H 'Content-Type: application/json' \
  -d '{
      "input_task_id": "018a210d-8ba4-705c-b111-1f1776f7f578"
    }'

  # Advanced request: name the parts, add connectors, export glb and obj
  curl https://api.meshy.ai/openapi/v1/print/split \
  -X POST \
  -H "Authorization: Bearer ${YOUR_API_KEY}" \
  -H 'Content-Type: application/json' \
  -d '{
      "input_task_id": "018a210d-8ba4-705c-b111-1f1776f7f578",
      "mode": "by_parts",
      "prompt": "split into the figure and the base",
      "target_formats": ["glb", "obj"],
      "layout": "on_plate",
      "connectors": true,
      "connector_type": "cylinder",
      "connector_size": 0.4
    }'
  ```

  ```javascript
  import axios from 'axios'

  const headers = { Authorization: `Bearer ${YOUR_API_KEY}` };

  // Simple request: let Meshy choose the cuts
  const payload = {
      input_task_id: "018a210d-8ba4-705c-b111-1f1776f7f578"
  };

  // Advanced request: name the parts, add connectors, export glb and obj
  const advancedPayload = {
      input_task_id: "018a210d-8ba4-705c-b111-1f1776f7f578",
      mode: "by_parts",
      prompt: "split into the figure and the base",
      target_formats: ["glb", "obj"],
      layout: "on_plate",
      connectors: true,
      connector_type: "cylinder",
      connector_size: 0.4
  };

  try {
      const response = await axios.post(
      'https://api.meshy.ai/openapi/v1/print/split',
      payload,
    { headers }
  );
      console.log(response.data);
  } catch (error) {
      console.error(error);
  }
  ```

  ```python
  import requests

  headers = {
      "Authorization": f"Bearer {YOUR_API_KEY}"
  }

  # Simple request: let Meshy choose the cuts
  payload = {
      "input_task_id": "018a210d-8ba4-705c-b111-1f1776f7f578"
  }

  # Advanced request: name the parts, add connectors, export glb and obj
  advanced_payload = {
      "input_task_id": "018a210d-8ba4-705c-b111-1f1776f7f578",
      "mode": "by_parts",
      "prompt": "split into the figure and the base",
      "target_formats": ["glb", "obj"],
      "layout": "on_plate",
      "connectors": True,
      "connector_type": "cylinder",
      "connector_size": 0.4
  }

  response = requests.post(
      "https://api.meshy.ai/openapi/v1/print/split",
      headers=headers,
      json=payload,
  )
  response.raise_for_status()
  print(response.json())
  ```

**Response**

```json
{
  "result": "0193bfc5-ee4f-73f8-8525-44b398884ce9"
}
```

---

## GET /openapi/v1/print/split/:id -- Retrieve an Auto Split Task

This endpoint retrieves an Auto Split task by its ID.

### Parameters

  - `id` · *path*

  The ID of the Auto Split task to retrieve.

### Returns

The Auto Split Task object.

  **cURL**

  ```bash
  curl https://api.meshy.ai/openapi/v1/print/split/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/split/${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/split/{task_id}",
      headers=headers,
  )
  response.raise_for_status()
  print(response.json())
  ```

**Response**

```json
{
  "id": "0193bfc5-ee4f-73f8-8525-44b398884ce9",
  "type": "print-split",
  "model_urls": {
    "glb": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.glb?Expires=***",
    "obj": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.obj?Expires=***"
  },
  "thumbnail_url": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/preview.png?Expires=***",
  "part_count": 4,
  "progress": 100,
  "status": "SUCCEEDED",
  "created_at": 1699999999000,
  "started_at": 1700000000000,
  "finished_at": 1700000082000,
  "task_error": null,
  "consumed_credits": 10
}
```

---

## DELETE /openapi/v1/print/split/:id -- Delete an Auto Split Task

This endpoint permanently deletes an Auto Split task, including all associated models and data. This action is irreversible.

### Path Parameters

  - `id` · *path*

  The ID of the Auto Split task to delete.

### Task Status

A task that is still `PENDING` is deleted and the credits consumed at
create-time are refunded.

A task that is already `IN_PROGRESS` cannot be deleted: the request is
rejected with `409 Conflict` and the task keeps running. Credits for a task
the worker has already started are not refundable, so deleting it mid-run
would cost you the credits and the result both. Wait for it to reach
`SUCCEEDED`, `FAILED` or `CANCELED`, then delete it.

A task in a terminal state (`SUCCEEDED`, `FAILED` or `CANCELED`) is deleted
without a refund.

### Returns

Returns `200 OK` on success, or `409 Conflict` when the task is
`IN_PROGRESS`.

  **cURL**

  ```bash
  curl --request DELETE \
    --url https://api.meshy.ai/openapi/v1/print/split/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/split/${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/split/{task_id}",
      headers=headers,
  )
  response.raise_for_status()
  ```

**Response**

```json
// 200 OK on success, with an empty body.
//
// 409 Conflict when the task is IN_PROGRESS — the task is left running:
{
  "message": "Task is IN_PROGRESS and cannot be deleted. Credits for a task the worker has already started are not refundable; wait for it to reach SUCCEEDED, FAILED or CANCELED, then delete it."
}
```

---

## GET /openapi/v1/print/split -- List Auto Split Tasks

This endpoint allows you to retrieve a list of Auto Split 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 `100` items; larger values are clamped to `100`.

  - `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 Auto Split Task Objects](#the-auto-split-task-object).

  **cURL**

  ```bash
  curl https://api.meshy.ai/openapi/v1/print/split?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/split?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/split",
      headers=headers,
      params={"page_size": 10}
  )
  response.raise_for_status()
  print(response.json())
  ```

**Response**

```json
[
  {
    "id": "0193bfc5-ee4f-73f8-8525-44b398884ce9",
    "type": "print-split",
    "model_urls": {
      "glb": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.glb?Expires=***"
    },
    "thumbnail_url": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/preview.png?Expires=***",
    "part_count": 4,
    "progress": 100,
    "status": "SUCCEEDED",
    "preceding_tasks": 0,
    "created_at": 1699999999000,
    "started_at": 1700000000000,
    "finished_at": 1700000082000,
    "task_error": null,
    "consumed_credits": 10
  }
]
```

---

## GET /openapi/v1/print/split/:id/stream -- Stream an Auto Split Task

This endpoint streams real-time updates for an Auto Split task using Server-Sent Events (SSE).

### Parameters

  - `id` · *path*

  Unique identifier for the Auto Split task to stream.

### Returns

Returns a stream of [The Auto Split Task Objects](#the-auto-split-task-object) as Server-Sent Events.

Every `message` event carries the full task object as returned by [Retrieve an Auto Split Task](#retrieve-an-auto-split-task), including `consumed_credits`, the timestamps and `prompt_ignored`; while the task is `PENDING` or `IN_PROGRESS` the fields that change between frames are `progress`, `status`, `started_at` and `preceding_tasks`, and `model_urls`, `thumbnail_url` and `part_count` appear once it reaches `SUCCEEDED`. An `error` event carries only `status_code` and `message`, so branch on the event name before reading `status`.

  **cURL**

  ```bash
  curl -N https://api.meshy.ai/openapi/v1/print/split/a43b5c6d-7e8f-901a-234b-567c890d1e2f/stream \
  -H "Authorization: Bearer ${YOUR_API_KEY}"
  ```

  ```javascript
  const response = await fetch(
    'https://api.meshy.ai/openapi/v1/print/split/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/split/a43b5c6d-7e8f-901a-234b-567c890d1e2f/stream',
      headers=headers,
      stream=True
  )

  event = 'message'
  for line in response.iter_lines():
      if not line:
          continue
      if line.startswith(b'event:'):
          event = line.decode('utf-8')[6:].strip()
      elif line.startswith(b'data:'):
          data = json.loads(line.decode('utf-8')[5:])
          print(event, data)

          if event == 'error':
              break  # {"status_code": ..., "message": ...}
          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 (other task fields omitted here for brevity;
  // each frame is the full task object).
  event: message
  data: {
    "id": "a43b5c6d-7e8f-901a-234b-567c890d1e2f",
    "progress": 0,
    "status": "PENDING"
  }

  event: message
  data: {
    "id": "a43b5c6d-7e8f-901a-234b-567c890d1e2f",
    "type": "print-split",
    "model_urls": {
      "glb": "https://assets.meshy.ai/***/tasks/a43b5c6d-7e8f-901a-234b-567c890d1e2f/output/model.glb?Expires=***"
    },
    "thumbnail_url": "https://assets.meshy.ai/***/tasks/a43b5c6d-7e8f-901a-234b-567c890d1e2f/output/preview.png?Expires=***",
    "part_count": 4,
    "progress": 100,
    "status": "SUCCEEDED",
    "preceding_tasks": 0,
    "created_at": 1699999999000,
    "started_at": 1700000000000,
    "finished_at": 1700000082000,
    "task_error": null,
    "consumed_credits": 10
  }
  ```

---

## The Auto Split Task Object

An Auto Split task carries only the properties below. The generation-prompt fields other task objects include (`name`, `object_prompt`, `texture_prompt` and so on), the single `model_url`, and `texture_urls` are never populated for a split and are not returned. Properties that fill in as the task runs (`thumbnail_url`, `model_urls`, the timestamps) are always present, empty until they have a value, so the set of keys does not change between `PENDING` and `SUCCEEDED`.

  - `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 `print-split`.

  - `model_urls` · *object*

  Downloadable URLs to the split model, one per requested format. Formats that support scene objects keep each part as a separate object; `stl` fuses them into one solid. The property for a format will be omitted if the format was not requested.

- `glb` · *string*

  Downloadable URL to the split model in GLB format.

- `obj` · *string*

  Downloadable URL to the split model in OBJ format.

- `fbx` · *string*

  Downloadable URL to the split model in FBX format.

- `stl` · *string*

  Downloadable URL to the split model in STL format. All parts are fused into one solid; request `3mf` for separately selectable parts.

- `usdz` · *string*

  Downloadable URL to the split model in USDZ format.

- `blend` · *string*

  Downloadable URL to the split model in Blender format.

- `3mf` · *string*

  Downloadable URL to the split model in 3MF format.

  - `thumbnail_url` · *string*

  Downloadable URL to a rendered preview of the split model, with each part in a distinct color, in the requested `layout`.

  - `prompt_ignored` · *boolean*

  `true` when a `by_parts` or `by_color` request's `prompt` named no parts, so Meshy split the model automatically instead — the part names in the result are Meshy's, not yours. Present from `PENDING` on. Omitted for `auto` tasks and whenever the prompt was followed.

  - `part_count` · *integer*

  Number of printable parts the split produced. Formats that support scene objects carry one object per part; `stl` fuses them into one solid, and the count still reports the parts. Collapsed slivers that the segmentation could not turn into a printable piece are removed from the files before export and are not counted.

  - `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`, `CANCELED`.

  - `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. Always present: `10` once the task has been accepted, and `0` for `FAILED` tasks because the charge is refunded on failure. Deleting a task while it is still `PENDING` also refunds it.

**The Auto Split Task Object**

```json
{
  "id": "0193bfc5-ee4f-73f8-8525-44b398884ce9",
  "type": "print-split",
  "model_urls": {
    "glb": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.glb?Expires=***",
    "obj": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/model.obj?Expires=***"
  },
  "thumbnail_url": "https://assets.meshy.ai/***/tasks/0193bfc5-ee4f-73f8-8525-44b398884ce9/output/preview.png?Expires=***",
  "part_count": 4,
  "progress": 100,
  "status": "SUCCEEDED",
  "preceding_tasks": 0,
  "created_at": 1699999999000,
  "started_at": 1700000000000,
  "finished_at": 1700000082000,
  "task_error": null,
  "consumed_credits": 10
}
```
