diff --git a/client/src/standalone/player/player.ts b/client/src/standalone/player/player.ts
index 119f5e035..9776fda12 100644
--- a/client/src/standalone/player/player.ts
+++ b/client/src/standalone/player/player.ts
@@ -170,6 +170,27 @@ export class PeerTubePlayer {
     await this.sendMessage('setPlaybackRate', rate)
   }
 
+  /**
+   * Play next video in playlist
+   */
+  async playNextVideo () {
+    await this.sendMessage('playNextVideo')
+  }
+
+  /**
+   * Play previous video in playlist
+   */
+  async playPreviousVideo () {
+    await this.sendMessage('playPreviousVideo')
+  }
+
+  /**
+   * Get video position currently played (starts from 1)
+   */
+  async getCurrentPosition () {
+    return this.sendMessage<void, number>('getCurrentPosition')
+  }
+
   private constructChannel () {
     this.channel = Channel.build({
       window: this.embedElement.contentWindow,
diff --git a/client/src/standalone/videos/embed-api.ts b/client/src/standalone/videos/embed-api.ts
index efc23a1fc..94e39ec29 100644
--- a/client/src/standalone/videos/embed-api.ts
+++ b/client/src/standalone/videos/embed-api.ts
@@ -50,6 +50,10 @@ export class PeerTubeEmbedApi {
     channel.bind('setPlaybackRate', (txn, playbackRate) => this.embed.player.playbackRate(playbackRate))
     channel.bind('getPlaybackRate', (txn, params) => this.embed.player.playbackRate())
     channel.bind('getPlaybackRates', (txn, params) => this.embed.player.options_.playbackRates)
+
+    channel.bind('playNextVideo', (txn, params) => this.embed.playNextVideo())
+    channel.bind('playPreviousVideo', (txn, params) => this.embed.playPreviousVideo())
+    channel.bind('getCurrentPosition', (txn, params) => this.embed.getCurrentPosition())
     this.channel = channel
   }
 
diff --git a/client/src/standalone/videos/embed.ts b/client/src/standalone/videos/embed.ts
index 7372c80c6..a7fb087b1 100644
--- a/client/src/standalone/videos/embed.ts
+++ b/client/src/standalone/videos/embed.ts
@@ -211,6 +211,36 @@ export class PeerTubeEmbed {
     return params.has(name) ? params.get(name) : defaultValue
   }
 
+  async playNextVideo () {
+    const next = this.getNextPlaylistElement()
+    if (!next) {
+      console.log('Next element not found in playlist.')
+      return
+    }
+
+    this.currentPlaylistElement = next
+
+    return this.loadVideoAndBuildPlayer(this.currentPlaylistElement.video.uuid)
+  }
+
+  async playPreviousVideo () {
+    const previous = this.getPreviousPlaylistElement()
+    if (!previous) {
+      console.log('Previous element not found in playlist.')
+      return
+    }
+
+    this.currentPlaylistElement = previous
+
+    await this.loadVideoAndBuildPlayer(this.currentPlaylistElement.video.uuid)
+  }
+
+  getCurrentPosition () {
+    if (!this.currentPlaylistElement) return -1
+
+    return this.currentPlaylistElement.position
+  }
+
   async init () {
     try {
       this.userTokens = Tokens.load()
@@ -342,30 +372,6 @@ export class PeerTubeEmbed {
     })
   }
 
-  private async playNextVideo () {
-    const next = this.getNextPlaylistElement()
-    if (!next) {
-      console.log('Next element not found in playlist.')
-      return
-    }
-
-    this.currentPlaylistElement = next
-
-    return this.loadVideoAndBuildPlayer(this.currentPlaylistElement.video.uuid)
-  }
-
-  private async playPreviousVideo () {
-    const previous = this.getPreviousPlaylistElement()
-    if (!previous) {
-      console.log('Previous element not found in playlist.')
-      return
-    }
-
-    this.currentPlaylistElement = previous
-
-    return this.loadVideoAndBuildPlayer(this.currentPlaylistElement.video.uuid)
-  }
-
   private async loadVideoAndBuildPlayer (uuid: string) {
     const res = await this.loadVideo(uuid)
     if (res === undefined) return
diff --git a/client/src/standalone/videos/test-embed.html b/client/src/standalone/videos/test-embed.html
index 9e1d6fc61..2b4918681 100644
--- a/client/src/standalone/videos/test-embed.html
+++ b/client/src/standalone/videos/test-embed.html
@@ -27,6 +27,8 @@
         <button onclick="player.seek(parseInt(prompt('Enter position to seek to (in seconds)')))">Seek</button>
         <button onclick="player.setVolume(0)">Mute</button>
         <button onclick="player.setVolume(1)">Unmute</button>
+        <button onclick="player.playNextVideo()">Next video</button>
+        <button onclick="player.playPreviousVideo()">Previous video</button>
       </div>
       <br/>
 
@@ -52,6 +54,11 @@
           <legend>Volume</legend>
           <div id="volume"></div>
         </fieldset>
+
+        <fieldset>
+          <legend>Playlist position</legend>
+          <div id="playlist-position"></div>
+        </fieldset>
       </div>
 
     </div>
diff --git a/client/src/standalone/videos/test-embed.ts b/client/src/standalone/videos/test-embed.ts
index 24cb62230..5f8e97562 100644
--- a/client/src/standalone/videos/test-embed.ts
+++ b/client/src/standalone/videos/test-embed.ts
@@ -1,14 +1,19 @@
 import './test-embed.scss'
+import { PeerTubeResolution, PlayerEventType } from '../player/definitions'
 import { PeerTubePlayer } from '../player/player'
-import { PeerTubeResolution, PlayerEventType, PeerTubeTextTrack } from '../player/definitions'
 
 window.addEventListener('load', async () => {
   const urlParts = window.location.href.split('/')
   const lastPart = urlParts[ urlParts.length - 1 ]
-  const videoId = lastPart.indexOf('?') === -1 ? lastPart : lastPart.split('?')[ 0 ]
+
+  const isPlaylist = window.location.pathname.startsWith('/video-playlists/')
+
+  const elementId = lastPart.indexOf('?') === -1 ? lastPart : lastPart.split('?')[ 0 ]
 
   const iframe = document.createElement('iframe')
-  iframe.src = `/videos/embed/${videoId}?api=1`
+  iframe.src = isPlaylist
+    ? `/videos/embed/${elementId}?api=1`
+    : `/video-playlists/embed/${elementId}?api=1`
 
   const mainElement = document.querySelector('#host')
   mainElement.appendChild(iframe)
@@ -32,6 +37,9 @@ window.addEventListener('load', async () => {
   monitoredEvents.forEach(e => {
     player.addEventListener(e as PlayerEventType, (param) => console.log(`PLAYER: event '${e}' received`, param))
     console.log(`PLAYER: now listening for event '${e}'`)
+
+    player.getCurrentPosition()
+      .then(position => document.getElementById('playlist-position').innerHTML = position + '')
   })
 
   let playbackRates: number[] = []
diff --git a/server/controllers/client.ts b/server/controllers/client.ts
index b97c935a5..39a198b59 100644
--- a/server/controllers/client.ts
+++ b/server/controllers/client.ts
@@ -36,10 +36,11 @@ const embedMiddlewares = [
 
 clientsRouter.use('/videos/embed', ...embedMiddlewares)
 clientsRouter.use('/video-playlists/embed', ...embedMiddlewares)
-clientsRouter.use(
-  '/videos/test-embed',
-  (req: express.Request, res: express.Response) => res.sendFile(testEmbedPath)
-)
+
+const testEmbedController = (req: express.Request, res: express.Response) => res.sendFile(testEmbedPath)
+
+clientsRouter.use('/videos/test-embed', testEmbedController)
+clientsRouter.use('/video-playlists/test-embed', testEmbedController)
 
 // Static HTML/CSS/JS client files
 const staticClientFiles = [
diff --git a/support/doc/api/embeds.md b/support/doc/api/embeds.md
index e3df35efc..d64615764 100644
--- a/support/doc/api/embeds.md
+++ b/support/doc/api/embeds.md
@@ -115,6 +115,18 @@ Update current caption using the caption id.
 
 Get video captions.
 
+## `playNextVideo(): Promise<void>`
+
+Play next video in playlist.
+
+## `playPreviousVideo(): Promise<void>`
+
+Play previous video in playlist.
+
+## `getCurrentPosition(): Promise<void>`
+
+Get current position in playlist (starts from 1).
+
 # Events
 
 You can subscribe to events by using `addEventListener()`. See above for details.