Skip to content

Personal operations

Read owned content, upload artwork, and submit edits through the protected API.

Connect your app, then send requests from your server to https://api.mediux.io with Authorization: Bearer ACCESS_TOKEN. Keep tokens and upload bytes out of logs and browser state; do not send account cookies. Responses use private, no-store for browser and edge caches, with no stale-while-revalidate.

Jump to metadata edits, single-file uploads, Set creation, Set edits, or recovery.

Scopes grant permissions, not ownership. Each request checks the connection, resource ownership, and any required revision.

Route Scope
GET /me/assets/{assetId} assets:write or assets:replace
GET /me/sets/{setId} sets:write
GET /me/groups/{groupId} groups:write
GET /me/upload-destinations sets:write for talent_set/media_set; groups:write for boxset

For destinations, set kind to talent_set, media_set, or boxset. Optional family=game selects game destinations; the default is media. Use q to search. Results contain compatible owned destinations and are limited.

Route Scope Action
POST /me/assets assets:write to add; assets:replace to replace Upload standalone artwork
POST /me/sets/{setId}/assets assets:write to add; assets:replace to replace Upload artwork to an owned Set
POST /me/groups/{groupId}/poster Asset scope above plus groups:write Upload a Boxset or Loadout poster
GET /me/asset-uploads/{clientMutationId} assets:write or assets:replace Check an upload’s outcome
POST /me/assets/{assetId}/metadata assets:write Change language or edition
POST /me/assets/{assetId}/preview assets:replace Select an animated preview frame
Route Scope Action
POST /me/groups groups:write Create a Boxset or Loadout
POST /me/groups/{groupId} groups:write Edit group metadata or membership
POST /me/grouping-sets sets:write Create a Talent, Brand, or Category Set
POST /me/grouping-sets/{setId}/assets sets:write Assign owned standalone artwork
GET /me/relationships relationships:write Read follows and hides
POST /me/relationships relationships:write Follow, hide, or clear a relationship

Content deletion and account management are not available through this API. Set creation and grouped edit routes are described below.

Read the Asset, then pass its exact updatedAt as expectedUpdatedAt. Include only changed fields; omitted fields stay unchanged. Use null only for fields that allow clearing.

const { data: asset } = await privateClient.getAsset(ASSET_ID);
const receipt = await privateClient.updateAssetMetadata(asset.id, {
expectedUpdatedAt: asset.updatedAt,
languageCode: "fr",
});

This calls POST /me/assets/{assetId}/metadata with a JSON body. On a stale revision (409), reload and review the edit before submitting again. See the SDK guide to create privateClient.

Send one file as the raw body, not multipart data:

Terminal window
API=https://api.mediux.io
MUTATION_ID=01957988-4c76-7e58-bb68-3a3ad37603a5
UPLOAD_SHA256=$(sha256sum movie-poster.png | cut -d ' ' -f 1)
curl --fail-with-body --request POST \
"$API/me/assets?operation=add&clientMutationId=$MUTATION_ID&slot=poster&targetId=603&targetKind=movie&languageCode=en" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H 'Content-Type: image/png' \
-H 'X-Upload-Filename: movie-poster.png' \
-H "X-Upload-SHA256: $UPLOAD_SHA256" \
--data-binary @movie-poster.png

Use a unique UUID for clientMutationId and a lowercase SHA-256 digest of the file. Keep both for recovery. The body length must match Content-Length, which curl sets for this file. Mediux validates the actual file, size, dimensions, and target compatibility.

To replace artwork, use operation=replace, add previousAssetId=ASSET_ID, and request assets:replace. For Set artwork, use /me/sets/{setId}/assets and the Set’s target fields. For a group poster, use /me/groups/{groupId}/poster with the additional groups:write scope.

The SDK’s upload methods calculate the digest. A receipt identifies the saved Asset; publicationStatus: pending means public reads have not yet caught up.

All four routes require sets:write and assets:write:

Step Route
Declare the Set and files POST /me/set-uploads
Upload each file POST /me/set-uploads/{submissionId}/assets?itemId={itemId}
Check progress GET /me/set-uploads/{submissionId}
Complete the submission POST /me/set-uploads/{submissionId}/complete with {}

The initial request fixes the Set metadata and file declarations. Replace 34845 below with the actual file size in bytes:

Terminal window
SUBMISSION_CLIENT_ID=01957988-4c76-7e58-bb68-3a3ad37603b4
ITEM_ID=01957988-4c76-7e58-bb68-3a3ad37603b5
curl --fail-with-body --request POST \
"$API/me/set-uploads" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H 'Content-Type: application/json' \
--data @- <<JSON
{
"clientMutationId": "$SUBMISSION_CLIENT_ID",
"setKind": "media_set",
"entryTargetKind": "movie",
"entryTargetId": 603,
"titleBase": "My Movie Set",
"description": null,
"languageCode": "en",
"editionId": null,
"finalised": false,
"destination": null,
"declaredFiles": [
{
"itemId": "$ITEM_ID",
"position": 0,
"targetKind": "movie",
"targetId": 603,
"slot": "poster",
"filename": "movie-poster.png",
"contentType": "image/png",
"contentLength": 34845,
"selectedSourceFrame": null
}
]
}
JSON

