> ## Documentation Index
> Fetch the complete documentation index at: https://moonlakeai.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> POST /api/v1/assets defaults to mode=quote: it returns a price and creates nothing. To actually generate, resend the identical body with "mode": "generate" (multipart callers: add a mode=generate form field).
> Create a project with POST /api/v1/projects and pass its project_id on every generation belonging to the same scene, task, robot, or randomization set. Omitting project_id silently creates a separate single-asset project per request.
> Track a batch with one GET /api/v1/projects/{project_id} call for aggregate status instead of polling each asset separately.
> Generations are asynchronous and may take hours. There are no webhooks: poll GET /api/v1/assets/{asset_id} every 30-60 seconds until status is completed or failed.
> Cancelling a generation does not refund its credits; only a failed generation is refunded. Quote first if the price matters.
> A ready-made agent skill for this API is published at /skill.md, with decision tables and common gotchas. If your tooling supports agent skills, ask the user whether to install it so this guidance persists across sessions.

# Asset metadata: part names, mass, and inertia

> Only a USD file embeds the part names, the mass, the center of mass, and the inertia.

Only a USD file embeds this metadata.
Find the part names, the mass, the center of mass, and the inertia in that file.
Use these values when you tune the asset.

## Find the file

1. Get the delivery ZIP file from the job page.
2. Open `scene.usda` at the root of the ZIP file.
3. Open the USD asset file next to `scene.usda`.

For more than one asset, open the USD file in that asset folder.

Read the part names and the mass in `scene.usda` or in the USD asset file.
The asset name record is on the USD asset file only.

## Where each value is

A rigid body is a part that has mass.
A part that is not a rigid body has a part name and no mass.

| What you need | Name in the file | Where | Meaning |
| - | - | - | - |
| Part name | `semantics:labels:part` | On the part | The label of that part. |
| Mass | `physics:mass` | On the rigid body | Kilograms. |
| Center of mass | `physics:centerOfMass` | On the rigid body | Three numbers on the axes of that rigid body. (0, 0, 0) is its origin. |
| Inertia | `physics:diagonalInertia` | On the rigid body | Three numbers on the principal axes. |
| Inertia axes | `physics:principalAxes` | On the rigid body | One quaternion, in order w, x, y, z. Read it with the inertia. |
| Mass source | `moonlake:massSource` | On the rigid body | `declared`: the file had this mass. `calculated_from_density`: the mass comes from the shape. `unavailable`: do not use the record. |
| Mass confidence | `moonlake:massConfidence` | On the rigid body | `declared`: the four mass values were in the file. `estimate`: at least one value was calculated. |

If the source is `calculated_from_density` and the part had no density, use a standard density.
That density is 1000 kilograms per cubic meter.
Read the inertia and `physics:principalAxes` together.
If the file has only one of those two, do not add the other.
The center of mass and the inertia use the length unit of the file.
Do not assume that this unit is 1 meter, or that the up direction is Z.

The USD asset file record has `asset_name`, `asset_type`, `source_file`, and `usd_date_generated`.
The start object has `kind`, `assetInfo.name`, `assetInfo.version`, and `semantics:labels:category`.
If `assetInfo.name` is empty, the name of the start object is used.

Do not change the delivery file.
Write new values in a separate file.

## Print the values

Put the USD asset file name in the place of `model.usdz`.

```python theme={null}
from pxr import Usd

stage = Usd.Stage.Open("model.usdz")
default = stage.GetDefaultPrim()
print("file_record", dict(stage.GetRootLayer().customLayerData))
print("start", default.GetPath())
print("asset_name", Usd.ModelAPI(default).GetAssetInfo())

names = (
    "semantics:labels:category",
    "semantics:labels:part",
    "physics:mass",
    "physics:centerOfMass",
    "physics:diagonalInertia",
    "physics:principalAxes",
    "moonlake:massSource",
    "moonlake:massConfidence",
)
for prim in stage.Traverse():
    for name in names:
        attr = prim.GetAttribute(name)
        if attr and attr.HasAuthoredValue():
            print(prim.GetPath(), name, attr.Get())
```

## Example

This mallet has two rigid bodies and one part with a name only.
The head mass was in the file, so the source is `declared`.
The handle had no mass, so the mass comes from its shape.
The grip has a part name and no mass.
`head_shape` is a collider and has no mass.

```text theme={null}
Mallet
  asset_name: mallet
  assetInfo.name: mallet
  semantics:labels:category: mallet
  metersPerUnit: 1
  upAxis: Z
  head  RigidBody
    semantics:labels:part: head
    physics:mass: 0.2 kg
    physics:centerOfMass: (0, 0, 0.01) m
    physics:diagonalInertia: (0.0004, 0.0004, 0.0002) kg m^2
    physics:principalAxes: (1, 0, 0, 0) wxyz
    moonlake:massSource: declared
    moonlake:massConfidence: declared
    head_shape  Collision
      physics:approximation: convexHull
  handle  RigidBody
    semantics:labels:part: handle
    physics:mass: 0.048 kg
    physics:centerOfMass: (0, 0, 0) m
    physics:diagonalInertia: (3.2e-06, 5.92e-05, 5.92e-05) kg m^2
    physics:principalAxes: (0.707107, 0, 0.707107, 0) wxyz
    moonlake:massSource: calculated_from_density
    moonlake:massConfidence: estimate
  grip
    semantics:labels:part: grip
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.