Beta warning
APIExpose is still in beta and can modify EmulationStation settings, gamelists, media projections, collections and theme files. Depending on the options you enable, it will write or update gamelists and media files. Before using it on your main setup, make a full backup of your RetroBat folder or test it on a copy of RetroBat.
APIExpose is a local companion for RetroBat. It adds practical automation around EmulationStation: media and gamelist updates, ROM pack installation, dynamic collections, theme data, CPO panel data, WebSocket streams and a local API.
French version: README.fr.md
Launch only start.bat from E:\RetroBat\plugins\APIExpose. Do not start
RetroBat before it, and do not relaunch RetroBat manually after it:
start.bat stops previous RetroBat.Api, emulationstation and RetroBat
processes, starts APIExpose, waits until the APIExpose health endpoint on
127.0.0.1:12345 is ready, then launches RetroBat. This does not wait for the
EmulationStation API on 127.0.0.1:1234; ES is launched by RetroBat afterward.
The wait gives APIExpose time to update EmulationStation settings, install its
menu entries, run startup migrations and prepare on-the-fly ROM pack
gamelists/media before ES reads them.
For API console diagnostics, use start-log.bat. This mode applies the same
startup cleanup, but keeps APIExpose in the foreground and does not launch
RetroBat automatically.
- Auto-scrape local and remote media, then update the current game view when a useful change is found.
- Keep a local-first media store so your own files, downloaded media and pack media are organized before they are projected into ES.
- Install ROM packs, gamelists and media automatically from
.zip,.7zor.rararchives. - Use on-the-fly ROM installation so large packs can appear in ES without extracting every ROM immediately.
- Generate or repair gamelists from ROM packs, media packs or local media.
- Build dynamic collections from gamelist
familyvalues, so collections can grow automatically when matching games are added. - Install collection packs and deploy collection theme assets.
- Apply collection themes to games when no dedicated game theme exists.
- Deploy theme media through configurable
ThemeDeploymentsandMediaDeploymentRules. - Expose CPO/control panel data for themes, LEDs and external clients.
- Expose in-game and arcade runtime events through WebSocket.
- Export high score data for modern theme data and legacy
.hiscoreworkflows. - Send useful marquee, logo, fanart and game context data to WebSocket clients.
- Add APIExpose options directly into RetroBat/EmulationStation menus with native locale support.
- Provide a local HTTP API and Swagger UI for tools, dashboards or future hub workflows.
APIExpose is built around a simple idea: RetroBat stays the playable frontend, while APIExpose quietly prepares better local data for it.
The most important piece is the local media store. APIExpose tries to centralize
media in media/ first, then project it into RetroBat and EmulationStation
formats only when needed. This avoids random one-off writes in gamelists and
keeps a clearer source of truth:
media/user -> your priority files
media -> canonical local store
roms/... -> EmulationStation projection
gamelist -> final ES view of the game
That local-first approach matters because packs, scraping, collection themes and manual media fixes all end up speaking the same language. If a theme or a gamelist changes later, APIExpose can rebuild the visible projection from local media instead of guessing from whatever was already written in a gamelist.
- ROM packs can be installed from
package-installer/at API startup. - On-the-fly ROM installation can build gamelists and media first, then extract the selected game only when it is needed.
- Collection packs can be installed from
package-installer/collections/<theme-name>/. - Collection themes can be applied to games from the same family when no dedicated game theme exists.
- Theme deployment is configurable from
appsettings.jsonthroughThemeDeploymentsandMediaDeploymentRules. - Local metadata can be normalized from Swagger without remote scraping. This cleans polluted locale values in local metadata and, if requested, rewrites matching gamelist fields from the qualified local value.
- Local Media Manager projections are strict:
LOGOaccepts simple logo/wheel media,WHEEL HDaccepts only the selected carbon or steel wheel, and missing source media leaves the visible ES slot empty. - Auto Scraping Manager can notify the end of heavy media scraping through
NOTIFIER LE SCRAP MEDIA. The notification is sent only when a manual, magazine or video is really imported. themehbis local-first. A canonical archive inmedia/systems/<system>/blocks remote ScreenScraper scraping, while installation into the active HyperBat theme only runs when the current ES theme set is an installed HyperBat folder.- APIExpose menu labels are translated through RetroBat's native
es_features.localefiles. APIExpose menu labels are kept complete across supported locales, while technical media names such asSCREENSHOT,TITLESHOT,THUMBNAILandMARQUEEintentionally stay stable.
| Goal | Put files here | What APIExpose does |
|---|---|---|
| Install a ROM pack | package-installer/ |
Imports ROMs, media and gamelist entries at startup. |
| Use on-the-fly ROMs | package-installer/ |
Prepares gamelist/media at startup, extracts a missing ROM on demand. |
| Install a collection/theme pack | package-installer/collections/<theme-name>/ |
Creates dynamic or static collections and deploys collection theme assets. |
| Add local game media | media/user/systems/<system>/games/<game-slug>/ |
Uses your files before downloaded/cache media and projects them into ES gamelists. |
| Add CPO panel definitions | resources/dynpanels/systems/ or resources/dynpanels/games/ |
Exposes button colors, functions and controller types to themes, LEDs and WebSocket clients. |
| Add RAM/event definitions | resources/ram/<system>/ |
Lets the in-game event listener expose runtime signals for supported games. |
| Add startup splash images | resources/startup-overlay/ |
Displays one numbered splash image during API startup and pack processing. |
| Add menu translations | resources/config-ESmenus/locales/<locale>/es-features.po |
Merges APIExpose menu translations into RetroBat's es_features.locale folder. |
Drop .zip, .7z or .rar packs directly into:
package-installer/
Example:
package-installer/GX4000 (26 games).7z
package-installer/Megadrive 32x (36 games).7z
At API startup, if ROMS PACK MANAGER > ROM PACK INSTALLER or
ROMS PACK MANAGER > ON-THE-FLY ROM INSTALLER is enabled, APIExpose scans the
folder and compares its pack index. The folder is not watched continuously: a
pack dropped while the API is already running is processed on next API startup,
after an installer option change, or through POST /api/v1/rom-packs/rescan.
A pack may contain:
gx4000/
roms/
images/
videos/
manuals/
gamelist.xml
or a simpler structure:
gx4000/
*.zip
*.7z
images/
APIExpose detects the target system from the pack name or from a top-level folder when possible.
Media naming rules inside ROM packs:
*-screenshot.* -> SCREENSHOT
*-image.* -> SCREENTITLE
*-marquee.* -> simple logo / wheel, not wheel-carbon/steel
*-thumb.* -> BOX 3D
*-thumbnail.* -> BOX 3D
*-fanart.* -> fanart
*-flyer.* -> flyer
*-video.* -> video
*-manual.* -> manual
The installer imports media into the canonical media/ store, then lets the
Local Media Manager decide which files are written to <image>, <marquee> and
<thumbnail> according to the ES options.
Localized media use the Local Media Manager region selector. By default it uses
the user locale (region_mode=local, user_region=auto). Forcing a region
acts like a media reallocation: the gamelist keeps one active slot such as
<boxart>, <cartridge> or extended <label>, while regional variants remain
in media/ as files like front-us.png, cartridge-eu.png or label-jp.png.
Enable ROMS PACK MANAGER > ON-THE-FLY ROM INSTALLER if you want games to be
visible without installing every ROM immediately. In this mode, startup prepares
the gamelist, canonical media and pack index only; it does not install the real
ROM payloads.
At startup APIExpose:
- indexes the pack,
- creates or enriches gamelist entries,
- imports media,
- forces
ParseGamelistOnly=truein ES settings, - keeps the ROM archive available for later extraction.
When a game stays selected long enough and its ROM is missing, APIExpose shows a message box asking you not to launch the game yet, extracts the archive, then notifies that the game is installed.
UNZIP ROMS is a transversal option: if enabled, internal ROM archives are also
extracted when a game is materialized from a pack.
Drop collection/theme packs into:
package-installer/collections/<theme-name>/
Example:
package-installer/collections/hyperbat/sonic.zip
package-installer/collections/hyperspin/mario.7z
At startup, if COLLECTIONS PACK MANAGER > COLLECTION PACK INSTALLER is
enabled, APIExpose installs the pack, creates collections and deploys theme
assets according to appsettings.json.
Dynamic collections are family-based. APIExpose consolidates family values
from gamelists and creates .xcc filters so the collection can grow later when
new matching games are added.
Example family-based collection:
<?xml version="1.0"?>
<filter name="mario">
<family>MARIO</family>
<family>MARIO KART, MARIO</family>
<family>MARIO, SUPER MARIO BROS</family>
</filter>If ENABLE FOR THEMES is enabled, a collection system theme can be converted
into a game theme for games in that collection when no dedicated game theme or
canonical parent/clone theme exists.
User media belongs in:
media/user/systems/<system>/games/<game-slug>/
Example:
media/user/systems/nes/games/super-mario-bros-3/
artwork/screens/ingame.png
artwork/box/front.png
ui/wheels/wheel.png
documents/manuals/manual.pdf
User media has priority over cache/downloaded media. APIExpose can project it to RetroBat paths and update the gamelist without mixing media families.
Visible ES slots are controlled by ES menu options:
MAIN IMAGE -> <image>
LOGO / MARQUEE -> <marquee>
THUMBNAIL -> <thumbnail>
WHEEL HD STYLE -> wheel-carbon or wheel-steel when selected
LOGO may use a simple logo or a simple ScreenScraper wheel because both are
plain logo-like assets for <marquee>. WHEEL HD is separate and only uses the
selected carbon or steel wheel. If the selected source does not exist, APIExpose
leaves the slot empty instead of replacing it with another media family.
Before a global reallocation or a ROM Set Manager change that affects games, return to the system screen first. If ES is still on a game card, APIExpose shows a message box: the current system may not refresh and the changes may not be visible there until you leave the game list.
Auto scraping is configured from EXTENDED OPTIONS > AUTO SCRAPING MANAGER.
APIExpose follows the appsettings-backed options exposed there: ES native
scraper flags are mirrored for the interface, but they do not block APIExpose's
local/remote scraping policy.
Important options:
ENABLE AUTO SCRAPING MANAGER
ENABLE SCREENSCRAPER
ENABLE SCRAPING QUEUE
REMOTE SCRAPE AFTER LOCAL
REFRESH GAME VIEW AFTER SCRAPE
NOTIFIER LE SCRAP MEDIA
SCRAPER LES MARQUEES
SCRAPER LES SCREEN MARQUEES
SCRAPER LES SMALL SCREEN MARQUEES
SCRAPER LES STEAMGRID
SCRAPER LES MIX
SCRAPER LES MANUELS
SCRAPER LES MAGAZINES
SCRAPER LES VIDEOS
SCRAPER LES VIDEOS NORMALISEES
SCRAPER LES BEZELS
BEZEL ASPECT
BEZEL ORIENTATION
NOTIFIER LE SCRAP MEDIA only controls the completion notification for heavy
remote media: manuals, magazines, videos and normalized videos. It does not
force a live /addgames refresh by itself.
Theme deployment rules are configured in appsettings.json.
Useful sections:
"ThemeDeployments": [],
"MediaDeploymentRules": []This lets you add a new deployable theme target without recompiling the API. A rule can define:
- which media kind to scrape or deploy,
- which active ES theme it applies to,
- where the archive is installed,
- extra media copies such as bezels, marquee assets or theme-specific folders.
For themehb, the canonical archive is:
media/systems/<system>/games/<game-slug>/themes/themehb.zip
Arcade-like systems such as mame, fbneo, fba and hbmame share the
canonical arcade media store. The canonical zip prevents a new remote
ScreenScraper download, but it can still be installed locally into the active
HyperBat theme when that theme set is currently selected and installed under
EmulationStation's themes/ folder. If the current ES theme is not HyperBat,
APIExpose skips the live themehb scrape, local extraction and F5 refresh.
Put system panel definitions here:
resources/dynpanels/systems/<system>.json
Put arcade game overrides here:
resources/dynpanels/games/<rom>.json
When enabled, APIExpose exposes:
- button colors,
- button functions,
- controller types,
- the resolved panel configuration in the WebSocket stream.
Game-level panel files are for arcade overrides. Console and computer systems normally use the system-level panel definition.
Runtime definitions are stored here:
resources/ram/<system>/<game>.MEM
resources/ram/<system>/alias.json
Example:
resources/ram/megadrive/sonic-the-hedgehog.MEM
resources/ram/megadrive/alias.json
These files let the in-game event listener expose useful signals to WebSocket clients, overlays, panels or score tools.
Startup images are stored in:
resources/startup-overlay/
Use numbered files:
splashscreen0.png
splashscreen1.png
splashscreen2.png
APIExpose can pick one randomly at startup. The splash also shows startup steps, including ROM pack checks and installation progress.
Default endpoints:
API: http://127.0.0.1:12345
Swagger: http://127.0.0.1:12345/swagger/index.html
WebSocket: ws://127.0.0.1:12345/ws
Health: GET /api/v1/health
Expected health response:
{
"status": "healthy",
"version": "1.0.0+20260518.000518"
}Useful maintenance endpoints are also exposed in Swagger:
POST /api/v1/media/gamelist/refresh-selections
POST /api/v1/media/metadata/normalize
refresh-selections reapplies the current Local Media Manager choices to one
or more systems. metadata/normalize cleans local metadata pollution and can
repair mojibake text. It can also normalize text fields already present in
gamelist.xml, but only when explicitly requested with
normalizeExistingGamelists: true. That pass also collapses multilingual genre
lists stored in a single tag. Neither endpoint starts a remote scrape by itself.
During live navigation, APIExpose does not directly rewrite
roms/<system>/gamelist.xml after /addgames: Batocera ES already does that.
Extended fields used by themes are staged under
media/aliases/shared/gamelist-extended-pending/, then exposed at API startup or
just before a reloadgames.
Controlled exception: when the Windows confirmation accepts the canonical
migration of legacy roms/<system>/images, videos and manuals folders,
APIExpose also updates gamelists so media tags point to canonical media/
paths. Without that pass, ES could keep references to files that were just moved
or removed from roms/.
A live /addgames is sent only when the current ES game card needs a visible
change: visible media was missing when the game was selected, or visible local
media has just been projected/changed. A disk gamelist.xml mismatch after a
global filter change does not refresh each card if ES is already showing a
complete card.
APIExpose is designed to be conservative:
- it does not delete ROMs automatically,
- it backs up gamelists before replacing them,
- it validates XML before writing,
- it uses pack indexes to avoid reinstalling unchanged packs,
- it debounces live scraping, extraction and UI refreshes,
- it sends one startup stabilization F5 a few seconds after the ES API responds,
- it spaces live
/addgamesPOSTs so ES can finish internal refresh work, - it defers extended gamelist tags outside
game-selected, - it removes its temporary ES feature integration when ES stops.
Detailed module notes are available in:
docs/ROM_PACK_INSTALLER.md
docs/DOCS_INDEX.md
docs/LOCAL_MEDIA_MANAGEMENT.md
docs/DATAS_THEME_EXPOSE.md
docs/VERSIONING_PROCESS.md
resources/config-ESmenus/README_APIExpose_RetroBat_Options.txt