API Reference
WebSocket API
Real-time events and session management via WebSocket connection.
WebSocket API
NodeLink uses WebSocket connections to provide real-time communication between the server and clients. This connection is essential for receiving player events, track updates, and server statistics.
Connection
Connect to this endpoint to establish a WebSocket session.
Headers
AuthorizationstringRequired
The server password defined in config.js.
Client-NamestringRequired
Name and version of your client (e.g., "MyMusicBot/1.0.0").
User-IdstringRequired
Discord User ID of the bot. Must be 18-19 digits.
Session-Idstring
Session ID to resume. If provided, attempts to resume previous session.
Response
Resume a previous session after disconnection within the timeout period (default: 60 seconds).
Response
When successfully resumed using the Session-Id header, the server sends a ready event with resumed: true. All queued events from the disconnection period are immediately sent, followed by current state updates from all active players.
Incoming Events (Server → Client)
NodeLink sends various events to keep clients informed about playback status, player state, and server statistics. All events are sent as JSON messages.
Ready Event
ReadyEvent
EVENTSent immediately after WebSocket connection is established.
Payload Structure
opstring
Always "ready"
resumedboolean
Whether this is a resumed session or new session
sessionIdstring
Unique session identifier for this connection
Example
{
"op": "ready",
"resumed": false,
"sessionId": "xY7kP2mN8vQ4rL1s"
}Player Update
PlayerUpdate
EVENTSent periodically (every 5 seconds) with current playback position and connection status for each active player.
Payload Structure
opstring
Always "playerUpdate"
guildIdstring
Discord guild ID where player is active
stateobject
Current player state
state.timenumber
Current Unix timestamp in milliseconds
state.positionnumber
Current track position in milliseconds
state.connectedboolean
Whether player is connected to voice channel
state.pingnumber
Voice connection ping in milliseconds
Example
{
"op": "playerUpdate",
"guildId": "987654321098765432",
"state": {
"time": 1701350400000,
"position": 45230,
"connected": true,
"ping": 42
}
}Stats Event
StatsEvent
EVENTServer statistics sent every minute with system resource usage and playback metrics.
Payload Structure
opstring
Always "stats"
playersnumber
Total number of active players across all guilds
playingPlayersnumber
Number of players currently playing audio
uptimenumber
Server uptime in milliseconds since start
memoryobject
Memory usage information in bytes
memory.freenumber
Free system memory
memory.usednumber
Memory used by NodeLink process
memory.allocatednumber
Total allocated memory
memory.reservablenumber
Maximum reservable memory
cpuobject
CPU usage information
cpu.coresnumber
Number of CPU cores
cpu.systemLoadnumber
System-wide CPU load (0.0-1.0)
cpu.processLoadnumber
NodeLink process CPU load (0.0-1.0)
frameStatsobject
Audio frame statistics (null if no active players)
frameStats.sentnumber
Total audio frames sent to Discord
frameStats.nullednumber
Frames that were null/empty
frameStats.deficitnumber
Frames that failed to send
Example
{
"op": "stats",
"players": 5,
"playingPlayers": 3,
"uptime": 3600000,
"memory": {
"free": 4294967296,
"used": 536870912,
"allocated": 1073741824,
"reservable": 8589934592
},
"cpu": {
"cores": 8,
"systemLoad": 0.25,
"processLoad": 0.08
},
"frameStats": {
"sent": 15000,
"nulled": 0,
"deficit": 0
}
}Track Start Event
TrackStartEvent
EVENTSent when a track begins playing on any player.
Payload Structure
opstring
Always "event"
typestring
Always "TrackStartEvent"
guildIdstring
Discord guild ID where track started
trackobject
Full track information including encoded data
track.encodedstring
Base64 encoded track data
track.infoobject
Track metadata
Example
{
"op": "event",
"type": "TrackStartEvent",
"guildId": "987654321098765432",
"track": {
"encoded": "QAAAjQIAJVJpY2sgQXN0bGV5IC0gTmV2ZXIgR29ubmEgR2l2ZSBZb3UgVXAADlJpY2tBc3RsZXlWRVZPAAAAAAACyPgAC2RRdzR3OVdnWGNRAAEAK2h0dHBzOi8vd3d3LnlvdXR1YmUuY29tL3dhdGNoP3Y9ZFF3NHc5V2dYY1EAB3lvdXR1YmUAAAAAAAAAAA==",
"info": {
"identifier": "dQw4w9WgXcQ",
"isSeekable": true,
"author": "Rick Astley",
"length": 212000,
"isStream": false,
"position": 0,
"title": "Never Gonna Give You Up",
"uri": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"artworkUrl": "https://i.ytimg.com/vi/dQw4w9WgXcQ/maxresdefault.jpg",
"isrc": null,
"sourceName": "youtube"
}
}
}Track End Event
TrackEndEvent
EVENTSent when a track finishes playing or is stopped for any reason.
Payload Structure
opstring
Always "event"
typestring
Always "TrackEndEvent"
guildIdstring
Discord guild ID
trackobject
Track information
reasonstring
End reason: stopped, finished, loadFailed, replaced, cleanup
End Reasons
finishedstring
Track completed normally
stoppedstring
Track was manually stopped
replacedstring
Track was replaced by another track
loadFailedstring
Track failed to load
cleanupstring
Track ended due to cleanup (player destroyed)
Example
{
"op": "event",
"type": "TrackEndEvent",
"guildId": "987654321098765432",
"track": {
"encoded": "QAAAjQIAJVJpY2sgQXN0bGV5IC0gTmV2ZXIgR29ubmEgR2l2ZSBZb3UgVXAADlJpY2tBc3RsZXlWRVZPAAAAAAACyPgAC2RRdzR3OVdnWGNRAAEAK2h0dHBzOi8vd3d3LnlvdXR1YmUuY29tL3dhdGNoP3Y9ZFF3NHc5V2dYY1EAB3lvdXR1YmUAAAAAAAAAAA==",
"info": {
"identifier": "dQw4w9WgXcQ",
"title": "Never Gonna Give You Up",
"author": "Rick Astley",
"length": 212000,
"sourceName": "youtube"
}
},
"reason": "finished"
}Track Exception Event
TrackExceptionEvent
EVENTSent when an error occurs during track playback.
Payload Structure
opstring
Always "event"
typestring
Always "TrackExceptionEvent"
guildIdstring
Discord guild ID
trackobject
Track that caused the exception
exceptionobject
Error details
exception.messagestring
Human-readable error message
exception.severitystring
Error severity: common, suspicious, fault
exception.causestring
Root cause description
Severity Levels
commonstring
Expected error (e.g., track unavailable)
suspiciousstring
Unusual but recoverable error
faultstring
Critical error that prevents playback
Example
{
"op": "event",
"type": "TrackExceptionEvent",
"guildId": "987654321098765432",
"track": {
"encoded": "...",
"info": {
"identifier": "invalid123",
"title": "Invalid Track"
}
},
"exception": {
"message": "Failed to load track",
"severity": "fault",
"cause": "Video unavailable"
}
}Track Stuck Event
TrackStuckEvent
EVENTSent when playback is stuck and hasn't progressed for the threshold period.
Payload Structure
opstring
Always "event"
typestring
Always "TrackStuckEvent"
guildIdstring
Discord guild ID
trackobject
Track that is stuck
thresholdMsnumber
Time in milliseconds before considering stuck (typically 10000ms)
Example
{
"op": "event",
"type": "TrackStuckEvent",
"guildId": "987654321098765432",
"track": {
"encoded": "...",
"info": {
"identifier": "dQw4w9WgXcQ",
"title": "Never Gonna Give You Up"
}
},
"thresholdMs": 10000
}WebSocket Closed Event
WebSocketClosedEvent
EVENTSent when the voice WebSocket connection to Discord closes.
Payload Structure
opstring
Always "event"
typestring
Always "WebSocketClosedEvent"
guildIdstring
Discord guild ID
codenumber
Discord voice WebSocket close code
reasonstring
Human-readable close reason
byRemoteboolean
Whether the close was initiated by Discord (true) or locally (false)
Common Discord Voice Close Codes
4014number
Disconnected - channel was deleted or you were kicked
4006number
Session no longer valid
4015number
Voice server crashed
Example
{
"op": "event",
"type": "WebSocketClosedEvent",
"guildId": "987654321098765432",
"code": 4014,
"reason": "Disconnected",
"byRemote": true
}Player Lifecycle Events
PlayerCreatedEvent
EVENTEmitted when a new player is created for a guild.
Payload Structure
opstring
Always "event"
typestring
Always "PlayerCreatedEvent"
guildIdstring
Discord guild ID
Example
{
"op": "event",
"type": "PlayerCreatedEvent",
"guildId": "987654321098765432"
}PlayerDestroyedEvent
EVENTEmitted when a player is destroyed.
Payload Structure
opstring
Always "event"
typestring
Always "PlayerDestroyedEvent"
guildIdstring
Discord guild ID
Example
{
"op": "event",
"type": "PlayerDestroyedEvent",
"guildId": "987654321098765432"
}PlayerConnectedEvent
EVENTEmitted when player successfully connects to Discord voice channel.
Payload Structure
opstring
Always "event"
typestring
Always "PlayerConnectedEvent"
guildIdstring
Discord guild ID
Example
{
"op": "event",
"type": "PlayerConnectedEvent",
"guildId": "987654321098765432"
}EVENT
Emitted when player is attempting to reconnect to voice.
Payload Structure
opstring
Always "event"
typestring
Always "PlayerReconnectingEvent"
guildIdstring
Discord guild ID
Example
{
"op": "event",
"type": "PlayerReconnectingEvent",
"guildId": "987654321098765432"
}Player State Events
VolumeChangedEvent
EVENTEmitted when player volume is changed.
Payload Structure
opstring
Always "event"
typestring
Always "VolumeChangedEvent"
guildIdstring
Discord guild ID
volumenumber
New volume level (0-1000)
Example
{
"op": "event",
"type": "VolumeChangedEvent",
"guildId": "987654321098765432",
"volume": 80
}FiltersChangedEvent
EVENTEmitted when audio filters are modified.
Payload Structure
opstring
Always "event"
typestring
Always "FiltersChangedEvent"
guildIdstring
Discord guild ID
filtersobject
Active filter configuration
Example
{
"op": "event",
"type": "FiltersChangedEvent",
"guildId": "987654321098765432",
"filters": {
"volume": 1.0,
"equalizer": [
{ "band": 0, "gain": 0.2 }
]
}
}SeekEvent
EVENTEmitted when seeking to a position in the track.
Payload Structure
opstring
Always "event"
typestring
Always "SeekEvent"
guildIdstring
Discord guild ID
positionnumber
New position in milliseconds
Example
{
"op": "event",
"type": "SeekEvent",
"guildId": "987654321098765432",
"position": 60000
}PauseEvent
EVENTEmitted when playback is paused or resumed.
Payload Structure
opstring
Always "event"
typestring
Always "PauseEvent"
guildIdstring
Discord guild ID
pausedboolean
Whether playback is now paused (true) or resumed (false)
Example
{
"op": "event",
"type": "PauseEvent",
"guildId": "987654321098765432",
"paused": true
}EVENT
Emitted when voice connection status changes.
Payload Structure
opstring
Always "event"
typestring
Always "ConnectionStatusEvent"
guildIdstring
Discord guild ID
connectedboolean
Current connection status
Example
{
"op": "event",
"type": "ConnectionStatusEvent",
"guildId": "987654321098765432",
"connected": true
}