API Implementation guidelines¶
How to write your own client.
Required capabilities of your Discord library¶
- You must be able to send messages via a shard's gateway connection.
- You must be able to intercept voice server & voice state updates from the gateway on your shard connection.
Insomnia Collection¶
You can find an Insomnia collection in the here which contains all the endpoints and their respective payloads.
Significant changes¶
v3.7.0 -> v4.0.0¶
- removed all non version
/v3
or/v4
endpoints (except/version
). /v4/websocket
does not accept any messages anymore.v4
uses thesessionId
instead of theresumeKey
for resuming.v4
now returns the tracksartworkUrl
andisrc
if the source supports it.- removal of deprecated json fields like
track
. - addition of
artworkUrl
andisrc
fields to the Track Info object. - addition of the full Track object in TrackStartEvent, TrackEndEvent, TrackExceptionEvent and TrackStuckEvent.
- updated capitalization of Track End Reason and Severity
- reworked Load Result object
v4.0.0 Migration Guide
All websocket ops are removed as of v4.0.0
and replaced with the following endpoints and json fields:
play
-> Update Player EndpointencodedTrack
oridentifier
fieldstop
-> Update Player EndpointencodedTrack
field withnull
pause
-> Update Player Endpointpause
fieldseek
-> Update Player Endpointposition
fieldvolume
-> Update Player Endpointvolume
fieldfilters
-> Update Player Endpointfilters
fielddestroy
-> Destroy Player EndpointvoiceUpdate
-> Update Player Endpointvoice
fieldconfigureResuming
-> Update Session Endpoint
Older versions
v3.6.0 -> v3.7.0¶
- Moved HTTP endpoints under the new
/v3
path with/version
as the only exception. - Deprecation of the old HTTP paths.
- WebSocket handshakes should be done with
/v3/websocket
. Handshakes on/
are now deprecated. - Deprecation of all client-to-server messages (play, stop, pause, seek, volume, filters, destroy, voiceUpdate & configureResuming).
- Addition of REST endpoints intended to replace client requests.
- Addition of new WebSocket dispatch Ready OP to get
sessionId
andresume
status. - Addition of new Session/Player REST API.
- Addition of
/v3/info
, replaces/plugins
. - Deprecation of
Track.track
in existing endpoints. UseTrack.encoded
instead. - Deprecation of
TrackXEvent.track
in WebSocket dispatches. UseTrackXEvent.encodedTrack
instead. - Player now has a
state
field which contains the same structure as returned by theplayerUpdate
OP.
v3.7.0 Migration Guide
All websocket ops are deprecated as of v3.7.0
and replaced with the following endpoints and json fields:
play
-> Update Player Endpointtrack
oridentifier
fieldstop
-> Update Player Endpointtrack
field withnull
pause
-> Update Player Endpointpause
fieldseek
-> Update Player Endpointposition
fieldvolume
-> Update Player Endpointvolume
fieldfilters
-> Update Player Endpointfilters
fielddestroy
-> Destroy Player EndpointvoiceUpdate
-> Update Player Endpointvoice
fieldconfigureResuming
-> Update Session Endpoint
v3.3 -> v3.4¶
- Added filters
- The
error
string on theTrackExceptionEvent
has been deprecated and replaced by the Exception object following the same structure as theLOAD_FAILED
error on/loadtracks
. - Added the
connected
boolean to player updates. - Added source name to REST api track objects
- Clients are now requested to make their name known during handshake
v2.0 -> v3.0¶
- The response of
/loadtracks
has been completely changed (again since the initial v3.0 pre-release). - Lavalink v3.0 now reports its version as a handshake response header.
Lavalink-Major-Version
has a value of3
for v3.0 only. It's missing for any older version.
v1.3 -> v2.0¶
With the release of v2.0 many unnecessary ops were removed:
connect
disconnect
validationRes
isConnectedRes
validationReq
isConnectedReq
sendWS
With Lavalink 1.x the server had the responsibility of handling Discord VOICE_SERVER_UPDATE
s as well as its own internal ratelimiting.
This remote handling makes things unnecessarily complicated and adds a lot og points where things could go wrong.
One problem we noticed is that since JDA is unaware of ratelimits on the bot's gateway connection, it would keep adding
to the ratelimit queue to the gateway. With this update this is now the responsibility of the Lavalink client or the
Discord client.
A voice connection is now initiated by forwarding a voiceUpdate
(VOICE_SERVER_UPDATE) to the server. When you want to
disconnect or move to a different voice channel you must send Discord a new VOICE_STATE_UPDATE. If you want to move your
connection to a new Lavalink server you can simply send the VOICE_SERVER_UPDATE to the new node, and the other node
will be disconnected by Discord.
Depending on your Discord library, it may be possible to take advantage of the library's OP 4 handling. For instance, the JDA client takes advantage of JDA's websocket write thread to send OP 4s for connects, disconnects and reconnects.
Protocol¶
Reference¶
Fields marked with ?
are optional and types marked with ?
are nullable.
Resuming¶
What happens after your client disconnects is dependent on whether the session has been configured for resuming.
- If resuming is disabled all voice connections are closed immediately.
- If resuming is enabled all music will continue playing. You will then be able to resume your session, allowing you to control the players again.
To enable resuming, you must call the Update Session endpoint with the resuming
and timeout
.
To resume a session, specify the session id in your WebSocket handshake request headers:
Session-Id: The id of the session you want to resume.
You can tell if your session was resumed by looking at the handshake response header Session-Resumed
which is either true
or false
.
Session-Resumed: true
In case your websocket library doesn't support reading headers you can listen for the ready op and check the resumed
field.
When a session is paused, any events that would normally have been sent are queued up. When the session is resumed, this queue is then emptied and the events are replayed.
Special notes¶
-
When your shard's main WS connection dies, so does all your Lavalink audio connections
- This also includes resumes
-
If Lavalink-Server suddenly dies (think SIGKILL) the client will have to terminate any audio connections by sending this event to Discord:
{
"op": 4,
"d": {
"self_deaf": false,
"guild_id": "GUILD_ID_HERE",
"channel_id": null,
"self_mute": false
}
}
Common pitfalls¶
Admittedly Lavalink isn't inherently the most intuitive thing ever, and people tend to run into the same mistakes over again. Please double-check the following if you run into problems developing your client, and you can't connect to a voice channel or play audio:
- Check that you are intercepting
VOICE_SERVER_UPDATE
s andVOICE_STATE_UPDATE
s to Lavalink. You only need theendpoint
,token
, andsession_id
. - Check that you aren't expecting to hear audio when you have forgotten to queue something up OR forgotten to join a voice channel.
- Check that you are not trying to create a voice connection with your Discord library.
- When in doubt, check the debug logfile at
/logs/debug.log
.