Asset management
Upload synchronously or asynchronously, query tasks, download, modify, and retrieve assets.
Upload assets
For large files, use asynchronous uploads below and query the task for its result.
Endpoint: /upload-assets
Method: POST
Description: Upload assets to the DAM system.
Request parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| - | List<EnterpriseAssetSaveReq> | Yes | Asset save requests |
This section describes uploading from a downloadable URL. The parameters below apply to this integration method.
EnterpriseAssetSaveReq fields:
| Field | Type | Required | Description |
|---|---|---|---|
| folderIds | List<Long> | No | Target folder IDs. If empty, global upload permission such as upload to all assets is required. Otherwise, upload permission is required for every folder |
| name | String | No | Display filename; if omitted, the server attempts to infer it from the url path |
| url | String | Yes | Directly downloadable asset URL (GET returns 200). The server downloads the file and stores it under a new key. Avoid short links blocked by hotlink protection or regional restrictions |
| extension | String | Yes | File extension, such as jpg or mp4, matching the resource type |
| size | Long | No | Declared size in bytes. The stored file size takes precedence after upload. Use the local size to assist validation |
| width | Integer | No | Image or video cover width in pixels. For images, the server attempts to read it from the downloaded file when omitted |
| height | Integer | No | Image or video cover height in pixels. For images, the server attempts to read it from the downloaded file when omitted |
| duration | Long | No | Video duration in milliseconds |
| link | String | No | Associated webpage or source link |
| description | String | No | Notes |
| rating | Integer | No | Rating; written to the asset rating field, corresponding to internal score |
| userId | Long | No | Asset owner user ID; defaults to the creator (the API key user). A specified user must belong to the current team |
| oldAssetId | Long | No | Original asset ID (>0) when uploading a new version; used for cover/version association |
| metadatas | List<MetadataDTO> | No | Custom metadata; only effective when enabled for the team. fieldId must match an ID from the metadata fields endpoint. Field validity is checked |
| skipDuplicateByEtag | Boolean | No | Skip duplicates. When true, the server checks the team's OSS ETags after downloading to the asset bucket but before adding to the library. Existing identical content is not added again; returned id, key, and accessUrl refer to the existing asset. Defaults to false |
| licenseAgreementIds | List<Long> | No | Linked license agreement IDs; only effective when copyright management is enabled, otherwise ignored |
| startTime | Date | No | Asset validity start; only effective when copyright management is disabled, otherwise ignored |
| endTime | Date | No | Asset validity end; only effective when copyright management is disabled, otherwise ignored |
| isPermanent | Boolean | No | Whether the asset is permanently valid; only effective when copyright management is disabled, otherwise ignored |
Upload requests use startTime / endTime to set asset validity; search and batch retrieval return validStartTime / validEndTime. With copyright management enabled, link agreements using licenseAgreementIds; validity comes from the agreement scopes.
MetadataDTO (metadatas item):
| Field | Type | Required | Description |
|---|---|---|---|
| fieldId | String | Conditional | Metadata field ID used during upload, matching the fields endpoint; paired with value |
| value | Object | No | Field value; type must match the field definition |
Response fields:
| Parameter | Type | Description |
|---|---|---|
| assets | List<Item> | Successfully saved assets |
Item fields:
| Field | Type | Description |
|---|---|---|
| id | Long | Asset ID |
| key | String | File URL, OSS key, or downloadable file |
| storePath | String | Asset OSS storage path; same as key |
| skippedDuplicateByEtag | Boolean | true when an existing team asset is reused after an ETag match; id, key, and accessUrl refer to that asset |
| name | String | Title |
| accessUrl | String | Access URL |
| uploadResult | String | NEW: newly uploaded and added to the library. DUPLICATE_BY_ETAG: duplicate found; no new asset added |
Example:
Request example:
curl --location --request POST 'https://open.musedam.ai/api/muse/upload-assets' \--header 'Authorization: Bearer your_api_key' \--header 'Content-Type: application/json' \--data-raw '[{"folderIds": [23015],"url": "https://example.com/assets/sample.jpg","name": "Sample image","extension": "jpeg"}]'
Response example:
{"code": "0","message": "OK","result": {"assets": [{"id": 6908936,"key": "api_b9648d4570d2e08364a451b1eec88eea.jpeg","storePath": "api_b9648d4570d2e08364a451b1eec88eea.jpeg","uploadResult": "NEW","skippedDuplicateByEtag": false,"name": "Sample image","accessUrl": "https://example.com/assets/sample.jpg"}]}}
Upload assets asynchronously
Endpoint: /upload-assets-async
Method: POST
Upload assets from downloadable URLs asynchronously. The endpoint returns task IDs immediately while downloading and ingestion run in the background. Use this endpoint for files over 20 MB to avoid synchronous download timeouts. A successful submission returns a task ID; query the task to confirm that the asset was uploaded successfully.
Request parameters
A JSON array containing 1–50 items. Each item uses the public EnterpriseAssetSaveReq fields and permission requirements in Upload assets. Every item must have a directly downloadable url. If any item has no url, the request fails with 30313.
| Field | Type | Required | Description |
|---|---|---|---|
| callbackUrl | String | No | Optional HTTP or HTTPS callback URL, used only for asynchronous uploads. The server POSTs the task result once when the task reaches SUCCESS or FAILED |
Task reuse and retries
- Tasks are reused for the same team, API Key user, and exact
urlstring. The asset owneruserIddoes not participate in task reuse. - If the task is running or already successful, the original
taskIdis returned without downloading or ingesting again. Folders, name, and metadata remain as submitted the first time. - If the previous attempt failed, submitting the same URL reuses the original
taskIdand restarts the task with the new request parameters. - Changing a signature or expiry parameter in the URL creates a different URL and therefore a new task.
Response parameters
| Field | Type | Description |
|---|---|---|
| tasks | List<Item> | One task entry for each submitted URL |
| tasks[].taskId | String | 32-character UUID without hyphens; use this to query the task, not as an asset ID |
| tasks[].url | String | The submitted URL string |
Request example
curl --request POST 'https://open.musedam.ai/api/muse/upload-assets-async' \--header 'Authorization: Bearer your_api_key' \--header 'Content-Type: application/json' \--data-raw '[{"folderIds": [23015],"url": "https://example.com/assets/sample.mp4","name": "Product video","extension": "mp4","callbackUrl": "https://example.com/webhooks/musedam-upload"}]'
Response example
{"code": "0","message": "success","result": {"tasks": [{"taskId": "a1b2c3d4e5f64789a0b1c2d3e4f56789","url": "https://example.com/assets/sample.mp4"}]}}
Callbacks
Callbacks use Content-Type: application/json. The body is the query endpoint’s result object directly, without the outer code, message, or result wrapper. Success includes asset information; failure includes stage: FAILED and failReason. Callback failure does not change the task status. Only one callback attempt is made; keep task polling as a fallback.
{"taskId": "a1b2c3d4e5f64789a0b1c2d3e4f56789","stage": "SUCCESS","progress": 100,"transferredBytes": 52428800,"totalBytes": 52428800,"failReason": null,"materialId": 6908936,"storePath": "api_example.mp4","name": "Product video","accessUrl": "https://example.com/assets/sample.mp4"}
Query an async upload task
Endpoint: /upload-assets-task
Method: POST
Query a task by taskId. It must belong to the current team and API Key user. A missing task or an ownership mismatch returns 30312.
Request parameters
| Field | Type | Required | Description |
|---|---|---|---|
| taskId | String | Yes | 32-character UUID without hyphens; use this to query the task, not as an asset ID |
Response parameters
| Field | Type | Description |
|---|---|---|
| taskId | String | Public task ID |
| stage | String | Current stage; see the table below |
| progress | Integer | 0–100: downloading up to 80, saving 85, ingesting 95, success 100; downloading stays at 0 when the total size is unknown |
| transferredBytes | Long | Bytes downloaded from the URL |
| totalBytes | Long | Content-Length from the source URL response; null if unavailable |
| failReason | String | Failure reason; empty during processing or after success |
| materialId | Long | Asset ID after success |
| storePath | String | Storage key after success |
| name | String | Asset name after success |
| accessUrl | String | Returned only for SUCCESS; re-signed on every query and valid for 1 day |
Task stages
| Stage | Meaning |
|---|---|
| WAITING | Waiting to be processed |
| DOWNLOADING | Downloading from the URL |
| SAVING | Writing to file storage |
| INGESTING | Ingesting the asset |
| SUCCESS | Upload complete; the returned asset information is ready to use |
| FAILED | Upload failed; check failReason, correct the cause, then resubmit |
Poll until stage becomes SUCCESS or FAILED. progress represents overall processing progress. When the source file size is unknown, download progress stays at 0; use transferredBytes to track downloaded bytes instead of treating 0 as a stalled task.
Request example
curl --request POST 'https://open.musedam.ai/api/muse/upload-assets-task' \--header 'Authorization: Bearer your_api_key' \--header 'Content-Type: application/json' \--data-raw '{"taskId": "a1b2c3d4e5f64789a0b1c2d3e4f56789"}'
Response example
{"code": "0","message": "success","result": {"taskId": "a1b2c3d4e5f64789a0b1c2d3e4f56789","stage": "SUCCESS","progress": 100,"transferredBytes": 52428800,"totalBytes": 52428800,"failReason": null,"materialId": 6908936,"storePath": "api_example.mp4","name": "Product video","accessUrl": "https://example.com/assets/sample.mp4"}}
Download assets
Asset downloads do not require a separate endpoint. Obtain a download link in either of these ways:
- Search assets: each asset returned by
/search-assetsincludes adownloadUrlfield. - Retrieve assets in bulk: the batch asset retrieval response also includes download links.
Use downloadUrl directly to download the asset. Links generally contain the required authentication and access information and can be opened in a browser or used with a download tool.
Notes:
- Download links may expire after 10 hours. Use them promptly.
- Ensure a stable connection when downloading large files.
- For batch downloads, consider server-side scripts to reduce client download failures.
Public links for original files
Your team must have the Asset Derivatives / Public Links add-on enabled. Otherwise, both requests return a module-not-enabled error. These endpoints apply only to original files and do not check folder-level public link settings or roles.
| Field | Type | Required | Description |
|---|---|---|---|
| assetIds | List<Long> | Yes | Up to 200 materialId values returned by asset search or upload. |
Query original file links
POST /public-links-get
Reads existing links without creating them. The business result is an object keyed by materialId. Each value is the original public URL without image processing parameters, or "" if the asset does not exist or has no public link.
curl --request POST 'https://open.musedam.ai/api/muse/public-links-get' \--header 'Authorization: Bearer your_api_key' \--header 'Content-Type: application/json' \--data-raw '{"assetIds": [1234567890, 9876543210]}'
Example business result
{"1234567890": "https://cdn.example.com/assets/photo.jpg","9876543210": ""}
Generate original file links
POST /public-links-generate
Publishes a public link for each original file. Repeated requests return the same existing link. The result has the same shape as the query response. A missing asset or a per-asset generation failure returns "" for that ID; other assets in the batch are still processed.
curl --request POST 'https://open.musedam.ai/api/muse/public-links-generate' \--header 'Authorization: Bearer your_api_key' \--header 'Content-Type: application/json' \--data-raw '{"assetIds": [1234567890, 9876543210]}'
For resized or reformatted images, use processed-public-links. For public links to derivative versions, use asset-derivative-versions. See Analysis & delivery.
Modify assets
Endpoint: /modify-assets
Method: POST
Description: Update basic asset information such as name, description, and rating.
Request parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| - | AssetModifyReq | Yes | Asset modification request |
AssetModifyReq fields:
| Field | Type | Required | Description |
|---|---|---|---|
| id | Long | Yes | Asset ID |
| name | String | No | Filename |
| description | String | No | Description |
| score | Integer | No | Rating (1–5) |
| link | String | No | Webpage link |
| tags | List<Long> | No | Tag IDs |
Response fields:
| Parameter | Type | Description |
|---|---|---|
| - | MiniDamAssetDTO | Updated asset information |
MiniDamAssetDTO fields:
See MiniDamAssetDTO fields in asset search
Example:
Request example:
curl --location --request POST 'https://open.musedam.ai/api/muse/modify-assets' \--header 'Authorization: Bearer your_api_key' \--header 'Content-Type: application/json' \--data-raw '{"id":6908914,"name":"bottomTip45","description":"description 451","score":5,"link":"wwww.baidu.com"}'
Response example:
{"code": "0","message": "OK","result": {"id": 6908914,"parentIds": [],"userId": "1673603133161799680","name": "bottomTip45","downloadUrl": "https://example.com/assets/sample.jpg","source": null,"link": "wwww.baidu.com","extension": "png","duration": null,"size": 111948,"width": 290,"height": 220,"description": "description 451","score": 5,"createTime": 1753428273000,"createUser": "1673603133161799680","updateTime": 1753942888000,"updateUser": 367024606,"tags": [],"thumbnailAccessUrl": "https://example.com/assets/sample.jpg"},"traceId": "17539429013299310816"}
Move assets to a folder
Endpoint: /move-assets-to-folder
Method: POST
Description: Move or add a batch of assets from a source folder to a target folder.
Request parameters:
| Field | Type | Required | Description |
|---|---|---|---|
| assetIds | List<Long> | Yes | Asset IDs; maximum 200 per request |
| fromFolderId | Long | Conditional | Required and >0 when operationType=0 (move). The current folder association to remove |
| toFolderId | Long | Yes | Target folder ID (>0) |
| operationType | Integer | No | 0: move (remove from fromFolderId and add to toFolderId); 1: add (keep source association). Defaults to 0 |
Response: Boolean
Example request (move):
curl --location --request POST 'https://open.musedam.ai/api/muse/move-assets-to-folder' \--header 'Authorization: Bearer your_api_key' \--header 'Content-Type: application/json' \--data-raw '{"assetIds": [6908914, 6908820],"fromFolderId": 10001,"toFolderId": 10002,"operationType": 0}'
Notes:
- Assets and folders must exist and belong to the current team. Edit permission for the relevant folders is required.
- operationType=0 moves assets; =1 adds them while keeping them in both folders.
Delete assets in bulk
POST /delete-assets moves the specified assets to the recycle bin. It cannot delete folders. The Open API does not support permanent deletion or restoring assets from the recycle bin.
Permissions: Requires an administrator API key or appKey. On the Enterprise plan, the key must be bound to the system administrator role. Member keys and user login sessions cannot call this endpoint. It does not check individual folder or asset permissions. Rate limit: 5 QPS.
| Request field | Type | Required | Description |
|---|---|---|---|
| assetIds | List<Long> | Yes | Supply 1–200 asset materialId values returned by asset search or upload. |
Response: The business result is a Boolean: true on success. Failures return an Open API or business error.
Request example:
curl --request POST 'https://open.musedam.ai/api/muse/delete-assets' \--header 'Authorization: Bearer your_admin_api_key' \--header 'Content-Type: application/json' \--data-raw '{"assetIds": [6908914, 6908820]}'
Retrieve assets in bulk
Endpoint: /assets-by-ids
Method: POST
Description: Retrieve asset details for a list of asset IDs.
Request parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| - | List<Long> | Yes | Asset IDs |
Response fields:
| Parameter | Type | Description |
|---|---|---|
| - | List<MiniDamAssetDTO> | Asset information |
MiniDamAssetDTO fields:
See MiniDamAssetDTO fields in asset search
Each returned MiniDamAssetDTO also includes externalApp (external application identifier) and externalResourceRef (external resource reference). For an IngenOps canvas these are ingenops and its corresponding workspace_ref; both are null when the asset has no external association.
Example:
Request example:
curl --location --request POST 'https://open.musedam.ai/api/muse/assets-by-ids' \--header 'Authorization: Bearer your_api_key' \--header 'Content-Type: application/json' \--data-raw '[6908914,6908820]'
Response example:
{"code": "0","message": "OK","result": [{"id": 6908914,"parentIds": [28566],"userId": "1673603133161799680","name": "bottomTip45","downloadUrl": "https://example.com/assets/sample.jpg","source": null,"link": "wwww.baidu.com","extension": "png","duration": null,"size": 111948,"width": 290,"height": 220,"description": "description 451","score": 5,"createTime": 1753428273000,"createUser": "1673603133161799680","updateTime": 1753942901660,"updateUser": 367024606,"tags": [],"thumbnailAccessUrl": "https://example.com/assets/sample.jpg"},{"id": 6908820,"parentIds": [],"userId": "1673603133161799680","name": "Full-Stack-Serverless","downloadUrl": "https://example.com/assets/sample.jpg","source": null,"link": null,"extension": "epub","duration": null,"size": 4567444,"width": null,"height": null,"description": null,"score": null,"createTime": 1753264933000,"createUser": "1673603133161799680","updateTime": 1753264933000,"updateUser": 1673603133161799680,"tags": [{"name": "Social media design","id": 8223},{"name": "Platform customization","id": 8247},{"name": "cadahsjdkhasdhasjkdhajshdasjkhdajskhdjakshdasjhdajshdjkashd","id": 9084},{"name": "asdashdlajksdhjkashdjksahdjashdlasdj","id": 9096},{"name": "ccc","id": 9097},{"name": "Web design","id": 8224},{"name": "Interactive elements","id": 8270}],"thumbnailAccessUrl": "https://example.com/assets/sample.jpg"}],"traceId": "1753943463848693869"}
Query custom metadata by asset ID
Endpoint: /metadata-records-by-ids
Method: POST
Description: Retrieve saved custom metadata values for asset IDs in bulk. IDs are omitted when custom metadata is disabled for the team or the asset has no metadata record.
Request parameters:
| Field | Type | Required | Description |
|---|---|---|---|
| materialIds | List<Long> | Yes | Asset IDs; maximum 50 per request |
Response: Map<Long, Object>. Keys are asset IDs; values are metadata objects mapping field names to values, including recordId, materialId, and other fields.
Request example:
curl --location --request POST 'https://open.musedam.ai/api/muse/metadata-records-by-ids' \--header 'Authorization: Bearer your_api_key' \--header 'Content-Type: application/json' \--data-raw '{"materialIds":[6908914,6908820]}'
Example response:
{"code": "0","message": "OK","result": {"6908914": {"materialId": 6908914,"recordId": "rec_xxx","yourFieldName": "Custom value"}},"traceId": "..."}
Notes:
- Only assets with metadata records are returned. IDs without records are omitted from result.
- Uploading metadata uses fieldId (see the upload endpoint); this read endpoint uses field names as keys.
Query team metadata fields
Endpoint: /metadata-fields
Method: GET
Description: Query configured custom metadata field definitions for the current team. Use the returned field id as metadatas[].fieldId during upload. Returns an empty list if custom metadata is disabled.
Response: List<Object>; each item is a field definition:
| Field | Type | Description |
|---|---|---|
| id | String | Field ID; use as fieldId during upload |
| name | String | Field name; use as name when modifying asset metadata |
| field_type / type | String | Field type, such as text, number, or select; refer to the actual response |
Request example:
curl --location --request GET 'https://open.musedam.ai/api/muse/metadata-fields' \--header 'Authorization: Bearer your_api_key'
Note: Built-in fields such as materialId also appear in the list. Filter them as needed.
Check transferred assets in bulk
Description: Determine whether assets were created by a member resource transfer, such as resources transferred to another member when someone leaves or is removed.
Endpoint: /check-transferred-materials
Method: POST
Request parameters: enterpriseTransferMaterialCheckReq
| Field | Type | Required | Description |
|---|---|---|---|
| assetIds | List<Long> | Yes | Asset IDs; equivalent to materialId and to id / assetIds elsewhere in the Open API |
Response: Map<Long, Boolean>;
- Key: An asset ID (assetId) from the request
- Value:
truefor an asset created by a transfer;falseotherwise, including nonexistent assets
Example request:
curl --location --request POST 'https://open.musedam.ai/api/muse/check-transferred-materials' \--header 'Authorization: Bearer your_api_key' \--header 'Content-Type: application/json' \--data-raw '{"assetIds": [1234567890, 9876543210]}'
Example response:
{"code": "0","message": "OK","result": {"1234567890": true,"9876543210": false},"traceId": "17561978534182325498"}
Notes:
- The request parameter is named
assetIds. - Nonexistent asset IDs are also returned, with a value of
false.
Query asset users
Description: Query users who downloaded or shared an asset, with pagination. Operation logs are aggregated by user to return counts and most recent activity. The asset must exist in the current team.
Endpoint: /material-access-users-query
Method: POST
Request parameters:
| Field | Type | Required | Description |
|---|---|---|---|
| assetId | Long | Yes | Asset ID |
| operationTypes | List<Integer> | No | Operation types: 1 download, 2 share. Omit or leave empty to count both |
| page | Integer | No | Page number; defaults to 1 |
| pageSize | Integer | No | Page size; defaults to 20, maximum 100 |
Response: Contains total and items. Each item has:
| Field | Type | Description |
|---|---|---|
| userId | Long | User ID |
| realName | String | Full name |
| nickName | String | Nickname |
| String | ||
| phone | String | Phone number |
| avatarUrl | String | Avatar URL |
| downloadCount | Long | Download count; 0 if operationTypes excludes 1 |
| lastDownloadTime | Date | Most recent download time |
| shareCount | Long | Share count; 0 if operationTypes excludes 2 |
| lastShareTime | Date | Most recent share time |
| lastOperationTime | Date | Most recent download or share time |
Request example:
curl --location --request POST 'https://open.musedam.ai/api/muse/material-access-users-query' \--header 'Authorization: Bearer your_api_key' \--header 'Content-Type: application/json' \--data-raw '{"assetId": 123456789,"operationTypes": [1, 2],"page": 1,"pageSize": 20}'
Notes:
- Only operations by users in the current team are counted. Departed or deleted users are still returned if logs remain, including userId and counts; profile fields such as name may be empty.
- One record is returned per userId, combining download and share statistics.