// OPENBOX DOCS
API local administrator
Local administrator operations that are not a stable remote contract.
These routes manage the local installation and process. They are not a stable remote contract: treat them as local-administrator operations and verify behavior against the running version. All require X-OpenBox-Token: TOKEN; POST bodies are JSON objects.
Updates
/api/updateCheck for a new release. Queries the GitHub releases API for vindeckyy/OpenBoxGL (30-second timeout) and returns:
{
"current": "0.9.0",
"latest": "0.9.0",
"available": true,
"notes": "...",
"appimage": "https://github.com/vindeckyy/OpenBoxGL/releases/download/.../OpenBox-x86_64.AppImage",
"checksum": "sha256:...",
"checksum_url": "...",
"page": "https://github.com/.../releases/tag/..."
}
Rules:
- Pre-release and build-suffixed tags are never
available. - The AppImage asset must come from the trusted
https://github.com/vindeckyy/OpenBoxGL/releases/download/prefix and a SHA-256 checksum must be present (asset digest or.sha256file); otherwise400with a clear reason. - GitHub failures return
400("GitHub releases request failed (...)"/"Could not reach GitHub releases: ..."). SettingGITHUB_TOKEN(orGH_TOKEN) in~/.envauthenticates the request for a higher rate limit.
/api/update/installDownload and atomically install the verified update into the running AppImage. Prerequisites:
APPIMAGEmust be set (the process must run from an AppImage), else400"Automatic updates require the OpenBox AppImage."- The update must be
availableand its URLs trusted. - The download streams with a 2 GiB cap and the SHA-256 is verified before the swap.
- The current AppImage is renamed to
<name>.previous<ext>; a failed swap restores it.
Returns {"installed": "<version>", "backup": "<path>"}. Restart to use the update.
Shutdown
/api/shutdown{"force": bool} stops every running game (SIGTERM, or SIGKILL with force: true) and returns {"stopped": <count>, "forced": bool}. Games that already exited are skipped.
State recovery
/api/state/recoverRestore the library from library.json.bak (see Data and recovery). Success returns {"ok": true, "games": <count>}; an unusable backup raises 503-class errors (surfaced as 400 with the message).
Desktop integration
/api/desktop/installWrite the desktop entry and icon for the running AppImage: ~/.local/share/applications/io.openbox.GameLauncher.desktop and ~/.local/share/icons/hicolor/scalable/apps/io.openbox.GameLauncher.svg. Requires APPIMAGE (else 400). Returns {"desktop": "<path>"}.
Themes
/api/themes?platform=<name> returns {"themes": [...], "selected": "...", "global": "...", "mappings": {...}}. Stock themes are installed on demand (Midnight Circuit, Phosphor Terminal, Harbor Light, Cinema Marquee, Nordic Mist). selected is the per-platform mapping when platform is given, else the global theme.
/api/themes/select{"name": "theme-name"|"", "platform": ""} sets the global theme (or clears it with ""); with platform, sets/clears a per-platform mapping. Unknown theme file: 400. Returns {"selected", "platform"}.
/api/themes/import{"path": "/path/to/theme.css"} copies a CSS file into themes/ (.css suffix required). Returns {"theme": "<stem>"}.
/api/themes/open-folderOpen the themes folder in the file manager via xdg-open (missing xdg-open: 400). Returns {"path"}.
Plugins
/api/plugins{"plugins": [{"id", "name", "version", "entry", "hooks", "enabled"}, ...]} sorted by id. Invalid packages are skipped.
/api/plugins/install{"path": "/path/to/plugin-dir-or.zip"} installs or updates a plugin package (safe extraction, staging, rollback on failure). Returns {"plugin": {...manifest..., "updated": bool}}.
/api/plugins/toggle{"id", "enabled": bool} enables/disables a plugin (persisted in plugins-state.json). Returns {"enabled": bool}.
/api/plugins/remove{"id"} moves the plugin directory to plugins/.removed/<id>-<timestamp> (reversible by moving it back) and clears its disabled state. Returns {"removed": "<id>"}.
/api/plugins/catalog{"catalog": [...]} from the bundled local catalog, falling back to the remote catalog (raw.githubusercontent.com/vindeckyy/OpenBoxGL/master/plugins/catalog.json, 20-second timeout, 4 MiB cap).
/api/plugins/catalog/install{"id"} downloads the catalog entry's package (128 MiB cap, SHA-256 verified when the entry provides one, 120-second timeout) and installs it. Unknown id or local_only entries raise 400 ("This catalog entry is documentation-only. Install local plugin packages manually."). Returns {"plugin": {...}}.
See Plugins for the manifest and hook contract.
Premium read models
/api/premium/strings?locale=en|es|de|fr|pt returns {"locale", "strings": {...}}; unknown locales fall back to English.
/api/premium/media-packs{"packs": [{"id", "name", "description", "kinds", "active"}, ...]}. Bundled packs: clear-logos-default, controller-xbox, controller-playstation, badges-core.
/api/premium/platform-categories{"categories": {...}} platform-to-category mapping (Nintendo, Sony, Microsoft, Computer, Arcade, Adventure, ...) with user overrides merged.
/api/premium/media-packs/apply{"id": "<pack id>"} activates a pack (and sets the controller prompt pack/hint for controller packs). Unknown pack: 400. Returns {"pack": {...}, "settings": {...}}.
Local reads
/api/log{"log": "<last 250 KB of openbox.log>"}. The log redacts tokens, passwords, API keys, and authorization headers, but can contain game names and local file paths.
/api/theme.css?name=<theme> serves the theme CSS with revalidation headers; unknown themes return an empty stylesheet.
GET /api/platform/documents and GET /api/platform/document
Per-platform document lists and file serving (?platform=&index=). Documents are validated to be regular files; symlinks are rejected. Missing documents return 404.
/api/platform/documents{"platform", "documents": [{"name", "path"}, ...]} replaces the platform's document list (capped at 100 entries). Returns {"saved", "count"}.
GET /api/document
Serves a game's document file for inline viewing (?game_id=&index=). The file is validated to be a regular file (symlinks rejected), served with its guessed MIME type and a sanitized Content-Disposition name. Missing game, index, or file returns 404 {"error": "Document not found"}.
GET /api/explorer/facets
Facet counts for the Explorer rail (?field=genre|developer|publisher|platform|progress|esrb). Hidden games are skipped; missing values fall back to Unspecified / Unset / Unrated; results are sorted by count descending then name, capped at 40. Returns {"field", "facets": [{"value", "count"}, ...]}. Unknown fields return an empty list.
POST /api/bigbox/mode
Signals a Big Box entry so the configured bigbox_shutdown_commands run on the host. Body {"entering": true} runs the commands in new session groups (failures are logged, never block); any other body is a no-op. Returns {"ok": true}.
Errors
These routes fail loudly on missing prerequisites (400 with the exact requirement) and never silently skip destructive steps. See REST API overview for the shared envelope.