Umbraco Management API Wonders

Posted on October 3, 2026 in umbraco

You may have heard me talk about Rick Dangerous, a 1989 game I reversed-engineered long ago, which can now be played directly on the web, thanks to WebAssembly.

All it takes is one .wasm file, and a couple of .js files. Now, because rick-dangerous.org is running Umbraco, and because it is simpler to have everything in the same place, those files are managed as Umbraco media.

So each time I rebuild the game, I need to update those media files. But browsing in the media section is a manual and tedious process. Can we do better?

Umbraco Management API

The Umbraco Management API is the API that was introduced in order to support the revamped back-office in a clean and independent way. And straight from the beginning, it was meant to be.

First create a dedicated API user. Second, authenticate:

CLIENT_ID=umbraco-back-office-rick-dangerous-api
CLIENT_SECRET=*****

API_URL=https://www.zpqrtbnk.net/umbraco/management/api/v1

TOKEN=$( \
  curl -s $API_URL/security/back-office/token \
    -d "client_id=$CLIENT_ID" \
    -d "client_secret=$CLIENT_SECRET" \
    -d 'grant_type=client_credentials' \
  | jq -r .access_token
)

If all goes well, the $TOKEN shell variable now contains your authentication token. We are going to define a simple helper method for invoking the API:

curl_api() {
  METHOD=$1
  shift
  API=$1
  shift
  curl -s \
    -H "Authorization: Bearer $TOKEN" \
    -X $METHOD \
    $API_URL/$API "$@"
  fi
}

Let us test it by retrieving the authenticated user name:

curl_api GET user/current | jq -r .name

Now let's assume that the media item containing the WASM file has a given UUID that we have retrieved from the UI, and we want to update its file with the recently built file xrick/build/web/xrick.wasm. This is what it takes:

MEDIA_WASM="11467372-23fb-4d45-818b-fc78edf889a6"
FILE_WASM=xrick/build/web/xrick.wasm

# get the media name (required for updates?)
MEDIA_NAME=$( \
  curl_api GET media/$MEDIA_WASM | jq -r .variants[0].name
)

# create a UUID for the temporary file
UUID=$(uuidgen)

# upload the file as a temporary file
curl_api POST temporary-file -F "Id=$UUID" -F "File=@./$FILE_WASM"

# edit the media to remove the current file
curl_api PUT media/$MEDIA_WASM \
  -H "Content-Type: application/json" \
  -d "{\"id\":\"$MEDIA_WASM\",\"values\":[{\"alias\":\"umbracoFile\",\"culture\":null,\"segment\":null,\"value\":{}}],\"variants\":[{\"culture\":null,\"segment\":null,\"name\":\"$MEDIA_NAME\"}]}"

# edit the media again, with the temporary file
curl_api PUT media/$MEDIA_WASM \
  -H "Content-Type: application/json" \
  -d "{\"id\":\"$MEDIA_WASM\",\"values\":[{\"alias\":\"umbracoFile\",\"culture\":null,\"segment\":null,\"value\":{\"src\":\"\",\"temporaryFileId\":\"$UUID\"}}],\"variants\":[{\"culture\":null,\"segment\":null,\"name\":\"$MEDIA_NAME\"}]}"

And... that is all. You will want to add some error checking here and there, but basically, this is all it takes to fully script the update of a media file.

The list of things that can be done this easily is huge—pretty much anything in fact. Which is absolutely impressive. Loving it, would recommend.

There used to be Disqus-powered comments here. They got very little engagement, and I am not a big fan of Disqus. So, comments are gone. If you want to discuss this article, your best bet is to ping me on Mastodon.