]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blobdiff - support/doc/api/openapi.yaml
Add runner jobs openapi
[github/Chocobozzz/PeerTube.git] / support / doc / api / openapi.yaml
index c4bc507fdc05a95092540e30f425bbedf572e5b9..4230fc82716b12ffb615fa641505490224c48ad7 100644 (file)
@@ -1,7 +1,7 @@
 openapi: 3.0.0
 info:
   title: PeerTube
-  version: 4.0.0
+  version: 5.1.0
   contact:
     name: PeerTube Community
     url: https://joinpeertube.org
@@ -21,7 +21,7 @@ info:
     - [Go](https://framagit.org/framasoft/peertube/clients/go)
     - [Kotlin](https://framagit.org/framasoft/peertube/clients/kotlin)
 
-    See the [REST API quick start](https://docs.joinpeertube.org/api-rest-getting-started) for a few
+    See the [REST API quick start](https://docs.joinpeertube.org/api/rest-getting-started) for a few
     examples of using the PeerTube API.
 
     # Authentication
@@ -33,7 +33,7 @@ info:
     ## Roles
 
     Accounts are given permissions based on their role. There are three roles on
-    PeerTube: Administrator, Moderator, and User. See the [roles guide](https://docs.joinpeertube.org/admin-managing-users?id=roles) for a detail of their permissions.
+    PeerTube: Administrator, Moderator, and User. See the [roles guide](https://docs.joinpeertube.org/admin/managing-users#roles) for a detail of their permissions.
 
     # Errors
 
@@ -145,7 +145,6 @@ info:
     | `/api/*`                    |
     | `/download/*`               |
     | `/lazy-static/*`            |
-    | `/live/segments-sha256/*`   |
     | `/.well-known/webfinger`    |
 
     In addition, all routes serving ActivityPub are CORS-enabled for all origins.
@@ -205,7 +204,7 @@ tags:
       information across its social graph by posting activities to actors' inbox
       endpoints.
     externalDocs:
-      url: https://docs.joinpeertube.org/admin-following-instances?id=instances-follows
+      url: https://docs.joinpeertube.org/admin/following-instances#instances-follows
   - name: Instance Redundancy
     description: >
       Redundancy is part of the inter-server solidarity that PeerTube fosters.
@@ -213,12 +212,12 @@ tags:
       to the policy of video selection of your choice. Note that you have a similar functionality
       to mirror individual videos, see [video mirroring](#tag/Video-Mirroring).
     externalDocs:
-      url: https://docs.joinpeertube.org/admin-following-instances?id=instances-redundancy
+      url: https://docs.joinpeertube.org/admin/following-instances#instances-redundancy
   - name: Plugins
     description: >
       Managing plugins installed from a local path or from NPM, or search for new ones.
     externalDocs:
-      url: https://docs.joinpeertube.org/api-plugins
+      url: https://docs.joinpeertube.org/api/plugins
   - name: Abuses
     description: |
       Abuses deal with reports of local or remote videos/comments/accounts alike.
@@ -275,10 +274,10 @@ tags:
     description: Operations on video files
   - name: Video Transcoding
     description: Video transcoding related operations
-  - name: Video stats
+  - name: Video Stats
     description: Video statistics
-  - name: Feeds
-    description: Server syndication feeds
+  - name: Video Feeds
+    description: Server syndication feeds of videos
   - name: Search
     description: |
       The search helps to find _videos_ or _channels_ from within the instance and beyond.
@@ -298,8 +297,17 @@ tags:
   - name: Stats
     description: |
       Statistics
+  - name: Runner Registration Token
+    description: |
+      Manage runner registration token
 
 x-tagGroups:
+  - name: Static endpoints
+    tags:
+      - Static Video Files
+  - name: Feeds
+    tags:
+      - Video Feeds
   - name: Auth
     tags:
       - Register
@@ -328,7 +336,6 @@ x-tagGroups:
       - Video Files
       - Video Transcoding
       - Live Videos
-      - Feeds
       - Channels Sync
   - name: Search
     tags:
@@ -349,222 +356,555 @@ x-tagGroups:
       - Stats
       - Logs
       - Job
+  - name: Remote Jobs
+    tags:
+      - Runner Registration Token
+      - Runner Jobs
+      - Runners
+
 paths:
-  '/accounts/{name}':
+  '/static/webseed/{filename}':
     get:
       tags:
-        - Accounts
-      summary: Get an account
-      operationId: getAccount
+        - Static Video Files
+      summary: Get public WebTorrent video file
       parameters:
-        - $ref: '#/components/parameters/name'
+        - $ref: '#/components/parameters/staticFilename'
       responses:
         '200':
           description: successful operation
-          content:
-            application/json:
-              schema:
-                $ref: '#/components/schemas/Account'
         '404':
-          description: account not found
-
-  '/accounts/{name}/videos':
+          description: not found
+  '/static/webseed/private/{filename}':
     get:
       tags:
-        - Accounts
-        - Video
-      summary: 'List videos of an account'
-      operationId: getAccountVideos
+        - Static Video Files
+      summary: Get private WebTorrent video file
       parameters:
-        - $ref: '#/components/parameters/name'
-        - $ref: '#/components/parameters/categoryOneOf'
-        - $ref: '#/components/parameters/isLive'
-        - $ref: '#/components/parameters/tagsOneOf'
-        - $ref: '#/components/parameters/tagsAllOf'
-        - $ref: '#/components/parameters/licenceOneOf'
-        - $ref: '#/components/parameters/languageOneOf'
-        - $ref: '#/components/parameters/nsfw'
-        - $ref: '#/components/parameters/isLocal'
-        - $ref: '#/components/parameters/include'
-        - $ref: '#/components/parameters/privacyOneOf'
-        - $ref: '#/components/parameters/hasHLSFiles'
-        - $ref: '#/components/parameters/hasWebtorrentFiles'
-        - $ref: '#/components/parameters/skipCount'
-        - $ref: '#/components/parameters/start'
-        - $ref: '#/components/parameters/count'
-        - $ref: '#/components/parameters/videosSort'
+        - $ref: '#/components/parameters/staticFilename'
+        - $ref: '#/components/parameters/videoFileToken'
+      security:
+        - OAuth2: []
       responses:
         '200':
           description: successful operation
-          content:
-            application/json:
-              schema:
-                $ref: '#/components/schemas/VideoListResponse'
-      x-codeSamples:
-        - lang: JavaScript
-          source: |
-            fetch('https://peertube2.cpy.re/api/v1/accounts/{name}/videos')
-            .then(function(response) {
-              return response.json()
-            }).then(function(data) {
-              console.log(data)
-            })
-        - lang: Shell
-          source: |
-            ## DEPENDENCIES: jq
-            curl -s https://peertube2.cpy.re/api/v1/accounts/{name}/videos | jq
-        - lang: Ruby
-          source: |
-            require 'net/http'
-            require 'json'
-
-            uri = URI.parse("https://peertube2.cpy.re/api/v1/accounts/{name}/videos")
-
-            http = Net::HTTP.new(uri.host, uri.port)
-            http.use_ssl = true
-
-            response = http.get(uri.request_uri)
-
-            puts JSON.parse(response.read_body)
-        - lang: Python
-          source: |
-            import requests
-
-            r = requests.get("https://peertube2.cpy.re/api/v1//accounts/{name}/videos")
-            json = r.json()
-
-            print(json)
+        '403':
+          description: invalid auth
+        '404':
+          description: not found
 
-  '/accounts/{name}/followers':
+  '/static/streaming-playlists/hls/{filename}':
     get:
       tags:
-        - Accounts
-      summary: 'List followers of an account'
+        - Static Video Files
+      summary: Get public HLS video file
+      parameters:
+        - $ref: '#/components/parameters/staticFilename'
       security:
         - OAuth2: []
-      operationId: getAccountFollowers
-      parameters:
-        - $ref: '#/components/parameters/name'
-        - $ref: '#/components/parameters/start'
-        - $ref: '#/components/parameters/count'
-        - $ref: '#/components/parameters/followersSort'
-        - $ref: '#/components/parameters/search'
       responses:
         '200':
           description: successful operation
-          content:
-            application/json:
-              schema:
-                type: object
-                properties:
-                  total:
-                    type: integer
-                    example: 1
-                  data:
-                    type: array
-                    items:
-                      $ref: '#/components/schemas/Follow'
-
-  /accounts:
+        '403':
+          description: invalid auth
+        '404':
+          description: not found
+  '/static/streaming-playlists/hls/private/{filename}':
     get:
       tags:
-        - Accounts
-      summary: List accounts
-      operationId: getAccounts
+        - Static Video Files
+      summary: Get private HLS video file
       parameters:
-        - $ref: '#/components/parameters/start'
-        - $ref: '#/components/parameters/count'
-        - $ref: '#/components/parameters/sort'
+        - $ref: '#/components/parameters/staticFilename'
+        - $ref: '#/components/parameters/videoFileToken'
+        - $ref: '#/components/parameters/reinjectVideoFileToken'
+      security:
+        - OAuth2: []
       responses:
         '200':
           description: successful operation
-          content:
-            'application/json':
-              schema:
-                type: array
-                items:
-                  $ref: '#/components/schemas/Account'
+        '403':
+          description: invalid auth
+        '404':
+          description: not found
 
-  /config:
+
+  '/feeds/video-comments.{format}':
     get:
       tags:
-        - Config
-      summary: Get instance public configuration
-      operationId: getConfig
+        - Video Feeds
+      summary: List comments on videos
+      operationId: getSyndicatedComments
+      parameters:
+        - name: format
+          in: path
+          required: true
+          description: 'format expected (we focus on making `rss` the most featureful ; it serves [Media RSS](https://www.rssboard.org/media-rss))'
+          schema:
+            type: string
+            enum:
+              - xml
+              - rss
+              - rss2
+              - atom
+              - atom1
+              - json
+              - json1
+        - name: videoId
+          in: query
+          description: 'limit listing to a specific video'
+          schema:
+            type: string
+        - name: accountId
+          in: query
+          description: 'limit listing to a specific account'
+          schema:
+            type: string
+        - name: accountName
+          in: query
+          description: 'limit listing to a specific account'
+          schema:
+            type: string
+        - name: videoChannelId
+          in: query
+          description: 'limit listing to a specific video channel'
+          schema:
+            type: string
+        - name: videoChannelName
+          in: query
+          description: 'limit listing to a specific video channel'
+          schema:
+            type: string
       responses:
-        '200':
+        '204':
           description: successful operation
+          headers:
+            Cache-Control:
+              schema:
+                type: string
+                default: 'max-age=900' # 15 min cache
           content:
-            application/json:
+            application/xml:
               schema:
-                $ref: '#/components/schemas/ServerConfig'
+                $ref: '#/components/schemas/VideoCommentsForXML'
               examples:
                 nightly:
-                  externalValue: https://peertube2.cpy.re/api/v1/config
-
-  /config/about:
-    get:
-      summary: Get instance "About" information
-      operationId: getAbout
-      tags:
-        - Config
-      responses:
-        '200':
-          description: successful operation
-          content:
-            application/json:
+                  externalValue: https://peertube2.cpy.re/feeds/video-comments.xml?filter=local
+            application/rss+xml:
               schema:
-                $ref: '#/components/schemas/ServerConfigAbout'
+                $ref: '#/components/schemas/VideoCommentsForXML'
               examples:
                 nightly:
-                  externalValue: https://peertube2.cpy.re/api/v1/config/about
-
-  /config/custom:
-    get:
-      summary: Get instance runtime configuration
-      operationId: getCustomConfig
-      tags:
-        - Config
-      security:
-        - OAuth2:
-          - admin
-      responses:
-        '200':
-          description: successful operation
-          content:
+                  externalValue: https://peertube2.cpy.re/feeds/video-comments.rss?filter=local
+            text/xml:
+              schema:
+                $ref: '#/components/schemas/VideoCommentsForXML'
+              examples:
+                nightly:
+                  externalValue: https://peertube2.cpy.re/feeds/video-comments.xml?filter=local
+            application/atom+xml:
+              schema:
+                $ref: '#/components/schemas/VideoCommentsForXML'
+              examples:
+                nightly:
+                  externalValue: https://peertube2.cpy.re/feeds/video-comments.atom?filter=local
             application/json:
               schema:
-                $ref: '#/components/schemas/ServerConfigCustom'
-    put:
-      summary: Set instance runtime configuration
-      operationId: putCustomConfig
-      tags:
-        - Config
-      security:
-        - OAuth2:
-          - admin
-      responses:
-        '200':
-          description: successful operation
+                type: object
+              examples:
+                nightly:
+                  externalValue: https://peertube2.cpy.re/feeds/video-comments.json?filter=local
         '400':
           x-summary: field inconsistencies
           description: >
             Arises when:
-              - the emailer is disabled and the instance is open to registrations
-              - webtorrent and hls are disabled with transcoding enabled - you need at least one enabled
-    delete:
-      summary: Delete instance runtime configuration
-      operationId: delCustomConfig
-      tags:
-        - Config
-      security:
-        - OAuth2:
-          - admin
-      responses:
-        '200':
-          description: successful operation
+              - videoId filter is mixed with a channel filter
+        '404':
+          description: video, video channel or account not found
+        '406':
+          description: accept header unsupported
 
-  /custom-pages/homepage/instance:
+  '/feeds/videos.{format}':
+    get:
+      tags:
+        - Video Feeds
+      summary: List videos
+      operationId: getSyndicatedVideos
+      parameters:
+        - name: format
+          in: path
+          required: true
+          description: 'format expected (we focus on making `rss` the most featureful ; it serves [Media RSS](https://www.rssboard.org/media-rss))'
+          schema:
+            type: string
+            enum:
+              - xml
+              - rss
+              - rss2
+              - atom
+              - atom1
+              - json
+              - json1
+        - name: accountId
+          in: query
+          description: 'limit listing to a specific account'
+          schema:
+            type: string
+        - name: accountName
+          in: query
+          description: 'limit listing to a specific account'
+          schema:
+            type: string
+        - name: videoChannelId
+          in: query
+          description: 'limit listing to a specific video channel'
+          schema:
+            type: string
+        - name: videoChannelName
+          in: query
+          description: 'limit listing to a specific video channel'
+          schema:
+            type: string
+        - $ref: '#/components/parameters/sort'
+        - $ref: '#/components/parameters/nsfw'
+        - $ref: '#/components/parameters/isLocal'
+        - $ref: '#/components/parameters/include'
+        - $ref: '#/components/parameters/privacyOneOf'
+        - $ref: '#/components/parameters/hasHLSFiles'
+        - $ref: '#/components/parameters/hasWebtorrentFiles'
+      responses:
+        '204':
+          description: successful operation
+          headers:
+            Cache-Control:
+              schema:
+                type: string
+                default: 'max-age=900' # 15 min cache
+          content:
+            application/xml:
+              schema:
+                $ref: '#/components/schemas/VideosForXML'
+              examples:
+                nightly:
+                  externalValue: https://peertube2.cpy.re/feeds/videos.xml?filter=local
+            application/rss+xml:
+              schema:
+                $ref: '#/components/schemas/VideosForXML'
+              examples:
+                nightly:
+                  externalValue: https://peertube2.cpy.re/feeds/videos.rss?filter=local
+            text/xml:
+              schema:
+                $ref: '#/components/schemas/VideosForXML'
+              examples:
+                nightly:
+                  externalValue: https://peertube2.cpy.re/feeds/videos.xml?filter=local
+            application/atom+xml:
+              schema:
+                $ref: '#/components/schemas/VideosForXML'
+              examples:
+                nightly:
+                  externalValue: https://peertube2.cpy.re/feeds/videos.atom?filter=local
+            application/json:
+              schema:
+                type: object
+              examples:
+                nightly:
+                  externalValue: https://peertube2.cpy.re/feeds/videos.json?filter=local
+        '404':
+          description: video channel or account not found
+        '406':
+          description: accept header unsupported
+
+  '/feeds/subscriptions.{format}':
+    get:
+      tags:
+        - Video Feeds
+      summary: List videos of subscriptions tied to a token
+      operationId: getSyndicatedSubscriptionVideos
+      parameters:
+        - name: format
+          in: path
+          required: true
+          description: 'format expected (we focus on making `rss` the most featureful ; it serves [Media RSS](https://www.rssboard.org/media-rss))'
+          schema:
+            type: string
+            enum:
+              - xml
+              - rss
+              - rss2
+              - atom
+              - atom1
+              - json
+              - json1
+        - name: accountId
+          in: query
+          description: limit listing to a specific account
+          schema:
+            type: string
+          required: true
+        - name: token
+          in: query
+          description: private token allowing access
+          schema:
+            type: string
+          required: true
+        - $ref: '#/components/parameters/sort'
+        - $ref: '#/components/parameters/nsfw'
+        - $ref: '#/components/parameters/isLocal'
+        - $ref: '#/components/parameters/include'
+        - $ref: '#/components/parameters/privacyOneOf'
+        - $ref: '#/components/parameters/hasHLSFiles'
+        - $ref: '#/components/parameters/hasWebtorrentFiles'
+      responses:
+        '204':
+          description: successful operation
+          headers:
+            Cache-Control:
+              schema:
+                type: string
+                default: 'max-age=900' # 15 min cache
+          content:
+            application/xml:
+              schema:
+                $ref: '#/components/schemas/VideosForXML'
+            application/rss+xml:
+              schema:
+                $ref: '#/components/schemas/VideosForXML'
+            text/xml:
+              schema:
+                $ref: '#/components/schemas/VideosForXML'
+            application/atom+xml:
+              schema:
+                $ref: '#/components/schemas/VideosForXML'
+            application/json:
+              schema:
+                type: object
+        '406':
+          description: accept header unsupported
+
+  '/api/v1/accounts/{name}':
+    get:
+      tags:
+        - Accounts
+      summary: Get an account
+      operationId: getAccount
+      parameters:
+        - $ref: '#/components/parameters/name'
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/Account'
+        '404':
+          description: account not found
+
+  '/api/v1/accounts/{name}/videos':
+    get:
+      tags:
+        - Accounts
+        - Video
+      summary: 'List videos of an account'
+      operationId: getAccountVideos
+      parameters:
+        - $ref: '#/components/parameters/name'
+        - $ref: '#/components/parameters/categoryOneOf'
+        - $ref: '#/components/parameters/isLive'
+        - $ref: '#/components/parameters/tagsOneOf'
+        - $ref: '#/components/parameters/tagsAllOf'
+        - $ref: '#/components/parameters/licenceOneOf'
+        - $ref: '#/components/parameters/languageOneOf'
+        - $ref: '#/components/parameters/nsfw'
+        - $ref: '#/components/parameters/isLocal'
+        - $ref: '#/components/parameters/include'
+        - $ref: '#/components/parameters/privacyOneOf'
+        - $ref: '#/components/parameters/hasHLSFiles'
+        - $ref: '#/components/parameters/hasWebtorrentFiles'
+        - $ref: '#/components/parameters/skipCount'
+        - $ref: '#/components/parameters/start'
+        - $ref: '#/components/parameters/count'
+        - $ref: '#/components/parameters/videosSort'
+        - $ref: '#/components/parameters/excludeAlreadyWatched'
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/VideoListResponse'
+      x-codeSamples:
+        - lang: JavaScript
+          source: |
+            fetch('https://peertube2.cpy.re/api/v1/accounts/{name}/videos')
+            .then(function(response) {
+              return response.json()
+            }).then(function(data) {
+              console.log(data)
+            })
+        - lang: Shell
+          source: |
+            ## DEPENDENCIES: jq
+            curl -s https://peertube2.cpy.re/api/v1/accounts/{name}/videos | jq
+        - lang: Ruby
+          source: |
+            require 'net/http'
+            require 'json'
+
+            uri = URI.parse("https://peertube2.cpy.re/api/v1/accounts/{name}/videos")
+
+            http = Net::HTTP.new(uri.host, uri.port)
+            http.use_ssl = true
+
+            response = http.get(uri.request_uri)
+
+            puts JSON.parse(response.read_body)
+        - lang: Python
+          source: |
+            import requests
+
+            r = requests.get("https://peertube2.cpy.re/api/v1//accounts/{name}/videos")
+            json = r.json()
+
+            print(json)
+
+  '/api/v1/accounts/{name}/followers':
+    get:
+      tags:
+        - Accounts
+      summary: 'List followers of an account'
+      security:
+        - OAuth2: []
+      operationId: getAccountFollowers
+      parameters:
+        - $ref: '#/components/parameters/name'
+        - $ref: '#/components/parameters/start'
+        - $ref: '#/components/parameters/count'
+        - $ref: '#/components/parameters/followersSort'
+        - $ref: '#/components/parameters/search'
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                type: object
+                properties:
+                  total:
+                    type: integer
+                    example: 1
+                  data:
+                    type: array
+                    items:
+                      $ref: '#/components/schemas/Follow'
+
+  /api/v1/accounts:
+    get:
+      tags:
+        - Accounts
+      summary: List accounts
+      operationId: getAccounts
+      parameters:
+        - $ref: '#/components/parameters/start'
+        - $ref: '#/components/parameters/count'
+        - $ref: '#/components/parameters/sort'
+      responses:
+        '200':
+          description: successful operation
+          content:
+            'application/json':
+              schema:
+                type: object
+                properties:
+                  total:
+                    type: integer
+                    example: 1
+                  data:
+                    type: array
+                    items:
+                      $ref: '#/components/schemas/Account'
+
+  /api/v1/config:
+    get:
+      tags:
+        - Config
+      summary: Get instance public configuration
+      operationId: getConfig
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ServerConfig'
+              examples:
+                nightly:
+                  externalValue: https://peertube2.cpy.re/api/v1/config
+
+  /api/v1/config/about:
+    get:
+      summary: Get instance "About" information
+      operationId: getAbout
+      tags:
+        - Config
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ServerConfigAbout'
+              examples:
+                nightly:
+                  externalValue: https://peertube2.cpy.re/api/v1/config/about
+
+  /api/v1/config/custom:
+    get:
+      summary: Get instance runtime configuration
+      operationId: getCustomConfig
+      tags:
+        - Config
+      security:
+        - OAuth2:
+          - admin
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ServerConfigCustom'
+    put:
+      summary: Set instance runtime configuration
+      operationId: putCustomConfig
+      tags:
+        - Config
+      security:
+        - OAuth2:
+          - admin
+      responses:
+        '200':
+          description: successful operation
+        '400':
+          x-summary: field inconsistencies
+          description: >
+            Arises when:
+              - the emailer is disabled and the instance is open to registrations
+              - webtorrent and hls are disabled with transcoding enabled - you need at least one enabled
+    delete:
+      summary: Delete instance runtime configuration
+      operationId: delCustomConfig
+      tags:
+        - Config
+      security:
+        - OAuth2:
+          - admin
+      responses:
+        '200':
+          description: successful operation
+
+  /api/v1/custom-pages/homepage/instance:
     get:
       summary: Get instance custom homepage
       tags:
@@ -598,7 +938,7 @@ paths:
         '204':
           description: successful operation
 
-  /jobs/pause:
+  /api/v1/jobs/pause:
     post:
       summary: Pause job queue
       security:
@@ -610,7 +950,7 @@ paths:
         '204':
           description: successful operation
 
-  /jobs/resume:
+  /api/v1/jobs/resume:
     post:
       summary: Resume job queue
       security:
@@ -622,7 +962,7 @@ paths:
         '204':
           description: successful operation
 
-  /jobs/{state}:
+  /api/v1/jobs/{state}:
     get:
       summary: List instance jobs
       operationId: getJobs
@@ -666,7 +1006,7 @@ paths:
                     items:
                       $ref: '#/components/schemas/Job'
 
-  /server/followers:
+  /api/v1/server/followers:
     get:
       tags:
         - Instance Follows
@@ -693,7 +1033,7 @@ paths:
                     items:
                       $ref: '#/components/schemas/Follow'
 
-  '/server/followers/{nameWithHost}':
+  '/api/v1/server/followers/{nameWithHost}':
     delete:
       summary: Remove or reject a follower to your server
       security:
@@ -715,7 +1055,7 @@ paths:
         '404':
           description: follower not found
 
-  '/server/followers/{nameWithHost}/reject':
+  '/api/v1/server/followers/{nameWithHost}/reject':
     post:
       summary: Reject a pending follower to your server
       security:
@@ -737,7 +1077,7 @@ paths:
         '404':
           description: follower not found
 
-  '/server/followers/{nameWithHost}/accept':
+  '/api/v1/server/followers/{nameWithHost}/accept':
     post:
       summary: Accept a pending follower to your server
       security:
@@ -759,7 +1099,7 @@ paths:
         '404':
           description: follower not found
 
-  /server/following:
+  /api/v1/server/following:
     get:
       tags:
         - Instance Follows
@@ -815,7 +1155,7 @@ paths:
                     type: string
                   uniqueItems: true
 
-  '/server/following/{hostOrHandle}':
+  '/api/v1/server/following/{hostOrHandle}':
     delete:
       summary: Unfollow an actor (PeerTube instance, channel or account)
       security:
@@ -836,7 +1176,7 @@ paths:
         '404':
           description: host or handle not found
 
-  /users:
+  /api/v1/users:
     post:
       summary: Create a user
       operationId: addUser
@@ -903,7 +1243,7 @@ paths:
                 items:
                   $ref: '#/components/schemas/User'
 
-  '/users/{id}':
+  '/api/v1/users/{id}':
     parameters:
       - $ref: '#/components/parameters/id'
     delete:
@@ -959,7 +1299,7 @@ paths:
               $ref: '#/components/schemas/UpdateUser'
         required: true
 
-  /oauth-clients/local:
+  /api/v1/oauth-clients/local:
     get:
       summary: Login prerequisite
       description: You need to retrieve a client id and secret before [logging in](#operation/getOAuthToken).
@@ -987,7 +1327,7 @@ paths:
             ## AUTH
             curl -s "$API/oauth-clients/local"
 
-  /users/token:
+  /api/v1/users/token:
     post:
       summary: Login
       operationId: getOAuthToken
@@ -1064,7 +1404,7 @@ paths:
               --data password="$PASSWORD" \
               | jq -r ".access_token"
 
-  /users/revoke-token:
+  /api/v1/users/revoke-token:
     post:
       summary: Logout
       description: Revokes your access token and its associated refresh token, destroying your current session.
@@ -1077,30 +1417,57 @@ paths:
         '200':
           description: successful operation
 
-  /users/register:
+  /api/v1/users/ask-send-verify-email:
     post:
-      summary: Register a user
-      operationId: registerUser
+      summary: Resend user verification link
+      operationId: resendEmailToVerifyUser
       tags:
         - Users
         - Register
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: object
+              properties:
+                email:
+                  type: string
+                  description: User email
+              required:
+                - email
       responses:
         '204':
           description: successful operation
+
+  /api/v1/users/registrations/ask-send-verify-email:
+    post:
+      summary: Resend verification link to registration email
+      operationId: resendEmailToVerifyRegistration
+      tags:
+        - Register
       requestBody:
         content:
           application/json:
             schema:
-              $ref: '#/components/schemas/RegisterUser'
-        required: true
+              type: object
+              properties:
+                email:
+                  type: string
+                  description: Registration email
+              required:
+                - email
+      responses:
+        '204':
+          description: successful operation
 
-  /users/{id}/verify-email:
+  /api/v1/users/{id}/verify-email:
     post:
       summary: Verify a user
       operationId: verifyUser
       description: |
         Following a user registration, the new user will receive an email asking to click a link
         containing a secret.
+        This endpoint can also be used to verify a new email set in the user account.
       tags:
         - Users
         - Register
@@ -1127,18 +1494,127 @@ paths:
         '404':
           description: user not found
 
-  /users/ask-send-verify-email:
+  /api/v1/users/registrations/{registrationId}/verify-email:
     post:
-      summary: Resend user verification link
-      operationId: resendEmailToVerifyUser
+      summary: Verify a registration email
+      operationId: verifyRegistrationEmail
+      description: |
+        Following a user registration request, the user will receive an email asking to click a link
+        containing a secret.
       tags:
-        - Users
         - Register
+      parameters:
+        - $ref: '#/components/parameters/registrationId'
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: object
+              properties:
+                verificationString:
+                  type: string
+                  format: url
+              required:
+                - verificationString
+      responses:
+        '204':
+          description: successful operation
+        '403':
+          description: invalid verification string
+        '404':
+          description: registration not found
+
+  /api/v1/users/{id}/two-factor/request:
+    post:
+      summary: Request two factor auth
+      operationId: requestTwoFactor
+      description: Request two factor authentication for a user
+      tags:
+        - Users
+      parameters:
+        - $ref: '#/components/parameters/id'
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: object
+              properties:
+                currentPassword:
+                  type: string
+                  description: Password of the currently authenticated user
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  $ref: '#/components/schemas/RequestTwoFactorResponse'
+        '403':
+          description: invalid password
+        '404':
+          description: user not found
+
+  /api/v1/users/{id}/two-factor/confirm-request:
+    post:
+      summary: Confirm two factor auth
+      operationId: confirmTwoFactorRequest
+      description: Confirm a two factor authentication request
+      tags:
+        - Users
+      parameters:
+        - $ref: '#/components/parameters/id'
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: object
+              properties:
+                requestToken:
+                  type: string
+                  description: Token to identify the two factor request
+                otpToken:
+                  type: string
+                  description: OTP token generated by the app
+              required:
+                - requestToken
+                - otpToken
+      responses:
+        '204':
+          description: successful operation
+        '403':
+          description: invalid request token or OTP token
+        '404':
+          description: user not found
+
+  /api/v1/users/{id}/two-factor/disable:
+    post:
+      summary: Disable two factor auth
+      operationId: disableTwoFactor
+      description: Disable two factor authentication of a user
+      tags:
+        - Users
+      parameters:
+        - $ref: '#/components/parameters/id'
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: object
+              properties:
+                currentPassword:
+                  type: string
+                  description: Password of the currently authenticated user
       responses:
         '204':
           description: successful operation
+        '403':
+          description: invalid password
+        '404':
+          description: user not found
 
-  /users/me:
+  /api/v1/users/me:
     get:
       summary: Get my user information
       operationId: getUserInfo
@@ -1174,7 +1650,7 @@ paths:
               $ref: '#/components/schemas/UpdateMe'
         required: true
 
-  /users/me/videos/imports:
+  /api/v1/users/me/videos/imports:
     get:
       summary: Get video imports of my user
       security:
@@ -1201,6 +1677,13 @@ paths:
           description: Filter on imports created by a specific channel synchronization
           schema:
             type: number
+        -
+          name: search
+          in: query
+          required: false
+          description: Search in video names
+          schema:
+            type: string
       responses:
         '200':
           description: successful operation
@@ -1209,7 +1692,7 @@ paths:
               schema:
                 $ref: '#/components/schemas/VideoImportsList'
 
-  /users/me/video-quota-used:
+  /api/v1/users/me/video-quota-used:
     get:
       summary: Get my user used quota
       security:
@@ -1234,7 +1717,7 @@ paths:
                     description: The user video quota used today in bytes
                     example: 1681014151
 
-  '/users/me/videos/{videoId}/rating':
+  '/api/v1/users/me/videos/{videoId}/rating':
     get:
       summary: Get rate of my user for a video
       security:
@@ -1257,7 +1740,7 @@ paths:
               schema:
                 $ref: '#/components/schemas/GetMeVideoRating'
 
-  /users/me/videos:
+  /api/v1/users/me/videos:
     get:
       summary: Get videos of my user
       security:
@@ -1278,7 +1761,7 @@ paths:
               schema:
                 $ref: '#/components/schemas/VideoListResponse'
 
-  /users/me/subscriptions:
+  /api/v1/users/me/subscriptions:
     get:
       summary: Get my user subscriptions
       security:
@@ -1324,7 +1807,7 @@ paths:
         '200':
           description: successful operation
 
-  /users/me/subscriptions/exist:
+  /api/v1/users/me/subscriptions/exist:
     get:
       summary: Get if subscriptions exist for my user
       security:
@@ -1342,7 +1825,7 @@ paths:
               schema:
                 type: object
 
-  /users/me/subscriptions/videos:
+  /api/v1/users/me/subscriptions/videos:
     get:
       summary: List videos of subscriptions of my user
       security:
@@ -1368,6 +1851,7 @@ paths:
         - $ref: '#/components/parameters/start'
         - $ref: '#/components/parameters/count'
         - $ref: '#/components/parameters/videosSort'
+        - $ref: '#/components/parameters/excludeAlreadyWatched'
       responses:
         '200':
           description: successful operation
@@ -1376,7 +1860,7 @@ paths:
               schema:
                 $ref: '#/components/schemas/VideoListResponse'
 
-  '/users/me/subscriptions/{subscriptionHandle}':
+  '/api/v1/users/me/subscriptions/{subscriptionHandle}':
     get:
       summary: Get subscription of my user
       security:
@@ -1406,7 +1890,7 @@ paths:
         '200':
           description: successful operation
 
-  /users/me/notifications:
+  /api/v1/users/me/notifications:
     get:
       summary: List my notifications
       security:
@@ -1430,7 +1914,7 @@ paths:
               schema:
                 $ref: '#/components/schemas/NotificationListResponse'
 
-  /users/me/notifications/read:
+  /api/v1/users/me/notifications/read:
     post:
       summary: Mark notifications as read by their id
       security:
@@ -1454,7 +1938,7 @@ paths:
         '204':
           description: successful operation
 
-  /users/me/notifications/read-all:
+  /api/v1/users/me/notifications/read-all:
     post:
       summary: Mark all my notification as read
       security:
@@ -1465,7 +1949,7 @@ paths:
         '204':
           description: successful operation
 
-  /users/me/notification-settings:
+  /api/v1/users/me/notification-settings:
     put:
       summary: Update my notification settings
       security:
@@ -1506,7 +1990,7 @@ paths:
         '204':
           description: successful operation
 
-  /users/me/history/videos:
+  /api/v1/users/me/history/videos:
     get:
       summary: List watched videos history
       security:
@@ -1525,7 +2009,7 @@ paths:
               schema:
                 $ref: '#/components/schemas/VideoListResponse'
 
-  /users/me/history/videos/{videoId}:
+  /api/v1/users/me/history/videos/{videoId}:
     delete:
       summary: Delete history element
       security:
@@ -1542,7 +2026,7 @@ paths:
         '204':
           description: successful operation
 
-  /users/me/history/videos/remove:
+  /api/v1/users/me/history/videos/remove:
     post:
       summary: Clear video history
       security:
@@ -1563,7 +2047,7 @@ paths:
         '204':
           description: successful operation
 
-  /users/me/avatar/pick:
+  /api/v1/users/me/avatar/pick:
     post:
       summary: Update my user avatar
       security:
@@ -1604,7 +2088,7 @@ paths:
               avatarfile:
                 contentType: image/png, image/jpeg
 
-  /users/me/avatar:
+  /api/v1/users/me/avatar:
     delete:
       summary: Delete my avatar
       security:
@@ -1615,7 +2099,159 @@ paths:
         '204':
           description: successful operation
 
-  /videos/ownership:
+  /api/v1/users/register:
+    post:
+      summary: Register a user
+      operationId: registerUser
+      description: Signup has to be enabled and signup approval is not required
+      tags:
+        - Register
+      responses:
+        '204':
+          description: successful operation
+        '400':
+          description: request error
+        '403':
+          description: user registration is not enabled, user limit is reached, registration is not allowed for the ip, requires approval or blocked by a plugin
+        '409':
+          description: 'a user with this username, channel name or email already exists'
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/RegisterUser'
+        required: true
+
+  /api/v1/users/registrations/request:
+    post:
+      summary: Request registration
+      description: Signup has to be enabled and require approval on the instance
+      operationId: requestRegistration
+      tags:
+        - Register
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/UserRegistration'
+        '400':
+          description: request error or signup approval is not enabled on the instance
+        '403':
+          description: user registration is not enabled, user limit is reached, registration is not allowed for the ip or blocked by a plugin
+        '409':
+          description: 'a user or registration with this username, channel name or email already exists'
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/UserRegistrationRequest'
+
+  /api/v1/users/registrations/{registrationId}/accept:
+    post:
+      security:
+        - OAuth2:
+          - admin
+          - moderator
+      summary: Accept registration
+      operationId: acceptRegistration
+      tags:
+        - Register
+      parameters:
+        - $ref: '#/components/parameters/registrationId'
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/UserRegistrationAcceptOrReject'
+      responses:
+        '204':
+          description: successful operation
+
+  /api/v1/users/registrations/{registrationId}/reject:
+    post:
+      security:
+        - OAuth2:
+          - admin
+          - moderator
+      summary: Reject registration
+      operationId: rejectRegistration
+      tags:
+        - Register
+      parameters:
+        - $ref: '#/components/parameters/registrationId'
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/UserRegistrationAcceptOrReject'
+      responses:
+        '204':
+          description: successful operation
+
+  /api/v1/users/registrations/{registrationId}:
+    delete:
+      security:
+        - OAuth2:
+          - admin
+          - moderator
+      summary: Delete registration
+      description: 'Delete the registration entry. It will not remove the user associated with this registration (if any)'
+      operationId: deleteRegistration
+      tags:
+        - Register
+      parameters:
+        - $ref: '#/components/parameters/registrationId'
+      responses:
+        '204':
+          description: successful operation
+
+  /api/v1/users/registrations:
+    get:
+      security:
+        - OAuth2:
+          - admin
+          - moderator
+      summary: List registrations
+      operationId: listRegistrations
+      tags:
+        - Register
+      parameters:
+        - $ref: '#/components/parameters/start'
+        - $ref: '#/components/parameters/count'
+        - name: search
+          in: query
+          required: false
+          schema:
+            type: string
+        - name: sort
+          in: query
+          required: false
+          schema:
+            type: string
+            enum:
+            - -createdAt
+            - createdAt
+            - state
+            - -state
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                type: object
+                properties:
+                  total:
+                    type: integer
+                    example: 1
+                  data:
+                    type: array
+                    items:
+                      $ref: '#/components/schemas/UserRegistration'
+
+  /api/v1/videos/ownership:
     get:
       summary: List video ownership changes
       tags:
@@ -1626,7 +2262,7 @@ paths:
         '200':
           description: successful operation
 
-  '/videos/ownership/{id}/accept':
+  '/api/v1/videos/ownership/{id}/accept':
     post:
       summary: Accept ownership change request
       tags:
@@ -1643,7 +2279,7 @@ paths:
         '404':
           description: video ownership change not found
 
-  '/videos/ownership/{id}/refuse':
+  '/api/v1/videos/ownership/{id}/refuse':
     post:
       summary: Refuse ownership change request
       tags:
@@ -1660,7 +2296,7 @@ paths:
         '404':
           description: video ownership change not found
 
-  '/videos/{id}/give-ownership':
+  '/api/v1/videos/{id}/give-ownership':
     post:
       summary: Request ownership change
       tags:
@@ -1681,14 +2317,37 @@ paths:
               required:
                 - username
       responses:
-        '204':
+        '204':
+          description: successful operation
+        '400':
+          description: changing video ownership to a remote account is not supported yet
+        '404':
+          description: video not found
+
+  '/api/v1/videos/{id}/token':
+    post:
+      summary: Request video token
+      operationId: requestVideoToken
+      description: Request special tokens that expire quickly to use them in some context (like accessing private static files)
+      tags:
+        - Video
+      security:
+        - OAuth2: []
+      parameters:
+        - $ref: '#/components/parameters/idOrUUID'
+      responses:
+        '200':
           description: successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/VideoTokenResponse'
         '400':
-          description: changing video ownership to a remote account is not supported yet
+          description: incorrect parameters
         '404':
           description: video not found
 
-  /videos/{id}/studio/edit:
+  /api/v1/videos/{id}/studio/edit:
     post:
       summary: Create a studio task
       tags:
@@ -1713,7 +2372,7 @@ paths:
         '404':
           description: video not found
 
-  /videos:
+  /api/v1/videos:
     get:
       summary: List videos
       operationId: getVideos
@@ -1736,6 +2395,7 @@ paths:
         - $ref: '#/components/parameters/start'
         - $ref: '#/components/parameters/count'
         - $ref: '#/components/parameters/videosSort'
+        - $ref: '#/components/parameters/excludeAlreadyWatched'
       responses:
         '200':
           description: successful operation
@@ -1744,7 +2404,7 @@ paths:
               schema:
                 $ref: '#/components/schemas/VideoListResponse'
 
-  /videos/categories:
+  /api/v1/videos/categories:
     get:
       summary: List available video categories
       operationId: getCategories
@@ -1763,7 +2423,7 @@ paths:
                 nightly:
                   externalValue: https://peertube2.cpy.re/api/v1/videos/categories
 
-  /videos/licences:
+  /api/v1/videos/licences:
     get:
       summary: List available video licences
       operationId: getLicences
@@ -1782,7 +2442,7 @@ paths:
                 nightly:
                   externalValue: https://peertube2.cpy.re/api/v1/videos/licences
 
-  /videos/languages:
+  /api/v1/videos/languages:
     get:
       summary: List available video languages
       operationId: getLanguages
@@ -1801,10 +2461,10 @@ paths:
                 nightly:
                   externalValue: https://peertube2.cpy.re/api/v1/videos/languages
 
-  /videos/privacies:
+  /api/v1/videos/privacies:
     get:
       summary: List available video privacy policies
-      operationId: getPrivacyPolicies
+      operationId: getVideoPrivacyPolicies
       tags:
         - Video
       responses:
@@ -1820,7 +2480,7 @@ paths:
                 nightly:
                   externalValue: https://peertube2.cpy.re/api/v1/videos/privacies
 
-  '/videos/{id}':
+  '/api/v1/videos/{id}':
     put:
       summary: Update a video
       operationId: putVideo
@@ -1926,7 +2586,7 @@ paths:
         '204':
           description: successful operation
 
-  '/videos/{id}/description':
+  '/api/v1/videos/{id}/description':
     get:
       summary: Get complete video description
       operationId: getVideoDesc
@@ -1947,7 +2607,7 @@ paths:
                 example: |
                   **[Want to help to translate this video?](https://weblate.framasoft.org/projects/what-is-peertube-video/)**\r\n\r\n**Take back the control of your videos! [#JoinPeertube](https://joinpeertube.org)**
 
-  '/videos/{id}/source':
+  '/api/v1/videos/{id}/source':
     post:
       summary: Get video source file metadata
       operationId: getVideoSource
@@ -1963,7 +2623,7 @@ paths:
               schema:
                 $ref: '#/components/schemas/VideoSource'
 
-  '/videos/{id}/views':
+  '/api/v1/videos/{id}/views':
     post:
       summary: Notify user is watching a video
       description: Call this endpoint regularly (every 5-10 seconds for example) to notify the server the user is watching the video. After a while, PeerTube will increase video's viewers counter. If the user is authenticated, PeerTube will also store the current player time.
@@ -1982,7 +2642,7 @@ paths:
         '204':
           description: successful operation
 
-  '/videos/{id}/watching':
+  '/api/v1/videos/{id}/watching':
     put:
       summary: Set watching progress of a video
       deprecated: true
@@ -2003,7 +2663,7 @@ paths:
         '204':
           description: successful operation
 
-  '/videos/{id}/stats/overall':
+  '/api/v1/videos/{id}/stats/overall':
     get:
       summary: Get overall stats of a video
       tags:
@@ -2032,7 +2692,7 @@ paths:
               schema:
                 $ref: '#/components/schemas/VideoStatsOverall'
 
-  '/videos/{id}/stats/retention':
+  '/api/v1/videos/{id}/stats/retention':
     get:
       summary: Get retention stats of a video
       tags:
@@ -2049,7 +2709,7 @@ paths:
               schema:
                 $ref: '#/components/schemas/VideoStatsRetention'
 
-  '/videos/{id}/stats/timeseries/{metric}':
+  '/api/v1/videos/{id}/stats/timeseries/{metric}':
     get:
       summary: Get timeserie stats of a video
       tags:
@@ -2088,7 +2748,7 @@ paths:
               schema:
                 $ref: '#/components/schemas/VideoStatsTimeserie'
 
-  /videos/upload:
+  /api/v1/videos/upload:
     post:
       summary: Upload a video
       description: Uses a single request to upload a video.
@@ -2166,7 +2826,7 @@ paths:
               --form channelId=$CHANNEL_ID \
               --form name="$NAME"
 
-  /videos/upload-resumable:
+  /api/v1/videos/upload-resumable:
     post:
       summary: Initialize the resumable upload of a video
       description: Uses [a resumable protocol](https://github.com/kukhariev/node-uploadx/blob/master/proto.md) to initialize the upload of a video
@@ -2340,7 +3000,7 @@ paths:
         '404':
           description: upload not found
 
-  /videos/imports:
+  /api/v1/videos/imports:
     post:
       summary: Import a video
       description: Import a torrent or magnetURI or HTTP resource (if enabled by the instance administrator)
@@ -2376,7 +3036,7 @@ paths:
         '409':
           description: HTTP or Torrent/magnetURI import not enabled
 
-  /videos/imports/{id}/cancel:
+  /api/v1/videos/imports/{id}/cancel:
     post:
       summary: Cancel video import
       description: Cancel a pending video import
@@ -2390,7 +3050,7 @@ paths:
         '204':
           description: successful operation
 
-  /videos/imports/{id}:
+  /api/v1/videos/imports/{id}:
     delete:
       summary: Delete video import
       description: Delete ended video import
@@ -2404,7 +3064,7 @@ paths:
         '204':
           description: successful operation
 
-  /videos/live:
+  /api/v1/videos/live:
     post:
       summary: Create a live
       operationId: addLive
@@ -2445,6 +3105,8 @@ paths:
                   type: integer
                 saveReplay:
                   type: boolean
+                replaySettings:
+                  $ref: '#/components/schemas/LiveVideoReplaySettings'
                 permanentLive:
                   description: User can stream multiple times in a permanent live
                   type: boolean
@@ -2506,7 +3168,7 @@ paths:
               previewfile:
                 contentType: image/jpeg
 
-  /videos/live/{id}:
+  /api/v1/videos/live/{id}:
     get:
       summary: Get information about a live
       operationId: getLiveId
@@ -2546,7 +3208,7 @@ paths:
           description: bad parameters or trying to update a live that has already started
         '403':
           description: trying to save replay of the live but saving replay is not enabled on the instance
-  /videos/live/{id}/sessions:
+  /api/v1/videos/live/{id}/sessions:
     get:
       summary: List live sessions
       description: List all sessions created in a particular live
@@ -2571,7 +3233,7 @@ paths:
                     type: array
                     items:
                       $ref: '#/components/schemas/LiveVideoSessionResponse'
-  /videos/{id}/live-session:
+  /api/v1/videos/{id}/live-session:
     get:
       summary: Get live session of a replay
       description: If the video is a replay of a live, you can find the associated live session using this endpoint
@@ -2589,7 +3251,7 @@ paths:
               schema:
                 $ref: '#/components/schemas/LiveVideoSessionResponse'
 
-  /users/me/abuses:
+  /api/v1/users/me/abuses:
     get:
       summary: List my abuses
       operationId: getMyAbuses
@@ -2627,7 +3289,7 @@ paths:
                     items:
                       $ref: '#/components/schemas/Abuse'
 
-  /abuses:
+  /api/v1/abuses:
     get:
       summary: List abuses
       operationId: getAbuses
@@ -2780,7 +3442,7 @@ paths:
         '400':
           description: incorrect request parameters
 
-  '/abuses/{abuseId}':
+  '/api/v1/abuses/{abuseId}':
     put:
       summary: Update an abuse
       security:
@@ -2825,7 +3487,7 @@ paths:
         '404':
           description: block not found
 
-  '/abuses/{abuseId}/messages':
+  '/api/v1/abuses/{abuseId}/messages':
     get:
       summary: List messages of an abuse
       security:
@@ -2877,7 +3539,7 @@ paths:
         '400':
           description: incorrect request parameters
 
-  '/abuses/{abuseId}/messages/{abuseMessageId}':
+  '/api/v1/abuses/{abuseId}/messages/{abuseMessageId}':
     delete:
       summary: Delete an abuse message
       security:
@@ -2891,7 +3553,7 @@ paths:
         '204':
           description: successful operation
 
-  '/videos/{id}/blacklist':
+  '/api/v1/videos/{id}/blacklist':
     post:
       summary: Block a video
       operationId: addVideoBlock
@@ -2923,7 +3585,7 @@ paths:
         '404':
           description: block not found
 
-  /videos/blacklist:
+  /api/v1/videos/blacklist:
     get:
       tags:
         - Video Blocks
@@ -2971,7 +3633,7 @@ paths:
                     items:
                       $ref: '#/components/schemas/VideoBlacklist'
 
-  /videos/{id}/captions:
+  /api/v1/videos/{id}/captions:
     get:
       summary: List captions of a video
       operationId: getVideoCaptions
@@ -2995,7 +3657,7 @@ paths:
                     items:
                       $ref: '#/components/schemas/VideoCaption'
 
-  /videos/{id}/captions/{captionLanguage}:
+  /api/v1/videos/{id}/captions/{captionLanguage}:
     put:
       summary: Add or replace a video caption
       operationId: addVideoCaption
@@ -3042,7 +3704,7 @@ paths:
         '404':
           description: video or language or caption for that language not found
 
-  /video-channels:
+  /api/v1/video-channels:
     get:
       summary: List video channels
       operationId: getVideoChannels
@@ -3085,7 +3747,7 @@ paths:
             schema:
               $ref: '#/components/schemas/VideoChannelCreate'
 
-  '/video-channels/{channelHandle}':
+  '/api/v1/video-channels/{channelHandle}':
     get:
       summary: Get a video channel
       operationId: getVideoChannel
@@ -3130,7 +3792,7 @@ paths:
         '204':
           description: successful operation
 
-  '/video-channels/{channelHandle}/videos':
+  '/api/v1/video-channels/{channelHandle}/videos':
     get:
       summary: List videos of a video channel
       operationId: getVideoChannelVideos
@@ -3155,6 +3817,7 @@ paths:
         - $ref: '#/components/parameters/start'
         - $ref: '#/components/parameters/count'
         - $ref: '#/components/parameters/videosSort'
+        - $ref: '#/components/parameters/excludeAlreadyWatched'
       responses:
         '200':
           description: successful operation
@@ -3163,7 +3826,35 @@ paths:
               schema:
                 $ref: '#/components/schemas/VideoListResponse'
 
-  '/video-channels/{channelHandle}/followers':
+  '/api/v1/video-channels/{channelHandle}/video-playlists':
+    get:
+      summary: List playlists of a channel
+      tags:
+        - Video Playlists
+        - Video Channels
+      parameters:
+        - $ref: '#/components/parameters/channelHandle'
+        - $ref: '#/components/parameters/start'
+        - $ref: '#/components/parameters/count'
+        - $ref: '#/components/parameters/sort'
+        - $ref: '#/components/parameters/videoPlaylistType'
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                type: object
+                properties:
+                  total:
+                    type: integer
+                    example: 1
+                  data:
+                    type: array
+                    items:
+                      $ref: '#/components/schemas/VideoPlaylist'
+
+  '/api/v1/video-channels/{channelHandle}/followers':
     get:
       tags:
         - Video Channels
@@ -3193,7 +3884,7 @@ paths:
                     items:
                       $ref: '#/components/schemas/Follow'
 
-  '/video-channels/{channelHandle}/avatar/pick':
+  '/api/v1/video-channels/{channelHandle}/avatar/pick':
     post:
       summary: Update channel avatar
       security:
@@ -3236,7 +3927,7 @@ paths:
               avatarfile:
                 contentType: image/png, image/jpeg
 
-  '/video-channels/{channelHandle}/avatar':
+  '/api/v1/video-channels/{channelHandle}/avatar':
     delete:
       summary: Delete channel avatar
       security:
@@ -3249,7 +3940,7 @@ paths:
         '204':
           description: successful operation
 
-  '/video-channels/{channelHandle}/banner/pick':
+  '/api/v1/video-channels/{channelHandle}/banner/pick':
     post:
       summary: Update channel banner
       security:
@@ -3292,7 +3983,7 @@ paths:
               bannerfile:
                 contentType: image/png, image/jpeg
 
-  '/video-channels/{channelHandle}/banner':
+  '/api/v1/video-channels/{channelHandle}/banner':
     delete:
       summary: Delete channel banner
       security:
@@ -3305,7 +3996,27 @@ paths:
         '204':
           description: successful operation
 
-  '/video-channel-syncs':
+  '/api/v1/video-channels/{channelHandle}/import-videos':
+    post:
+      summary: Import videos in channel
+      description: Import a remote channel/playlist videos into a channel
+      security:
+        - OAuth2: []
+      tags:
+        - Video Channels
+        - Channels Sync
+      parameters:
+        - $ref: '#/components/parameters/channelHandle'
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/ImportVideosInChannelCreate'
+      responses:
+        '204':
+          description: successful operation
+
+  '/api/v1/video-channel-syncs':
     post:
       summary: Create a synchronization for a video channel
       operationId: addVideoChannelSync
@@ -3329,7 +4040,7 @@ paths:
                   videoChannelSync:
                     $ref: "#/components/schemas/VideoChannelSync"
 
-  '/video-channel-syncs/{channelSyncId}':
+  '/api/v1/video-channel-syncs/{channelSyncId}':
     delete:
       summary: Delete a video channel synchronization
       operationId: delVideoChannelSync
@@ -3343,7 +4054,7 @@ paths:
         '204':
           description: successful operation
 
-  '/video-channel-syncs/{channelSyncId}/sync':
+  '/api/v1/video-channel-syncs/{channelSyncId}/sync':
     post:
       summary: Triggers the channel synchronization job, fetching all the videos from the remote channel
       operationId: triggerVideoChannelSync
@@ -3358,7 +4069,7 @@ paths:
           description: successful operation
 
 
-  /video-playlists/privacies:
+  /api/v1/video-playlists/privacies:
     get:
       summary: List available playlist privacy policies
       operationId: getPlaylistPrivacyPolicies
@@ -3377,7 +4088,7 @@ paths:
                 nightly:
                   externalValue: https://peertube2.cpy.re/api/v1/video-playlists/privacies
 
-  /video-playlists:
+  /api/v1/video-playlists:
     get:
       summary: List video playlists
       operationId: getPlaylists
@@ -3387,6 +4098,7 @@ paths:
         - $ref: '#/components/parameters/start'
         - $ref: '#/components/parameters/count'
         - $ref: '#/components/parameters/sort'
+        - $ref: '#/components/parameters/videoPlaylistType'
       responses:
         '200':
           description: successful operation
@@ -3459,7 +4171,7 @@ paths:
               thumbnailfile:
                 contentType: image/jpeg
 
-  /video-playlists/{playlistId}:
+  /api/v1/video-playlists/{playlistId}:
     get:
       summary: Get a video playlist
       tags:
@@ -3524,7 +4236,7 @@ paths:
         '204':
           description: successful operation
 
-  /video-playlists/{playlistId}/videos:
+  /api/v1/video-playlists/{playlistId}/videos:
     get:
       summary: 'List videos of a playlist'
       operationId: getVideoPlaylistVideos
@@ -3588,7 +4300,7 @@ paths:
               required:
                 - videoId
 
-  /video-playlists/{playlistId}/videos/reorder:
+  /api/v1/video-playlists/{playlistId}/videos/reorder:
     post:
       summary: 'Reorder a playlist'
       operationId: reorderVideoPlaylist
@@ -3623,7 +4335,7 @@ paths:
                 - startPosition
                 - insertAfterPosition
 
-  /video-playlists/{playlistId}/videos/{playlistElementId}:
+  /api/v1/video-playlists/{playlistId}/videos/{playlistElementId}:
     put:
       summary: Update a playlist element
       operationId: putVideoPlaylistVideo
@@ -3665,7 +4377,7 @@ paths:
         '204':
           description: successful operation
 
-  '/users/me/video-playlists/videos-exist':
+  '/api/v1/users/me/video-playlists/videos-exist':
     get:
       summary: Check video exists in my playlists
       security:
@@ -3703,9 +4415,37 @@ paths:
                           format: seconds
                         stopTimestamp:
                           type: integer
-                          format: seconds
 
-  '/accounts/{name}/video-channels':
+  '/api/v1/accounts/{name}/video-playlists':
+    get:
+      summary: List playlists of an account
+      tags:
+        - Video Playlists
+        - Accounts
+      parameters:
+        - $ref: '#/components/parameters/name'
+        - $ref: '#/components/parameters/start'
+        - $ref: '#/components/parameters/count'
+        - $ref: '#/components/parameters/sort'
+        - $ref: '#/components/parameters/search'
+        - $ref: '#/components/parameters/videoPlaylistType'
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                type: object
+                properties:
+                  total:
+                    type: integer
+                    example: 1
+                  data:
+                    type: array
+                    items:
+                      $ref: '#/components/schemas/VideoPlaylist'
+
+  '/api/v1/accounts/{name}/video-channels':
     get:
       summary: List video channels of an account
       tags:
@@ -3729,7 +4469,7 @@ paths:
               schema:
                 $ref: '#/components/schemas/VideoChannelList'
 
-  '/accounts/{name}/video-channel-syncs':
+  '/api/v1/accounts/{name}/video-channel-syncs':
     get:
       summary: List the synchronizations of video channels of an account
       tags:
@@ -3749,7 +4489,7 @@ paths:
               schema:
                 $ref: '#/components/schemas/VideoChannelSyncList'
 
-  '/accounts/{name}/ratings':
+  '/api/v1/accounts/{name}/ratings':
     get:
       summary: List ratings of an account
       security:
@@ -3780,7 +4520,7 @@ paths:
                 items:
                   $ref: '#/components/schemas/VideoRating'
 
-  '/videos/{id}/comment-threads':
+  '/api/v1/videos/{id}/comment-threads':
     get:
       summary: List threads of a video
       tags:
@@ -3828,7 +4568,7 @@ paths:
               required:
                 - text
 
-  '/videos/{id}/comment-threads/{threadId}':
+  '/api/v1/videos/{id}/comment-threads/{threadId}':
     get:
       summary: Get a thread
       tags:
@@ -3844,7 +4584,7 @@ paths:
               schema:
                 $ref: '#/components/schemas/VideoCommentThreadTree'
 
-  '/videos/{id}/comments/{commentId}':
+  '/api/v1/videos/{id}/comments/{commentId}':
     post:
       summary: Reply to a thread of a video
       security:
@@ -3895,7 +4635,7 @@ paths:
         '409':
           description: comment is already deleted
 
-  '/videos/{id}/rate':
+  '/api/v1/videos/{id}/rate':
     put:
       summary: Like/dislike a video
       security:
@@ -3923,7 +4663,7 @@ paths:
         '404':
           description: video does not exist
 
-  '/videos/{id}/hls':
+  '/api/v1/videos/{id}/hls':
     delete:
       summary: Delete video HLS files
       security:
@@ -3939,7 +4679,7 @@ paths:
           description: successful operation
         '404':
           description: video does not exist
-  '/videos/{id}/webtorrent':
+  '/api/v1/videos/{id}/webtorrent':
     delete:
       summary: Delete video WebTorrent files
       security:
@@ -3956,7 +4696,7 @@ paths:
         '404':
           description: video does not exist
 
-  '/videos/{id}/transcoding':
+  '/api/v1/videos/{id}/transcoding':
     post:
       summary: Create a transcoding job
       security:
@@ -3986,7 +4726,7 @@ paths:
         '404':
           description: video does not exist
 
-  /search/videos:
+  /api/v1/search/videos:
     get:
       tags:
         - Search
@@ -4013,6 +4753,7 @@ paths:
         - $ref: '#/components/parameters/isLocal'
         - $ref: '#/components/parameters/include'
         - $ref: '#/components/parameters/privacyOneOf'
+        - $ref: '#/components/parameters/uuids'
         - $ref: '#/components/parameters/hasHLSFiles'
         - $ref: '#/components/parameters/hasWebtorrentFiles'
         - $ref: '#/components/parameters/skipCount'
@@ -4020,6 +4761,7 @@ paths:
         - $ref: '#/components/parameters/count'
         - $ref: '#/components/parameters/searchTarget'
         - $ref: '#/components/parameters/videosSearchSort'
+        - $ref: '#/components/parameters/excludeAlreadyWatched'
         - name: startDate
           in: query
           description: Get videos that are published after this date
@@ -4067,7 +4809,7 @@ paths:
         '500':
           description: search index unavailable
 
-  /search/video-channels:
+  /api/v1/search/video-channels:
     get:
       tags:
         - Search
@@ -4100,7 +4842,7 @@ paths:
         '500':
           description: search index unavailable
 
-  /search/video-playlists:
+  /api/v1/search/video-playlists:
     get:
       tags:
         - Search
@@ -4141,7 +4883,7 @@ paths:
         '500':
           description: search index unavailable
 
-  /blocklist/status:
+  /api/v1/blocklist/status:
     get:
       tags:
         - Account Blocks
@@ -4174,7 +4916,7 @@ paths:
               schema:
                 $ref: '#/components/schemas/BlockStatus'
 
-  /server/blocklist/accounts:
+  /api/v1/server/blocklist/accounts:
     get:
       tags:
         - Account Blocks
@@ -4214,7 +4956,7 @@ paths:
         '409':
           description: self-blocking forbidden
 
-  '/server/blocklist/accounts/{accountName}':
+  '/api/v1/server/blocklist/accounts/{accountName}':
     delete:
       tags:
         - Account Blocks
@@ -4235,7 +4977,7 @@ paths:
         '404':
           description: account or account block does not exist
 
-  /server/blocklist/servers:
+  /api/v1/server/blocklist/servers:
     get:
       tags:
         - Server Blocks
@@ -4275,7 +5017,7 @@ paths:
         '409':
           description: self-blocking forbidden
 
-  '/server/blocklist/servers/{host}':
+  '/api/v1/server/blocklist/servers/{host}':
     delete:
       tags:
         - Server Blocks
@@ -4297,7 +5039,7 @@ paths:
         '404':
           description: account block does not exist
 
-  /server/redundancy/{host}:
+  /api/v1/server/redundancy/{host}:
     put:
       tags:
         - Instance Redundancy
@@ -4330,7 +5072,7 @@ paths:
         '404':
           description: server is not already known
 
-  /server/redundancy/videos:
+  /api/v1/server/redundancy/videos:
     get:
       tags:
         - Video Mirroring
@@ -4389,588 +5131,780 @@ paths:
         '409':
           description: video is already mirrored
 
-  /server/redundancy/videos/{redundancyId}:
-    delete:
+  /api/v1/server/redundancy/videos/{redundancyId}:
+    delete:
+      tags:
+        - Video Mirroring
+      summary: Delete a mirror done on a video
+      operationId: delMirroredVideo
+      security:
+        - OAuth2:
+          - admin
+      parameters:
+        - name: redundancyId
+          in: path
+          required: true
+          description: id of an existing redundancy on a video
+          schema:
+            type: string
+      responses:
+        '204':
+          description: successful operation
+        '404':
+          description: video redundancy not found
+
+  /api/v1/server/stats:
+    get:
+      tags:
+        - Stats
+      summary: Get instance stats
+      description: Get instance public statistics. This endpoint is cached.
+      operationId: getInstanceStats
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ServerStats'
+
+  /api/v1/server/logs/client:
+    post:
+      tags:
+        - Logs
+      summary: Send client log
+      operationId: sendClientLog
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/SendClientLog'
+      responses:
+        '204':
+          description: successful operation
+
+  /api/v1/server/logs:
+    get:
+      tags:
+        - Logs
+      summary: Get instance logs
+      operationId: getInstanceLogs
+      security:
+        - OAuth2:
+          - admin
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  type: string
+
+  /api/v1/server/audit-logs:
+    get:
+      tags:
+        - Logs
+      summary: Get instance audit logs
+      operationId: getInstanceAuditLogs
+      security:
+        - OAuth2:
+          - admin
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  type: string
+
+  /api/v1/plugins:
+    get:
+      tags:
+        - Plugins
+      summary: List plugins
+      operationId: getPlugins
+      security:
+        - OAuth2:
+          - admin
+      parameters:
+        - name: pluginType
+          in: query
+          schema:
+            type: integer
+        - name: uninstalled
+          in: query
+          schema:
+            type: boolean
+        - $ref: '#/components/parameters/start'
+        - $ref: '#/components/parameters/count'
+        - $ref: '#/components/parameters/sort'
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/PluginResponse'
+
+  /api/v1/plugins/available:
+    get:
+      tags:
+        - Plugins
+      summary: List available plugins
+      operationId: getAvailablePlugins
+      security:
+        - OAuth2:
+          - admin
+      parameters:
+        - name: search
+          in: query
+          schema:
+            type: string
+        - name: pluginType
+          in: query
+          schema:
+            type: integer
+        - name: currentPeerTubeEngine
+          in: query
+          schema:
+            type: string
+        - $ref: '#/components/parameters/start'
+        - $ref: '#/components/parameters/count'
+        - $ref: '#/components/parameters/sort'
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/PluginResponse'
+        '503':
+          description: plugin index unavailable
+
+  /api/v1/plugins/install:
+    post:
+      tags:
+        - Plugins
+      summary: Install a plugin
+      operationId: addPlugin
+      security:
+        - OAuth2:
+          - admin
+      requestBody:
+        content:
+          application/json:
+            schema:
+              oneOf:
+                - type: object
+                  properties:
+                    npmName:
+                      type: string
+                      example: peertube-plugin-auth-ldap
+                  required:
+                    - npmName
+                  additionalProperties: false
+                - type: object
+                  properties:
+                    path:
+                      type: string
+                  required:
+                    - path
+                  additionalProperties: false
+      responses:
+        '204':
+          description: successful operation
+        '400':
+          description: should have either `npmName` or `path` set
+
+  /api/v1/plugins/update:
+    post:
       tags:
-        - Video Mirroring
-      summary: Delete a mirror done on a video
-      operationId: delMirroredVideo
+        - Plugins
+      summary: Update a plugin
+      operationId: updatePlugin
       security:
         - OAuth2:
           - admin
-      parameters:
-        - name: redundancyId
-          in: path
-          required: true
-          description: id of an existing redundancy on a video
-          schema:
-            type: string
+      requestBody:
+        content:
+          application/json:
+            schema:
+              oneOf:
+                - type: object
+                  properties:
+                    npmName:
+                      type: string
+                      example: peertube-plugin-auth-ldap
+                  required:
+                    - npmName
+                  additionalProperties: false
+                - type: object
+                  properties:
+                    path:
+                      type: string
+                  required:
+                    - path
+                  additionalProperties: false
       responses:
         '204':
           description: successful operation
+        '400':
+          description: should have either `npmName` or `path` set
         '404':
-          description: video redundancy not found
-
-  /server/stats:
-    get:
-      tags:
-        - Stats
-      summary: Get instance stats
-      description: Get instance public statistics. This endpoint is cached.
-      operationId: getInstanceStats
-      responses:
-        '200':
-          description: successful operation
-          content:
-            application/json:
-              schema:
-                $ref: '#/components/schemas/ServerStats'
+          description: existing plugin not found
 
-  /server/logs/client:
+  /api/v1/plugins/uninstall:
     post:
       tags:
-        - Logs
-      summary: Send client log
-      operationId: sendClientLog
+        - Plugins
+      summary: Uninstall a plugin
+      operationId: uninstallPlugin
+      security:
+        - OAuth2:
+          - admin
       requestBody:
         content:
           application/json:
             schema:
-              $ref: '#/components/schemas/SendClientLog'
+              type: object
+              properties:
+                npmName:
+                  type: string
+                  description: name of the plugin/theme in its package.json
+                  example: peertube-plugin-auth-ldap
+              required:
+                - npmName
       responses:
         '204':
           description: successful operation
+        '404':
+          description: existing plugin not found
 
-  /server/logs:
+  /api/v1/plugins/{npmName}:
     get:
       tags:
-        - Logs
-      summary: Get instance logs
-      operationId: getInstanceLogs
+        - Plugins
+      summary: Get a plugin
+      operationId: getPlugin
       security:
         - OAuth2:
           - admin
+      parameters:
+        - $ref: '#/components/parameters/npmName'
       responses:
         '200':
           description: successful operation
           content:
             application/json:
               schema:
-                type: array
-                items:
-                  type: string
+                $ref: '#/components/schemas/Plugin'
+        '404':
+          description: plugin not found
 
-  /server/audit-logs:
-    get:
+  /api/v1/plugins/{npmName}/settings:
+    put:
       tags:
-        - Logs
-      summary: Get instance audit logs
-      operationId: getInstanceAuditLogs
+        - Plugins
+      summary: Set a plugin's settings
       security:
         - OAuth2:
           - admin
-      responses:
-        '200':
-          description: successful operation
-          content:
-            application/json:
-              schema:
-                type: array
-                items:
-                  type: string
-
-  '/feeds/video-comments.{format}':
-    get:
-      tags:
-        - Feeds
-      summary: List comments on videos
-      operationId: getSyndicatedComments
       parameters:
-        - name: format
-          in: path
-          required: true
-          description: 'format expected (we focus on making `rss` the most featureful ; it serves [Media RSS](https://www.rssboard.org/media-rss))'
-          schema:
-            type: string
-            enum:
-              - xml
-              - rss
-              - rss2
-              - atom
-              - atom1
-              - json
-              - json1
-        - name: videoId
-          in: query
-          description: 'limit listing to a specific video'
-          schema:
-            type: string
-        - name: accountId
-          in: query
-          description: 'limit listing to a specific account'
-          schema:
-            type: string
-        - name: accountName
-          in: query
-          description: 'limit listing to a specific account'
-          schema:
-            type: string
-        - name: videoChannelId
-          in: query
-          description: 'limit listing to a specific video channel'
-          schema:
-            type: string
-        - name: videoChannelName
-          in: query
-          description: 'limit listing to a specific video channel'
-          schema:
-            type: string
+        - $ref: '#/components/parameters/npmName'
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: object
+              properties:
+                settings:
+                  type: object
+                  additionalProperties: true
       responses:
         '204':
           description: successful operation
-          headers:
-            Cache-Control:
-              schema:
-                type: string
-                default: 'max-age=900' # 15 min cache
-          content:
-            application/xml:
-              schema:
-                $ref: '#/components/schemas/VideoCommentsForXML'
-              examples:
-                nightly:
-                  externalValue: https://peertube2.cpy.re/feeds/video-comments.xml?filter=local
-            application/rss+xml:
-              schema:
-                $ref: '#/components/schemas/VideoCommentsForXML'
-              examples:
-                nightly:
-                  externalValue: https://peertube2.cpy.re/feeds/video-comments.rss?filter=local
-            text/xml:
-              schema:
-                $ref: '#/components/schemas/VideoCommentsForXML'
-              examples:
-                nightly:
-                  externalValue: https://peertube2.cpy.re/feeds/video-comments.xml?filter=local
-            application/atom+xml:
-              schema:
-                $ref: '#/components/schemas/VideoCommentsForXML'
-              examples:
-                nightly:
-                  externalValue: https://peertube2.cpy.re/feeds/video-comments.atom?filter=local
-            application/json:
-              schema:
-                type: object
-              examples:
-                nightly:
-                  externalValue: https://peertube2.cpy.re/feeds/video-comments.json?filter=local
-        '400':
-          x-summary: field inconsistencies
-          description: >
-            Arises when:
-              - videoId filter is mixed with a channel filter
         '404':
-          description: video, video channel or account not found
-        '406':
-          description: accept header unsupported
+          description: plugin not found
 
-  '/feeds/videos.{format}':
+  /api/v1/plugins/{npmName}/public-settings:
     get:
       tags:
-        - Feeds
-      summary: List videos
-      operationId: getSyndicatedVideos
+        - Plugins
+      summary: Get a plugin's public settings
       parameters:
-        - name: format
-          in: path
-          required: true
-          description: 'format expected (we focus on making `rss` the most featureful ; it serves [Media RSS](https://www.rssboard.org/media-rss))'
-          schema:
-            type: string
-            enum:
-              - xml
-              - rss
-              - rss2
-              - atom
-              - atom1
-              - json
-              - json1
-        - name: accountId
-          in: query
-          description: 'limit listing to a specific account'
-          schema:
-            type: string
-        - name: accountName
-          in: query
-          description: 'limit listing to a specific account'
-          schema:
-            type: string
-        - name: videoChannelId
-          in: query
-          description: 'limit listing to a specific video channel'
-          schema:
-            type: string
-        - name: videoChannelName
-          in: query
-          description: 'limit listing to a specific video channel'
-          schema:
-            type: string
-        - $ref: '#/components/parameters/sort'
-        - $ref: '#/components/parameters/nsfw'
-        - $ref: '#/components/parameters/isLocal'
-        - $ref: '#/components/parameters/include'
-        - $ref: '#/components/parameters/privacyOneOf'
-        - $ref: '#/components/parameters/hasHLSFiles'
-        - $ref: '#/components/parameters/hasWebtorrentFiles'
+        - $ref: '#/components/parameters/npmName'
       responses:
-        '204':
+        '200':
           description: successful operation
-          headers:
-            Cache-Control:
-              schema:
-                type: string
-                default: 'max-age=900' # 15 min cache
           content:
-            application/xml:
-              schema:
-                $ref: '#/components/schemas/VideosForXML'
-              examples:
-                nightly:
-                  externalValue: https://peertube2.cpy.re/feeds/videos.xml?filter=local
-            application/rss+xml:
-              schema:
-                $ref: '#/components/schemas/VideosForXML'
-              examples:
-                nightly:
-                  externalValue: https://peertube2.cpy.re/feeds/videos.rss?filter=local
-            text/xml:
-              schema:
-                $ref: '#/components/schemas/VideosForXML'
-              examples:
-                nightly:
-                  externalValue: https://peertube2.cpy.re/feeds/videos.xml?filter=local
-            application/atom+xml:
-              schema:
-                $ref: '#/components/schemas/VideosForXML'
-              examples:
-                nightly:
-                  externalValue: https://peertube2.cpy.re/feeds/videos.atom?filter=local
             application/json:
               schema:
                 type: object
-              examples:
-                nightly:
-                  externalValue: https://peertube2.cpy.re/feeds/videos.json?filter=local
+                additionalProperties: true
         '404':
-          description: video channel or account not found
-        '406':
-          description: accept header unsupported
+          description: plugin not found
 
-  '/feeds/subscriptions.{format}':
+  /api/v1/plugins/{npmName}/registered-settings:
     get:
       tags:
-        - Feeds
-        - Account
-      summary: List videos of subscriptions tied to a token
-      operationId: getSyndicatedSubscriptionVideos
+        - Plugins
+      summary: Get a plugin's registered settings
+      security:
+        - OAuth2:
+          - admin
       parameters:
-        - name: format
-          in: path
-          required: true
-          description: 'format expected (we focus on making `rss` the most featureful ; it serves [Media RSS](https://www.rssboard.org/media-rss))'
-          schema:
-            type: string
-            enum:
-              - xml
-              - rss
-              - rss2
-              - atom
-              - atom1
-              - json
-              - json1
-        - name: accountId
-          in: query
-          description: limit listing to a specific account
-          schema:
-            type: string
-          required: true
-        - name: token
-          in: query
-          description: private token allowing access
-          schema:
-            type: string
-          required: true
-        - $ref: '#/components/parameters/sort'
-        - $ref: '#/components/parameters/nsfw'
-        - $ref: '#/components/parameters/isLocal'
-        - $ref: '#/components/parameters/include'
-        - $ref: '#/components/parameters/privacyOneOf'
-        - $ref: '#/components/parameters/hasHLSFiles'
-        - $ref: '#/components/parameters/hasWebtorrentFiles'
+        - $ref: '#/components/parameters/npmName'
       responses:
-        '204':
+        '200':
           description: successful operation
-          headers:
-            Cache-Control:
-              schema:
-                type: string
-                default: 'max-age=900' # 15 min cache
           content:
-            application/xml:
-              schema:
-                $ref: '#/components/schemas/VideosForXML'
-            application/rss+xml:
-              schema:
-                $ref: '#/components/schemas/VideosForXML'
-            text/xml:
-              schema:
-                $ref: '#/components/schemas/VideosForXML'
-            application/atom+xml:
-              schema:
-                $ref: '#/components/schemas/VideosForXML'
             application/json:
               schema:
                 type: object
-        '406':
-          description: accept header unsupported
+                additionalProperties: true
+        '404':
+          description: plugin not found
 
-  /plugins:
-    get:
+  /api/v1/metrics/playback:
+    post:
+      summary: Create playback metrics
+      description: These metrics are exposed by OpenTelemetry metrics exporter if enabled.
       tags:
-        - Plugins
-      summary: List plugins
-      operationId: getPlugins
+        - Stats
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/PlaybackMetricCreate'
+      responses:
+        '204':
+          description: successful operation
+
+  /api/v1/runners/registration-tokens/generate:
+    post:
+      summary: Generate registration token
+      description: Generate a new runner registration token
+      security:
+        - OAuth2:
+          - admin
+      tags:
+        - Runner Registration Token
+      responses:
+        '204':
+          description: successful operation
+
+  /api/v1/runners/registration-tokens/{registrationTokenId}:
+    delete:
+      summary: Remove registration token
+      description: Remove a registration token. Runners that used this token for their registration are automatically removed.
       security:
         - OAuth2:
           - admin
+      tags:
+        - Runner Registration Token
+      parameters:
+        - $ref: '#/components/parameters/registrationTokenId'
+      responses:
+        '204':
+          description: successful operation
+
+  /api/v1/runners/registration-tokens:
+    get:
+      summary: List registration tokens
+      security:
+        - OAuth2:
+          - admin
+      tags:
+        - Runner Registration Token
       parameters:
-        - name: pluginType
-          in: query
-          schema:
-            type: integer
-        - name: uninstalled
-          in: query
-          schema:
-            type: boolean
         - $ref: '#/components/parameters/start'
         - $ref: '#/components/parameters/count'
-        - $ref: '#/components/parameters/sort'
+        - $ref: '#/components/parameters/registrationTokenSort'
       responses:
         '200':
           description: successful operation
           content:
             application/json:
               schema:
-                $ref: '#/components/schemas/PluginResponse'
+                type: object
+                properties:
+                  total:
+                    type: integer
+                    example: 1
+                  data:
+                    type: array
+                    items:
+                      $ref: '#/components/schemas/RunnerRegistrationToken'
 
-  /plugins/available:
-    get:
+  /api/v1/runners/register:
+    post:
+      summary: Register a new runner
+      description: API used by PeerTube runners
       tags:
-        - Plugins
-      summary: List available plugins
-      operationId: getAvailablePlugins
+        - Runners
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: object
+              properties:
+                registrationToken:
+                  type: string
+                name:
+                  type: string
+                description:
+                  type: string
+              required:
+                - registrationToken
+                - name
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                type: object
+                properties:
+                  id:
+                    type: integer
+                    description: Runner id
+                  runnerToken:
+                    type: string
+
+  /api/v1/runners/unregister:
+    post:
+      summary: Unregister a runner
+      description: API used by PeerTube runners
+      tags:
+        - Runners
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: object
+              properties:
+                runnerToken:
+                  type: string
+              required:
+                - runnerToken
+      responses:
+        '204':
+          description: successful operation
+
+  /api/v1/runners/{runnerId}:
+    delete:
+      summary: Delete a runner
       security:
         - OAuth2:
           - admin
+      tags:
+        - Runners
+      parameters:
+        - $ref: '#/components/parameters/runnerId'
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: object
+              properties:
+                runnerToken:
+                  type: string
+              required:
+                - runnerToken
+      responses:
+        '204':
+          description: successful operation
+
+  /api/v1/runners:
+    get:
+      summary: List runners
+      security:
+        - OAuth2:
+          - admin
+      tags:
+        - Runners
       parameters:
-        - name: search
-          in: query
-          schema:
-            type: string
-        - name: pluginType
-          in: query
-          schema:
-            type: integer
-        - name: currentPeerTubeEngine
-          in: query
-          schema:
-            type: string
         - $ref: '#/components/parameters/start'
         - $ref: '#/components/parameters/count'
-        - $ref: '#/components/parameters/sort'
+        - $ref: '#/components/parameters/runnerSort'
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                type: object
+                properties:
+                  total:
+                    type: integer
+                    example: 1
+                  data:
+                    type: array
+                    items:
+                      $ref: '#/components/schemas/Runner'
+
+
+  /api/v1/runners/jobs/request:
+    post:
+      summary: Request a new job
+      description: API used by PeerTube runners
+      tags:
+        - Runner Jobs
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: object
+              properties:
+                runnerToken:
+                  type: string
+              required:
+                - runnerToken
       responses:
         '200':
           description: successful operation
           content:
             application/json:
               schema:
-                $ref: '#/components/schemas/PluginResponse'
-        '503':
-          description: plugin index unavailable
-
-  /plugins/install:
+                type: object
+                properties:
+                  availableJobs:
+                    type: array
+                    items:
+                      type: object
+                      properties:
+                        uuid:
+                          $ref: '#/components/schemas/UUIDv4'
+                        type:
+                          $ref: '#/components/schemas/RunnerJobType'
+                        payload:
+                          $ref: '#/components/schemas/RunnerJobPayload'
+
+  /api/v1/runners/jobs/{jobUUID}/accept:
     post:
+      summary: Accept job
+      description: API used by PeerTube runners
       tags:
-        - Plugins
-      summary: Install a plugin
-      operationId: addPlugin
-      security:
-        - OAuth2:
-          - admin
+        - Runner Jobs
+      parameters:
+        - $ref: '#/components/parameters/jobUUID'
       requestBody:
         content:
           application/json:
             schema:
-              oneOf:
-                - type: object
-                  properties:
-                    npmName:
-                      type: string
-                      example: peertube-plugin-auth-ldap
-                  required:
-                    - npmName
-                  additionalProperties: false
-                - type: object
-                  properties:
-                    path:
-                      type: string
-                  required:
-                    - path
-                  additionalProperties: false
+              type: object
+              properties:
+                runnerToken:
+                  type: string
+              required:
+                - runnerToken
       responses:
-        '204':
+        '200':
           description: successful operation
-        '400':
-          description: should have either `npmName` or `path` set
-
-  /plugins/update:
+          content:
+            application/json:
+              schema:
+                type: object
+                properties:
+                  job:
+                    allOf:
+                      - $ref: '#/components/schemas/RunnerJob'
+                      - type: object
+                        properties:
+                          jobToken:
+                            type: string
+
+  /api/v1/runners/jobs/{jobUUID}/abort:
     post:
+      summary: Abort job
+      description: API used by PeerTube runners
       tags:
-        - Plugins
-      summary: Update a plugin
-      operationId: updatePlugin
-      security:
-        - OAuth2:
-          - admin
+        - Runner Jobs
+      parameters:
+        - $ref: '#/components/parameters/jobUUID'
       requestBody:
         content:
           application/json:
             schema:
-              oneOf:
-                - type: object
-                  properties:
-                    npmName:
-                      type: string
-                      example: peertube-plugin-auth-ldap
-                  required:
-                    - npmName
-                  additionalProperties: false
-                - type: object
-                  properties:
-                    path:
-                      type: string
-                  required:
-                    - path
-                  additionalProperties: false
+              type: object
+              properties:
+                runnerToken:
+                  type: string
+                jobToken:
+                  type: string
+                reason:
+                  type: string
+                  description: Why the runner aborts this job
+              required:
+                - runnerToken
+                - jobToken
+                - reason
       responses:
         '204':
           description: successful operation
-        '400':
-          description: should have either `npmName` or `path` set
-        '404':
-          description: existing plugin not found
 
-  /plugins/uninstall:
+  /api/v1/runners/jobs/{jobUUID}/update:
     post:
+      summary: Update job
+      description: API used by PeerTube runners
       tags:
-        - Plugins
-      summary: Uninstall a plugin
-      operationId: uninstallPlugin
-      security:
-        - OAuth2:
-          - admin
+        - Runner Jobs
+      parameters:
+        - $ref: '#/components/parameters/jobUUID'
       requestBody:
         content:
           application/json:
             schema:
               type: object
               properties:
-                npmName:
+                runnerToken:
                   type: string
-                  description: name of the plugin/theme in its package.json
-                  example: peertube-plugin-auth-ldap
+                jobToken:
+                  type: string
+                progress:
+                  type: integer
+                  description: Update job progression percentage (optional)
+                payload:
+                  anyOf:
+                    - type: object
+                      description: Provide live transcoding chunks update
+                      properties:
+                        type:
+                          type: string
+                          enum:
+                            - 'add-chunk'
+                            - 'remove-chunk'
+                        masterPlaylistFile:
+                          type: string
+                          format: binary
+                        resolutionPlaylistFile:
+                          type: string
+                          format: binary
+                        resolutionPlaylistFilename:
+                          type: string
+                        videoChunkFile:
+                          type: string
+                          format: binary
+                        videoChunkFilename:
+                          type: string
               required:
-                - npmName
+                - runnerToken
+                - jobToken
       responses:
         '204':
           description: successful operation
-        '404':
-          description: existing plugin not found
 
-  /plugins/{npmName}:
-    get:
+  /api/v1/runners/jobs/{jobUUID}/error:
+    post:
+      summary: Post job error
+      description: API used by PeerTube runners
       tags:
-        - Plugins
-      summary: Get a plugin
-      operationId: getPlugin
-      security:
-        - OAuth2:
-          - admin
+        - Runner Jobs
       parameters:
-        - $ref: '#/components/parameters/npmName'
+        - $ref: '#/components/parameters/jobUUID'
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: object
+              properties:
+                runnerToken:
+                  type: string
+                jobToken:
+                  type: string
+                message:
+                  type: string
+                  description: Why the runner failed to process this job
+              required:
+                - runnerToken
+                - jobToken
+                - message
       responses:
-        '200':
+        '204':
           description: successful operation
-          content:
-            application/json:
-              schema:
-                $ref: '#/components/schemas/Plugin'
-        '404':
-          description: plugin not found
 
-  /plugins/{npmName}/settings:
-    put:
+  /api/v1/runners/jobs/{jobUUID}/success:
+    post:
+      summary: Post job success
+      description: API used by PeerTube runners
       tags:
-        - Plugins
-      summary: Set a plugin's settings
-      security:
-        - OAuth2:
-          - admin
+        - Runner Jobs
       parameters:
-        - $ref: '#/components/parameters/npmName'
+        - $ref: '#/components/parameters/jobUUID'
       requestBody:
         content:
           application/json:
             schema:
               type: object
               properties:
-                settings:
-                  type: object
-                  additionalProperties: true
+                runnerToken:
+                  type: string
+                jobToken:
+                  type: string
+                payload:
+                  anyOf:
+                    - type: object
+                      title: VOD web video transcoding
+                      properties:
+                        videoFile:
+                          type: string
+                          format: binary
+                    - type: object
+                      title: VOD HLS transcoding
+                      properties:
+                        videoFile:
+                          type: string
+                          format: binary
+                        resolutionPlaylistFile:
+                          type: string
+                          format: binary
+                    - type: object
+                      title: VOD audio merge transcoding
+                      properties:
+                        videoFile:
+                          type: string
+                          format: binary
+                    - type: object
+                      title: Live RTMP to HLS transcoding
+              required:
+                - runnerToken
+                - jobToken
+                - payload
       responses:
         '204':
           description: successful operation
-        '404':
-          description: plugin not found
 
-  /plugins/{npmName}/public-settings:
+  /api/v1/runners/jobs/{jobUUID}/cancel:
     get:
+      summary: Cancel a job
+      security:
+        - OAuth2:
+          - admin
       tags:
-        - Plugins
-      summary: Get a plugin's public settings
+        - Runner Jobs
       parameters:
-        - $ref: '#/components/parameters/npmName'
+        - $ref: '#/components/parameters/jobUUID'
       responses:
-        '200':
+        '204':
           description: successful operation
-          content:
-            application/json:
-              schema:
-                type: object
-                additionalProperties: true
-        '404':
-          description: plugin not found
 
-  /plugins/{npmName}/registered-settings:
+  /api/v1/runners/jobs:
     get:
-      tags:
-        - Plugins
-      summary: Get a plugin's registered settings
+      summary: List jobs
       security:
         - OAuth2:
           - admin
+      tags:
+        - Runner Jobs
       parameters:
-        - $ref: '#/components/parameters/npmName'
+        - $ref: '#/components/parameters/start'
+        - $ref: '#/components/parameters/count'
+        - $ref: '#/components/parameters/runnerJobSort'
+        - $ref: '#/components/parameters/search'
       responses:
         '200':
           description: successful operation
@@ -4978,16 +5912,21 @@ paths:
             application/json:
               schema:
                 type: object
-                additionalProperties: true
-        '404':
-          description: plugin not found
+                properties:
+                  total:
+                    type: integer
+                    example: 1
+                  data:
+                    type: array
+                    items:
+                      $ref: '#/components/schemas/RunnerJobAdmin'
 
 servers:
-  - url: 'https://peertube2.cpy.re/api/v1'
+  - url: 'https://peertube2.cpy.re'
     description: Live Test Server (live data - latest nightly version)
-  - url: 'https://peertube3.cpy.re/api/v1'
+  - url: 'https://peertube3.cpy.re'
     description: Live Test Server (live data - latest RC version)
-  - url: 'https://peertube.cpy.re/api/v1'
+  - url: 'https://peertube.cpy.re'
     description: Live Test Server (live data - stable version)
 components:
   parameters:
@@ -5163,6 +6102,38 @@ components:
         type: string
         enum:
         - createdAt
+    registrationTokenSort:
+      name: sort
+      in: query
+      required: false
+      description: Sort registration tokens by criteria
+      schema:
+        type: string
+        enum:
+        - createdAt
+    runnerSort:
+      name: sort
+      in: query
+      required: false
+      description: Sort runners by criteria
+      schema:
+        type: string
+        enum:
+        - createdAt
+    runnerJobSort:
+      name: sort
+      in: query
+      required: false
+      description: Sort runner jobs by criteria
+      schema:
+        type: string
+        enum:
+        - updatedAt
+        - createdAt
+        - priority
+        - state
+        - progress
+
     name:
       name: name
       in: path
@@ -5178,6 +6149,13 @@ components:
       description: Entity id
       schema:
         $ref: '#/components/schemas/id'
+    registrationId:
+      name: registrationId
+      in: path
+      required: true
+      description: Registration ID
+      schema:
+        $ref: '#/components/schemas/id'
     idOrUUID:
       name: id
       in: path
@@ -5382,6 +6360,20 @@ components:
       schema:
         $ref: '#/components/schemas/VideoPrivacySet'
       description: '**PeerTube >= 4.0** Display only videos in this specific privacy/privacies'
+    excludeAlreadyWatched:
+      name: excludeAlreadyWatched
+      in: query
+      description: Whether or not to exclude videos that are in the user's video history
+      schema:
+        type: boolean
+    uuids:
+      name: uuids
+      in: query
+      required: false
+      schema:
+        items:
+          type: string
+      description: 'Find videos with specific UUIDs'
     include:
       name: include
       in: query
@@ -5464,6 +6456,52 @@ components:
           - Group
           - Service
           - Organization
+    staticFilename:
+      name: filename
+      in: path
+      required: true
+      description: Filename
+      schema:
+        type: string
+    videoFileToken:
+      name: videoFileToken
+      in: query
+      required: false
+      description: Video file token [generated](#operation/requestVideoToken) by PeerTube so you don't need to provide an OAuth token in the request header.
+      schema:
+        type: string
+    reinjectVideoFileToken:
+      name: reinjectVideoFileToken
+      in: query
+      required: false
+      description: Ask the server to reinject videoFileToken in URLs in m3u8 playlist
+      schema:
+        type: boolean
+    videoPlaylistType:
+      name: playlistType
+      in: query
+      required: false
+      schema:
+        $ref: '#/components/schemas/VideoPlaylistTypeSet'
+    registrationTokenId:
+      name: registrationTokenId
+      in: path
+      required: true
+      schema:
+        type: integer
+    runnerId:
+      name: runnerId
+      in: path
+      required: true
+      schema:
+        type: integer
+    jobUUID:
+      name: jobUUID
+      in: path
+      required: true
+      schema:
+        $ref: '#/components/schemas/UUIDv4'
+
   securitySchemes:
     OAuth2:
       description: |
@@ -5476,7 +6514,7 @@ components:
         Note that the __access token is valid for 1 day__ and is given
         along with a __refresh token valid for 2 weeks__.
 
-        [Generate]: https://docs.joinpeertube.org/api-rest-getting-started
+        [Generate]: https://docs.joinpeertube.org/api/rest-getting-started
       type: oauth2
       flows:
         password:
@@ -5564,7 +6602,7 @@ components:
         - 1
         - 2
         - 3
-      description: Video playlist privacy policy (see [/video-playlists/privacies])
+      description: Video playlist privacy policy (see [/video-playlists/privacies](#operation/getPlaylistPrivacyPolicies))
     VideoPlaylistPrivacyConstant:
       properties:
         id:
@@ -5592,7 +6630,7 @@ components:
         - 2
         - 3
         - 4
-      description: privacy id of the video (see [/videos/privacies](#operation/getPrivacyPolicies))
+      description: privacy id of the video (see [/videos/privacies](#operation/getVideoPrivacyPolicies))
     VideoPrivacyConstant:
       properties:
         id:
@@ -5654,6 +6692,14 @@ components:
         - 3
       description: 'The live latency mode (Default = `1`, High latency = `2`, Small Latency = `3`)'
 
+    LiveVideoReplaySettings:
+      type: object
+      properties:
+        privacy:
+          # description: Video playlist privacy policy (see [../video-playlists/privacies])
+          $ref: '#/components/schemas/VideoPrivacySet'
+
+
     VideoStateConstant:
       properties:
         id:
@@ -7217,6 +8263,16 @@ components:
       properties:
         comment:
           $ref: '#/components/schemas/VideoComment'
+    VideoTokenResponse:
+      properties:
+        files:
+          type: object
+          properties:
+            token:
+              type: string
+            expires:
+              type: string
+              format: date-time
     VideoListResponse:
       properties:
         total:
@@ -7272,13 +8328,16 @@ components:
         nsfwPolicy:
           $ref: '#/components/schemas/NSFWPolicy'
         role:
-          $ref: '#/components/schemas/UserRole'
-        roleLabel:
-          type: string
-          enum:
-            - User
-            - Moderator
-            - Administrator
+          type: object
+          properties:
+            id:
+              $ref: '#/components/schemas/UserRole'
+            label:
+              type: string
+              enum:
+                - User
+                - Moderator
+                - Administrator
         theme:
           type: string
           description: Theme enabled by this user
@@ -7347,8 +8406,6 @@ components:
         - username
         - password
         - email
-        - videoQuota
-        - videoQuotaDaily
         - role
     UpdateUser:
       properties:
@@ -7455,6 +8512,7 @@ components:
       required:
         - video
         - rating
+
     RegisterUser:
       properties:
         username:
@@ -7485,6 +8543,77 @@ components:
         - password
         - email
 
+    UserRegistrationRequest:
+      allOf:
+        - $ref: '#/components/schemas/RegisterUser'
+        - type: object
+          properties:
+            registrationReason:
+              type: string
+              description: reason for the user to register on the instance
+          required:
+            - registrationReason
+
+    UserRegistrationAcceptOrReject:
+      type: object
+      properties:
+        moderationResponse:
+          type: string
+          description: Moderation response to send to the user
+        preventEmailDelivery:
+          type: boolean
+          description: Set it to true if you don't want PeerTube to send an email to the user
+      required:
+        - moderationResponse
+
+    UserRegistration:
+      properties:
+        id:
+          $ref: '#/components/schemas/id'
+        state:
+          type: object
+          properties:
+            id:
+              type: integer
+              enum:
+                - 1
+                - 2
+                - 3
+              description: 'The registration state (Pending = `1`, Rejected = `2`, Accepted = `3`)'
+            label:
+              type: string
+        registrationReason:
+          type: string
+        moderationResponse:
+          type: string
+          nullable: true
+        username:
+          type: string
+        email:
+          type: string
+          format: email
+        emailVerified:
+          type: boolean
+        accountDisplayName:
+          type: string
+        channelHandle:
+          type: string
+        channelDisplayName:
+          type: string
+        createdAt:
+          type: string
+          format: date-time
+        updatedAt:
+          type: string
+          format: date-time
+        user:
+          type: object
+          nullable: true
+          description: If the registration has been accepted, this is a partial user object created by the registration
+          properties:
+            id:
+              $ref: '#/components/schemas/id'
+
     OAuthClient:
       properties:
         client_id:
@@ -7583,9 +8712,18 @@ components:
                 uuid:
                   $ref: '#/components/schemas/UUIDv4'
 
+    VideoChannelEdit:
+      properties:
+        displayName:
+          description: Channel display name
+        description:
+          description: Channel description
+        support:
+          description: How to support/fund the channel
+
     VideoChannelCreate:
       allOf:
-        - $ref: '#/components/schemas/VideoChannel'
+        - $ref: '#/components/schemas/VideoChannelEdit'
         - properties:
             name:
               description: username of the channel to create
@@ -7596,11 +8734,12 @@ components:
         - displayName
     VideoChannelUpdate:
       allOf:
-        - $ref: '#/components/schemas/VideoChannel'
+        - $ref: '#/components/schemas/VideoChannelEdit'
         - properties:
             bulkVideosSupportUpdate:
               type: boolean
               description: Update the support field for all videos of this channel
+
     VideoChannelList:
       properties:
         total:
@@ -7613,6 +8752,18 @@ components:
               - $ref: '#/components/schemas/VideoChannel'
               - $ref: '#/components/schemas/Actor'
 
+    ImportVideosInChannelCreate:
+      type: object
+      properties:
+        externalChannelUrl:
+          type: string
+          example: https://youtube.com/c/UC_myfancychannel
+        videoChannelSyncId:
+          type: integer
+          description: If part of a channel sync process, specify its id to assign video imports to this channel synchronization
+      required:
+        - 'externalChannelUrl'
+
     VideoChannelSync:
       type: object
       properties:
@@ -7847,17 +8998,13 @@ components:
     NotificationSettingValue:
       type: integer
       description: >
-        Notification type
+        Notification type. One of the following values, or a sum of multiple values:
 
         - `0` NONE
 
         - `1` WEB
 
         - `2` EMAIL
-      enum:
-        - 0
-        - 1
-        - 2
     Notification:
       properties:
         id:
@@ -8066,6 +9213,8 @@ components:
       properties:
         saveReplay:
           type: boolean
+        replaySettings:
+          $ref: '#/components/schemas/LiveVideoReplaySettings'
         permanentLive:
           description: User can stream multiple times in a permanent live
           type: boolean
@@ -8086,6 +9235,8 @@ components:
           description: RTMP stream key to use to stream into this live video. Included in the response if an appropriate token is provided
         saveReplay:
           type: boolean
+        replaySettings:
+          $ref: '#/components/schemas/LiveVideoReplaySettings'
         permanentLive:
           description: User can stream multiple times in a permanent live
           type: boolean
@@ -8093,6 +9244,21 @@ components:
           description: User can select live latency mode if enabled by the instance
           $ref: '#/components/schemas/LiveVideoLatencyMode'
 
+    RequestTwoFactorResponse:
+      properties:
+        otpRequest:
+          type: object
+          properties:
+            requestToken:
+              type: string
+              description: The token to send to confirm this request
+            secret:
+              type: string
+              description: The OTP secret
+            uri:
+              type: string
+              description: The OTP URI
+
     VideoStudioCreateTask:
       type: array
       items:
@@ -8156,44 +9322,275 @@ components:
                     format: binary
 
     LiveVideoSessionResponse:
-        properties:
-          id:
-            type: integer
-          startDate:
-            type: string
-            format: date-time
-            description: Start date of the live session
-          endDate:
-            type: string
-            format: date-time
-            nullable: true
-            description: End date of the live session
-          error:
-            type: integer
-            enum:
-              - 1
-              - 2
-              - 3
-              - 4
-              - 5
-            nullable: true
-            description: >
-              Error type if an error occurred during the live session:
-                - `1`: Bad socket health (transcoding is too slow)
-                - `2`: Max duration exceeded
-                - `3`: Quota exceeded
-                - `4`: Quota FFmpeg error
-                - `5`: Video has been blacklisted during the live
-          replayVideo:
-            type: object
-            description: Video replay information
-            properties:
-              id:
-                type: number
-              uuid:
-                $ref: '#/components/schemas/UUIDv4'
-              shortUUID:
-                $ref: '#/components/schemas/shortUUID'
+      properties:
+        id:
+          type: integer
+        startDate:
+          type: string
+          format: date-time
+          description: Start date of the live session
+        endDate:
+          type: string
+          format: date-time
+          nullable: true
+          description: End date of the live session
+        error:
+          type: integer
+          enum:
+            - 1
+            - 2
+            - 3
+            - 4
+            - 5
+          nullable: true
+          description: >
+            Error type if an error occurred during the live session:
+              - `1`: Bad socket health (transcoding is too slow)
+              - `2`: Max duration exceeded
+              - `3`: Quota exceeded
+              - `4`: Quota FFmpeg error
+              - `5`: Video has been blacklisted during the live
+        replayVideo:
+          type: object
+          description: Video replay information
+          properties:
+            id:
+              type: number
+            uuid:
+              $ref: '#/components/schemas/UUIDv4'
+            shortUUID:
+              $ref: '#/components/schemas/shortUUID'
+
+    PlaybackMetricCreate:
+      properties:
+        playerMode:
+          type: string
+          enum:
+            - 'p2p-media-loader'
+            - 'webtorrent'
+        resolution:
+          type: number
+          description: Current player video resolution
+        fps:
+          type: number
+          description: Current player video fps
+        resolutionChanges:
+          type: number
+          description: How many resolution changes occured since the last metric creation
+        errors:
+          type: number
+          description: How many errors occured since the last metric creation
+        downloadedBytesP2P:
+          type: number
+          description: How many bytes were downloaded with P2P since the last metric creation
+        downloadedBytesHTTP:
+          type: number
+          description: How many bytes were downloaded with HTTP since the last metric creation
+        uploadedBytesP2P:
+          type: number
+          description: How many bytes were uploaded with P2P since the last metric creation
+        videoId:
+          oneOf:
+            - $ref: '#/components/schemas/id'
+            - $ref: '#/components/schemas/UUIDv4'
+            - $ref: '#/components/schemas/shortUUID'
+      required:
+        - playerMode
+        - resolutionChanges
+        - errors
+        - downloadedBytesP2P
+        - downloadedBytesHTTP
+        - uploadedBytesP2P
+        - videoId
+
+    RunnerRegistrationToken:
+      properties:
+        id:
+          type: integer
+        registrationToken:
+          type: string
+        createdAt:
+          type: string
+          format: date-time
+        updatedAt:
+          type: string
+          format: date-time
+        registeredRunnersCount:
+          type: integer
+
+    Runner:
+      properties:
+        id:
+          type: integer
+        name:
+          type: string
+        description:
+          type: string
+        ip:
+          type: string
+        updatedAt:
+          type: string
+          format: date-time
+        createdAt:
+          type: string
+          format: date-time
+        lastContact:
+          type: string
+          format: date-time
+
+    RunnerJobType:
+      type: string
+      enum:
+        - vod-web-video-transcoding
+        - vod-hls-transcoding
+        - vod-audio-merge-transcoding
+        - live-rtmp-hls-transcoding
+
+    RunnerJobState:
+      type: integer
+      enum:
+        - 1
+        - 2
+        - 3
+        - 4
+        - 5
+        - 6
+        - 7
+        - 8
+      description: >
+        The runner job state:
+          - `1` Pending
+          - `2` Processing
+          - `3` Completed
+          - `4` Errored
+          - `5` Waiting for a parent job
+          - `6` Cancelled
+          - `7` Parent had an error
+          - `8` Parent has been cancelled
+
+    RunnerJobStateConstant:
+      type: object
+      properties:
+        id:
+          $ref: '#/components/schemas/RunnerJobState'
+        label:
+          type: string
+          example: 'Processing'
+
+    RunnerJobPayload:
+      anyOf:
+        - type: object
+          title: VOD web video transcoding
+          properties:
+            input:
+              type: object
+              properties:
+                videoFileUrl:
+                  type: string
+            output:
+              type: object
+              properties:
+                resolution:
+                  type: number
+                fps:
+                  type: number
+        - type: object
+          title: VOD HLS transcoding
+          properties:
+            input:
+              type: object
+              properties:
+                videoFileUrl:
+                  type: string
+            output:
+              type: object
+              properties:
+                resolution:
+                  type: number
+                fps:
+                  type: number
+        - type: object
+          title: VOD audio merge transcoding
+          properties:
+            input:
+              type: object
+              properties:
+                audioFileUrl:
+                  type: string
+                previewFileUrl:
+                  type: string
+            output:
+              type: object
+              properties:
+                resolution:
+                  type: number
+                fps:
+                  type: number
+
+    RunnerJob:
+      properties:
+        uuid:
+          $ref: '#/components/schemas/UUIDv4'
+        type:
+          $ref: '#/components/schemas/RunnerJobType'
+        state:
+          $ref: '#/components/schemas/RunnerJobStateConstant'
+        payload:
+          $ref: '#/components/schemas/RunnerJobPayload'
+        failures:
+          type: integer
+          description: Number of times a remote runner failed to process this job. After too many failures, the job in "error" state
+        error:
+          nullable: true
+          type: string
+          description: Error message if the job is errored
+        progress:
+          type: integer
+          description: Percentage progress
+        priority:
+          type: integer
+          description: Job priority (less has more priority)
+        updatedAt:
+          type: string
+          format: date-time
+        createdAt:
+          type: string
+          format: date-time
+        startedAt:
+          type: string
+          format: date-time
+        finishedAt:
+          type: string
+          format: date-time
+        parent:
+          nullable: true
+          description: If job has a parent job
+          type: object
+          properties:
+            type:
+              $ref: '#/components/schemas/RunnerJobType'
+            state:
+              $ref: '#/components/schemas/RunnerJobStateConstant'
+            uuid:
+              $ref: '#/components/schemas/UUIDv4'
+        runner:
+          nullable: true
+          description: If job is associated to a runner
+          properties:
+            id:
+              type: number
+            name:
+              type: string
+            description:
+              type: string
+
+    RunnerJobAdmin:
+      allOf:
+        - $ref: '#/components/schemas/RunnerJob'
+        - type: object
+          properties:
+            privatePayload:
+              type: object
 
   callbacks:
     searchIndex: