For the complete documentation index, see llms.txt. This page is also available as Markdown.

Assets

Upload source files and manage generated assets.

Assets represent the files you upload and the material outputs the API generates. Use these endpoints to upload source files, list assets, fetch metadata and download URLs, and delete assets you no longer need.

Start uploading a batch of files.

post

Creates an upload batch for 5 to 200 files at once. For each file you provide the filename, size, and optional content type; the response returns a presigned upload URL and the exact headers you must send with the PUT.

Upload the raw bytes directly to each URL, then poll GET /batch/uploads/{upload_batch_id} until every file is ready.

Files are validated after upload. A file that fails validation becomes rejected rather than ready. The upload endpoint itself only rejects obvious request-level problems, such as an unsupported file type or a size mismatch. Images must be 4096×4096 pixels or smaller.

Authorizations
AuthorizationstringRequired

API key created in the Marso Studio dashboard. The value has the form mxr_live_<entropy> and is sent as a Bearer token in the Authorization header.

Body

Request body for POST /batch/uploads. Describe 5 to 200 files you want to upload; the response returns a presigned upload URL for each one.

Responses
201

Upload URLs in the same order as the request.

application/json

Response from POST /batch/uploads. Contains the upload batch ID and the presigned upload URL for each file.

upload_batch_idstringOptional

The ID that groups the created pending assets. Poll GET /batch/uploads/{upload_batch_id} for aggregate readiness. If this field is absent, poll each asset individually.

post/batch/uploads
POST /api/public/v1/batch/uploads HTTP/1.1
Host: api.marso.app/
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 68

{
  "files": [
    {
      "filename": "text",
      "content_type": "text",
      "size_bytes": 1
    }
  ]
}
{
  "upload_batch_id": "text",
  "files": [
    {
      "asset_id": "text",
      "upload_url": "https://example.com",
      "headers": {
        "ANY_ADDITIONAL_PROPERTY": "text"
      }
    }
  ]
}

Retrieve an upload batch.

get

Returns the state of an upload batch created with POST /batch/uploads, including the validation status of each file. Poll this endpoint until state reaches a terminal value (COMPLETED, PARTIALLY_COMPLETED, or FAILED), then use the ready asset IDs to submit a PBR batch.

Authorizations
AuthorizationstringRequired

API key created in the Marso Studio dashboard. The value has the form mxr_live_<entropy> and is sent as a Bearer token in the Authorization header.

Path parameters
upload_batch_idstring · uuidRequired
Responses
200

Upload batch status.

application/json

Response from GET /batch/uploads/{upload_batch_id}. Contains the aggregate state of the batch and the validation status of each file.

statestring · enumRequired

Aggregate state of an upload batch.

Possible enum values:

  • UPLOADING: at least one file is still being validated.
  • COMPLETED: every file in the batch is ready.
  • PARTIALLY_COMPLETED: the batch has a mix of ready and rejected files; this is a terminal state.
  • FAILED: every file in the batch was rejected.
Possible values:
created_atinteger · int64Required

Time represented as milliseconds since the Unix epoch.

completed_atinteger · nullableOptional

Time represented as milliseconds since the Unix epoch, or null when the field has not been set.

get/batch/uploads/{upload_batch_id}
GET /api/public/v1/batch/uploads/{upload_batch_id} HTTP/1.1
Host: api.marso.app/
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
  "state": "UPLOADING",
  "files": [
    {
      "file_name": "text",
      "status": "pending"
    }
  ],
  "created_at": 1,
  "completed_at": null
}

Start uploading a single file.

post

Creates an upload for one file. You provide the file name, size, and optional content type; the response returns a presigned upload URL and the exact headers you must send with the PUT.

Upload the raw bytes directly to that URL, then poll GET /uploads/{asset_id} until the status is ready.

