// OPENBOX DOCS
API library and settings
Library, settings, profiles, running sessions, history, launch, and CRUD routes.
Read and write the library, settings, profiles, launch configuration, and game records. All routes require X-OpenBox-Token: TOKEN; all POST bodies are JSON objects.
Library and state
/api/libraryReturns the full public library projection, cached until the library file, media epoch, or plugin epoch changes. Served gzip-compressed to clients that accept it (the compressed bytes are computed once per state change, so polling is cheap) with an ETag for conditional GET: a client that sends If-None-Match gets 304 Not Modified when nothing changed. Top-level keys:
games: array of game objects. Each game includes every editable field (with""defaults), plus computed flags:id(numeric index),game_id(stable id),favorite,hidden,hide_in_bigbox,last_played,play_count,playtime_seconds,path_exists,has_cover,has_background,has_clear_logo,has_fanart,has_banner,has_icon,has_box_back,has_box_spine,has_box_3d,has_title_screen,has_video,active_video_field,has_music,has_saves,has_documents,has_versions,has_achievements,has_highscores,has_missing_media,extract_archive,applications,versions,documents,save_paths,screenshots,alternate_names,available_screenshots,esrb,custom_fields,platform_category,tags,store_catalog,store_installed,owned,installable,gameyfin_id. Editable string fields also includecollection(a free-text grouping used by related-game scoring) and, for per-game tracking overrides,tracking_mode,tracking_delay,tracking_frequency, andtracking_process_name.playlists,filter_presets,ra_configured,settings,discovery,media_epoch.
In safe mode the library hook is skipped; otherwise plugin library hooks can transform the games list before it is returned.
/api/gameCreate or update one game. Locate by id (numeric) or game_id (stable) for updates; omit both to create. Validation:
namerequired and non-empty.pathmust point to an existing local file (creation and updates).progressmust be one of"",Playing,Paused,Beaten,Completed,Mastered,Abandoned.ratingis a float between 0 and 5.disc_countis a non-negative integer.save_pathscapped at 50 entries,screenshotsat 100,alternate_namesat 20 (string input splits on;).applications,versions,documentsare lists capped at 100 entries each; extras need apath, get aname(defaults to the path stem), and applications/versions may carry acommand.custom_fieldsare normalized against the defined custom field defs.
Returns {"ok": true}.
/api/game/deleteRemove a game by id or game_id. With delete_media: true, associated media files (cover, background, screenshots, and all media fields) are removed only when they are safe files inside the data directory; media deletions bump the media epoch. Returns {"removed": "<name>"}.
/api/games/delete-steamRemove every game with source equal to Steam (case-insensitive). Returns {"removed": <count>}.
/api/games/bulkApply the same change to many games. Body: {"ids": [...], "changes": {...}}. Allowed change keys: platform, genre, progress, rating, favorite, hidden, esrb, custom_fields, tags, tags_add, tags_remove. Rules:
idsaccept numeric indexes or stable game ids (including legacy aliases).tagscannot be combined withtags_add/tags_remove; a tag cannot be added and removed in the same request.favorite/hiddenmust be booleans;progressmust be a known value;ratingbetween 0 and 5.- Returns
{"updated": <count>}.
/api/games/bulk-wizardSame as bulk edit but validates against the bulk wizard fields (platform, genre, progress, rating, favorite, hidden, esrb, custom_fields). Returns {"updated": <count>, "fields": [...]}.
/api/favoriteToggle a game's favorite flag by id or game_id. Returns {"favorite": <bool>}.
Settings
/api/settingsReturns the public settings projection: every validated setting key with defaults, plus save_tools (ludusavi/hoard presence), safe_mode, version, appimage, gamescope_guest, and premium_features_free: true. Secrets are never included; credential presence is exposed as booleans (gameyfin_password_set, emumovies_configured).
/api/settingsPartial save: merge the posted keys into existing settings and validate. See Configuration for the full validation table. Empty gameyfin_password keeps the stored password. Returns the new public settings.
Profiles
/api/profilesReturns {"profiles": state.profiles, "detected": discover_profiles()} where detected lists launchable platform defaults from binaries on PATH (DOSBox, Wine, MAME, Dolphin, PCSX2, PPSSPP, RPCS3, DuckStation).
/api/profilesReplace all profiles: {"profiles": {"Platform": "command {path}", ...}} (blank entries dropped). Returns {"saved": <count>}.
GET /api/perf_profiles / POST /api/perf_profiles
Per-launch-profile TDP limits for handheld tuning. Each entry: {"enabled": bool, "tdp_w": float, "restore_tdp_w": float}; blank names and all-zero entries are dropped; non-numeric TDP raises 400. Returns {"saved": <count>}.
Running sessions and history
/api/running{"running": [...], "events": [...], "last_event": <sequence>}. Poll with ?after=<sequence> to receive only new session lifecycle events (id, kind started|stopped|paused|resumed, launch_id, game, time, optional exit_code/seconds). In-memory event buffer holds the last 100 events.
/api/session/control{"launch_id": "...", "action": "pause"|"resume"|"stop"|"restart"|"kill"}. stop/restart send SIGTERM to the process group, kill sends SIGKILL; paused games are resumed first except for kill. A game that is no longer running raises 400. Returns {"ok": true, "action": action}.
/api/history{"history": [...], "enabled": <track_session_history>}. Sessions are newest first; ?limit= clamps to 1..500 (default 100). Each session: game, started, seconds, exit_code.
Launch
/api/launchStart a game. Body: {"id": <index>} or {"game_id": "<stable>"} (or both). Resolution prefers game_id; a missing game raises 400. Before launch: archive extraction (if configured), performance profile apply, then before_launch plugins (unless safe mode) which may rewrite args/cwd or cancel the launch with an error. The process starts in a new session; the response returns the running-session entry (launch_id, pid, game, game_path, started, and storefront ids). Launch validation errors include missing path, nonexistent path, non-executable file without a command, and plugin failures.
/api/extra/launchLaunch an application/version/document extra: {"id"|"game_id", "kind": "applications"|"versions"|"documents", "index": <n>}. Documents open with xdg-open; extras with a command substitute {path}; others execute directly. Missing file or xdg-open raises 400.
Related games
/api/related?id=<index> returns {"ids": [indexes]} scored from local metadata only (genre overlap, series, collection, developer, platform, publisher). Unknown game returns 404.
/api/related/rich?id=<index> returns {"items": [{"id", "score", "reasons": [...]}]} with human-readable reasons. 404 when the game is missing.
Playlists
/api/playlistsSave a playlist: {"name", "type": "filter"|"manual", "rules": {...}, "members"|"ids": [...], "parent", "notes"}. Filter playlists keep rules and drop members; manual playlists store stable game_ids in order (deduplicated, at most 100,000). Updating an existing name replaces it. Returns {"saved": "<name>"}.
/api/playlists/delete{"name": "..."} removes the playlist. Returns {"deleted": "<name>"}.
Filter presets
/api/filter-presets{"presets": [...], "bigbox_quick": [...]} (at most 8 quick presets).
/api/filter-presets{"name", "rules", "bigbox_quick": bool}. Rules keys: platform, view, query, esrb, progress, favorite, installed, platform_category, genre, developer, publisher, hidden. At least one rule required. Returns {"saved": "<name>"}.
/api/filter-presets/delete{"name"} removes it; unknown names raise 400.
Image groups
/api/image-group{"group": "default"|"cover"|"background"|"screenshot"|"clear_logo"|"fanart"|"banner"|"icon"|"box_back"|"box_spine"|"box_3d"|"title_screen", "scope": "global"|"platform"|"playlist", "name": "<platform or playlist>"}. Global sets image_group; scoped sets/clears image_group_by_platform or image_group_by_playlist. Returns updated settings.
Errors
All handlers return {"error": "..."}; unknown games, bad payloads, and validation failures surface as 400, missing game lookups as 404, corrupt state as 503. See REST API overview for the shared envelope.