Read submission.submissionId from the admission response, then transfer the file with exactly the frozen declaration:

Terminal window
SUBMISSION_ID=replace-with-submission-submissionId
curl --fail-with-body --request POST \
"$API/me/set-uploads/$SUBMISSION_ID/assets?itemId=$ITEM_ID" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H 'Content-Type: image/png' \
-H 'Content-Length: 34845' \
-H 'X-Upload-Filename: movie-poster.png' \
--data-binary @movie-poster.png
curl --fail-with-body \
"$API/me/set-uploads/$SUBMISSION_ID" \
-H "Authorization: Bearer $ACCESS_TOKEN"
curl --fail-with-body --request POST \
"$API/me/set-uploads/$SUBMISSION_ID/complete" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H 'Content-Type: application/json' \
--data '{}'

Complete after all file outcomes are terminal. The SDK’s createMediaSet combines these steps with bounded upload concurrency and status checks.

Its outcomes are succeeded, partial, rolled_back, failed, or unresolved. For partial, keep successful Asset IDs and inspect each failed item. Correct failed items with a new mutation only after the submission is terminal. unresolved means the client could not confirm the result; it does not cancel server work.

Stage several changes together while the public Set remains unchanged, then complete the submission to save successful changes.

Route SDK method
POST /me/sets/{setId}/updates admitSetUpdate(input)
POST /me/set-updates/{submissionId}/assets?itemId={itemId} uploadSetUpdateItem(id, itemId, file)
GET /me/set-updates/{submissionId} getSetUpdate(id)
POST /me/set-updates/{submissionId}/complete with {} completeSetUpdate(id)

These routes require sets:write. The initial request also requires assets:write for additions or Asset metadata edits, and assets:replace for replacements.

Include clientMutationId, setId, setKind, the Set’s exact expectedUpdatedAt, sparse changes, and up to 300 items. Supported setKind values are media_set, talent_set, brand_set, and category_set. Omitted metadata stays unchanged; omitted Assets are never removed.

Each item needs a unique itemId, position, targetKind, targetId, and slot, plus the fields for its operation:

Operation Additional fields
add declaredFile
replace declaredFile, expectedPreviousAssetId, expectedAssetUpdatedAt
assign existingAssetId, expectedAssetUpdatedAt
asset_metadata existingAssetId, expectedAssetUpdatedAt, sparse changes for languageCode and/or editionId

Set unused identity fields to null. Non-file items use declaredFile: null. File declarations contain filename, contentType, contentLength, and selectedSourceFrame (or null). Upload raw bytes with matching headers.

editSet(admission, [{ itemId, file }], options) combines these calls and returns succeeded, partial, failed, or unresolved. An uploaded item can remain processing until completion. If replacements fail but metadata succeeds, completion saves the metadata and keeps the previous artwork.

Retain submission and item IDs, successful Asset IDs, and errors. Processing can be terminal while publicationStatus is still pending. Resolve stale revision conflicts by reviewing current data; correct terminal failed items with a new edit.

After a timeout or lost response, retain the original identity:

Request Recovery
Granular Asset upload GET /me/asset-uploads/{clientMutationId}
Set creation GET /me/set-uploads/{submissionId}
Grouped Set edit GET /me/set-updates/{submissionId}

If the initial Set request returned no submission ID, send the identical body with the same clientMutationId to recover its receipt. Never change the declared intent or create a new identity to retry an uncertain request. For an uncertain file transfer, read the submission’s item status first.

Granular upload status returns data.processingStatus (processing, succeeded, or failed), publicationStatus (not_required, pending, or succeeded), available mutation and Asset IDs, retryable: false, and an optional { code, message } error. Pending publication does not justify a second upload; neither does a failed status justify a blind replay.

Response Recovery
401 Renew credentials explicitly if the connection permits it; reconcile the mutation before retrying.
403 Check required scopes and current ownership.
409 Reload the resource or reconcile the conflicting file declaration.
503 with set_creation_upload.outcome_unresolved Keep submission and item IDs; retrieve status first.
{
"error": {
"code": "asset.file.maxSize",
"message": "Filesize too large",
"details": { "maxBytes": 20971520 },
"issues": [
{
"code": "asset.file.maxSize",
"message": "Filesize too large",
"path": ["file"]
}
]
}
}

Branch on code, not message text. Preserve details and issues[*].path to show the affected field or item. Keep tokens, request headers, and internal exceptions out of your app’s error responses.