The file is validated after upload. A file that fails validation becomes rejected rather than ready. This endpoint itself only rejects request-level problems, such as an unsupported file type or a size over the limit. Images must be 4096 by 4096 pixels or smaller.

Use POST /batch/uploads instead when you have 5 or more files to upload at once.

Authorizations
AuthorizationstringRequired

API key created in the Marso Studio dashboard. The value has the form mxr_live_<entropy> and is sent as a Bearer token in the Authorization header.

Body

Request body for POST /uploads. Describes the one file you want to upload.

filenamestringRequired

The name of the file, including its extension. The extension selects the asset type and must be one of .usd, .glb, .jpg, .jpeg, or .png.

content_typestringOptional

The MIME type of the file. Optional: it is inferred from the file extension when omitted. When present it must match the extension.

size_bytesinteger · int64Required

The exact size of the file in bytes. The uploaded byte count must match this value. Must be at least 1, and no more than 5 MB for an image or 100 MB for a mesh.

Responses
201

The upload URL was created.

application/json

Presigned upload URL and metadata returned by POST /uploads. There is no upload batch ID: a single upload is polled with GET /uploads/{asset_id}.

asset_idstringRequired

The ID of the pending asset created for this file. Use it to poll the upload and, once the status is ready, to submit the asset for PBR generation.

upload_urlstring · uriRequired

Presigned PUT URL. Upload the raw file bytes to this URL using the headers provided in headers.

post/uploads
POST /api/public/v1/uploads HTTP/1.1
Host: api.marso.app/
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 56

{
  "filename": "text",
  "content_type": "text",
  "size_bytes": 1
}
{
  "asset_id": "text",
  "upload_url": "https://example.com",
  "headers": {
    "ANY_ADDITIONAL_PROPERTY": "text"
  }
}

Retrieve the status of a single upload.

get

Returns the validation status of one file uploaded with POST /uploads. Poll this endpoint until the status is ready, then submit the asset ID for PBR generation.

Authorizations
AuthorizationstringRequired

API key created in the Marso Studio dashboard. The value has the form mxr_live_<entropy> and is sent as a Bearer token in the Authorization header.

Path parameters
asset_idstring · uuidRequired

Unique identifier of the asset.

Responses
200

The status of the upload.

application/json

The validation status of one file uploaded with POST /uploads.

asset_idstringRequired

The ID of the asset created for this file.

file_namestringRequired

The file name as provided in the upload request.

statusstring · enumRequired

The validation status of this file.

Possible enum values:

  • pending: the file has not been validated yet.
  • ready: the file passed validation and can be used for PBR generation.
  • rejected: the file failed validation. The file must be uploaded again.
Possible values:
created_atinteger · int64Required

Time represented as milliseconds since the Unix epoch.

get/uploads/{asset_id}
GET /api/public/v1/uploads/{asset_id} HTTP/1.1
Host: api.marso.app/
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
  "asset_id": "text",
  "file_name": "text",
  "status": "pending",
  "created_at": 1
}

List your PBR assets, grouped by project.

get

Returns your PBR assets grouped by the project that produced them.

Only PBR assets are returned, not the image or 3D model you uploaded to produce them. Assets created through this API belong to no project and arrive in ungrouped_assets.

Each entry's id can be passed straight to POST /assets/download to get download URLs for its 3D model and all of its texture maps, and its file_name is the source 3D model's name.

type and group_by each have one supported value today (pbr and projects) and both default to it, so a bare request returns the grouped listing. Any other value is rejected rather than ignored.

Authorizations
AuthorizationstringRequired

API key created in the Marso Studio dashboard. The value has the form mxr_live_<entropy> and is sent as a Bearer token in the Authorization header.

Query parameters
limitinteger · min: 1Optional

Page size. Defaults to 25 and has a maximum of 25. Other values use the default.

