Web Dashboard API
The Web Dashboard is a small web server on your device, and every page in it reads the same API you can use from your own scripts, home automation or a status display. This page lists each request, what it needs and what it returns.
http://muos.local.curl http://muos.local/state/status.json
Key ideas
JSONEvery API answer is JSON. Errors come back as {"error": "..."} with a plain-language message you can show to people.Plain text bodiesRequests that send a name or path send it as plain text in the body. The core assignment editor is the one exception, and sends JSON.Same originAny request other than GET that carries an Origin header must come from the dashboard address itself, or it is refused with 403. Scripts that send no Origin header are not affected.No cachingAnswers are sent with Cache-Control: no-store, so each request shows the device as it is now.Authentication
Authentication is set in Configuration > Connectivity > Web Services. When it is on, the device shows a six digit code that changes every 30 seconds. Send the code with a request, or trade it for a session that lasts while you use it.
| Header | Use |
|---|---|
X-muOS-Code | The code currently shown on the device. Accepted on any request that needs unlocking. |
X-muOS-Session | A session token from POST/api/session. Ends after 30 minutes without use. |
# Open a session with the code shown on the device
curl -X POST -H "X-muOS-Code: 123456" http://muos.local/api/session
# Use the token from the answer for later requests
curl -H "X-muOS-Session: 0f4c..." http://muos.local/api/screen
/api/authWhether a code is needed. Returns required, readonly, lists_open, player_open, unlocked (true when your session is still valid), step (seconds per code), digits and remaining (seconds until the code changes)./api/sessionSend the code in X-muOS-Code. Returns token and idle (seconds a session lasts without use). Up to four sessions are kept, and a new one replaces the session closest to ending./api/sessionEnds the session named in X-muOS-Session.With Authentication off, dashboard changes and controls are available to everyone on the local network. Enable Authentication on shared or untrusted networks.
Five wrong codes in a minute from one address locks that address out with 429, starting at a minute and doubling up to 15 minutes. More than 30 wrong codes a minute from all addresses together locks everyone out for a short time.
Device status
These are files the device refreshes in the background, about every 5 seconds for status and every minute for the slower details. They never need a code.
| File | What is in it |
|---|---|
GET/state/status.json | Clock and time zone, uptime, address, device name and version, battery, the running program with the frontend module it is showing, the running content, storage use and an activity summary. |
GET/state/detail.json | System Information: processor, battery, network, integrity, frontend, power, traffic and storage details. |
GET/state/activity.json | Play statistics for each title, keyed by name: total time, launches, average and last session, core and device. |
GET/state/tracker.json | The full Activity Tracker records, one per title, including first and last play, longest session and time per core and device. |
GET/state/lang.json | The language file in use on the device, for showing the same words as the device. |
curl -s http://muos.local/state/status.json | jq '.battery'
File Management
File Management exposes the same mounted storage locations as the dashboard. User storage is writable whenever it is mounted. Internal and boot storage are protected, and each change must also include X-muOS-System-Write: confirm.
/api/filesLists the available storage roots. Each root includes an id, display label, filesystem path and whether it is protected. Removable roots only appear while mounted./api/files/{root}/browse/{path}Lists a folder, its free and total space, and its files. Each item includes its name, type, size and modification time./api/files/{root}/download/{path}Downloads a file. Byte ranges are supported for large media and resumable transfers. A folder downloads as a ZIP file./api/files/{root}/archive/{path}Starts building one ZIP file from two or more items in the folder. Send their names as plain text, one to a line. Returns a job, or 429 while two archives are already being built./api/files/{root}/archive-status/{job}Returns state (waiting, working, ready or failed), the current item, completed and total items, the archive size in bytes and an error when it failed./api/files/{root}/archive-download/{job}Downloads a ready archive once. It is removed from the device afterwards, and unclaimed archives are removed after an hour./api/files/{root}/upload/{path}Uploads one file as the request body. Uploads are streamed to disk and limited by the free space on the destination./api/files/{root}/mkdir/{path}Creates a folder./api/files/{root}/move/{path}Moves or renames an item. Send the destination path as plain text in the body./api/files/{root}/copy/{path}Copies an item. Send the destination path as plain text in the body./api/files/{root}/remove/{path}Removes a file or folder recursively.Sensitive system paths are never exposed. Take particular care with protected storage: removing or replacing system files can prevent MustardOS from starting.
History and Collections
History and Collections are lists of shortcuts to your content. Changes are refused with 409 while the matching screen is open on the device.
/api/historyReturns busy (the History screen is open) and items, each with id, path, system, name, modified and exists (the content is still on the card)./api/history/{id}Removes the entry from History./api/history/{id}/pathPoints the entry at a new content path, sent as the body./api/history/{id}/renameRenames the underlying content file and updates every matching History and Collection entry. Send the complete new file name as plain text in the body./api/history/{id}/collectAdds the entry to a collection. The body is the collection name, or empty for the top level./api/collectionReturns busy, items (as above, with the collection folder in the id) and collections./api/collection/{name}Creates an empty collection./api/collection/{name}/renameRenames a collection. The body is the new name./api/collection/{name}Removes a collection. It must be empty first./api/collection/{name}/addAdds existing content to a collection. Send the full path of the content file on the device as the body. Returns 409 when the collection already holds it./api/collection/{id}/pathPoints an entry at a new content path./api/collection/{id}/renameRenames the underlying content file and updates every matching History and Collection entry. Send the complete new file name as plain text in the body./api/collection/{id}/moveMoves an entry to another collection, named in the body, or to the top level with an empty body./api/collection/{id}Removes the entry from its collection.curl -X POST -H "X-muOS-Session: 0f4c..." --data "Favourites" \
"http://muos.local/api/history/Descent-0B5695F2.cfg/collect"
Now Playing
Wasabi
Controls Wasabi, the music and video player. These follow the same rule as History and Collections, so they are open to everyone when Authentication is off.
/api/playerWhat Wasabi is playing, or {"active": false} when nothing has played in the last 10 seconds. Includes title, artist, album, uri, paused, position, duration, index and count in the playlist, volume, shuffle and repeat./api/player/listThe playlist or channel list as items, each with a title and index./api/player/{command}One of toggle, play, pause, stop, next, previous, skip, seek, volume, setvolume, jump, shuffle or repeat. Returns 409 when Wasabi is not running.| Command | Body |
|---|---|
seek | A position in seconds. |
skip | Seconds to move forward, or back with a minus sign. |
volume | An amount to raise or lower the volume by. |
setvolume | The volume to set, from 0 to 200. |
jump | The index of the playlist item or channel to play. |
shuffle | 1 to turn shuffle on or 0 to turn it off. |
repeat | 0 for off, 1 to repeat the item or 2 to repeat all. |
curl -X POST --data 3 http://muos.local/api/player/jump
Pickles
Controls the game running in Pickles. These follow the same rule as Wasabi, so they are open to everyone when Authentication is off, and need a code or session when it is on.
/api/gameWhat Pickles is running, or {"active": false}. Includes name, folder, core, library, version, paused, speed (normal, fast_forward or slow_motion), menu (the Pickles menu is open), netplay, saves (state saves are allowed), quicksave (a quick save exists), fps and played (seconds of play this session)./api/game/{command}One of pause, resume, toggle, fast_forward, slow_motion, quicksave, quickload, fps or quit. fast_forward and slow_motion take 1 or 0 as the body. Returns 409 when Pickles is not running.Commands work the same way as the hotkeys on the device. While the Pickles menu is open only quit is carried out, pausing and speed changes are refused during netplay, and quick saves follow the game’s save state rules. quit saves first when Auto Save is on.
curl -X POST -H "X-muOS-Session: 0f4c..." http://muos.local/api/game/quicksave
Remote View
Remote View pictures the device screen. It needs Authentication and a code or session, unless privacy was turned off on the device. While a private screen is open, such as the Web Dashboard Code or a password entry, nothing is captured.
/api/screenReturns captured (time of the last picture), age (seconds since), interval, rotate (degrees to turn the picture), live (Live is chosen), audio (Live Sound is on), audio_rate (its sample rate), manual (Manual is chosen) and state (ok, hidden or failed). Takes a new picture when the last one is older than the interval, except in Manual. Add ?peek=1 to only read the status./api/screenTakes a new picture now. At most one every 10 seconds./api/screen/imageThe last picture, as PNG./api/screen/liveA live MJPEG stream (multipart/x-mixed-replace), when Live is chosen on the device. Each part is a JPEG, or a short text part while a private screen is open. Up to two streams at once. Each ends after 30 minutes, when the session that opened it is locked, or when the dashboard restarts. Add ?raw=1 to receive the same stream as application/octet-stream, which Safari passes to scripts unchanged./api/screen/audioThe sound the device is playing, when Live Sound is turned on. The body is raw signed 16-bit little endian stereo, and the X-Audio-Format header gives the sample rate. It follows the same rules as the live picture, with up to two streams at once, and the capture stops when the connection closes.curl -X POST -H "X-muOS-Code: 123456" http://muos.local/api/screen
curl -H "X-muOS-Code: 123456" -o screen.png http://muos.local/api/screen/image
Remote Controls
Presses buttons and changes the volume and brightness, as if you were holding the device. Available when Remote Controls is on in Web Services, and every change needs a code or session. With Authentication and Remote View Privacy both disabled, no code is needed, but the controls are only available while Remote View is set to Live.
/api/inputReturns buttons, the buttons and stick axes this device has, and ready (the input service is running), local_active (someone is using the device itself, so the controls are paused) and locked (the physical controls are locked)./api/input/{button}Send 1 to press and 0 to release. Buttons are up, down, left, right, a, b, x, y, l1, r1, l2, r2, l3, r3, select, start and menu. A press lasts 1.5 seconds, so send 1 again every half second to keep holding it. A press is held for at least 60 milliseconds, so a quick press and release still registers./api/input/stickMoves the analogue sticks, on devices that have them. Send axis and level pairs such as lx 0.5 ly -1, where lx and ly are the left stick, rx and ry the right stick, and each level runs from -1 to 1. A stick returns to the centre 300 milliseconds after the last update, so send the levels again at least every 150 milliseconds while it is held. When the physical stick is also moved, whichever is further from the centre wins./api/input/lockSend 1 once a second to lock the physical controls on the device. Each request renews a three second lease, so the controls unlock by themselves when the client disconnects. Send 0 to unlock them straight away. This works even while the controls are paused./api/input/clearReleases every button and centres the sticks. This always works, even while the controls are paused./api/input/volume/upSteps the volume up, as the volume button does. Use down to step it down, and brightness/up or brightness/down for the brightness.With Device Input Priority on, presses and stick moves return 409 for a moment after someone uses a button or stick on the device.
# Press and release A
curl -X POST -H "X-muOS-Session: 0f4c..." --data 1 http://muos.local/api/input/a
curl -X POST -H "X-muOS-Session: 0f4c..." --data 0 http://muos.local/api/input/a
Editors and Tools
The Editors and Tools in the dashboard open and save device files through these requests. Reading is open, and saving needs a code or session.
/api/toolsLists the areas with name and writable, plus whether core assignments and content folders are available./api/tools/{area}Lists the files in an area, each with path, size and modified. Add a folder name ending in / to list inside it./api/tools/{area}/{file}Reads a file./api/tools/{area}/{file}Saves a file. The body is the file itself.| Area | Files | Can save |
|---|---|---|
name | Custom content names (.json) | Yes |
profile | Settings profiles (.conf) | Yes |
profile-builtin | The built-in accessibility profiles | No |
equaliser | Wasabi equaliser profiles (.eq) | Yes |
track | Activity Tracker records (.json) | Yes |
bios | BIOS files, for checking what is present | No |
theme | Installed themes, for checking | No |
/api/tools/coreReturns source: user when you have your own core assignments, or bundled./api/tools/core/core.jsonThe core assignments in use./api/tools/coreSaves your own core assignments. The body must be a JSON object./api/tools/coreGoes back to the bundled assignments, keeping a backup of yours./api/tools/contentLists the content folders as roots, each with an index and path. Browse one with /api/tools/content/{index}/{folder}/, and read or save .m3u playlists inside it.Library
These areas are available under Library in File Management. Reading is open, and changes need a code or session.
/api/contentFree and used storage, the artwork types and each content folder with its artwork counts./api/catalogueEvery catalogue system with its artwork counts. Add /{system} for the files of one system./api/catalogue/{system}/{type}/{file}Uploads artwork. Types are box, grid, preview, text, manual and the overlay/ types. box and preview also accept .mp4, and a video's start, end and fade settings are saved as _edit/{name}.conf beside it./api/catalogue/refreshReads the catalogue again, after artwork has been changed on the device./api/catalogue/{system}/{type}/{file}Removes artwork./api/picklesPickles save states, save files and backups. Each save file includes its core./api/pickles/state/{content}The save states of one title./api/pickles/state/{content}/{slot}Removes a save state and its preview image./api/pickles/sram/{save}Replaces or imports a save game with the request body, where {save} starts with the core folder. Accepts .srm, .rtc, .sav, .mcd, .mcr, .mpk, .eep, .fla, .dsv, .brm, .bkr, .vmu, .vms, .gme, .pak, .sgm and .nv./api/pickles/backup/{index}/{save}Restores an earlier copy of a save game over the current one./media/catalogue/{path}Downloads a catalogue file. /media/pickles/{path} does the same for saves.Uploads are limited to 32 MB.
Status codes
| Code | Meaning |
|---|---|
| 200 | Done. |
| 400 | Something in the request is not valid, such as a name, path or file type. |
| 401 | Unlock the dashboard with the code from Web Dashboard Code on the device. |
| 403 | Read only, a different origin, or the files cannot be changed from the dashboard. |
| 404 | Not found, or the feature is turned off on the device. |
| 405 | That method is not used for this request. |
| 409 | The matching screen is open on the device, or the change clashes with something already there. |
| 413 | The request is too large. File Management uploads are streamed instead and are limited by destination free space. |
| 429 | Too many wrong codes. Wait and try again. |
| 503 | Wasabi or the input service did not accept the request. |
| 507 | There is not enough free space to complete an upload. |