Skip to content

Streams

APIExpose exposes one firehose and 17 filtered streams:

Endpoint Content
ws://127.0.0.1:12345/ws every event except esevent.*
ws://127.0.0.1:12345/ws/<stream> only the events routed to that stream

By default the SDK opens the single /ws firehose. To subscribe to specific streams instead:

const client = new APIExposeClient({ streams: ['score', 'timer', 'frontend'] });

Each stream gets its own socket; the SDK reconnects each one independently and reports a single connection.lost / connection.restored state.

Routing table

Events are routed to streams by their Type prefix:

Stream Type prefixes
frontend ui.
marquee marquee.
topper topper.
instruction-card instruction-card.
screen screen.
panel panel., theme.
ingame ingame., retroarch., wrapper.
arcade arcade., mame., fbneo., outputs.
score score.live.
timer timer.live.
retroachievements retroachievements.
hiscore hiscore.
media media.
roms roms., rom-pack., romset.
system startup., health., version., hub., config., maintenance., rules., notifications.
control commands., intent., es-control.
esevent esevent.only available here, not on the firehose

Firehose or streams?

For overlays the firehose is simplest and cheap (loopback traffic). Use filtered streams when you embed the SDK in constrained clients or want hard isolation per concern — e.g. a marquee display only opening /ws/marquee.