What the number counts depends on which part of the listing you are in. While groups are still being returned it counts PROJECTS: one page carries up to 25 projects and every PBR asset each of them produced, so a single page can hold many more than 25 entries. Once the groups are exhausted it counts assets, and one page carries up to 25 entries in ungrouped_assets.

Default: 25
cursorstringOptional

Opaque pagination cursor returned by the previous page as next_cursor. Omit on the first request.

typestring · enumOptional

Which assets to return. pbr is the only supported value today and is the default, so you can omit this.

Default: pbrPossible values:
group_bystring · enumOptional

How to group the response. projects is the only supported value today and is the default, so you can omit this.

Default: projectsPossible values:
Responses
200

A page of your PBR assets grouped by project.

application/json

Response from GET /assets: your PBR assets grouped by the project that produced them, then the ones belonging to no project.

data and ungrouped_assets form ONE ordered sequence under a single cursor. Every group first, then the ungrouped assets. Just follow pagination.next_cursor until has_more is false.

A cursor is a position in that one sequence, and what it points at differs either side of the boundary between the two parts. Treat it as opaque and short-lived: echo the one you were just given, and start a fresh traversal rather than storing a cursor and replaying it later.

group_bystring · enumRequired

How the response is grouped, echoing the request.

Possible values:
get/assets
GET /api/public/v1/assets HTTP/1.1
Host: api.marso.app/
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
  "group_by": "projects",
  "data": [
    {
      "group_id": "text",
      "name": "text",
      "thumbnail_url": "https://example.com",
      "thumbnail_url_expires_at": 1,
      "assets": [
        {
          "id": "text",
          "name": "text",
          "file_name": "text",
          "thumbnail_url": "https://example.com",
          "thumbnail_url_expires_at": 1,
          "model_version": "text",
          "enriched_status": "not_started",
          "enrichment": {
            "schema_version": "text",
            "prompt_version": "text",
            "model": "text",
            "display_name": "text",
            "description_short": "text",
            "description_long": "text",
            "category": "text",
            "subcategory": "text",
            "detail": "text",
            "search_aliases": [
              "text"
            ],
            "tags": [
              "text"
            ],
            "materials": [
              "text"
            ],
            "style_period": "text",
            "region": "text",
            "setting": "text",
            "conditions": [
              "text"
            ],
            "cleanliness": [
              "text"
            ],
            "placements": [
              "text"
            ],
            "needs_review": true
          }
        }
      ]
    }
  ],
  "ungrouped_assets": [
    {
      "id": "text",
      "name": "text",
      "file_name": "text",
      "thumbnail_url": "https://example.com",
      "thumbnail_url_expires_at": 1,
      "model_version": "text",
      "enriched_status": "not_started",
      "enrichment": {
        "schema_version": "text",
        "prompt_version": "text",
        "model": "text",
        "display_name": "text",
        "description_short": "text",
        "description_long": "text",
        "category": "text",
        "subcategory": "text",
        "detail": "text",
        "search_aliases": [
          "text"
        ],
        "tags": [
          "text"
        ],
        "materials": [
          "text"
        ],
        "style_period": "text",
        "region": "text",
        "setting": "text",
        "conditions": [
          "text"
        ],
        "cleanliness": [
          "text"
        ],
        "placements": [
          "text"
        ],
        "needs_review": true
      }
    }
  ],
  "errors": [
    {
      "asset_id": "text",
      "file_name": "text",
      "code": "THUMBNAIL_URL_UNAVAILABLE",
      "message": "text"
    }
  ],
  "pagination": {
    "next_cursor": "text",
    "has_more": true
  }
}

Get download URLs for many assets.

post

Returns presigned download URLs for each asset ID you submit, so you can collect a whole set of assets in one call instead of one GET /assets/{asset_id} per asset. URLs are valid for about 2 minutes, so start each download as soon as you get the response.

Each entry lists every file for the ID you submitted. A PBR material resolves to its 3D model plus all of its texture maps (and its USDZ where one exists), so a single request gives you everything needed to use the material. A plain asset resolves to one file.

