Realtime Events
StreamerSonglist publishes realtime events over a WebSocket transport powered by Centrifugo. Subscribe to a streamer's channel(s) to receive push updates whenever the queue, songlist, play history, or saved queue changes — no polling required.
Endpoint
wss://events.streamersonglist.com/connection/websocket
Anonymous connections are accepted: you do not need to obtain a token to connect or subscribe.
Clients
You can integrate with any tool that speaks the Centrifugo client protocol:
- An official
centrifuge-*SDK in your language. See the SDK list — available SDKs includecentrifuge-js,centrifuge-go,centrifuge-python,centrifuge-java,centrifuge-swift, andcentrifuge-dart. - A native WebSocket client in your language, speaking the Centrifugo JSON framing directly. See the WebSocket transport and client protocol references.
Channels
Every event is published to a category-specific channel and the streamer's base channel. Subscribe to the base channel for a firehose of every event for a streamer; subscribe to a category channel to receive only the events you care about.
| Channel Pattern | Scope | Visibility |
|---|---|---|
streamer:{streamerId} | All public events for the streamer | Public |
streamer:{streamerId}-{category} | One category of public events for the streamer | Public |
streamer-admin:{streamerId} | All admin events for the streamer | Admin |
streamer-admin:{streamerId}-{category} | One category of admin events for the streamer | Admin |
The {category} segment is one of: queue, play_history, saved-queue,
song, action_log.
Event Envelope
Every publication has the following shape:
{
"type": "<event_type>",
"data": <payload or null>
}
When data is null, treat the event as a signal to refetch the relevant
resource via the REST API.
Event Reference
Queue
Channels: streamer:{streamerId}, streamer:{streamerId}-queue
| Type | Payload | When it fires |
|---|---|---|
queue_add | QueueDetails | A song was added to the queue |
queue_remove | { "id": number } | A queue entry was removed or marked played |
queue_update | null | The queue order changed or an entry was edited |
Play History
Channels: streamer:{streamerId}, streamer:{streamerId}-play_history
| Type | Payload | When it fires |
|---|---|---|
play_history_add | null | A new play history entry was created |
Saved Queue
Channels: streamer:{streamerId}, streamer:{streamerId}-saved-queue
| Type | Payload | When it fires |
|---|---|---|
saved_queue_update | null | The saved queue was modified |
Song
Channels: streamer:{streamerId}, streamer:{streamerId}-song
| Type | Payload | When it fires |
|---|---|---|
song_add | null | A new song was added to the songlist |
song_update | null | A song's metadata was edited |
Action Log
Channels: streamer-admin:{streamerId}, streamer-admin:{streamerId}-action_log
| Type | Payload | When it fires |
|---|---|---|
action_log_add | null | A new action log entry was created |
Payload Types
QueueDetails
{
id: number;
note: string | null;
createdAt: string; // ISO-8601
songId: number | null;
nonlistSong: string | null;
streamerId: number;
position: number;
song: {
title: string;
artist: string;
lastPlayed: string | null; // ISO-8601
lastPlayedFrom: string;
timesPlayed: number;
comment: string | null;
capo: string | null;
attributes: { name: string; image: string | null }[];
};
requests: {
id: number;
name: string;
amount: number;
requestText: string;
source: string;
createdAt: string; // ISO-8601
user: { username: string; platform: string } | null;
}[];
}
Example: centrifuge-js
import { Centrifuge } from 'centrifuge';
const client = new Centrifuge('wss://events.streamersonglist.com/connection/websocket');
const sub = client.newSubscription(`streamer:${streamerId}-queue`);
sub.on('publication', (ctx) => {
const event = ctx.data as { type: string; data: unknown };
switch (event.type) {
case 'queue_add':
// event.data is QueueDetails
break;
case 'queue_remove':
// event.data is { id: number }
break;
case 'queue_update':
// refetch the queue from the REST API
break;
}
});
sub.subscribe();
client.connect();
To receive every event for a streamer in a single subscription, subscribe to
streamer:${streamerId} instead and switch on event.type.
Example: native WebSocket
If you'd rather not pull in a Centrifugo SDK, you can speak the protocol
directly over a plain WebSocket. The framing is documented in the
Centrifugo client protocol
reference — at minimum you'll need to send a connect command on open and a
subscribe command for each channel, then read publication frames as they
arrive.