> For the complete documentation index, see [llms.txt](https://docs.m-xr.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.m-xr.com/marso-studio-api/api/pbr.md).

# PBR

Submit meshes and images for PBR generation.

Batches group one or more PBR generation jobs together. Use these endpoints to submit 3D mesh to PBR or image to PBR batches, poll a batch for progress, and list recent batches.

## Generate PBR materials from 3D meshes.

> Submits one or more ready mesh assets for 3D mesh to PBR generation. The same\
> \`options\` are applied to every mesh in the batch. Each asset must be a\
> \`ready\` mesh uploaded via \`POST /batch/uploads\`.\
> \
> The request returns immediately with a \`batch\_id\` (\`202\`). Poll\
> \`GET /batch/{batch\_id}\` for the batch status and, as each item finishes,\
> its generated material maps and download URLs. Credits are reserved when\
> you submit and refunded automatically for any item that fails, so you\
> are only charged for successful results.<br>

```json
{"openapi":"3.1.0","info":{"title":"Marso Studio API","version":"0.0.1"},"tags":[{"name":"pbr","description":"Batches group one or more PBR generation jobs together. Use these endpoints\nto submit 3D mesh to PBR or image to PBR batches, poll a batch for progress,\nand list recent batches.\n"}],"servers":[{"url":"https://api.marso.ai/api/public/v1","description":"Production server."}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"API key minted from the Marso Studio dashboard. The value has the form\n`mxr_live_<entropy>` and is sent as a Bearer token in the `Authorization`\nheader.\n"}},"schemas":{"CreatePBRMeshBatchRequest":{"type":"object","required":["asset_ids"],"description":"Request body for `POST /batch/pbr/mesh`. Submit one or more ready mesh\nassets for 3D mesh to PBR generation.\n","properties":{"asset_ids":{"type":"array","minItems":1,"maxItems":200,"items":{"type":"string","format":"uuid"},"description":"IDs of the `ready` mesh assets to process. These assets must have been\nuploaded via `POST /batch/uploads` and must currently be in the `ready`\nstate.\n"},"options":{"$ref":"#/components/schemas/PublicPBRMeshOptions"}}},"PublicPBRMeshOptions":{"type":"object","additionalProperties":false,"description":"Tuning options for a mesh PBR run. Every field is optional, and an\nomitted field uses the system default.\n\nThis is the image options plus `output_2d`, the 1 mesh-only option. It\nneeds a stage the image pipeline skips, so it appears on the mesh\nendpoints only. An image endpoint rejects it.\n\n**Every mesh result carries a USDZ.** The export is no longer an\noption. `output_3d` is gone, and a request that carries it gets a\n`400`. The pipeline always packages `material.usdz` for a mesh run,\nand the result lists it beside the texture maps.\n\nThis object rejects a field it does not declare, the same way\n`PublicPBRImageOptions` rejects one. Issue #2175 removed the same 6\noptions from both, and it removed `output_3d` from this object alone.\n\n4 of the 6 changed a mesh result before the removal. A mesh run now uses\nthe deployed value for each: 16 views, the `quality` solver profile, the\n`coverage` blend mode, and a bake at 4096. The PBR options reference\nholds the per-option detail. Delete these fields from your request body,\nbecause the endpoint now rejects them.\n","properties":{"detail_transfer":{"$ref":"#/components/schemas/PublicPBRDetailTransfer"},"output_2d":{"$ref":"#/components/schemas/PublicPBROutput2D"}}},"PublicPBRDetailTransfer":{"type":"object","additionalProperties":false,"description":"Settings for detail transfer during PBR generation.\n\nThis object lost `magnitude_only`. The pipeline tunes that value for\neach texture pass, so 1 value you send could only flatten the tuning.\n","properties":{"enabled":{"type":["boolean","null"],"default":true,"description":"Whether detail transfer is enabled. An omitted field, and an\nexplicit `null`, both leave the stage on.\n"}}},"PublicPBROutput2D":{"type":"object","additionalProperties":false,"description":"Container for 2D output options. All fields are optional; omitted fields\nuse system defaults.\n\nThis object lost `video`. The pipeline holds no video stage and no\nturntable stage.\n","properties":{"orm":{"$ref":"#/components/schemas/PublicPBROutput2DORM"}}},"PublicPBROutput2DORM":{"type":"object","additionalProperties":false,"description":"Settings for an occlusion/roughness/metallic (ORM) combined 2D output\nmap.\n\n**No result carries the ORM map yet.** The 2 mesh endpoints accept the\noption today, and the pipeline stage that packs the map is still in\nbuild. The option never fails a run, and it changes no result until that\nstage ships.\n","properties":{"enabled":{"type":["boolean","null"],"default":false,"description":"Whether to generate the ORM map. An omitted field, and an explicit\n`null`, both leave the map off.\nNo result carries the map yet, as the object description states.\n"},"channel_order":{"type":"string","enum":["ORM","RMO","MRO"],"default":"ORM","description":"Channel order for the combined map. An omitted field packs the\nchannels in the `ORM` order.\n\nPossible enum values:\n- `ORM`: occlusion, roughness, metallic.\n- `RMO`: roughness, metallic, occlusion.\n- `MRO`: metallic, roughness, occlusion.\n"}}},"BatchResponse":{"type":"object","required":["batch_id","status","request_counts","created_at","items"],"description":"Body returned by `POST /batch/pbr/*` (202) and `GET /batch/{batch_id}`\n(200). On submission `items` is empty; poll the batch to populate it.\n`completed_at` is set once the batch reaches a terminal status; `failed_at`\nis set only when that terminal status is `FAILED`.\n","properties":{"batch_id":{"type":"string","description":"Unique identifier of the batch.\n"},"status":{"$ref":"#/components/schemas/BatchStatus"},"request_counts":{"$ref":"#/components/schemas/BatchCountsBody"},"created_at":{"$ref":"#/components/schemas/EpochMillis"},"completed_at":{"$ref":"#/components/schemas/NullableEpochMillis"},"failed_at":{"$ref":"#/components/schemas/NullableEpochMillis"},"items":{"type":"array","description":"Settled results for each item. Empty until at least one item has\nfinished.\n","items":{"$ref":"#/components/schemas/BatchItemBody"}}}},"BatchStatus":{"type":"string","description":"Aggregate status of a PBR batch.\n\nPossible enum values:\n- `QUEUED`: the batch is waiting to start.\n- `RUNNING`: at least one item is being processed.\n- `COMPLETED`: every item succeeded.\n- `PARTIALLY_COMPLETED`: the batch finished with a mix of successes and\n  failures.\n- `FAILED`: every item failed.\n","enum":["QUEUED","RUNNING","COMPLETED","PARTIALLY_COMPLETED","FAILED"]},"BatchCountsBody":{"type":"object","required":["total","completed","failed","pending"],"description":"Count of items in a batch, grouped by status.\n","properties":{"total":{"type":"integer","description":"Total number of items in the batch.\n"},"completed":{"type":"integer","description":"Number of items that have reached a terminal state, whether they\nsucceeded or failed.\n"},"failed":{"type":"integer","description":"Number of items that failed.\n"},"pending":{"type":"integer","description":"Number of items that are still queued or running.\n"}}},"EpochMillis":{"type":"integer","format":"int64","description":"Time represented as milliseconds since the Unix epoch.\n"},"NullableEpochMillis":{"type":["integer","null"],"format":"int64","description":"Time represented as milliseconds since the Unix epoch, or `null` when the\nfield has not been set.\n"},"BatchItemBody":{"type":"object","required":["execution_id","status","created_at"],"description":"One item's result within a batch. `asset_id` is the source asset you\nsubmitted, so a failed item is always traceable to its input.\n`pbr_material_assets` maps each `\"<slot>/<pass>\"` to its generated texture\nasset and a ready-to-use `download_url`, so you can pull every result\ndirectly from the poll response. `thumbnail_url` is a preview image,\nalways present on a succeeded mesh item, and best-effort on a succeeded\nimage item (an image item may finish without one). `error` is set only\non failed items.\n","properties":{"execution_id":{"type":"string","description":"Unique identifier of the execution for this item.\n"},"asset_id":{"type":"string","description":"ID of the source asset that was submitted for this item.\n"},"status":{"$ref":"#/components/schemas/ExecutionStatus"},"thumbnail_url":{"type":"string","format":"uri","description":"URL of a preview image. Always present on a succeeded mesh item;\nbest-effort on a succeeded image item.\n"},"thumbnail_url_expires_at":{"$ref":"#/components/schemas/EpochMillis"},"pbr_material_assets":{"type":"object","description":"Map from `\"<slot>/<pass>\"` to the generated texture asset. Only\npresent on succeeded items.\n","additionalProperties":{"$ref":"#/components/schemas/BatchMaterialAssetBody"}},"error":{"$ref":"#/components/schemas/ExecutionErrorBody"},"created_at":{"$ref":"#/components/schemas/EpochMillis"}}},"ExecutionStatus":{"type":"string","description":"Status of a single item within a batch.\n\nPossible enum values:\n- `QUEUED`: the item is waiting to start.\n- `RUNNING`: the item is being processed.\n- `SUCCEEDED`: the item completed successfully.\n- `PARTIAL_SUCCEEDED`: the item completed but some optional outputs are\n  missing.\n- `FAILED`: the item failed. See the `error` field for details.\n","enum":["QUEUED","RUNNING","SUCCEEDED","PARTIAL_SUCCEEDED","FAILED"]},"BatchMaterialAssetBody":{"type":"object","required":["asset_id"],"description":"One generated PBR result asset within a batch item. `download_url` is a\nready-to-use link that expires at `expires_at`.\n","properties":{"asset_id":{"type":"string","description":"ID of the generated asset.\n"},"download_url":{"type":"string","format":"uri","description":"Presigned URL for downloading the generated asset. Valid until\n`expires_at`.\n"},"expires_at":{"$ref":"#/components/schemas/EpochMillis"}}},"ExecutionErrorBody":{"type":"object","description":"Failure detail for a failed batch item. The `code` is a stable,\nmachine-readable class drawn from a closed enum so clients can branch on\nthe failure kind. The `message` carries human-readable detail. Only\n`VALIDATION_FAILED` is permanent; do not retry the same input. The other\ncodes are generally retryable.\n","required":["code","message"],"properties":{"code":{"type":"string","enum":["VALIDATION_FAILED","PIPELINE_ERROR","TIMEOUT","INTERNAL"],"description":"Machine-readable class of the failure.\n\nPossible enum values:\n- `VALIDATION_FAILED`: the input is unsuitable or invalid. This is a\n  permanent failure; retrying the same input will not succeed.\n- `PIPELINE_ERROR`: the PBR pipeline attempted the item but failed.\n  Generally retryable.\n- `TIMEOUT`: the item exceeded its time budget. Generally retryable.\n- `INTERNAL`: an internal orchestration fault. Generally retryable.\n"},"message":{"type":"string","description":"Human-readable explanation of the failure.\n"}}},"Error":{"type":"object","required":["error"],"description":"Canonical error envelope. The error payload is nested under the `error`\nkey.\n","properties":{"error":{"$ref":"#/components/schemas/ErrorBody"}}},"ErrorBody":{"type":"object","description":"The body of an error response. The `code` is a stable value clients can\nbranch on; the `message` is a human-readable explanation.\n","required":["code","message"],"properties":{"code":{"$ref":"#/components/schemas/ErrorCode"},"message":{"type":"string","description":"Human-readable description of the error.\n"},"details":{"type":["object","null"],"description":"Additional structured information about the error, or `null` if no\nextra details are available.\n","additionalProperties":true}}},"ErrorCode":{"type":"string","description":"Machine-readable error code. The enum enumerates every code that can be\nreturned by this API, including infrastructure-level 5xx codes, so\ngenerated clients can decode any `error.code` they receive.\n\nPossible enum values:\n- `INVALID_REQUEST`: the request body or a query parameter failed validation.\n- `MALFORMED_UUID`: a path parameter that should be a UUID is not one.\n- `UNAUTHORIZED`: the request could not be authenticated.\n- `API_KEY_MISSING`: no API key was supplied.\n- `API_KEY_INVALID`: the supplied API key does not match any known key.\n- `API_KEY_REVOKED`: the supplied API key has been revoked.\n- `PLAN_FEATURE_REQUIRED`: the account plan does not include a required feature.\n- `INSUFFICIENT_CREDITS`: the account does not have enough credits for this request.\n- `QUOTA_EXCEEDED`: a usage quota for the account has been exceeded.\n- `FILE_TOO_LARGE`: an uploaded or referenced file exceeds the allowed size.\n- `INVALID_CONTENT_TYPE`: a file's content type does not match its declared or expected type.\n- `UNSUPPORTED_ASSET_FORMAT`: a file's extension is not one of the supported asset formats.\n- `FORMAT_NOT_AVAILABLE`: the requested downloadable format does not exist for this asset.\n- `ASSET_NOT_FOUND`: the asset does not exist or does not belong to the account.\n- `ASSET_IN_USE`: the asset is referenced by an active execution and cannot be deleted.\n- `BATCH_TOO_LARGE`: the batch contains more items than the endpoint allows.\n- `CONCURRENT_EXECUTION_LIMIT_EXCEEDED`: the account has reached its limit on simultaneous submissions.\n- `PBR_FAILURE_CAP_EXCEEDED`: the account has too many recent failed PBR runs; new submissions are temporarily blocked.\n- `EXECUTION_NOT_FOUND`: the execution or batch does not exist or does not belong to the account.\n- `EXECUTION_IN_PROGRESS`: the request conflicts with an execution that is still running.\n- `RATE_LIMITED`: the API key's rate limit was exceeded.\n- `SERVICE_UNAVAILABLE`: a dependent service is temporarily unavailable; retry later.\n- `MAINTENANCE_MODE`: the API is temporarily unavailable for maintenance.\n- `INTERNAL_SERVER_ERROR`: an unexpected server error occurred.\n- `WORKFLOW_CREATION_FAILED`: the platform could not start the underlying workflow.\n- `WORKFLOW_API_ERROR`: the platform's workflow system returned an unexpected error.\n","enum":["INVALID_REQUEST","MALFORMED_UUID","UNAUTHORIZED","API_KEY_MISSING","API_KEY_INVALID","API_KEY_REVOKED","PLAN_FEATURE_REQUIRED","INSUFFICIENT_CREDITS","QUOTA_EXCEEDED","FILE_TOO_LARGE","INVALID_CONTENT_TYPE","UNSUPPORTED_ASSET_FORMAT","FORMAT_NOT_AVAILABLE","ASSET_NOT_FOUND","ASSET_IN_USE","BATCH_TOO_LARGE","CONCURRENT_EXECUTION_LIMIT_EXCEEDED","PBR_FAILURE_CAP_EXCEEDED","EXECUTION_NOT_FOUND","EXECUTION_IN_PROGRESS","RATE_LIMITED","SERVICE_UNAVAILABLE","MAINTENANCE_MODE","INTERNAL_SERVER_ERROR","WORKFLOW_CREATION_FAILED","WORKFLOW_API_ERROR"]},"PlanFeatureRequiredError":{"type":"object","required":["error"],"description":"The error envelope for a missing subscription feature.","properties":{"error":{"type":"object","required":["code","message","details"],"description":"The missing-feature error body.","properties":{"code":{"type":"string","const":"PLAN_FEATURE_REQUIRED","description":"Stable error code for a missing subscription feature."},"message":{"type":"string","description":"Human-readable description of the error."},"details":{"$ref":"#/components/schemas/PlanFeatureRequiredErrorDetails"}}}}},"PlanFeatureRequiredErrorDetails":{"type":"object","required":["feature","upgrade_plan_codes"],"description":"The missing feature and the active plans that provide it.","properties":{"feature":{"$ref":"#/components/schemas/SubscriptionFeature"},"upgrade_plan_codes":{"type":"array","description":"Active plans available for purchase that provide the missing\nfeature. The array uses plan class and opaque code order.\n","items":{"$ref":"#/components/schemas/SubscriptionPlanCode"}}}},"SubscriptionFeature":{"type":"string","description":"Product capability available to the account.\n\nPossible enum values:\n- `commercial_license`: commercial-use rights.\n- `api_pbr`: PBR generation through the Public Platform API.\n- `api_asset_download`: asset downloads through the Public Platform API.\n- `custom_polycount`: custom polygon counts for 3D generation.\n- `image_edit`: image editing.\n- `multiview`: multiview generation.\n","enum":["commercial_license","api_pbr","api_asset_download","custom_polycount","image_edit","multiview"]},"SubscriptionPlanCode":{"type":"string","pattern":"^plan_[A-Za-z0-9]{7,64}$","description":"Opaque and immutable code for a subscription plan. Use the plan\ncatalogue for its current display name. The code must start with\n`plan_`, followed by 7 to 64 ASCII letters or digits.\n"}},"responses":{"Unauthorized":{"description":"The API key is missing, invalid, or revoked. Possible error codes:\n`API_KEY_MISSING`, `API_KEY_INVALID`, `API_KEY_REVOKED`, or `UNAUTHORIZED`.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"PlanFeatureRequired":{"description":"The account does not have the plan feature required by this operation\n(`PLAN_FEATURE_REQUIRED`).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlanFeatureRequiredError"}}}},"RateLimitedOrCapped":{"description":"The request could not be accepted because of a rate or concurrency limit.\nPossible error codes:\n\n- `RATE_LIMITED`: the API-key rate limit was exceeded.\n- `CONCURRENT_EXECUTION_LIMIT_EXCEEDED`: a single-mesh or binary submit\n  exceeded the concurrency limit.\n- `PBR_FAILURE_CAP_EXCEEDED`: too many consecutive failures; check the\n  input before retrying.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/batch/pbr/mesh":{"post":{"operationId":"createMeshPBRBatch","tags":["pbr"],"summary":"Generate PBR materials from 3D meshes.","description":"Submits one or more ready mesh assets for 3D mesh to PBR generation. The same\n`options` are applied to every mesh in the batch. Each asset must be a\n`ready` mesh uploaded via `POST /batch/uploads`.\n\nThe request returns immediately with a `batch_id` (`202`). Poll\n`GET /batch/{batch_id}` for the batch status and, as each item finishes,\nits generated material maps and download URLs. Credits are reserved when\nyou submit and refunded automatically for any item that fails, so you\nare only charged for successful results.\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePBRMeshBatchRequest"}}}},"responses":{"202":{"description":"Batch created and queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchResponse"}}}},"400":{"description":"The request is invalid because the `asset_ids` list is empty or too\nlong, an asset was not found or is not owned by the authenticated account, an asset\nis not a mesh, or an asset is not `ready` (`INVALID_REQUEST`).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/PlanFeatureRequired"},"429":{"$ref":"#/components/responses/RateLimitedOrCapped"}}}}}}
```

## Generate PBR materials from images.

> Submits one or more ready image assets for image to PBR generation. The\
> image counterpart of \`POST /batch/pbr/mesh\`. It takes the same options,\
> except \`output\_2d\`, which needs a stage the image pipeline skips. An\
> image result carries no USDZ, for the same reason.\
> \
> The request returns immediately with a \`batch\_id\` (\`202\`). Poll\
> \`GET /batch/{batch\_id}\` for the batch status and each image's generated\
> material maps and download URLs. Credits are reserved when you submit\
> and refunded automatically for any item that fails.<br>

```json
{"openapi":"3.1.0","info":{"title":"Marso Studio API","version":"0.0.1"},"tags":[{"name":"pbr","description":"Batches group one or more PBR generation jobs together. Use these endpoints\nto submit 3D mesh to PBR or image to PBR batches, poll a batch for progress,\nand list recent batches.\n"}],"servers":[{"url":"https://api.marso.ai/api/public/v1","description":"Production server."}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"API key minted from the Marso Studio dashboard. The value has the form\n`mxr_live_<entropy>` and is sent as a Bearer token in the `Authorization`\nheader.\n"}},"schemas":{"CreatePBRImageBatchRequest":{"type":"object","required":["asset_ids"],"description":"Request body for `POST /batch/pbr/image`. It has the same shape as\n`CreatePBRMeshBatchRequest`, except for the options. The image path\ntakes no `output_2d`, because that option needs a stage the image\npipeline skips.\n","properties":{"asset_ids":{"type":"array","minItems":1,"maxItems":200,"items":{"type":"string","format":"uuid"},"description":"IDs of the `ready` image assets to process. These assets must have\nbeen uploaded via `POST /batch/uploads` and must currently be in the\n`ready` state.\n"},"options":{"$ref":"#/components/schemas/PublicPBRImageOptions"}}},"PublicPBRImageOptions":{"type":"object","additionalProperties":false,"description":"Tuning options for an image PBR run. Every field is optional, and an\nomitted field uses the system default.\n\nThe image pipeline runs inference only. It reaches neither the 3D\ncontainer stage nor the packed 2D map stage, so `output_2d` appears on\nthe mesh endpoints only, and no image result carries a USDZ.\n`detail_transfer` is the whole surface here.\n\nThis object rejects a field it does not declare. Issue #2175 removed\n`pbr_mode`, `blend_mode`, `coverage`, `texture`,\n`detail_transfer.magnitude_only` and `output_2d.video`. A request that\nstill carries 1 of them gets a 400, and the message names the field.\nDelete them from your request body. The PBR options reference states\nwhat each removal changed.\n","properties":{"detail_transfer":{"$ref":"#/components/schemas/PublicPBRDetailTransfer"}}},"PublicPBRDetailTransfer":{"type":"object","additionalProperties":false,"description":"Settings for detail transfer during PBR generation.\n\nThis object lost `magnitude_only`. The pipeline tunes that value for\neach texture pass, so 1 value you send could only flatten the tuning.\n","properties":{"enabled":{"type":["boolean","null"],"default":true,"description":"Whether detail transfer is enabled. An omitted field, and an\nexplicit `null`, both leave the stage on.\n"}}},"BatchResponse":{"type":"object","required":["batch_id","status","request_counts","created_at","items"],"description":"Body returned by `POST /batch/pbr/*` (202) and `GET /batch/{batch_id}`\n(200). On submission `items` is empty; poll the batch to populate it.\n`completed_at` is set once the batch reaches a terminal status; `failed_at`\nis set only when that terminal status is `FAILED`.\n","properties":{"batch_id":{"type":"string","description":"Unique identifier of the batch.\n"},"status":{"$ref":"#/components/schemas/BatchStatus"},"request_counts":{"$ref":"#/components/schemas/BatchCountsBody"},"created_at":{"$ref":"#/components/schemas/EpochMillis"},"completed_at":{"$ref":"#/components/schemas/NullableEpochMillis"},"failed_at":{"$ref":"#/components/schemas/NullableEpochMillis"},"items":{"type":"array","description":"Settled results for each item. Empty until at least one item has\nfinished.\n","items":{"$ref":"#/components/schemas/BatchItemBody"}}}},"BatchStatus":{"type":"string","description":"Aggregate status of a PBR batch.\n\nPossible enum values:\n- `QUEUED`: the batch is waiting to start.\n- `RUNNING`: at least one item is being processed.\n- `COMPLETED`: every item succeeded.\n- `PARTIALLY_COMPLETED`: the batch finished with a mix of successes and\n  failures.\n- `FAILED`: every item failed.\n","enum":["QUEUED","RUNNING","COMPLETED","PARTIALLY_COMPLETED","FAILED"]},"BatchCountsBody":{"type":"object","required":["total","completed","failed","pending"],"description":"Count of items in a batch, grouped by status.\n","properties":{"total":{"type":"integer","description":"Total number of items in the batch.\n"},"completed":{"type":"integer","description":"Number of items that have reached a terminal state, whether they\nsucceeded or failed.\n"},"failed":{"type":"integer","description":"Number of items that failed.\n"},"pending":{"type":"integer","description":"Number of items that are still queued or running.\n"}}},"EpochMillis":{"type":"integer","format":"int64","description":"Time represented as milliseconds since the Unix epoch.\n"},"NullableEpochMillis":{"type":["integer","null"],"format":"int64","description":"Time represented as milliseconds since the Unix epoch, or `null` when the\nfield has not been set.\n"},"BatchItemBody":{"type":"object","required":["execution_id","status","created_at"],"description":"One item's result within a batch. `asset_id` is the source asset you\nsubmitted, so a failed item is always traceable to its input.\n`pbr_material_assets` maps each `\"<slot>/<pass>\"` to its generated texture\nasset and a ready-to-use `download_url`, so you can pull every result\ndirectly from the poll response. `thumbnail_url` is a preview image,\nalways present on a succeeded mesh item, and best-effort on a succeeded\nimage item (an image item may finish without one). `error` is set only\non failed items.\n","properties":{"execution_id":{"type":"string","description":"Unique identifier of the execution for this item.\n"},"asset_id":{"type":"string","description":"ID of the source asset that was submitted for this item.\n"},"status":{"$ref":"#/components/schemas/ExecutionStatus"},"thumbnail_url":{"type":"string","format":"uri","description":"URL of a preview image. Always present on a succeeded mesh item;\nbest-effort on a succeeded image item.\n"},"thumbnail_url_expires_at":{"$ref":"#/components/schemas/EpochMillis"},"pbr_material_assets":{"type":"object","description":"Map from `\"<slot>/<pass>\"` to the generated texture asset. Only\npresent on succeeded items.\n","additionalProperties":{"$ref":"#/components/schemas/BatchMaterialAssetBody"}},"error":{"$ref":"#/components/schemas/ExecutionErrorBody"},"created_at":{"$ref":"#/components/schemas/EpochMillis"}}},"ExecutionStatus":{"type":"string","description":"Status of a single item within a batch.\n\nPossible enum values:\n- `QUEUED`: the item is waiting to start.\n- `RUNNING`: the item is being processed.\n- `SUCCEEDED`: the item completed successfully.\n- `PARTIAL_SUCCEEDED`: the item completed but some optional outputs are\n  missing.\n- `FAILED`: the item failed. See the `error` field for details.\n","enum":["QUEUED","RUNNING","SUCCEEDED","PARTIAL_SUCCEEDED","FAILED"]},"BatchMaterialAssetBody":{"type":"object","required":["asset_id"],"description":"One generated PBR result asset within a batch item. `download_url` is a\nready-to-use link that expires at `expires_at`.\n","properties":{"asset_id":{"type":"string","description":"ID of the generated asset.\n"},"download_url":{"type":"string","format":"uri","description":"Presigned URL for downloading the generated asset. Valid until\n`expires_at`.\n"},"expires_at":{"$ref":"#/components/schemas/EpochMillis"}}},"ExecutionErrorBody":{"type":"object","description":"Failure detail for a failed batch item. The `code` is a stable,\nmachine-readable class drawn from a closed enum so clients can branch on\nthe failure kind. The `message` carries human-readable detail. Only\n`VALIDATION_FAILED` is permanent; do not retry the same input. The other\ncodes are generally retryable.\n","required":["code","message"],"properties":{"code":{"type":"string","enum":["VALIDATION_FAILED","PIPELINE_ERROR","TIMEOUT","INTERNAL"],"description":"Machine-readable class of the failure.\n\nPossible enum values:\n- `VALIDATION_FAILED`: the input is unsuitable or invalid. This is a\n  permanent failure; retrying the same input will not succeed.\n- `PIPELINE_ERROR`: the PBR pipeline attempted the item but failed.\n  Generally retryable.\n- `TIMEOUT`: the item exceeded its time budget. Generally retryable.\n- `INTERNAL`: an internal orchestration fault. Generally retryable.\n"},"message":{"type":"string","description":"Human-readable explanation of the failure.\n"}}},"Error":{"type":"object","required":["error"],"description":"Canonical error envelope. The error payload is nested under the `error`\nkey.\n","properties":{"error":{"$ref":"#/components/schemas/ErrorBody"}}},"ErrorBody":{"type":"object","description":"The body of an error response. The `code` is a stable value clients can\nbranch on; the `message` is a human-readable explanation.\n","required":["code","message"],"properties":{"code":{"$ref":"#/components/schemas/ErrorCode"},"message":{"type":"string","description":"Human-readable description of the error.\n"},"details":{"type":["object","null"],"description":"Additional structured information about the error, or `null` if no\nextra details are available.\n","additionalProperties":true}}},"ErrorCode":{"type":"string","description":"Machine-readable error code. The enum enumerates every code that can be\nreturned by this API, including infrastructure-level 5xx codes, so\ngenerated clients can decode any `error.code` they receive.\n\nPossible enum values:\n- `INVALID_REQUEST`: the request body or a query parameter failed validation.\n- `MALFORMED_UUID`: a path parameter that should be a UUID is not one.\n- `UNAUTHORIZED`: the request could not be authenticated.\n- `API_KEY_MISSING`: no API key was supplied.\n- `API_KEY_INVALID`: the supplied API key does not match any known key.\n- `API_KEY_REVOKED`: the supplied API key has been revoked.\n- `PLAN_FEATURE_REQUIRED`: the account plan does not include a required feature.\n- `INSUFFICIENT_CREDITS`: the account does not have enough credits for this request.\n- `QUOTA_EXCEEDED`: a usage quota for the account has been exceeded.\n- `FILE_TOO_LARGE`: an uploaded or referenced file exceeds the allowed size.\n- `INVALID_CONTENT_TYPE`: a file's content type does not match its declared or expected type.\n- `UNSUPPORTED_ASSET_FORMAT`: a file's extension is not one of the supported asset formats.\n- `FORMAT_NOT_AVAILABLE`: the requested downloadable format does not exist for this asset.\n- `ASSET_NOT_FOUND`: the asset does not exist or does not belong to the account.\n- `ASSET_IN_USE`: the asset is referenced by an active execution and cannot be deleted.\n- `BATCH_TOO_LARGE`: the batch contains more items than the endpoint allows.\n- `CONCURRENT_EXECUTION_LIMIT_EXCEEDED`: the account has reached its limit on simultaneous submissions.\n- `PBR_FAILURE_CAP_EXCEEDED`: the account has too many recent failed PBR runs; new submissions are temporarily blocked.\n- `EXECUTION_NOT_FOUND`: the execution or batch does not exist or does not belong to the account.\n- `EXECUTION_IN_PROGRESS`: the request conflicts with an execution that is still running.\n- `RATE_LIMITED`: the API key's rate limit was exceeded.\n- `SERVICE_UNAVAILABLE`: a dependent service is temporarily unavailable; retry later.\n- `MAINTENANCE_MODE`: the API is temporarily unavailable for maintenance.\n- `INTERNAL_SERVER_ERROR`: an unexpected server error occurred.\n- `WORKFLOW_CREATION_FAILED`: the platform could not start the underlying workflow.\n- `WORKFLOW_API_ERROR`: the platform's workflow system returned an unexpected error.\n","enum":["INVALID_REQUEST","MALFORMED_UUID","UNAUTHORIZED","API_KEY_MISSING","API_KEY_INVALID","API_KEY_REVOKED","PLAN_FEATURE_REQUIRED","INSUFFICIENT_CREDITS","QUOTA_EXCEEDED","FILE_TOO_LARGE","INVALID_CONTENT_TYPE","UNSUPPORTED_ASSET_FORMAT","FORMAT_NOT_AVAILABLE","ASSET_NOT_FOUND","ASSET_IN_USE","BATCH_TOO_LARGE","CONCURRENT_EXECUTION_LIMIT_EXCEEDED","PBR_FAILURE_CAP_EXCEEDED","EXECUTION_NOT_FOUND","EXECUTION_IN_PROGRESS","RATE_LIMITED","SERVICE_UNAVAILABLE","MAINTENANCE_MODE","INTERNAL_SERVER_ERROR","WORKFLOW_CREATION_FAILED","WORKFLOW_API_ERROR"]},"PlanFeatureRequiredError":{"type":"object","required":["error"],"description":"The error envelope for a missing subscription feature.","properties":{"error":{"type":"object","required":["code","message","details"],"description":"The missing-feature error body.","properties":{"code":{"type":"string","const":"PLAN_FEATURE_REQUIRED","description":"Stable error code for a missing subscription feature."},"message":{"type":"string","description":"Human-readable description of the error."},"details":{"$ref":"#/components/schemas/PlanFeatureRequiredErrorDetails"}}}}},"PlanFeatureRequiredErrorDetails":{"type":"object","required":["feature","upgrade_plan_codes"],"description":"The missing feature and the active plans that provide it.","properties":{"feature":{"$ref":"#/components/schemas/SubscriptionFeature"},"upgrade_plan_codes":{"type":"array","description":"Active plans available for purchase that provide the missing\nfeature. The array uses plan class and opaque code order.\n","items":{"$ref":"#/components/schemas/SubscriptionPlanCode"}}}},"SubscriptionFeature":{"type":"string","description":"Product capability available to the account.\n\nPossible enum values:\n- `commercial_license`: commercial-use rights.\n- `api_pbr`: PBR generation through the Public Platform API.\n- `api_asset_download`: asset downloads through the Public Platform API.\n- `custom_polycount`: custom polygon counts for 3D generation.\n- `image_edit`: image editing.\n- `multiview`: multiview generation.\n","enum":["commercial_license","api_pbr","api_asset_download","custom_polycount","image_edit","multiview"]},"SubscriptionPlanCode":{"type":"string","pattern":"^plan_[A-Za-z0-9]{7,64}$","description":"Opaque and immutable code for a subscription plan. Use the plan\ncatalogue for its current display name. The code must start with\n`plan_`, followed by 7 to 64 ASCII letters or digits.\n"}},"responses":{"Unauthorized":{"description":"The API key is missing, invalid, or revoked. Possible error codes:\n`API_KEY_MISSING`, `API_KEY_INVALID`, `API_KEY_REVOKED`, or `UNAUTHORIZED`.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"PlanFeatureRequired":{"description":"The account does not have the plan feature required by this operation\n(`PLAN_FEATURE_REQUIRED`).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlanFeatureRequiredError"}}}},"RateLimitedOrCapped":{"description":"The request could not be accepted because of a rate or concurrency limit.\nPossible error codes:\n\n- `RATE_LIMITED`: the API-key rate limit was exceeded.\n- `CONCURRENT_EXECUTION_LIMIT_EXCEEDED`: a single-mesh or binary submit\n  exceeded the concurrency limit.\n- `PBR_FAILURE_CAP_EXCEEDED`: too many consecutive failures; check the\n  input before retrying.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/batch/pbr/image":{"post":{"operationId":"createImagePBRBatch","tags":["pbr"],"summary":"Generate PBR materials from images.","description":"Submits one or more ready image assets for image to PBR generation. The\nimage counterpart of `POST /batch/pbr/mesh`. It takes the same options,\nexcept `output_2d`, which needs a stage the image pipeline skips. An\nimage result carries no USDZ, for the same reason.\n\nThe request returns immediately with a `batch_id` (`202`). Poll\n`GET /batch/{batch_id}` for the batch status and each image's generated\nmaterial maps and download URLs. Credits are reserved when you submit\nand refunded automatically for any item that fails.\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePBRImageBatchRequest"}}}},"responses":{"202":{"description":"Batch created and queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchResponse"}}}},"400":{"description":"The request is invalid because the `asset_ids` list is empty or too\nlong, an asset was not found or is not owned by the authenticated account, an asset\nis not an image, or an asset is not `ready` (`INVALID_REQUEST`).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/PlanFeatureRequired"},"429":{"$ref":"#/components/responses/RateLimitedOrCapped"}}}}}}
```

## List your batches.

> Returns your PBR batches, newest first, as paginated summaries. Each\
> summary contains the batch ID, status, per-status counts, and timestamps.\
> Per-item results are not included; use \`GET /batch/{batch\_id}\` to fetch\
> the full results for a batch.<br>

```json
{"openapi":"3.1.0","info":{"title":"Marso Studio API","version":"0.0.1"},"tags":[{"name":"pbr","description":"Batches group one or more PBR generation jobs together. Use these endpoints\nto submit 3D mesh to PBR or image to PBR batches, poll a batch for progress,\nand list recent batches.\n"}],"servers":[{"url":"https://api.marso.ai/api/public/v1","description":"Production server."}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"API key minted from the Marso Studio dashboard. The value has the form\n`mxr_live_<entropy>` and is sent as a Bearer token in the `Authorization`\nheader.\n"}},"parameters":{"Limit":{"name":"limit","in":"query","required":false,"description":"Page size. Defaults to 50 and is clamped to a maximum of 200. Non-positive\nor non-numeric values fall back to the default.\n","schema":{"type":"integer","minimum":1,"default":50}},"Cursor":{"name":"cursor","in":"query","required":false,"description":"Opaque pagination cursor returned by the previous page as `next_cursor`.\nOmit on the first request.\n","schema":{"type":"string"}}},"schemas":{"BatchListResponse":{"type":"object","required":["batches"],"description":"Response from `GET /batch`. A paginated list of batch summaries.\n","properties":{"batches":{"type":"array","description":"Batch summaries, newest first.\n","items":{"$ref":"#/components/schemas/BatchSummaryBody"}},"next_cursor":{"type":"string","description":"Opaque cursor for the next page. Absent or empty when the result set\nis exhausted.\n"}}},"BatchSummaryBody":{"type":"object","required":["batch_id","status","request_counts","created_at"],"description":"One row in `GET /batch`. Contains a batch's summary without per-item\nresults.\n","properties":{"batch_id":{"type":"string","description":"Unique identifier of the batch.\n"},"status":{"$ref":"#/components/schemas/BatchStatus"},"request_counts":{"$ref":"#/components/schemas/BatchCountsBody"},"created_at":{"$ref":"#/components/schemas/EpochMillis"},"completed_at":{"$ref":"#/components/schemas/NullableEpochMillis"},"failed_at":{"$ref":"#/components/schemas/NullableEpochMillis"}}},"BatchStatus":{"type":"string","description":"Aggregate status of a PBR batch.\n\nPossible enum values:\n- `QUEUED`: the batch is waiting to start.\n- `RUNNING`: at least one item is being processed.\n- `COMPLETED`: every item succeeded.\n- `PARTIALLY_COMPLETED`: the batch finished with a mix of successes and\n  failures.\n- `FAILED`: every item failed.\n","enum":["QUEUED","RUNNING","COMPLETED","PARTIALLY_COMPLETED","FAILED"]},"BatchCountsBody":{"type":"object","required":["total","completed","failed","pending"],"description":"Count of items in a batch, grouped by status.\n","properties":{"total":{"type":"integer","description":"Total number of items in the batch.\n"},"completed":{"type":"integer","description":"Number of items that have reached a terminal state, whether they\nsucceeded or failed.\n"},"failed":{"type":"integer","description":"Number of items that failed.\n"},"pending":{"type":"integer","description":"Number of items that are still queued or running.\n"}}},"EpochMillis":{"type":"integer","format":"int64","description":"Time represented as milliseconds since the Unix epoch.\n"},"NullableEpochMillis":{"type":["integer","null"],"format":"int64","description":"Time represented as milliseconds since the Unix epoch, or `null` when the\nfield has not been set.\n"},"Error":{"type":"object","required":["error"],"description":"Canonical error envelope. The error payload is nested under the `error`\nkey.\n","properties":{"error":{"$ref":"#/components/schemas/ErrorBody"}}},"ErrorBody":{"type":"object","description":"The body of an error response. The `code` is a stable value clients can\nbranch on; the `message` is a human-readable explanation.\n","required":["code","message"],"properties":{"code":{"$ref":"#/components/schemas/ErrorCode"},"message":{"type":"string","description":"Human-readable description of the error.\n"},"details":{"type":["object","null"],"description":"Additional structured information about the error, or `null` if no\nextra details are available.\n","additionalProperties":true}}},"ErrorCode":{"type":"string","description":"Machine-readable error code. The enum enumerates every code that can be\nreturned by this API, including infrastructure-level 5xx codes, so\ngenerated clients can decode any `error.code` they receive.\n\nPossible enum values:\n- `INVALID_REQUEST`: the request body or a query parameter failed validation.\n- `MALFORMED_UUID`: a path parameter that should be a UUID is not one.\n- `UNAUTHORIZED`: the request could not be authenticated.\n- `API_KEY_MISSING`: no API key was supplied.\n- `API_KEY_INVALID`: the supplied API key does not match any known key.\n- `API_KEY_REVOKED`: the supplied API key has been revoked.\n- `PLAN_FEATURE_REQUIRED`: the account plan does not include a required feature.\n- `INSUFFICIENT_CREDITS`: the account does not have enough credits for this request.\n- `QUOTA_EXCEEDED`: a usage quota for the account has been exceeded.\n- `FILE_TOO_LARGE`: an uploaded or referenced file exceeds the allowed size.\n- `INVALID_CONTENT_TYPE`: a file's content type does not match its declared or expected type.\n- `UNSUPPORTED_ASSET_FORMAT`: a file's extension is not one of the supported asset formats.\n- `FORMAT_NOT_AVAILABLE`: the requested downloadable format does not exist for this asset.\n- `ASSET_NOT_FOUND`: the asset does not exist or does not belong to the account.\n- `ASSET_IN_USE`: the asset is referenced by an active execution and cannot be deleted.\n- `BATCH_TOO_LARGE`: the batch contains more items than the endpoint allows.\n- `CONCURRENT_EXECUTION_LIMIT_EXCEEDED`: the account has reached its limit on simultaneous submissions.\n- `PBR_FAILURE_CAP_EXCEEDED`: the account has too many recent failed PBR runs; new submissions are temporarily blocked.\n- `EXECUTION_NOT_FOUND`: the execution or batch does not exist or does not belong to the account.\n- `EXECUTION_IN_PROGRESS`: the request conflicts with an execution that is still running.\n- `RATE_LIMITED`: the API key's rate limit was exceeded.\n- `SERVICE_UNAVAILABLE`: a dependent service is temporarily unavailable; retry later.\n- `MAINTENANCE_MODE`: the API is temporarily unavailable for maintenance.\n- `INTERNAL_SERVER_ERROR`: an unexpected server error occurred.\n- `WORKFLOW_CREATION_FAILED`: the platform could not start the underlying workflow.\n- `WORKFLOW_API_ERROR`: the platform's workflow system returned an unexpected error.\n","enum":["INVALID_REQUEST","MALFORMED_UUID","UNAUTHORIZED","API_KEY_MISSING","API_KEY_INVALID","API_KEY_REVOKED","PLAN_FEATURE_REQUIRED","INSUFFICIENT_CREDITS","QUOTA_EXCEEDED","FILE_TOO_LARGE","INVALID_CONTENT_TYPE","UNSUPPORTED_ASSET_FORMAT","FORMAT_NOT_AVAILABLE","ASSET_NOT_FOUND","ASSET_IN_USE","BATCH_TOO_LARGE","CONCURRENT_EXECUTION_LIMIT_EXCEEDED","PBR_FAILURE_CAP_EXCEEDED","EXECUTION_NOT_FOUND","EXECUTION_IN_PROGRESS","RATE_LIMITED","SERVICE_UNAVAILABLE","MAINTENANCE_MODE","INTERNAL_SERVER_ERROR","WORKFLOW_CREATION_FAILED","WORKFLOW_API_ERROR"]}},"responses":{"Unauthorized":{"description":"The API key is missing, invalid, or revoked. Possible error codes:\n`API_KEY_MISSING`, `API_KEY_INVALID`, `API_KEY_REVOKED`, or `UNAUTHORIZED`.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Rate limit exceeded (`RATE_LIMITED`). The response includes a `Retry-After`\nheader with the number of seconds to wait before retrying, plus the\n`X-RateLimit-*` headers. Those headers are also present on successful (2xx)\nresponses so a client can pace itself.\n","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"description":"Request burst capacity for the API key.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current burst window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix epoch seconds when the burst capacity is fully restored.\n","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/batch":{"get":{"operationId":"listBatches","tags":["pbr"],"summary":"List your batches.","description":"Returns your PBR batches, newest first, as paginated summaries. Each\nsummary contains the batch ID, status, per-status counts, and timestamps.\nPer-item results are not included; use `GET /batch/{batch_id}` to fetch\nthe full results for a batch.\n","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"A page of batch summaries.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchListResponse"}}}},"400":{"description":"A query parameter is invalid (`INVALID_REQUEST`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"}}}}}}
```

## Retrieve a batch.

> Returns a batch's status, per-item counts, and the settled results for\
> each item. As items finish, the response includes their generated material\
> maps with ready-to-use download URLs, or a typed error for failed items.\
> This is the endpoint you poll after submitting a PBR batch. \`items\` is\
> empty until at least one item has reached a terminal state.<br>

```json
{"openapi":"3.1.0","info":{"title":"Marso Studio API","version":"0.0.1"},"tags":[{"name":"pbr","description":"Batches group one or more PBR generation jobs together. Use these endpoints\nto submit 3D mesh to PBR or image to PBR batches, poll a batch for progress,\nand list recent batches.\n"}],"servers":[{"url":"https://api.marso.ai/api/public/v1","description":"Production server."}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"API key minted from the Marso Studio dashboard. The value has the form\n`mxr_live_<entropy>` and is sent as a Bearer token in the `Authorization`\nheader.\n"}},"parameters":{"BatchId":{"name":"batch_id","in":"path","required":true,"description":"Unique identifier of the batch.","schema":{"type":"string","format":"uuid"}}},"schemas":{"BatchResponse":{"type":"object","required":["batch_id","status","request_counts","created_at","items"],"description":"Body returned by `POST /batch/pbr/*` (202) and `GET /batch/{batch_id}`\n(200). On submission `items` is empty; poll the batch to populate it.\n`completed_at` is set once the batch reaches a terminal status; `failed_at`\nis set only when that terminal status is `FAILED`.\n","properties":{"batch_id":{"type":"string","description":"Unique identifier of the batch.\n"},"status":{"$ref":"#/components/schemas/BatchStatus"},"request_counts":{"$ref":"#/components/schemas/BatchCountsBody"},"created_at":{"$ref":"#/components/schemas/EpochMillis"},"completed_at":{"$ref":"#/components/schemas/NullableEpochMillis"},"failed_at":{"$ref":"#/components/schemas/NullableEpochMillis"},"items":{"type":"array","description":"Settled results for each item. Empty until at least one item has\nfinished.\n","items":{"$ref":"#/components/schemas/BatchItemBody"}}}},"BatchStatus":{"type":"string","description":"Aggregate status of a PBR batch.\n\nPossible enum values:\n- `QUEUED`: the batch is waiting to start.\n- `RUNNING`: at least one item is being processed.\n- `COMPLETED`: every item succeeded.\n- `PARTIALLY_COMPLETED`: the batch finished with a mix of successes and\n  failures.\n- `FAILED`: every item failed.\n","enum":["QUEUED","RUNNING","COMPLETED","PARTIALLY_COMPLETED","FAILED"]},"BatchCountsBody":{"type":"object","required":["total","completed","failed","pending"],"description":"Count of items in a batch, grouped by status.\n","properties":{"total":{"type":"integer","description":"Total number of items in the batch.\n"},"completed":{"type":"integer","description":"Number of items that have reached a terminal state, whether they\nsucceeded or failed.\n"},"failed":{"type":"integer","description":"Number of items that failed.\n"},"pending":{"type":"integer","description":"Number of items that are still queued or running.\n"}}},"EpochMillis":{"type":"integer","format":"int64","description":"Time represented as milliseconds since the Unix epoch.\n"},"NullableEpochMillis":{"type":["integer","null"],"format":"int64","description":"Time represented as milliseconds since the Unix epoch, or `null` when the\nfield has not been set.\n"},"BatchItemBody":{"type":"object","required":["execution_id","status","created_at"],"description":"One item's result within a batch. `asset_id` is the source asset you\nsubmitted, so a failed item is always traceable to its input.\n`pbr_material_assets` maps each `\"<slot>/<pass>\"` to its generated texture\nasset and a ready-to-use `download_url`, so you can pull every result\ndirectly from the poll response. `thumbnail_url` is a preview image,\nalways present on a succeeded mesh item, and best-effort on a succeeded\nimage item (an image item may finish without one). `error` is set only\non failed items.\n","properties":{"execution_id":{"type":"string","description":"Unique identifier of the execution for this item.\n"},"asset_id":{"type":"string","description":"ID of the source asset that was submitted for this item.\n"},"status":{"$ref":"#/components/schemas/ExecutionStatus"},"thumbnail_url":{"type":"string","format":"uri","description":"URL of a preview image. Always present on a succeeded mesh item;\nbest-effort on a succeeded image item.\n"},"thumbnail_url_expires_at":{"$ref":"#/components/schemas/EpochMillis"},"pbr_material_assets":{"type":"object","description":"Map from `\"<slot>/<pass>\"` to the generated texture asset. Only\npresent on succeeded items.\n","additionalProperties":{"$ref":"#/components/schemas/BatchMaterialAssetBody"}},"error":{"$ref":"#/components/schemas/ExecutionErrorBody"},"created_at":{"$ref":"#/components/schemas/EpochMillis"}}},"ExecutionStatus":{"type":"string","description":"Status of a single item within a batch.\n\nPossible enum values:\n- `QUEUED`: the item is waiting to start.\n- `RUNNING`: the item is being processed.\n- `SUCCEEDED`: the item completed successfully.\n- `PARTIAL_SUCCEEDED`: the item completed but some optional outputs are\n  missing.\n- `FAILED`: the item failed. See the `error` field for details.\n","enum":["QUEUED","RUNNING","SUCCEEDED","PARTIAL_SUCCEEDED","FAILED"]},"BatchMaterialAssetBody":{"type":"object","required":["asset_id"],"description":"One generated PBR result asset within a batch item. `download_url` is a\nready-to-use link that expires at `expires_at`.\n","properties":{"asset_id":{"type":"string","description":"ID of the generated asset.\n"},"download_url":{"type":"string","format":"uri","description":"Presigned URL for downloading the generated asset. Valid until\n`expires_at`.\n"},"expires_at":{"$ref":"#/components/schemas/EpochMillis"}}},"ExecutionErrorBody":{"type":"object","description":"Failure detail for a failed batch item. The `code` is a stable,\nmachine-readable class drawn from a closed enum so clients can branch on\nthe failure kind. The `message` carries human-readable detail. Only\n`VALIDATION_FAILED` is permanent; do not retry the same input. The other\ncodes are generally retryable.\n","required":["code","message"],"properties":{"code":{"type":"string","enum":["VALIDATION_FAILED","PIPELINE_ERROR","TIMEOUT","INTERNAL"],"description":"Machine-readable class of the failure.\n\nPossible enum values:\n- `VALIDATION_FAILED`: the input is unsuitable or invalid. This is a\n  permanent failure; retrying the same input will not succeed.\n- `PIPELINE_ERROR`: the PBR pipeline attempted the item but failed.\n  Generally retryable.\n- `TIMEOUT`: the item exceeded its time budget. Generally retryable.\n- `INTERNAL`: an internal orchestration fault. Generally retryable.\n"},"message":{"type":"string","description":"Human-readable explanation of the failure.\n"}}},"Error":{"type":"object","required":["error"],"description":"Canonical error envelope. The error payload is nested under the `error`\nkey.\n","properties":{"error":{"$ref":"#/components/schemas/ErrorBody"}}},"ErrorBody":{"type":"object","description":"The body of an error response. The `code` is a stable value clients can\nbranch on; the `message` is a human-readable explanation.\n","required":["code","message"],"properties":{"code":{"$ref":"#/components/schemas/ErrorCode"},"message":{"type":"string","description":"Human-readable description of the error.\n"},"details":{"type":["object","null"],"description":"Additional structured information about the error, or `null` if no\nextra details are available.\n","additionalProperties":true}}},"ErrorCode":{"type":"string","description":"Machine-readable error code. The enum enumerates every code that can be\nreturned by this API, including infrastructure-level 5xx codes, so\ngenerated clients can decode any `error.code` they receive.\n\nPossible enum values:\n- `INVALID_REQUEST`: the request body or a query parameter failed validation.\n- `MALFORMED_UUID`: a path parameter that should be a UUID is not one.\n- `UNAUTHORIZED`: the request could not be authenticated.\n- `API_KEY_MISSING`: no API key was supplied.\n- `API_KEY_INVALID`: the supplied API key does not match any known key.\n- `API_KEY_REVOKED`: the supplied API key has been revoked.\n- `PLAN_FEATURE_REQUIRED`: the account plan does not include a required feature.\n- `INSUFFICIENT_CREDITS`: the account does not have enough credits for this request.\n- `QUOTA_EXCEEDED`: a usage quota for the account has been exceeded.\n- `FILE_TOO_LARGE`: an uploaded or referenced file exceeds the allowed size.\n- `INVALID_CONTENT_TYPE`: a file's content type does not match its declared or expected type.\n- `UNSUPPORTED_ASSET_FORMAT`: a file's extension is not one of the supported asset formats.\n- `FORMAT_NOT_AVAILABLE`: the requested downloadable format does not exist for this asset.\n- `ASSET_NOT_FOUND`: the asset does not exist or does not belong to the account.\n- `ASSET_IN_USE`: the asset is referenced by an active execution and cannot be deleted.\n- `BATCH_TOO_LARGE`: the batch contains more items than the endpoint allows.\n- `CONCURRENT_EXECUTION_LIMIT_EXCEEDED`: the account has reached its limit on simultaneous submissions.\n- `PBR_FAILURE_CAP_EXCEEDED`: the account has too many recent failed PBR runs; new submissions are temporarily blocked.\n- `EXECUTION_NOT_FOUND`: the execution or batch does not exist or does not belong to the account.\n- `EXECUTION_IN_PROGRESS`: the request conflicts with an execution that is still running.\n- `RATE_LIMITED`: the API key's rate limit was exceeded.\n- `SERVICE_UNAVAILABLE`: a dependent service is temporarily unavailable; retry later.\n- `MAINTENANCE_MODE`: the API is temporarily unavailable for maintenance.\n- `INTERNAL_SERVER_ERROR`: an unexpected server error occurred.\n- `WORKFLOW_CREATION_FAILED`: the platform could not start the underlying workflow.\n- `WORKFLOW_API_ERROR`: the platform's workflow system returned an unexpected error.\n","enum":["INVALID_REQUEST","MALFORMED_UUID","UNAUTHORIZED","API_KEY_MISSING","API_KEY_INVALID","API_KEY_REVOKED","PLAN_FEATURE_REQUIRED","INSUFFICIENT_CREDITS","QUOTA_EXCEEDED","FILE_TOO_LARGE","INVALID_CONTENT_TYPE","UNSUPPORTED_ASSET_FORMAT","FORMAT_NOT_AVAILABLE","ASSET_NOT_FOUND","ASSET_IN_USE","BATCH_TOO_LARGE","CONCURRENT_EXECUTION_LIMIT_EXCEEDED","PBR_FAILURE_CAP_EXCEEDED","EXECUTION_NOT_FOUND","EXECUTION_IN_PROGRESS","RATE_LIMITED","SERVICE_UNAVAILABLE","MAINTENANCE_MODE","INTERNAL_SERVER_ERROR","WORKFLOW_CREATION_FAILED","WORKFLOW_API_ERROR"]},"PlanFeatureRequiredError":{"type":"object","required":["error"],"description":"The error envelope for a missing subscription feature.","properties":{"error":{"type":"object","required":["code","message","details"],"description":"The missing-feature error body.","properties":{"code":{"type":"string","const":"PLAN_FEATURE_REQUIRED","description":"Stable error code for a missing subscription feature."},"message":{"type":"string","description":"Human-readable description of the error."},"details":{"$ref":"#/components/schemas/PlanFeatureRequiredErrorDetails"}}}}},"PlanFeatureRequiredErrorDetails":{"type":"object","required":["feature","upgrade_plan_codes"],"description":"The missing feature and the active plans that provide it.","properties":{"feature":{"$ref":"#/components/schemas/SubscriptionFeature"},"upgrade_plan_codes":{"type":"array","description":"Active plans available for purchase that provide the missing\nfeature. The array uses plan class and opaque code order.\n","items":{"$ref":"#/components/schemas/SubscriptionPlanCode"}}}},"SubscriptionFeature":{"type":"string","description":"Product capability available to the account.\n\nPossible enum values:\n- `commercial_license`: commercial-use rights.\n- `api_pbr`: PBR generation through the Public Platform API.\n- `api_asset_download`: asset downloads through the Public Platform API.\n- `custom_polycount`: custom polygon counts for 3D generation.\n- `image_edit`: image editing.\n- `multiview`: multiview generation.\n","enum":["commercial_license","api_pbr","api_asset_download","custom_polycount","image_edit","multiview"]},"SubscriptionPlanCode":{"type":"string","pattern":"^plan_[A-Za-z0-9]{7,64}$","description":"Opaque and immutable code for a subscription plan. Use the plan\ncatalogue for its current display name. The code must start with\n`plan_`, followed by 7 to 64 ASCII letters or digits.\n"}},"responses":{"Unauthorized":{"description":"The API key is missing, invalid, or revoked. Possible error codes:\n`API_KEY_MISSING`, `API_KEY_INVALID`, `API_KEY_REVOKED`, or `UNAUTHORIZED`.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"PlanFeatureRequired":{"description":"The account does not have the plan feature required by this operation\n(`PLAN_FEATURE_REQUIRED`).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlanFeatureRequiredError"}}}},"BatchNotFound":{"description":"The batch does not exist or does not belong to your account (`EXECUTION_NOT_FOUND`).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Rate limit exceeded (`RATE_LIMITED`). The response includes a `Retry-After`\nheader with the number of seconds to wait before retrying, plus the\n`X-RateLimit-*` headers. Those headers are also present on successful (2xx)\nresponses so a client can pace itself.\n","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"description":"Request burst capacity for the API key.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current burst window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix epoch seconds when the burst capacity is fully restored.\n","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/batch/{batch_id}":{"get":{"operationId":"getBatch","tags":["pbr"],"summary":"Retrieve a batch.","description":"Returns a batch's status, per-item counts, and the settled results for\neach item. As items finish, the response includes their generated material\nmaps with ready-to-use download URLs, or a typed error for failed items.\nThis is the endpoint you poll after submitting a PBR batch. `items` is\nempty until at least one item has reached a terminal state.\n","parameters":[{"$ref":"#/components/parameters/BatchId"}],"responses":{"200":{"description":"Batch status + settled items.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/PlanFeatureRequired"},"404":{"$ref":"#/components/responses/BatchNotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}}}}
```

## Generate PBR materials from one 3D mesh.

> Submits one ready mesh asset for 3D mesh to PBR generation. The asset must\
> be a \`ready\` mesh uploaded with \`POST /uploads\` or \`POST /batch/uploads\`.\
> \
> The request returns immediately with an \`execution\_id\` (\`202\`). Poll\
> \`GET /pbr/executions/{execution\_id}\` for the status and, once the run\
> finishes, the generated material maps and their download URLs. Credits are\
> reserved when you submit and refunded automatically if the run fails, so\
> you are only charged for a successful result.\
> \
> Use \`POST /batch/pbr/mesh\` instead when you have several meshes to submit\
> together.<br>

```json
{"openapi":"3.1.0","info":{"title":"Marso Studio API","version":"0.0.1"},"tags":[{"name":"pbr","description":"Batches group one or more PBR generation jobs together. Use these endpoints\nto submit 3D mesh to PBR or image to PBR batches, poll a batch for progress,\nand list recent batches.\n"}],"servers":[{"url":"https://api.marso.ai/api/public/v1","description":"Production server."}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"API key minted from the Marso Studio dashboard. The value has the form\n`mxr_live_<entropy>` and is sent as a Bearer token in the `Authorization`\nheader.\n"}},"schemas":{"CreatePBRMeshExecutionRequest":{"type":"object","required":["asset_id"],"description":"Request body for `POST /pbr/execute/mesh`. Submit one ready mesh asset\nfor PBR generation.\n","properties":{"asset_id":{"type":"string","format":"uuid","description":"The ID of the mesh asset to process. Upload it with `POST /uploads`\nor `POST /batch/uploads` first. Its status must be `ready`.\n"},"options":{"$ref":"#/components/schemas/PublicPBRMeshOptions"}}},"PublicPBRMeshOptions":{"type":"object","additionalProperties":false,"description":"Tuning options for a mesh PBR run. Every field is optional, and an\nomitted field uses the system default.\n\nThis is the image options plus `output_2d`, the 1 mesh-only option. It\nneeds a stage the image pipeline skips, so it appears on the mesh\nendpoints only. An image endpoint rejects it.\n\n**Every mesh result carries a USDZ.** The export is no longer an\noption. `output_3d` is gone, and a request that carries it gets a\n`400`. The pipeline always packages `material.usdz` for a mesh run,\nand the result lists it beside the texture maps.\n\nThis object rejects a field it does not declare, the same way\n`PublicPBRImageOptions` rejects one. Issue #2175 removed the same 6\noptions from both, and it removed `output_3d` from this object alone.\n\n4 of the 6 changed a mesh result before the removal. A mesh run now uses\nthe deployed value for each: 16 views, the `quality` solver profile, the\n`coverage` blend mode, and a bake at 4096. The PBR options reference\nholds the per-option detail. Delete these fields from your request body,\nbecause the endpoint now rejects them.\n","properties":{"detail_transfer":{"$ref":"#/components/schemas/PublicPBRDetailTransfer"},"output_2d":{"$ref":"#/components/schemas/PublicPBROutput2D"}}},"PublicPBRDetailTransfer":{"type":"object","additionalProperties":false,"description":"Settings for detail transfer during PBR generation.\n\nThis object lost `magnitude_only`. The pipeline tunes that value for\neach texture pass, so 1 value you send could only flatten the tuning.\n","properties":{"enabled":{"type":["boolean","null"],"default":true,"description":"Whether detail transfer is enabled. An omitted field, and an\nexplicit `null`, both leave the stage on.\n"}}},"PublicPBROutput2D":{"type":"object","additionalProperties":false,"description":"Container for 2D output options. All fields are optional; omitted fields\nuse system defaults.\n\nThis object lost `video`. The pipeline holds no video stage and no\nturntable stage.\n","properties":{"orm":{"$ref":"#/components/schemas/PublicPBROutput2DORM"}}},"PublicPBROutput2DORM":{"type":"object","additionalProperties":false,"description":"Settings for an occlusion/roughness/metallic (ORM) combined 2D output\nmap.\n\n**No result carries the ORM map yet.** The 2 mesh endpoints accept the\noption today, and the pipeline stage that packs the map is still in\nbuild. The option never fails a run, and it changes no result until that\nstage ships.\n","properties":{"enabled":{"type":["boolean","null"],"default":false,"description":"Whether to generate the ORM map. An omitted field, and an explicit\n`null`, both leave the map off.\nNo result carries the map yet, as the object description states.\n"},"channel_order":{"type":"string","enum":["ORM","RMO","MRO"],"default":"ORM","description":"Channel order for the combined map. An omitted field packs the\nchannels in the `ORM` order.\n\nPossible enum values:\n- `ORM`: occlusion, roughness, metallic.\n- `RMO`: roughness, metallic, occlusion.\n- `MRO`: metallic, roughness, occlusion.\n"}}},"PBRExecutionResponse":{"type":"object","required":["execution_id","status","created_at"],"description":"Body returned by `POST /pbr/execute/*` (202) and\n`GET /pbr/executions/{execution_id}` (200). It describes one execution and\nis not a batch envelope: there is no batch ID, no counts, and no items\narray.\n\nOn submission every result field is empty, because nothing has finished\nyet. `asset_id` is the source asset you submitted, so a failed execution is\nalways traceable to its input. `pbr_material_assets` maps each\n`\"<slot>/<pass>\"` to its generated texture asset and a ready-to-use\n`download_url`. `thumbnail_url` is a preview image, always present on a\nsucceeded mesh execution, and best-effort on a succeeded image execution.\n`error` is set only when the execution failed.\n","properties":{"execution_id":{"type":"string","description":"Unique identifier of the execution. Poll it at\n`GET /pbr/executions/{execution_id}`.\n"},"asset_id":{"type":"string","description":"The ID of the source asset that was submitted.\n"},"status":{"$ref":"#/components/schemas/ExecutionStatus"},"thumbnail_url":{"type":"string","format":"uri","description":"URL of a preview image. Always present on a succeeded mesh execution;\nbest-effort on a succeeded image execution.\n"},"thumbnail_url_expires_at":{"$ref":"#/components/schemas/EpochMillis"},"pbr_material_assets":{"type":"object","description":"Map from `\"<slot>/<pass>\"` to the generated texture asset. Only present\non a succeeded execution.\n","additionalProperties":{"$ref":"#/components/schemas/BatchMaterialAssetBody"}},"error":{"$ref":"#/components/schemas/ExecutionErrorBody"},"created_at":{"$ref":"#/components/schemas/EpochMillis"},"completed_at":{"$ref":"#/components/schemas/NullableEpochMillis"}}},"ExecutionStatus":{"type":"string","description":"Status of a single item within a batch.\n\nPossible enum values:\n- `QUEUED`: the item is waiting to start.\n- `RUNNING`: the item is being processed.\n- `SUCCEEDED`: the item completed successfully.\n- `PARTIAL_SUCCEEDED`: the item completed but some optional outputs are\n  missing.\n- `FAILED`: the item failed. See the `error` field for details.\n","enum":["QUEUED","RUNNING","SUCCEEDED","PARTIAL_SUCCEEDED","FAILED"]},"EpochMillis":{"type":"integer","format":"int64","description":"Time represented as milliseconds since the Unix epoch.\n"},"BatchMaterialAssetBody":{"type":"object","required":["asset_id"],"description":"One generated PBR result asset within a batch item. `download_url` is a\nready-to-use link that expires at `expires_at`.\n","properties":{"asset_id":{"type":"string","description":"ID of the generated asset.\n"},"download_url":{"type":"string","format":"uri","description":"Presigned URL for downloading the generated asset. Valid until\n`expires_at`.\n"},"expires_at":{"$ref":"#/components/schemas/EpochMillis"}}},"ExecutionErrorBody":{"type":"object","description":"Failure detail for a failed batch item. The `code` is a stable,\nmachine-readable class drawn from a closed enum so clients can branch on\nthe failure kind. The `message` carries human-readable detail. Only\n`VALIDATION_FAILED` is permanent; do not retry the same input. The other\ncodes are generally retryable.\n","required":["code","message"],"properties":{"code":{"type":"string","enum":["VALIDATION_FAILED","PIPELINE_ERROR","TIMEOUT","INTERNAL"],"description":"Machine-readable class of the failure.\n\nPossible enum values:\n- `VALIDATION_FAILED`: the input is unsuitable or invalid. This is a\n  permanent failure; retrying the same input will not succeed.\n- `PIPELINE_ERROR`: the PBR pipeline attempted the item but failed.\n  Generally retryable.\n- `TIMEOUT`: the item exceeded its time budget. Generally retryable.\n- `INTERNAL`: an internal orchestration fault. Generally retryable.\n"},"message":{"type":"string","description":"Human-readable explanation of the failure.\n"}}},"NullableEpochMillis":{"type":["integer","null"],"format":"int64","description":"Time represented as milliseconds since the Unix epoch, or `null` when the\nfield has not been set.\n"},"Error":{"type":"object","required":["error"],"description":"Canonical error envelope. The error payload is nested under the `error`\nkey.\n","properties":{"error":{"$ref":"#/components/schemas/ErrorBody"}}},"ErrorBody":{"type":"object","description":"The body of an error response. The `code` is a stable value clients can\nbranch on; the `message` is a human-readable explanation.\n","required":["code","message"],"properties":{"code":{"$ref":"#/components/schemas/ErrorCode"},"message":{"type":"string","description":"Human-readable description of the error.\n"},"details":{"type":["object","null"],"description":"Additional structured information about the error, or `null` if no\nextra details are available.\n","additionalProperties":true}}},"ErrorCode":{"type":"string","description":"Machine-readable error code. The enum enumerates every code that can be\nreturned by this API, including infrastructure-level 5xx codes, so\ngenerated clients can decode any `error.code` they receive.\n\nPossible enum values:\n- `INVALID_REQUEST`: the request body or a query parameter failed validation.\n- `MALFORMED_UUID`: a path parameter that should be a UUID is not one.\n- `UNAUTHORIZED`: the request could not be authenticated.\n- `API_KEY_MISSING`: no API key was supplied.\n- `API_KEY_INVALID`: the supplied API key does not match any known key.\n- `API_KEY_REVOKED`: the supplied API key has been revoked.\n- `PLAN_FEATURE_REQUIRED`: the account plan does not include a required feature.\n- `INSUFFICIENT_CREDITS`: the account does not have enough credits for this request.\n- `QUOTA_EXCEEDED`: a usage quota for the account has been exceeded.\n- `FILE_TOO_LARGE`: an uploaded or referenced file exceeds the allowed size.\n- `INVALID_CONTENT_TYPE`: a file's content type does not match its declared or expected type.\n- `UNSUPPORTED_ASSET_FORMAT`: a file's extension is not one of the supported asset formats.\n- `FORMAT_NOT_AVAILABLE`: the requested downloadable format does not exist for this asset.\n- `ASSET_NOT_FOUND`: the asset does not exist or does not belong to the account.\n- `ASSET_IN_USE`: the asset is referenced by an active execution and cannot be deleted.\n- `BATCH_TOO_LARGE`: the batch contains more items than the endpoint allows.\n- `CONCURRENT_EXECUTION_LIMIT_EXCEEDED`: the account has reached its limit on simultaneous submissions.\n- `PBR_FAILURE_CAP_EXCEEDED`: the account has too many recent failed PBR runs; new submissions are temporarily blocked.\n- `EXECUTION_NOT_FOUND`: the execution or batch does not exist or does not belong to the account.\n- `EXECUTION_IN_PROGRESS`: the request conflicts with an execution that is still running.\n- `RATE_LIMITED`: the API key's rate limit was exceeded.\n- `SERVICE_UNAVAILABLE`: a dependent service is temporarily unavailable; retry later.\n- `MAINTENANCE_MODE`: the API is temporarily unavailable for maintenance.\n- `INTERNAL_SERVER_ERROR`: an unexpected server error occurred.\n- `WORKFLOW_CREATION_FAILED`: the platform could not start the underlying workflow.\n- `WORKFLOW_API_ERROR`: the platform's workflow system returned an unexpected error.\n","enum":["INVALID_REQUEST","MALFORMED_UUID","UNAUTHORIZED","API_KEY_MISSING","API_KEY_INVALID","API_KEY_REVOKED","PLAN_FEATURE_REQUIRED","INSUFFICIENT_CREDITS","QUOTA_EXCEEDED","FILE_TOO_LARGE","INVALID_CONTENT_TYPE","UNSUPPORTED_ASSET_FORMAT","FORMAT_NOT_AVAILABLE","ASSET_NOT_FOUND","ASSET_IN_USE","BATCH_TOO_LARGE","CONCURRENT_EXECUTION_LIMIT_EXCEEDED","PBR_FAILURE_CAP_EXCEEDED","EXECUTION_NOT_FOUND","EXECUTION_IN_PROGRESS","RATE_LIMITED","SERVICE_UNAVAILABLE","MAINTENANCE_MODE","INTERNAL_SERVER_ERROR","WORKFLOW_CREATION_FAILED","WORKFLOW_API_ERROR"]},"PlanFeatureRequiredError":{"type":"object","required":["error"],"description":"The error envelope for a missing subscription feature.","properties":{"error":{"type":"object","required":["code","message","details"],"description":"The missing-feature error body.","properties":{"code":{"type":"string","const":"PLAN_FEATURE_REQUIRED","description":"Stable error code for a missing subscription feature."},"message":{"type":"string","description":"Human-readable description of the error."},"details":{"$ref":"#/components/schemas/PlanFeatureRequiredErrorDetails"}}}}},"PlanFeatureRequiredErrorDetails":{"type":"object","required":["feature","upgrade_plan_codes"],"description":"The missing feature and the active plans that provide it.","properties":{"feature":{"$ref":"#/components/schemas/SubscriptionFeature"},"upgrade_plan_codes":{"type":"array","description":"Active plans available for purchase that provide the missing\nfeature. The array uses plan class and opaque code order.\n","items":{"$ref":"#/components/schemas/SubscriptionPlanCode"}}}},"SubscriptionFeature":{"type":"string","description":"Product capability available to the account.\n\nPossible enum values:\n- `commercial_license`: commercial-use rights.\n- `api_pbr`: PBR generation through the Public Platform API.\n- `api_asset_download`: asset downloads through the Public Platform API.\n- `custom_polycount`: custom polygon counts for 3D generation.\n- `image_edit`: image editing.\n- `multiview`: multiview generation.\n","enum":["commercial_license","api_pbr","api_asset_download","custom_polycount","image_edit","multiview"]},"SubscriptionPlanCode":{"type":"string","pattern":"^plan_[A-Za-z0-9]{7,64}$","description":"Opaque and immutable code for a subscription plan. Use the plan\ncatalogue for its current display name. The code must start with\n`plan_`, followed by 7 to 64 ASCII letters or digits.\n"}},"responses":{"Unauthorized":{"description":"The API key is missing, invalid, or revoked. Possible error codes:\n`API_KEY_MISSING`, `API_KEY_INVALID`, `API_KEY_REVOKED`, or `UNAUTHORIZED`.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"PlanFeatureRequired":{"description":"The account does not have the plan feature required by this operation\n(`PLAN_FEATURE_REQUIRED`).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlanFeatureRequiredError"}}}},"RateLimitedOrCapped":{"description":"The request could not be accepted because of a rate or concurrency limit.\nPossible error codes:\n\n- `RATE_LIMITED`: the API-key rate limit was exceeded.\n- `CONCURRENT_EXECUTION_LIMIT_EXCEEDED`: a single-mesh or binary submit\n  exceeded the concurrency limit.\n- `PBR_FAILURE_CAP_EXCEEDED`: too many consecutive failures; check the\n  input before retrying.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/pbr/execute/mesh":{"post":{"operationId":"createMeshPBRExecution","tags":["pbr"],"summary":"Generate PBR materials from one 3D mesh.","description":"Submits one ready mesh asset for 3D mesh to PBR generation. The asset must\nbe a `ready` mesh uploaded with `POST /uploads` or `POST /batch/uploads`.\n\nThe request returns immediately with an `execution_id` (`202`). Poll\n`GET /pbr/executions/{execution_id}` for the status and, once the run\nfinishes, the generated material maps and their download URLs. Credits are\nreserved when you submit and refunded automatically if the run fails, so\nyou are only charged for a successful result.\n\nUse `POST /batch/pbr/mesh` instead when you have several meshes to submit\ntogether.\n","requestBody":{"required":true,"description":"The mesh asset to submit, and the options for the run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePBRMeshExecutionRequest"}}}},"responses":{"202":{"description":"The execution was created and queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PBRExecutionResponse"}}}},"400":{"description":"The request is invalid because `asset_id` is missing, an option is not\nsupported by the pipeline, the asset is not a mesh, or the asset is not\n`ready` (`INVALID_REQUEST`).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/PlanFeatureRequired"},"404":{"description":"The asset does not exist or does not belong to the authenticated\naccount (`ASSET_NOT_FOUND`).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimitedOrCapped"}}}}}}
```

## Generate PBR materials from one image.

> Submits one ready image asset for image to PBR generation. The image\
> counterpart of \`POST /pbr/execute/mesh\`. It takes the same options,\
> except \`output\_2d\`, which needs a stage the image pipeline skips. An\
> image result carries no USDZ, for the same reason.\
> \
> The request returns immediately with an \`execution\_id\` (\`202\`). Poll\
> \`GET /pbr/executions/{execution\_id}\` for the status and the generated\
> material maps. Credits are reserved when you submit and refunded\
> automatically if the run fails.\
> \
> Use \`POST /batch/pbr/image\` instead when you have several images to submit\
> together.<br>

```json
{"openapi":"3.1.0","info":{"title":"Marso Studio API","version":"0.0.1"},"tags":[{"name":"pbr","description":"Batches group one or more PBR generation jobs together. Use these endpoints\nto submit 3D mesh to PBR or image to PBR batches, poll a batch for progress,\nand list recent batches.\n"}],"servers":[{"url":"https://api.marso.ai/api/public/v1","description":"Production server."}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"API key minted from the Marso Studio dashboard. The value has the form\n`mxr_live_<entropy>` and is sent as a Bearer token in the `Authorization`\nheader.\n"}},"schemas":{"CreatePBRImageExecutionRequest":{"type":"object","required":["asset_id"],"description":"Request body for `POST /pbr/execute/image`. Submit one ready image asset\nfor PBR generation. It has the same shape as\n`CreatePBRMeshExecutionRequest`, except for the options. The image path\ntakes no `output_2d`, because that option needs a stage the image\npipeline skips.\n","properties":{"asset_id":{"type":"string","format":"uuid","description":"The ID of the image asset to process. Upload it with\n`POST /uploads` or `POST /batch/uploads` first. Its status must be\n`ready`.\n"},"options":{"$ref":"#/components/schemas/PublicPBRImageOptions"}}},"PublicPBRImageOptions":{"type":"object","additionalProperties":false,"description":"Tuning options for an image PBR run. Every field is optional, and an\nomitted field uses the system default.\n\nThe image pipeline runs inference only. It reaches neither the 3D\ncontainer stage nor the packed 2D map stage, so `output_2d` appears on\nthe mesh endpoints only, and no image result carries a USDZ.\n`detail_transfer` is the whole surface here.\n\nThis object rejects a field it does not declare. Issue #2175 removed\n`pbr_mode`, `blend_mode`, `coverage`, `texture`,\n`detail_transfer.magnitude_only` and `output_2d.video`. A request that\nstill carries 1 of them gets a 400, and the message names the field.\nDelete them from your request body. The PBR options reference states\nwhat each removal changed.\n","properties":{"detail_transfer":{"$ref":"#/components/schemas/PublicPBRDetailTransfer"}}},"PublicPBRDetailTransfer":{"type":"object","additionalProperties":false,"description":"Settings for detail transfer during PBR generation.\n\nThis object lost `magnitude_only`. The pipeline tunes that value for\neach texture pass, so 1 value you send could only flatten the tuning.\n","properties":{"enabled":{"type":["boolean","null"],"default":true,"description":"Whether detail transfer is enabled. An omitted field, and an\nexplicit `null`, both leave the stage on.\n"}}},"PBRExecutionResponse":{"type":"object","required":["execution_id","status","created_at"],"description":"Body returned by `POST /pbr/execute/*` (202) and\n`GET /pbr/executions/{execution_id}` (200). It describes one execution and\nis not a batch envelope: there is no batch ID, no counts, and no items\narray.\n\nOn submission every result field is empty, because nothing has finished\nyet. `asset_id` is the source asset you submitted, so a failed execution is\nalways traceable to its input. `pbr_material_assets` maps each\n`\"<slot>/<pass>\"` to its generated texture asset and a ready-to-use\n`download_url`. `thumbnail_url` is a preview image, always present on a\nsucceeded mesh execution, and best-effort on a succeeded image execution.\n`error` is set only when the execution failed.\n","properties":{"execution_id":{"type":"string","description":"Unique identifier of the execution. Poll it at\n`GET /pbr/executions/{execution_id}`.\n"},"asset_id":{"type":"string","description":"The ID of the source asset that was submitted.\n"},"status":{"$ref":"#/components/schemas/ExecutionStatus"},"thumbnail_url":{"type":"string","format":"uri","description":"URL of a preview image. Always present on a succeeded mesh execution;\nbest-effort on a succeeded image execution.\n"},"thumbnail_url_expires_at":{"$ref":"#/components/schemas/EpochMillis"},"pbr_material_assets":{"type":"object","description":"Map from `\"<slot>/<pass>\"` to the generated texture asset. Only present\non a succeeded execution.\n","additionalProperties":{"$ref":"#/components/schemas/BatchMaterialAssetBody"}},"error":{"$ref":"#/components/schemas/ExecutionErrorBody"},"created_at":{"$ref":"#/components/schemas/EpochMillis"},"completed_at":{"$ref":"#/components/schemas/NullableEpochMillis"}}},"ExecutionStatus":{"type":"string","description":"Status of a single item within a batch.\n\nPossible enum values:\n- `QUEUED`: the item is waiting to start.\n- `RUNNING`: the item is being processed.\n- `SUCCEEDED`: the item completed successfully.\n- `PARTIAL_SUCCEEDED`: the item completed but some optional outputs are\n  missing.\n- `FAILED`: the item failed. See the `error` field for details.\n","enum":["QUEUED","RUNNING","SUCCEEDED","PARTIAL_SUCCEEDED","FAILED"]},"EpochMillis":{"type":"integer","format":"int64","description":"Time represented as milliseconds since the Unix epoch.\n"},"BatchMaterialAssetBody":{"type":"object","required":["asset_id"],"description":"One generated PBR result asset within a batch item. `download_url` is a\nready-to-use link that expires at `expires_at`.\n","properties":{"asset_id":{"type":"string","description":"ID of the generated asset.\n"},"download_url":{"type":"string","format":"uri","description":"Presigned URL for downloading the generated asset. Valid until\n`expires_at`.\n"},"expires_at":{"$ref":"#/components/schemas/EpochMillis"}}},"ExecutionErrorBody":{"type":"object","description":"Failure detail for a failed batch item. The `code` is a stable,\nmachine-readable class drawn from a closed enum so clients can branch on\nthe failure kind. The `message` carries human-readable detail. Only\n`VALIDATION_FAILED` is permanent; do not retry the same input. The other\ncodes are generally retryable.\n","required":["code","message"],"properties":{"code":{"type":"string","enum":["VALIDATION_FAILED","PIPELINE_ERROR","TIMEOUT","INTERNAL"],"description":"Machine-readable class of the failure.\n\nPossible enum values:\n- `VALIDATION_FAILED`: the input is unsuitable or invalid. This is a\n  permanent failure; retrying the same input will not succeed.\n- `PIPELINE_ERROR`: the PBR pipeline attempted the item but failed.\n  Generally retryable.\n- `TIMEOUT`: the item exceeded its time budget. Generally retryable.\n- `INTERNAL`: an internal orchestration fault. Generally retryable.\n"},"message":{"type":"string","description":"Human-readable explanation of the failure.\n"}}},"NullableEpochMillis":{"type":["integer","null"],"format":"int64","description":"Time represented as milliseconds since the Unix epoch, or `null` when the\nfield has not been set.\n"},"Error":{"type":"object","required":["error"],"description":"Canonical error envelope. The error payload is nested under the `error`\nkey.\n","properties":{"error":{"$ref":"#/components/schemas/ErrorBody"}}},"ErrorBody":{"type":"object","description":"The body of an error response. The `code` is a stable value clients can\nbranch on; the `message` is a human-readable explanation.\n","required":["code","message"],"properties":{"code":{"$ref":"#/components/schemas/ErrorCode"},"message":{"type":"string","description":"Human-readable description of the error.\n"},"details":{"type":["object","null"],"description":"Additional structured information about the error, or `null` if no\nextra details are available.\n","additionalProperties":true}}},"ErrorCode":{"type":"string","description":"Machine-readable error code. The enum enumerates every code that can be\nreturned by this API, including infrastructure-level 5xx codes, so\ngenerated clients can decode any `error.code` they receive.\n\nPossible enum values:\n- `INVALID_REQUEST`: the request body or a query parameter failed validation.\n- `MALFORMED_UUID`: a path parameter that should be a UUID is not one.\n- `UNAUTHORIZED`: the request could not be authenticated.\n- `API_KEY_MISSING`: no API key was supplied.\n- `API_KEY_INVALID`: the supplied API key does not match any known key.\n- `API_KEY_REVOKED`: the supplied API key has been revoked.\n- `PLAN_FEATURE_REQUIRED`: the account plan does not include a required feature.\n- `INSUFFICIENT_CREDITS`: the account does not have enough credits for this request.\n- `QUOTA_EXCEEDED`: a usage quota for the account has been exceeded.\n- `FILE_TOO_LARGE`: an uploaded or referenced file exceeds the allowed size.\n- `INVALID_CONTENT_TYPE`: a file's content type does not match its declared or expected type.\n- `UNSUPPORTED_ASSET_FORMAT`: a file's extension is not one of the supported asset formats.\n- `FORMAT_NOT_AVAILABLE`: the requested downloadable format does not exist for this asset.\n- `ASSET_NOT_FOUND`: the asset does not exist or does not belong to the account.\n- `ASSET_IN_USE`: the asset is referenced by an active execution and cannot be deleted.\n- `BATCH_TOO_LARGE`: the batch contains more items than the endpoint allows.\n- `CONCURRENT_EXECUTION_LIMIT_EXCEEDED`: the account has reached its limit on simultaneous submissions.\n- `PBR_FAILURE_CAP_EXCEEDED`: the account has too many recent failed PBR runs; new submissions are temporarily blocked.\n- `EXECUTION_NOT_FOUND`: the execution or batch does not exist or does not belong to the account.\n- `EXECUTION_IN_PROGRESS`: the request conflicts with an execution that is still running.\n- `RATE_LIMITED`: the API key's rate limit was exceeded.\n- `SERVICE_UNAVAILABLE`: a dependent service is temporarily unavailable; retry later.\n- `MAINTENANCE_MODE`: the API is temporarily unavailable for maintenance.\n- `INTERNAL_SERVER_ERROR`: an unexpected server error occurred.\n- `WORKFLOW_CREATION_FAILED`: the platform could not start the underlying workflow.\n- `WORKFLOW_API_ERROR`: the platform's workflow system returned an unexpected error.\n","enum":["INVALID_REQUEST","MALFORMED_UUID","UNAUTHORIZED","API_KEY_MISSING","API_KEY_INVALID","API_KEY_REVOKED","PLAN_FEATURE_REQUIRED","INSUFFICIENT_CREDITS","QUOTA_EXCEEDED","FILE_TOO_LARGE","INVALID_CONTENT_TYPE","UNSUPPORTED_ASSET_FORMAT","FORMAT_NOT_AVAILABLE","ASSET_NOT_FOUND","ASSET_IN_USE","BATCH_TOO_LARGE","CONCURRENT_EXECUTION_LIMIT_EXCEEDED","PBR_FAILURE_CAP_EXCEEDED","EXECUTION_NOT_FOUND","EXECUTION_IN_PROGRESS","RATE_LIMITED","SERVICE_UNAVAILABLE","MAINTENANCE_MODE","INTERNAL_SERVER_ERROR","WORKFLOW_CREATION_FAILED","WORKFLOW_API_ERROR"]},"PlanFeatureRequiredError":{"type":"object","required":["error"],"description":"The error envelope for a missing subscription feature.","properties":{"error":{"type":"object","required":["code","message","details"],"description":"The missing-feature error body.","properties":{"code":{"type":"string","const":"PLAN_FEATURE_REQUIRED","description":"Stable error code for a missing subscription feature."},"message":{"type":"string","description":"Human-readable description of the error."},"details":{"$ref":"#/components/schemas/PlanFeatureRequiredErrorDetails"}}}}},"PlanFeatureRequiredErrorDetails":{"type":"object","required":["feature","upgrade_plan_codes"],"description":"The missing feature and the active plans that provide it.","properties":{"feature":{"$ref":"#/components/schemas/SubscriptionFeature"},"upgrade_plan_codes":{"type":"array","description":"Active plans available for purchase that provide the missing\nfeature. The array uses plan class and opaque code order.\n","items":{"$ref":"#/components/schemas/SubscriptionPlanCode"}}}},"SubscriptionFeature":{"type":"string","description":"Product capability available to the account.\n\nPossible enum values:\n- `commercial_license`: commercial-use rights.\n- `api_pbr`: PBR generation through the Public Platform API.\n- `api_asset_download`: asset downloads through the Public Platform API.\n- `custom_polycount`: custom polygon counts for 3D generation.\n- `image_edit`: image editing.\n- `multiview`: multiview generation.\n","enum":["commercial_license","api_pbr","api_asset_download","custom_polycount","image_edit","multiview"]},"SubscriptionPlanCode":{"type":"string","pattern":"^plan_[A-Za-z0-9]{7,64}$","description":"Opaque and immutable code for a subscription plan. Use the plan\ncatalogue for its current display name. The code must start with\n`plan_`, followed by 7 to 64 ASCII letters or digits.\n"}},"responses":{"Unauthorized":{"description":"The API key is missing, invalid, or revoked. Possible error codes:\n`API_KEY_MISSING`, `API_KEY_INVALID`, `API_KEY_REVOKED`, or `UNAUTHORIZED`.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"PlanFeatureRequired":{"description":"The account does not have the plan feature required by this operation\n(`PLAN_FEATURE_REQUIRED`).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlanFeatureRequiredError"}}}},"RateLimitedOrCapped":{"description":"The request could not be accepted because of a rate or concurrency limit.\nPossible error codes:\n\n- `RATE_LIMITED`: the API-key rate limit was exceeded.\n- `CONCURRENT_EXECUTION_LIMIT_EXCEEDED`: a single-mesh or binary submit\n  exceeded the concurrency limit.\n- `PBR_FAILURE_CAP_EXCEEDED`: too many consecutive failures; check the\n  input before retrying.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/pbr/execute/image":{"post":{"operationId":"createImagePBRExecution","tags":["pbr"],"summary":"Generate PBR materials from one image.","description":"Submits one ready image asset for image to PBR generation. The image\ncounterpart of `POST /pbr/execute/mesh`. It takes the same options,\nexcept `output_2d`, which needs a stage the image pipeline skips. An\nimage result carries no USDZ, for the same reason.\n\nThe request returns immediately with an `execution_id` (`202`). Poll\n`GET /pbr/executions/{execution_id}` for the status and the generated\nmaterial maps. Credits are reserved when you submit and refunded\nautomatically if the run fails.\n\nUse `POST /batch/pbr/image` instead when you have several images to submit\ntogether.\n","requestBody":{"required":true,"description":"The image asset to submit, and the options for the run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePBRImageExecutionRequest"}}}},"responses":{"202":{"description":"The execution was created and queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PBRExecutionResponse"}}}},"400":{"description":"The request is invalid because `asset_id` is missing, an option is not\nsupported by the pipeline, the asset is not an image, or the asset is\nnot `ready` (`INVALID_REQUEST`).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/PlanFeatureRequired"},"404":{"description":"The asset does not exist or does not belong to the authenticated\naccount (`ASSET_NOT_FOUND`).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimitedOrCapped"}}}}}}
```

## Retrieve a single PBR execution.

> Returns the status of one execution submitted with\
> \`POST /pbr/execute/mesh\` or \`POST /pbr/execute/image\` and, once it\
> finishes, its generated material maps with ready-to-use download URLs, or\
> a typed error if it failed. This is the endpoint you poll after a single\
> submission.\
> \
> The status moves from \`QUEUED\` straight to its terminal value. A single\
> execution does not report \`RUNNING\`, so poll for a terminal status rather\
> than waiting for a start signal.\
> \
> This endpoint serves single submissions only. The items of a batch are\
> read with \`GET /batch/{batch\_id}\`.<br>

```json
{"openapi":"3.1.0","info":{"title":"Marso Studio API","version":"0.0.1"},"tags":[{"name":"pbr","description":"Batches group one or more PBR generation jobs together. Use these endpoints\nto submit 3D mesh to PBR or image to PBR batches, poll a batch for progress,\nand list recent batches.\n"}],"servers":[{"url":"https://api.marso.ai/api/public/v1","description":"Production server."}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"API key minted from the Marso Studio dashboard. The value has the form\n`mxr_live_<entropy>` and is sent as a Bearer token in the `Authorization`\nheader.\n"}},"parameters":{"ExecutionId":{"name":"execution_id","in":"path","required":true,"description":"Unique identifier of the execution.","schema":{"type":"string","format":"uuid"}}},"schemas":{"PBRExecutionResponse":{"type":"object","required":["execution_id","status","created_at"],"description":"Body returned by `POST /pbr/execute/*` (202) and\n`GET /pbr/executions/{execution_id}` (200). It describes one execution and\nis not a batch envelope: there is no batch ID, no counts, and no items\narray.\n\nOn submission every result field is empty, because nothing has finished\nyet. `asset_id` is the source asset you submitted, so a failed execution is\nalways traceable to its input. `pbr_material_assets` maps each\n`\"<slot>/<pass>\"` to its generated texture asset and a ready-to-use\n`download_url`. `thumbnail_url` is a preview image, always present on a\nsucceeded mesh execution, and best-effort on a succeeded image execution.\n`error` is set only when the execution failed.\n","properties":{"execution_id":{"type":"string","description":"Unique identifier of the execution. Poll it at\n`GET /pbr/executions/{execution_id}`.\n"},"asset_id":{"type":"string","description":"The ID of the source asset that was submitted.\n"},"status":{"$ref":"#/components/schemas/ExecutionStatus"},"thumbnail_url":{"type":"string","format":"uri","description":"URL of a preview image. Always present on a succeeded mesh execution;\nbest-effort on a succeeded image execution.\n"},"thumbnail_url_expires_at":{"$ref":"#/components/schemas/EpochMillis"},"pbr_material_assets":{"type":"object","description":"Map from `\"<slot>/<pass>\"` to the generated texture asset. Only present\non a succeeded execution.\n","additionalProperties":{"$ref":"#/components/schemas/BatchMaterialAssetBody"}},"error":{"$ref":"#/components/schemas/ExecutionErrorBody"},"created_at":{"$ref":"#/components/schemas/EpochMillis"},"completed_at":{"$ref":"#/components/schemas/NullableEpochMillis"}}},"ExecutionStatus":{"type":"string","description":"Status of a single item within a batch.\n\nPossible enum values:\n- `QUEUED`: the item is waiting to start.\n- `RUNNING`: the item is being processed.\n- `SUCCEEDED`: the item completed successfully.\n- `PARTIAL_SUCCEEDED`: the item completed but some optional outputs are\n  missing.\n- `FAILED`: the item failed. See the `error` field for details.\n","enum":["QUEUED","RUNNING","SUCCEEDED","PARTIAL_SUCCEEDED","FAILED"]},"EpochMillis":{"type":"integer","format":"int64","description":"Time represented as milliseconds since the Unix epoch.\n"},"BatchMaterialAssetBody":{"type":"object","required":["asset_id"],"description":"One generated PBR result asset within a batch item. `download_url` is a\nready-to-use link that expires at `expires_at`.\n","properties":{"asset_id":{"type":"string","description":"ID of the generated asset.\n"},"download_url":{"type":"string","format":"uri","description":"Presigned URL for downloading the generated asset. Valid until\n`expires_at`.\n"},"expires_at":{"$ref":"#/components/schemas/EpochMillis"}}},"ExecutionErrorBody":{"type":"object","description":"Failure detail for a failed batch item. The `code` is a stable,\nmachine-readable class drawn from a closed enum so clients can branch on\nthe failure kind. The `message` carries human-readable detail. Only\n`VALIDATION_FAILED` is permanent; do not retry the same input. The other\ncodes are generally retryable.\n","required":["code","message"],"properties":{"code":{"type":"string","enum":["VALIDATION_FAILED","PIPELINE_ERROR","TIMEOUT","INTERNAL"],"description":"Machine-readable class of the failure.\n\nPossible enum values:\n- `VALIDATION_FAILED`: the input is unsuitable or invalid. This is a\n  permanent failure; retrying the same input will not succeed.\n- `PIPELINE_ERROR`: the PBR pipeline attempted the item but failed.\n  Generally retryable.\n- `TIMEOUT`: the item exceeded its time budget. Generally retryable.\n- `INTERNAL`: an internal orchestration fault. Generally retryable.\n"},"message":{"type":"string","description":"Human-readable explanation of the failure.\n"}}},"NullableEpochMillis":{"type":["integer","null"],"format":"int64","description":"Time represented as milliseconds since the Unix epoch, or `null` when the\nfield has not been set.\n"},"Error":{"type":"object","required":["error"],"description":"Canonical error envelope. The error payload is nested under the `error`\nkey.\n","properties":{"error":{"$ref":"#/components/schemas/ErrorBody"}}},"ErrorBody":{"type":"object","description":"The body of an error response. The `code` is a stable value clients can\nbranch on; the `message` is a human-readable explanation.\n","required":["code","message"],"properties":{"code":{"$ref":"#/components/schemas/ErrorCode"},"message":{"type":"string","description":"Human-readable description of the error.\n"},"details":{"type":["object","null"],"description":"Additional structured information about the error, or `null` if no\nextra details are available.\n","additionalProperties":true}}},"ErrorCode":{"type":"string","description":"Machine-readable error code. The enum enumerates every code that can be\nreturned by this API, including infrastructure-level 5xx codes, so\ngenerated clients can decode any `error.code` they receive.\n\nPossible enum values:\n- `INVALID_REQUEST`: the request body or a query parameter failed validation.\n- `MALFORMED_UUID`: a path parameter that should be a UUID is not one.\n- `UNAUTHORIZED`: the request could not be authenticated.\n- `API_KEY_MISSING`: no API key was supplied.\n- `API_KEY_INVALID`: the supplied API key does not match any known key.\n- `API_KEY_REVOKED`: the supplied API key has been revoked.\n- `PLAN_FEATURE_REQUIRED`: the account plan does not include a required feature.\n- `INSUFFICIENT_CREDITS`: the account does not have enough credits for this request.\n- `QUOTA_EXCEEDED`: a usage quota for the account has been exceeded.\n- `FILE_TOO_LARGE`: an uploaded or referenced file exceeds the allowed size.\n- `INVALID_CONTENT_TYPE`: a file's content type does not match its declared or expected type.\n- `UNSUPPORTED_ASSET_FORMAT`: a file's extension is not one of the supported asset formats.\n- `FORMAT_NOT_AVAILABLE`: the requested downloadable format does not exist for this asset.\n- `ASSET_NOT_FOUND`: the asset does not exist or does not belong to the account.\n- `ASSET_IN_USE`: the asset is referenced by an active execution and cannot be deleted.\n- `BATCH_TOO_LARGE`: the batch contains more items than the endpoint allows.\n- `CONCURRENT_EXECUTION_LIMIT_EXCEEDED`: the account has reached its limit on simultaneous submissions.\n- `PBR_FAILURE_CAP_EXCEEDED`: the account has too many recent failed PBR runs; new submissions are temporarily blocked.\n- `EXECUTION_NOT_FOUND`: the execution or batch does not exist or does not belong to the account.\n- `EXECUTION_IN_PROGRESS`: the request conflicts with an execution that is still running.\n- `RATE_LIMITED`: the API key's rate limit was exceeded.\n- `SERVICE_UNAVAILABLE`: a dependent service is temporarily unavailable; retry later.\n- `MAINTENANCE_MODE`: the API is temporarily unavailable for maintenance.\n- `INTERNAL_SERVER_ERROR`: an unexpected server error occurred.\n- `WORKFLOW_CREATION_FAILED`: the platform could not start the underlying workflow.\n- `WORKFLOW_API_ERROR`: the platform's workflow system returned an unexpected error.\n","enum":["INVALID_REQUEST","MALFORMED_UUID","UNAUTHORIZED","API_KEY_MISSING","API_KEY_INVALID","API_KEY_REVOKED","PLAN_FEATURE_REQUIRED","INSUFFICIENT_CREDITS","QUOTA_EXCEEDED","FILE_TOO_LARGE","INVALID_CONTENT_TYPE","UNSUPPORTED_ASSET_FORMAT","FORMAT_NOT_AVAILABLE","ASSET_NOT_FOUND","ASSET_IN_USE","BATCH_TOO_LARGE","CONCURRENT_EXECUTION_LIMIT_EXCEEDED","PBR_FAILURE_CAP_EXCEEDED","EXECUTION_NOT_FOUND","EXECUTION_IN_PROGRESS","RATE_LIMITED","SERVICE_UNAVAILABLE","MAINTENANCE_MODE","INTERNAL_SERVER_ERROR","WORKFLOW_CREATION_FAILED","WORKFLOW_API_ERROR"]},"PlanFeatureRequiredError":{"type":"object","required":["error"],"description":"The error envelope for a missing subscription feature.","properties":{"error":{"type":"object","required":["code","message","details"],"description":"The missing-feature error body.","properties":{"code":{"type":"string","const":"PLAN_FEATURE_REQUIRED","description":"Stable error code for a missing subscription feature."},"message":{"type":"string","description":"Human-readable description of the error."},"details":{"$ref":"#/components/schemas/PlanFeatureRequiredErrorDetails"}}}}},"PlanFeatureRequiredErrorDetails":{"type":"object","required":["feature","upgrade_plan_codes"],"description":"The missing feature and the active plans that provide it.","properties":{"feature":{"$ref":"#/components/schemas/SubscriptionFeature"},"upgrade_plan_codes":{"type":"array","description":"Active plans available for purchase that provide the missing\nfeature. The array uses plan class and opaque code order.\n","items":{"$ref":"#/components/schemas/SubscriptionPlanCode"}}}},"SubscriptionFeature":{"type":"string","description":"Product capability available to the account.\n\nPossible enum values:\n- `commercial_license`: commercial-use rights.\n- `api_pbr`: PBR generation through the Public Platform API.\n- `api_asset_download`: asset downloads through the Public Platform API.\n- `custom_polycount`: custom polygon counts for 3D generation.\n- `image_edit`: image editing.\n- `multiview`: multiview generation.\n","enum":["commercial_license","api_pbr","api_asset_download","custom_polycount","image_edit","multiview"]},"SubscriptionPlanCode":{"type":"string","pattern":"^plan_[A-Za-z0-9]{7,64}$","description":"Opaque and immutable code for a subscription plan. Use the plan\ncatalogue for its current display name. The code must start with\n`plan_`, followed by 7 to 64 ASCII letters or digits.\n"}},"responses":{"Unauthorized":{"description":"The API key is missing, invalid, or revoked. Possible error codes:\n`API_KEY_MISSING`, `API_KEY_INVALID`, `API_KEY_REVOKED`, or `UNAUTHORIZED`.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"PlanFeatureRequired":{"description":"The account does not have the plan feature required by this operation\n(`PLAN_FEATURE_REQUIRED`).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlanFeatureRequiredError"}}}},"ExecutionNotFound":{"description":"The execution does not exist, does not belong to your account, or was not\ncreated by a single submission (`EXECUTION_NOT_FOUND`). The items of a\nbatch are read with `GET /batch/{batch_id}`.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Rate limit exceeded (`RATE_LIMITED`). The response includes a `Retry-After`\nheader with the number of seconds to wait before retrying, plus the\n`X-RateLimit-*` headers. Those headers are also present on successful (2xx)\nresponses so a client can pace itself.\n","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"description":"Request burst capacity for the API key.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current burst window.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix epoch seconds when the burst capacity is fully restored.\n","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/pbr/executions/{execution_id}":{"get":{"operationId":"getPBRExecution","tags":["pbr"],"summary":"Retrieve a single PBR execution.","description":"Returns the status of one execution submitted with\n`POST /pbr/execute/mesh` or `POST /pbr/execute/image` and, once it\nfinishes, its generated material maps with ready-to-use download URLs, or\na typed error if it failed. This is the endpoint you poll after a single\nsubmission.\n\nThe status moves from `QUEUED` straight to its terminal value. A single\nexecution does not report `RUNNING`, so poll for a terminal status rather\nthan waiting for a start signal.\n\nThis endpoint serves single submissions only. The items of a batch are\nread with `GET /batch/{batch_id}`.\n","parameters":[{"$ref":"#/components/parameters/ExecutionId"}],"responses":{"200":{"description":"The status and settled result of the execution.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PBRExecutionResponse"}}}},"400":{"description":"The execution ID is malformed (`MALFORMED_UUID`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/PlanFeatureRequired"},"404":{"$ref":"#/components/responses/ExecutionNotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}}}}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.m-xr.com/marso-studio-api/api/pbr.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
