Skip to content

Events

Every APIExpose event is a JSON envelope pushed over WebSocket:

{
  "Type": "ui.game.started",
  "Ts": "2026-07-08T13:05:12.412Z",
  "NodeId": "cab-01",
  "CorrelationId": "6f0c…",
  "Payload": { }
}

The SDK normalizes it before your handlers run:

client.on('game.changed', (event) => {
  event.type;      // normalized name that matched your subscription
  event.rawType;   // original APIExpose Type, e.g. "ui.game.started"
  event.timestamp; // ISO string
  event.nodeId;    // "cab-01"
  event.payload;   // Payload, camelCase and PascalCase both accepted
});

The raw type is always re-emitted as-is alongside any alias — nothing is hidden. The JSON Schema of the envelope lives in schemas/event.schema.json.

Normalized aliases

Alias Raw prefix / type Fires when
game.changed ui.game.selected* (deduplicated per system+rom) a different game is selected or started
game.selected ui.game.selected* every selection event
system.changed ui.system.selected* the ES system changes
score.changed score.live.* the live score changes in-game
timer.changed timer.live.* the live timer ticks
hiscore.changed hiscore.* hiscore data is refreshed
achievement.unlocked retroachievements.achievement.unlock* a RetroAchievements cheevo pops
arcade.output.changed mame.output.changed, arcade.output* MAME/FBNeo lamps & outputs
media.changed media.* media/scraping activity
panel.changed panel.state the control-panel layout changes
connection.lost / connection.restored (SDK-internal) WebSocket connectivity

Wildcards

client.on('retroachievements.*', handler); // any raw type with that prefix
client.on('*', handler);                   // everything (used by the debug monitor)

Real event types, observed live

Captured on APIExpose 1.1.1 while launching Sonic The Hedgehog (Megadrive, RetroArch):

ui.game.started.raw / ui.game.started
retroarch.wrapper.connected
retroarch.memory.changed
retroachievements.session.login.detected
retroachievements.session.started
retroachievements.session.updated
retroachievements.catalog.updated
retroachievements.achievementsets.loaded
retroachievements.proxy.requested / retroachievements.proxy.response
panel.state
cpo.panel.config.selected
marquee.snapshot / marquee.snapshot.updated
topper.snapshot
instruction-card.snapshot
screen.snapshot

During gameplay (including ES demo mode) score.live.changed and timer.live.changed flow for systems with score support.

Payload shapes vary

Payloads are event-specific and may evolve with APIExpose. Treat unknown fields as optional — the Event Debug Monitor is the quickest way to inspect the exact payloads your installation produces.