The call changes nothing and is safe to retry. Responses are not cacheable.

Unrecognised IDs do not fail the call. Every ID you submit comes back in exactly one of assets (resolved, with a URL) or errors (with a reason), so a single stale ID never costs you the rest of the batch. An asset that belongs to another account reports ASSET_NOT_FOUND, the same as one that does not exist.

Repeated IDs collapse to a single entry, keeping the order you sent them in.

Authorizations
AuthorizationstringRequired

API key created in the Marso Studio dashboard. The value has the form mxr_live_<entropy> and is sent as a Bearer token in the Authorization header.

Body

Request body for POST /assets/download. The asset IDs you want download URLs for.

asset_idsstring · uuid[] · min: 1 · max: 100Required

Asset IDs to get download URLs for. Repeated IDs collapse to a single entry. Every ID must be a well-formed asset ID. One malformed value rejects the whole request.

Responses
200

Download URLs for the resolved assets, plus a reason for each ID that could not be resolved.

application/json

Response from POST /assets/download. Together assets and errors account for every distinct asset ID submitted.

post/assets/download
POST /api/public/v1/assets/download HTTP/1.1
Host: api.marso.app/
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 54

{
  "asset_ids": [
    "123e4567-e89b-12d3-a456-426614174000"
  ]
}
{
  "assets": [
    {
      "asset_id": "text",
      "type": "text",
      "file_name": "text",
      "files": [
        {
          "asset_id": "text",
          "role": "source",
          "pass": "text",
          "type": "text",
          "size_bytes": 1,
          "download_url": "https://example.com",
          "expires_at": 1
        }
      ]
    }
  ],
  "errors": [
    {
      "asset_id": "text",
      "file_name": "text",
      "code": "ASSET_NOT_FOUND",
      "message": "text"
    }
  ]
}

Retrieve an asset.

get

Returns the metadata for a single asset, plus a fresh presigned download URL valid for about 1 minute. For PBR material assets, the response includes the generated mesh, material, and texture components.

Authorizations
AuthorizationstringRequired

API key created in the Marso Studio dashboard. The value has the form mxr_live_<entropy> and is sent as a Bearer token in the Authorization header.

Path parameters
asset_idstring · uuidRequired

Unique identifier of the asset.

Query parameters
formatstring · enumOptional

Request a specific downloadable representation. usdz is available for PBR material assets that produced a USDZ component.

Possible values:
Responses
200

Asset metadata and presigned download URL, or PBR material detail.

application/json
or
get/assets/{asset_id}
GET /api/public/v1/assets/{asset_id} HTTP/1.1
Host: api.marso.app/
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
  "asset_id": "text",
  "name": "text",
  "type": "text",
  "size_bytes": 1,
  "created_at": 1,
  "download_url": "https://example.com",
  "expires_at": 1
}

Delete an asset.

delete

Deletes an asset owned by the authenticated account. For a PBR material, this operation deletes every material slot, physical component, and enrichment commit object from the same PBR execution. The operation returns ASSET_IN_USE without deleting data when an active execution uses a component or when another PBR execution shares a source or target component.

Authorizations
AuthorizationstringRequired

API key created in the Marso Studio dashboard. The value has the form mxr_live_<entropy> and is sent as a Bearer token in the Authorization header.

Path parameters
asset_idstring · uuidRequired

Unique identifier of the asset.

Responses
200

Deletion acknowledged.

application/json

Response from DELETE /assets/{asset_id}.

asset_idstringRequired

Unique identifier of the asset that was deleted.

deletedbooleanRequired

Whether the asset was deleted. If the asset was already deleted or did not exist, this may be false.

delete/assets/{asset_id}
DELETE /api/public/v1/assets/{asset_id} HTTP/1.1
Host: api.marso.app/
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
  "asset_id": "text",
  "deleted": true
}

Last updated