]> 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 70f2d97f55f81d90f832262c7b1e05c084a556a2..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.
@@ -247,13 +246,15 @@ tags:
       ### Import
 
       - _URL_-based: where the URL points to any service supported by [youtube-dl](https://ytdl-org.github.io/youtube-dl/)
-      - _magnet_-based: where the URI resolves to a BitTorrent ressource containing a single supported video file
-      - _torrent_-based: where the metainfo file resolves to a BitTorrent ressource containing a single supported video file
+      - _magnet_-based: where the URI resolves to a BitTorrent resource containing a single supported video file
+      - _torrent_-based: where the metainfo file resolves to a BitTorrent resource containing a single supported video file
 
       The import function is practical when the desired video/audio is available online. It makes PeerTube
       download it for you, saving you as much bandwidth and avoiding any instability or limitation your network might have.
   - name: Video Imports
     description: Operations dealing with listing, adding and removing video imports.
+  - name: Channels Sync
+    description: Operations dealing with synchronizing PeerTube user's channel with channels of other platforms
   - name: Video Captions
     description: Operations dealing with listing, adding and removing closed captions of a video.
   - name: Video Channels
@@ -273,8 +274,10 @@ tags:
     description: Operations on video files
   - name: Video Transcoding
     description: Video transcoding related operations
-  - name: Feeds
-    description: Server syndication feeds
+  - name: Video Stats
+    description: Video statistics
+  - 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.
@@ -291,7 +294,20 @@ tags:
       PeerTube instances can mirror videos from one another, and help distribute some videos.
 
       For importing videos as your own, refer to [video imports](#operation/importVideo).
+  - 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
@@ -314,454 +330,459 @@ x-tagGroups:
       - Video Comments
       - Video Rates
       - Video Playlists
+      - Video Stats
       - Video Ownership Change
       - Video Mirroring
       - Video Files
       - Video Transcoding
       - Live Videos
-      - Feeds
+      - Channels Sync
   - name: Search
     tags:
       - Search
-  - name: Custom pages
-    tags:
-      - Homepage
   - name: Moderation
     tags:
       - Abuses
       - Video Blocks
       - Account Blocks
       - Server Blocks
-  - name: Instance Configuration
+  - name: Instance
     tags:
       - Config
+      - Homepage
       - Instance Follows
       - Instance Redundancy
       - Plugins
-  - name: Jobs
-    tags:
+      - 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
+              - videoId filter is mixed with a channel filter
+        '404':
+          description: video, video channel or account not found
+        '406':
+          description: accept header unsupported
+
+  '/feeds/videos.{format}':
+    get:
       tags:
-        - Config
-      security:
-        - OAuth2:
-          - admin
-      responses:
-        '200':
-          description: successful operation
-
-  /custom-pages/homepage/instance:
-    get:
-      summary: Get instance custom homepage
-      tags:
-        - Homepage
+        - 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:
-        '404':
-          description: No homepage set
-        '200':
+        '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:
-                $ref: '#/components/schemas/CustomHomepage'
-    put:
-      summary: Set instance custom homepage
-      tags:
-        - Homepage
-      security:
-        - OAuth2:
-          - admin
-      requestBody:
-        content:
-          application/json:
-            schema:
-              type: object
-              properties:
-                content:
-                  type: string
-                  description: content of the homepage, that will be injected in the client
-      responses:
-        '204':
-          description: successful operation
-
-  /jobs/pause:
-    post:
-      summary: Pause job queue
-      security:
-        - OAuth2:
-          - admin
-      tags:
-        - Job
-      responses:
-        '204':
-          description: successful operation
-
-  /jobs/resume:
-    post:
-      summary: Resume job queue
-      security:
-        - OAuth2:
-          - admin
-      tags:
-        - Job
-      responses:
-        '204':
-          description: successful operation
+                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
 
-  /jobs/{state}:
+  '/feeds/subscriptions.{format}':
     get:
-      summary: List instance jobs
-      operationId: getJobs
-      security:
-        - OAuth2:
-          - admin
       tags:
-        - Job
+        - Video Feeds
+      summary: List videos of subscriptions tied to a token
+      operationId: getSyndicatedSubscriptionVideos
       parameters:
-        - name: state
+        - name: format
           in: path
           required: true
-          description: The state of the job ('' for for no filter)
+          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:
-              - ''
-              - active
-              - completed
-              - failed
-              - waiting
-              - delayed
-        - $ref: '#/components/parameters/jobType'
-        - $ref: '#/components/parameters/start'
-        - $ref: '#/components/parameters/count'
+              - 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:
-        '200':
+        '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
-                properties:
-                  total:
-                    type: integer
-                    example: 1
-                  data:
-                    type: array
-                    maxItems: 100
-                    items:
-                      $ref: '#/components/schemas/Job'
+        '406':
+          description: accept header unsupported
 
-  /server/followers:
+  '/api/v1/accounts/{name}':
     get:
       tags:
-        - Instance Follows
-      summary: List instances following the server
+        - Accounts
+      summary: Get an account
+      operationId: getAccount
       parameters:
-        - $ref: '#/components/parameters/followState'
-        - $ref: '#/components/parameters/actorType'
-        - $ref: '#/components/parameters/start'
-        - $ref: '#/components/parameters/count'
-        - $ref: '#/components/parameters/sort'
+        - $ref: '#/components/parameters/name'
       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'
+                $ref: '#/components/schemas/Account'
+        '404':
+          description: account not found
 
-  '/server/followers/{nameWithHost}':
-    delete:
-      summary: Remove or reject a follower to your server
-      security:
-        - OAuth2:
-          - admin
+  '/api/v1/accounts/{name}/videos':
+    get:
       tags:
-        - Instance Follows
+        - Accounts
+        - Video
+      summary: 'List videos of an account'
+      operationId: getAccountVideos
       parameters:
-        - name: nameWithHost
-          in: path
-          required: true
-          description: The remote actor handle to remove from your followers
-          schema:
-            type: string
-            format: email
+        - $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:
-        '204':
+        '200':
           description: successful operation
-        '404':
-          description: follower not found
+          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'
 
-  '/server/followers/{nameWithHost}/reject':
-    post:
-      summary: Reject a pending follower to your server
-      security:
-        - OAuth2:
-          - admin
-      tags:
-        - Instance Follows
-      parameters:
-        - name: nameWithHost
-          in: path
-          required: true
-          description: The remote actor handle to remove from your followers
-          schema:
-            type: string
-            format: email
-      responses:
-        '204':
-          description: successful operation
-        '404':
-          description: follower not found
+            uri = URI.parse("https://peertube2.cpy.re/api/v1/accounts/{name}/videos")
 
-  '/server/followers/{nameWithHost}/accept':
-    post:
-      summary: Accept a pending follower to your server
-      security:
-        - OAuth2:
-          - admin
-      tags:
-        - Instance Follows
-      parameters:
-        - name: nameWithHost
-          in: path
-          required: true
-          description: The remote actor handle to remove from your followers
-          schema:
-            type: string
-            format: email
-      responses:
-        '204':
-          description: successful operation
-        '404':
-          description: follower not found
+            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()
 
-  /server/following:
+            print(json)
+
+  '/api/v1/accounts/{name}/followers':
     get:
       tags:
-        - Instance Follows
-      summary: List instances followed by the server
+        - Accounts
+      summary: 'List followers of an account'
+      security:
+        - OAuth2: []
+      operationId: getAccountFollowers
       parameters:
-        - $ref: '#/components/parameters/followState'
-        - $ref: '#/components/parameters/actorType'
+        - $ref: '#/components/parameters/name'
         - $ref: '#/components/parameters/start'
         - $ref: '#/components/parameters/count'
-        - $ref: '#/components/parameters/sort'
+        - $ref: '#/components/parameters/followersSort'
+        - $ref: '#/components/parameters/search'
       responses:
         '200':
           description: successful operation
@@ -777,405 +798,194 @@ paths:
                     type: array
                     items:
                       $ref: '#/components/schemas/Follow'
-    post:
-      security:
-        - OAuth2:
-          - admin
-      tags:
-        - Instance Follows
-      summary: Follow a list of actors (PeerTube instance, channel or account)
-      responses:
-        '204':
-          description: successful operation
-        '500':
-          description: cannot follow a non-HTTPS server
-      requestBody:
-        content:
-          application/json:
-            schema:
-              type: object
-              properties:
-                hosts:
-                  type: array
-                  items:
-                    type: string
-                    format: hostname
-                  uniqueItems: true
-                handles:
-                  type: array
-                  items:
-                    type: string
-                  uniqueItems: true
 
-  '/server/following/{hostOrHandle}':
-    delete:
-      summary: Unfollow an actor (PeerTube instance, channel or account)
-      security:
-        - OAuth2:
-          - admin
+  /api/v1/accounts:
+    get:
       tags:
-        - Instance Follows
+        - Accounts
+      summary: List accounts
+      operationId: getAccounts
       parameters:
-        - name: hostOrHandle
-          in: path
-          required: true
-          description: The hostOrHandle to unfollow
-          schema:
-            type: string
+        - $ref: '#/components/parameters/start'
+        - $ref: '#/components/parameters/count'
+        - $ref: '#/components/parameters/sort'
       responses:
-        '204':
+        '200':
           description: successful operation
-        '404':
-          description: host or handle not found
+          content:
+            'application/json':
+              schema:
+                type: object
+                properties:
+                  total:
+                    type: integer
+                    example: 1
+                  data:
+                    type: array
+                    items:
+                      $ref: '#/components/schemas/Account'
 
-  /users:
-    post:
-      summary: Create a user
-      operationId: addUser
-      security:
-        - OAuth2:
-          - admin
+  /api/v1/config:
+    get:
       tags:
-        - Users
+        - Config
+      summary: Get instance public configuration
+      operationId: getConfig
       responses:
         '200':
-          description: user created
+          description: successful operation
           content:
             application/json:
               schema:
-                $ref: '#/components/schemas/AddUserResponse'
-          links:
-            # GET /users/{id}
-            GetUser:
-              operationId: getUser
-              parameters:
-                id: '$response.body#/user/id'
-            # PUT /users/{id}
-            PutUser:
-              operationId: putUser
-              parameters:
-                id: '$response.body#/user/id'
-            # DELETE /users/{id}
-            DelUser:
-              operationId: delUser
-              parameters:
-                id: '$response.body#/user/id'
-        '403':
-          description: insufficient authority to create an admin or moderator
-      requestBody:
-        content:
-          application/json:
-            schema:
-              $ref: '#/components/schemas/AddUser'
-        description: |
-          If the smtp server is configured, you can leave the password empty and an email will be sent
-          asking the user to set it first.
-        required: true
+                $ref: '#/components/schemas/ServerConfig'
+              examples:
+                nightly:
+                  externalValue: https://peertube2.cpy.re/api/v1/config
+
+  /api/v1/config/about:
     get:
-      summary: List users
-      operationId: getUsers
-      security:
-        - OAuth2:
-          - admin
+      summary: Get instance "About" information
+      operationId: getAbout
       tags:
-        - Users
-      parameters:
-        - $ref: '#/components/parameters/usersSearch'
-        - $ref: '#/components/parameters/usersBlocked'
-        - $ref: '#/components/parameters/start'
-        - $ref: '#/components/parameters/count'
-        - $ref: '#/components/parameters/usersSort'
+        - Config
       responses:
         '200':
           description: successful operation
           content:
             application/json:
               schema:
-                type: array
-                items:
-                  $ref: '#/components/schemas/User'
+                $ref: '#/components/schemas/ServerConfigAbout'
+              examples:
+                nightly:
+                  externalValue: https://peertube2.cpy.re/api/v1/config/about
 
-  '/users/{id}':
-    parameters:
-      - $ref: '#/components/parameters/id'
-    delete:
-      summary: Delete a user
+  /api/v1/config/custom:
+    get:
+      summary: Get instance runtime configuration
+      operationId: getCustomConfig
+      tags:
+        - Config
       security:
         - OAuth2:
           - admin
-      tags:
-        - Users
-      operationId: delUser
       responses:
-        '204':
+        '200':
           description: successful operation
-    get:
-      summary: Get a user
-      security:
-        - OAuth2: []
-      tags:
-        - Users
-      operationId: getUser
-      parameters:
-        - name: withStats
-          in: query
-          description: include statistics about the user (only available as a moderator/admin)
-          schema:
-            type: boolean
-      responses:
-        '200':
-          x-summary: successful operation
-          description: |
-            As an admin/moderator, you can request a response augmented with statistics about the user's
-            moderation relations and videos usage, by using the `withStats` parameter.
           content:
             application/json:
               schema:
-                oneOf:
-                  - $ref: '#/components/schemas/User'
-                  - $ref: '#/components/schemas/UserWithStats'
+                $ref: '#/components/schemas/ServerConfigCustom'
     put:
-      summary: Update a user
-      security:
-        - OAuth2: []
+      summary: Set instance runtime configuration
+      operationId: putCustomConfig
       tags:
-        - Users
-      operationId: putUser
+        - Config
+      security:
+        - OAuth2:
+          - admin
       responses:
-        '204':
+        '200':
           description: successful operation
-      requestBody:
-        content:
-          application/json:
-            schema:
-              $ref: '#/components/schemas/UpdateUser'
-        required: true
-
-  /oauth-clients/local:
-    get:
-      summary: Login prerequisite
-      description: You need to retrieve a client id and secret before [logging in](#operation/getOAuthToken).
-      operationId: getOAuthClient
+        '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:
-        - Session
+        - Config
+      security:
+        - OAuth2:
+          - admin
       responses:
         '200':
           description: successful operation
-          content:
-            application/json:
-              schema:
-                $ref: '#/components/schemas/OAuthClient'
-          links:
-            UseOAuthClientToLogin:
-              operationId: getOAuthToken
-              parameters:
-                client_id: '$response.body#/client_id'
-                client_secret: '$response.body#/client_secret'
-      x-codeSamples:
-        - lang: Shell
-          source: |
-            API="https://peertube2.cpy.re/api/v1"
-
-            ## AUTH
-            curl -s "$API/oauth-clients/local"
 
-  /users/token:
-    post:
-      summary: Login
-      operationId: getOAuthToken
-      description: With your [client id and secret](#operation/getOAuthClient), you can retrieve an access and refresh tokens.
+  /api/v1/custom-pages/homepage/instance:
+    get:
+      summary: Get instance custom homepage
       tags:
-        - Session
-      requestBody:
-        content:
-          application/x-www-form-urlencoded:
-            schema:
-              oneOf:
-                - $ref: '#/components/schemas/OAuthToken-password'
-                - $ref: '#/components/schemas/OAuthToken-refresh_token'
-              discriminator:
-                propertyName: grant_type
-                mapping:
-                  password: '#/components/schemas/OAuthToken-password'
-                  refresh_token: '#/components/schemas/OAuthToken-refresh_token'
+        - Homepage
       responses:
+        '404':
+          description: No homepage set
         '200':
           description: successful operation
           content:
             application/json:
               schema:
-                type: object
-                properties:
-                  token_type:
-                    type: string
-                    example: Bearer
-                  access_token:
-                    type: string
-                    example: 90286a0bdf0f7315d9d3fe8dabf9e1d2be9c97d0
-                    description: valid for 1 day
-                  refresh_token:
-                    type: string
-                    example: 2e0d675df9fc96d2e4ec8a3ebbbf45eca9137bb7
-                    description: valid for 2 weeks
-                  expires_in:
-                    type: integer
-                    minimum: 0
-                    example: 14399
-                  refresh_token_expires_in:
-                    type: integer
-                    minimum: 0
-                    example: 1209600
-        '400':
-          x-summary: client or credentials are invalid
-          description: |
-            Disambiguate via `type`:
-            - `invalid_client` for an unmatched `client_id`
-            - `invalid_grant` for unmatched credentials
-        '401':
-          x-summary: token expired
-          description: |
-            Disambiguate via `type`:
-            - default value for a regular authentication failure
-            - `invalid_token` for an expired token
-      x-codeSamples:
-        - lang: Shell
-          source: |
-            ## DEPENDENCIES: jq
-            API="https://peertube2.cpy.re/api/v1"
-            USERNAME="<your_username>"
-            PASSWORD="<your_password>"
-
-            ## AUTH
-            client_id=$(curl -s "$API/oauth-clients/local" | jq -r ".client_id")
-            client_secret=$(curl -s "$API/oauth-clients/local" | jq -r ".client_secret")
-            curl -s "$API/users/token" \
-              --data client_id="$client_id" \
-              --data client_secret="$client_secret" \
-              --data grant_type=password \
-              --data username="$USERNAME" \
-              --data password="$PASSWORD" \
-              | jq -r ".access_token"
-
-  /users/revoke-token:
-    post:
-      summary: Logout
-      description: Revokes your access token and its associated refresh token, destroying your current session.
-      operationId: revokeOAuthToken
+                $ref: '#/components/schemas/CustomHomepage'
+    put:
+      summary: Set instance custom homepage
       tags:
-        - Session
+        - Homepage
       security:
-        - OAuth2: []
-      responses:
-        '200':
-          description: successful operation
-
-  /users/register:
-    post:
-      summary: Register a user
-      operationId: registerUser
-      tags:
-        - Users
-        - Register
-      responses:
-        '204':
-          description: successful operation
-      requestBody:
-        content:
-          application/json:
-            schema:
-              $ref: '#/components/schemas/RegisterUser'
-        required: true
-
-  /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.
-      tags:
-        - Users
-        - Register
-      parameters:
-        - $ref: '#/components/parameters/id'
+        - OAuth2:
+          - admin
       requestBody:
         content:
           application/json:
             schema:
               type: object
               properties:
-                verificationString:
+                content:
                   type: string
-                  format: url
-                isPendingEmail:
-                  type: boolean
-              required:
-                - verificationString
+                  description: content of the homepage, that will be injected in the client
       responses:
         '204':
           description: successful operation
-        '403':
-          description: invalid verification string
-        '404':
-          description: user not found
 
-  /users/ask-send-verify-email:
+  /api/v1/jobs/pause:
     post:
-      summary: Resend user verification link
-      operationId: resendEmailToVerifyUser
-      tags:
-        - Users
-        - Register
-      responses:
-        '204':
-          description: successful operation
-
-  /users/me:
-    get:
-      summary: Get my user information
-      operationId: getUserInfo
+      summary: Pause job queue
       security:
         - OAuth2:
-          - user
+          - admin
       tags:
-        - My User
+        - Job
       responses:
-        '200':
+        '204':
           description: successful operation
-          content:
-            application/json:
-              schema:
-                type: array
-                items:
-                  $ref: '#/components/schemas/User'
-    put:
-      summary: Update my user information
-      operationId: putUserInfo
+
+  /api/v1/jobs/resume:
+    post:
+      summary: Resume job queue
       security:
         - OAuth2:
-          - user
+          - admin
       tags:
-        - My User
+        - Job
       responses:
         '204':
           description: successful operation
-      requestBody:
-        content:
-          application/json:
-            schema:
-              $ref: '#/components/schemas/UpdateMe'
-        required: true
 
-  /users/me/videos/imports:
+  /api/v1/jobs/{state}:
     get:
-      summary: Get video imports of my user
+      summary: List instance jobs
+      operationId: getJobs
       security:
         - OAuth2:
-          - user
+          - admin
       tags:
-        - Videos
-        - My User
+        - Job
       parameters:
+        - name: state
+          in: path
+          required: true
+          description: The state of the job ('' for for no filter)
+          schema:
+            type: string
+            enum:
+              - ''
+              - active
+              - completed
+              - failed
+              - waiting
+              - delayed
+        - $ref: '#/components/parameters/jobType'
         - $ref: '#/components/parameters/start'
         - $ref: '#/components/parameters/count'
         - $ref: '#/components/parameters/sort'
@@ -1185,16 +995,28 @@ paths:
           content:
             application/json:
               schema:
-                $ref: '#/components/schemas/VideoImportsList'
+                type: object
+                properties:
+                  total:
+                    type: integer
+                    example: 1
+                  data:
+                    type: array
+                    maxItems: 100
+                    items:
+                      $ref: '#/components/schemas/Job'
 
-  /users/me/video-quota-used:
+  /api/v1/server/followers:
     get:
-      summary: Get my user used quota
-      security:
-        - OAuth2:
-          - user
       tags:
-        - My User
+        - Instance Follows
+      summary: List instances following the server
+      parameters:
+        - $ref: '#/components/parameters/followState'
+        - $ref: '#/components/parameters/actorType'
+        - $ref: '#/components/parameters/start'
+        - $ref: '#/components/parameters/count'
+        - $ref: '#/components/parameters/sort'
       responses:
         '200':
           description: successful operation
@@ -1203,68 +1025,88 @@ paths:
               schema:
                 type: object
                 properties:
-                  videoQuotaUsed:
-                    type: number
-                    description: The user video quota used so far in bytes
-                    example: 16810141515
-                  videoQuotaUsedDaily:
-                    type: number
-                    description: The user video quota used today in bytes
-                    example: 1681014151
+                  total:
+                    type: integer
+                    example: 1
+                  data:
+                    type: array
+                    items:
+                      $ref: '#/components/schemas/Follow'
 
-  '/users/me/videos/{videoId}/rating':
-    get:
-      summary: Get rate of my user for a video
+  '/api/v1/server/followers/{nameWithHost}':
+    delete:
+      summary: Remove or reject a follower to your server
       security:
-        - OAuth2: []
+        - OAuth2:
+          - admin
       tags:
-        - My User
-        - Video Rates
+        - Instance Follows
       parameters:
-        - name: videoId
+        - name: nameWithHost
           in: path
           required: true
-          description: The video id
+          description: The remote actor handle to remove from your followers
           schema:
-            $ref: '#/components/schemas/Video/properties/id'
+            type: string
+            format: email
       responses:
-        '200':
+        '204':
           description: successful operation
-          content:
-            application/json:
-              schema:
-                $ref: '#/components/schemas/GetMeVideoRating'
+        '404':
+          description: follower not found
 
-  /users/me/videos:
-    get:
-      summary: Get videos of my user
+  '/api/v1/server/followers/{nameWithHost}/reject':
+    post:
+      summary: Reject a pending follower to your server
       security:
         - OAuth2:
-          - user
+          - admin
       tags:
-        - My User
-        - Videos
+        - Instance Follows
       parameters:
-        - $ref: '#/components/parameters/start'
-        - $ref: '#/components/parameters/count'
-        - $ref: '#/components/parameters/sort'
+        - name: nameWithHost
+          in: path
+          required: true
+          description: The remote actor handle to remove from your followers
+          schema:
+            type: string
+            format: email
       responses:
-        '200':
+        '204':
           description: successful operation
-          content:
-            application/json:
-              schema:
-                $ref: '#/components/schemas/VideoListResponse'
+        '404':
+          description: follower not found
 
-  /users/me/subscriptions:
-    get:
-      summary: Get my user subscriptions
+  '/api/v1/server/followers/{nameWithHost}/accept':
+    post:
+      summary: Accept a pending follower to your server
       security:
         - OAuth2:
-          - user
+          - admin
       tags:
-        - My Subscriptions
+        - Instance Follows
+      parameters:
+        - name: nameWithHost
+          in: path
+          required: true
+          description: The remote actor handle to remove from your followers
+          schema:
+            type: string
+            format: email
+      responses:
+        '204':
+          description: successful operation
+        '404':
+          description: follower not found
+
+  /api/v1/server/following:
+    get:
+      tags:
+        - Instance Follows
+      summary: List instances followed by the server
       parameters:
+        - $ref: '#/components/parameters/followState'
+        - $ref: '#/components/parameters/actorType'
         - $ref: '#/components/parameters/start'
         - $ref: '#/components/parameters/count'
         - $ref: '#/components/parameters/sort'
@@ -1274,280 +1116,236 @@ paths:
           content:
             application/json:
               schema:
-                $ref: '#/components/schemas/VideoChannelList'
+                type: object
+                properties:
+                  total:
+                    type: integer
+                    example: 1
+                  data:
+                    type: array
+                    items:
+                      $ref: '#/components/schemas/Follow'
     post:
-      tags:
-        - My Subscriptions
-      summary: Add subscription to my user
       security:
         - OAuth2:
-          - user
+          - admin
+      tags:
+        - Instance Follows
+      summary: Follow a list of actors (PeerTube instance, channel or account)
+      responses:
+        '204':
+          description: successful operation
+        '500':
+          description: cannot follow a non-HTTPS server
       requestBody:
         content:
           application/json:
             schema:
               type: object
               properties:
-                uri:
-                  type: string
-                  format: uri
-                  description: uri of the video channels to subscribe to
-              required:
-                - uri
-            examples:
-              default:
-                value:
-                  uri: 008a0e54-375d-49d0-8379-143202e24152@video.lqdn.fr
-      responses:
-        '200':
-          description: successful operation
-
-  /users/me/subscriptions/exist:
-    get:
-      summary: Get if subscriptions exist for my user
-      security:
-        - OAuth2:
-          - user
-      tags:
-        - My Subscriptions
-      parameters:
-        - $ref: '#/components/parameters/subscriptionsUris'
-      responses:
-        '200':
-          description: successful operation
-          content:
-            application/json:
-              schema:
-                type: object
+                hosts:
+                  type: array
+                  items:
+                    type: string
+                    format: hostname
+                  uniqueItems: true
+                handles:
+                  type: array
+                  items:
+                    type: string
+                  uniqueItems: true
 
-  /users/me/subscriptions/videos:
-    get:
-      summary: List videos of subscriptions of my user
+  '/api/v1/server/following/{hostOrHandle}':
+    delete:
+      summary: Unfollow an actor (PeerTube instance, channel or account)
       security:
         - OAuth2:
-          - user
+          - admin
       tags:
-        - My Subscriptions
-        - Videos
+        - Instance Follows
       parameters:
-        - $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'
+        - name: hostOrHandle
+          in: path
+          required: true
+          description: The hostOrHandle to unfollow
+          schema:
+            type: string
       responses:
-        '200':
+        '204':
           description: successful operation
-          content:
-            application/json:
-              schema:
-                $ref: '#/components/schemas/VideoListResponse'
+        '404':
+          description: host or handle not found
 
-  '/users/me/subscriptions/{subscriptionHandle}':
-    get:
-      summary: Get subscription of my user
+  /api/v1/users:
+    post:
+      summary: Create a user
+      operationId: addUser
       security:
         - OAuth2:
-          - user
+          - admin
       tags:
-        - My Subscriptions
-      parameters:
-        - $ref: '#/components/parameters/subscriptionHandle'
+        - Users
       responses:
         '200':
-          description: successful operation
+          description: user created
           content:
             application/json:
               schema:
-                $ref: '#/components/schemas/VideoChannel'
-    delete:
-      summary: Delete subscription of my user
-      security:
-        - OAuth2:
-          - user
-      tags:
-        - My Subscriptions
-      parameters:
-        - $ref: '#/components/parameters/subscriptionHandle'
-      responses:
-        '200':
-          description: successful operation
-
-  /users/me/notifications:
+                $ref: '#/components/schemas/AddUserResponse'
+          links:
+            # GET /users/{id}
+            GetUser:
+              operationId: getUser
+              parameters:
+                id: '$response.body#/user/id'
+            # PUT /users/{id}
+            PutUser:
+              operationId: putUser
+              parameters:
+                id: '$response.body#/user/id'
+            # DELETE /users/{id}
+            DelUser:
+              operationId: delUser
+              parameters:
+                id: '$response.body#/user/id'
+        '403':
+          description: insufficient authority to create an admin or moderator
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/AddUser'
+        description: |
+          If the smtp server is configured, you can leave the password empty and an email will be sent
+          asking the user to set it first.
+        required: true
     get:
-      summary: List my notifications
+      summary: List users
+      operationId: getUsers
       security:
-        - OAuth2: []
+        - OAuth2:
+          - admin
       tags:
-        - My Notifications
+        - Users
       parameters:
-        - name: unread
-          in: query
-          description: only list unread notifications
-          schema:
-            type: boolean
+        - $ref: '#/components/parameters/usersSearch'
+        - $ref: '#/components/parameters/usersBlocked'
         - $ref: '#/components/parameters/start'
         - $ref: '#/components/parameters/count'
-        - $ref: '#/components/parameters/sort'
+        - $ref: '#/components/parameters/usersSort'
       responses:
         '200':
           description: successful operation
           content:
             application/json:
               schema:
-                $ref: '#/components/schemas/NotificationListResponse'
+                type: array
+                items:
+                  $ref: '#/components/schemas/User'
 
-  /users/me/notifications/read:
-    post:
-      summary: Mark notifications as read by their id
+  '/api/v1/users/{id}':
+    parameters:
+      - $ref: '#/components/parameters/id'
+    delete:
+      summary: Delete a user
       security:
-        - OAuth2: []
+        - OAuth2:
+          - admin
       tags:
-        - My Notifications
-      requestBody:
-        content:
-          application/json:
-            schema:
-              type: object
-              properties:
-                ids:
-                  type: array
-                  description: ids of the notifications to mark as read
-                  items:
-                    type: integer
-              required:
-                - ids
+        - Users
+      operationId: delUser
       responses:
         '204':
           description: successful operation
-
-  /users/me/notifications/read-all:
-    post:
-      summary: Mark all my notification as read
+    get:
+      summary: Get a user
       security:
         - OAuth2: []
       tags:
-        - My Notifications
+        - Users
+      operationId: getUser
+      parameters:
+        - name: withStats
+          in: query
+          description: include statistics about the user (only available as a moderator/admin)
+          schema:
+            type: boolean
       responses:
-        '204':
-          description: successful operation
-
-  /users/me/notification-settings:
+        '200':
+          x-summary: successful operation
+          description: |
+            As an admin/moderator, you can request a response augmented with statistics about the user's
+            moderation relations and videos usage, by using the `withStats` parameter.
+          content:
+            application/json:
+              schema:
+                oneOf:
+                  - $ref: '#/components/schemas/User'
+                  - $ref: '#/components/schemas/UserWithStats'
     put:
-      summary: Update my notification settings
+      summary: Update a user
       security:
         - OAuth2: []
       tags:
-        - My Notifications
+        - Users
+      operationId: putUser
+      responses:
+        '204':
+          description: successful operation
       requestBody:
         content:
           application/json:
             schema:
-              type: object
-              properties:
-                newVideoFromSubscription:
-                  $ref: '#/components/schemas/NotificationSettingValue'
-                newCommentOnMyVideo:
-                  $ref: '#/components/schemas/NotificationSettingValue'
-                abuseAsModerator:
-                  $ref: '#/components/schemas/NotificationSettingValue'
-                videoAutoBlacklistAsModerator:
-                  $ref: '#/components/schemas/NotificationSettingValue'
-                blacklistOnMyVideo:
-                  $ref: '#/components/schemas/NotificationSettingValue'
-                myVideoPublished:
-                  $ref: '#/components/schemas/NotificationSettingValue'
-                myVideoImportFinished:
-                  $ref: '#/components/schemas/NotificationSettingValue'
-                newFollow:
-                  $ref: '#/components/schemas/NotificationSettingValue'
-                newUserRegistration:
-                  $ref: '#/components/schemas/NotificationSettingValue'
-                commentMention:
-                  $ref: '#/components/schemas/NotificationSettingValue'
-                newInstanceFollower:
-                  $ref: '#/components/schemas/NotificationSettingValue'
-                autoInstanceFollowing:
-                  $ref: '#/components/schemas/NotificationSettingValue'
-      responses:
-        '204':
-          description: successful operation
+              $ref: '#/components/schemas/UpdateUser'
+        required: true
 
-  /users/me/history/videos:
+  /api/v1/oauth-clients/local:
     get:
-      summary: List watched videos history
-      security:
-        - OAuth2: []
+      summary: Login prerequisite
+      description: You need to retrieve a client id and secret before [logging in](#operation/getOAuthToken).
+      operationId: getOAuthClient
       tags:
-        - My History
-      parameters:
-        - $ref: '#/components/parameters/start'
-        - $ref: '#/components/parameters/count'
-        - $ref: '#/components/parameters/search'
+        - Session
       responses:
         '200':
           description: successful operation
           content:
             application/json:
               schema:
-                $ref: '#/components/schemas/VideoListResponse'
+                $ref: '#/components/schemas/OAuthClient'
+          links:
+            UseOAuthClientToLogin:
+              operationId: getOAuthToken
+              parameters:
+                client_id: '$response.body#/client_id'
+                client_secret: '$response.body#/client_secret'
+      x-codeSamples:
+        - lang: Shell
+          source: |
+            API="https://peertube2.cpy.re/api/v1"
 
-  /users/me/history/videos/{videoId}:
-    delete:
-      summary: Delete history element
-      security:
-        - OAuth2: []
-      tags:
-        - My History
-      parameters:
-        - name: videoId
-          in: path
-          required: true
-          schema:
-            $ref: '#/components/schemas/Video/properties/id'
-      responses:
-        '204':
-          description: successful operation
+            ## AUTH
+            curl -s "$API/oauth-clients/local"
 
-  /users/me/history/videos/remove:
+  /api/v1/users/token:
     post:
-      summary: Clear video history
-      security:
-        - OAuth2: []
+      summary: Login
+      operationId: getOAuthToken
+      description: With your [client id and secret](#operation/getOAuthClient), you can retrieve an access and refresh tokens.
       tags:
-        - My History
+        - Session
       requestBody:
         content:
-          multipart/form-data:
+          application/x-www-form-urlencoded:
             schema:
-              type: object
-              properties:
-                beforeDate:
-                  description: history before this date will be deleted
-                  type: string
-                  format: date-time
-      responses:
-        '204':
-          description: successful operation
-
-  /users/me/avatar/pick:
-    post:
-      summary: Update my user avatar
-      security:
-        - OAuth2: []
-      tags:
-        - My User
+              oneOf:
+                - $ref: '#/components/schemas/OAuthToken-password'
+                - $ref: '#/components/schemas/OAuthToken-refresh_token'
+              discriminator:
+                propertyName: grant_type
+                mapping:
+                  password: '#/components/schemas/OAuthToken-password'
+                  refresh_token: '#/components/schemas/OAuthToken-refresh_token'
       responses:
         '200':
           description: successful operation
@@ -1556,153 +1354,194 @@ paths:
               schema:
                 type: object
                 properties:
-                  avatars:
-                    type: array
-                    items:
-                      $ref: '#/components/schemas/ActorImage'
-        '413':
-          description: image file too large
-          headers:
-            X-File-Maximum-Size:
-              schema:
-                type: string
-                format: Nginx size
-              description: Maximum file size for the avatar
-      requestBody:
-        content:
-          multipart/form-data:
-            schema:
-              type: object
-              properties:
-                avatarfile:
-                  description: The file to upload
-                  type: string
-                  format: binary
-            encoding:
-              avatarfile:
-                contentType: image/png, image/jpeg
-
-  /users/me/avatar:
-    delete:
-      summary: Delete my avatar
-      security:
-        - OAuth2: []
-      tags:
-        - My User
-      responses:
-        '204':
-          description: successful operation
+                  token_type:
+                    type: string
+                    example: Bearer
+                  access_token:
+                    type: string
+                    example: 90286a0bdf0f7315d9d3fe8dabf9e1d2be9c97d0
+                    description: valid for 1 day
+                  refresh_token:
+                    type: string
+                    example: 2e0d675df9fc96d2e4ec8a3ebbbf45eca9137bb7
+                    description: valid for 2 weeks
+                  expires_in:
+                    type: integer
+                    minimum: 0
+                    example: 14399
+                  refresh_token_expires_in:
+                    type: integer
+                    minimum: 0
+                    example: 1209600
+        '400':
+          x-summary: client or credentials are invalid
+          description: |
+            Disambiguate via `type`:
+            - `invalid_client` for an unmatched `client_id`
+            - `invalid_grant` for unmatched credentials
+        '401':
+          x-summary: token expired
+          description: |
+            Disambiguate via `type`:
+            - default value for a regular authentication failure
+            - `invalid_token` for an expired token
+      x-codeSamples:
+        - lang: Shell
+          source: |
+            ## DEPENDENCIES: jq
+            API="https://peertube2.cpy.re/api/v1"
+            USERNAME="<your_username>"
+            PASSWORD="<your_password>"
 
-  /videos/ownership:
-    get:
-      summary: List video ownership changes
+            ## AUTH
+            client_id=$(curl -s "$API/oauth-clients/local" | jq -r ".client_id")
+            client_secret=$(curl -s "$API/oauth-clients/local" | jq -r ".client_secret")
+            curl -s "$API/users/token" \
+              --data client_id="$client_id" \
+              --data client_secret="$client_secret" \
+              --data grant_type=password \
+              --data username="$USERNAME" \
+              --data password="$PASSWORD" \
+              | jq -r ".access_token"
+
+  /api/v1/users/revoke-token:
+    post:
+      summary: Logout
+      description: Revokes your access token and its associated refresh token, destroying your current session.
+      operationId: revokeOAuthToken
       tags:
-        - Video Ownership Change
+        - Session
       security:
         - OAuth2: []
       responses:
         '200':
           description: successful operation
 
-  '/videos/ownership/{id}/accept':
+  /api/v1/users/ask-send-verify-email:
     post:
-      summary: Accept ownership change request
+      summary: Resend user verification link
+      operationId: resendEmailToVerifyUser
       tags:
-        - Video Ownership Change
-      security:
-        - OAuth2: []
-      parameters:
-        - $ref: '#/components/parameters/idOrUUID'
+        - Users
+        - Register
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: object
+              properties:
+                email:
+                  type: string
+                  description: User email
+              required:
+                - email
       responses:
         '204':
           description: successful operation
-        '403':
-          description: cannot terminate an ownership change of another user
-        '404':
-          description: video ownership change not found
 
-  '/videos/ownership/{id}/refuse':
+  /api/v1/users/registrations/ask-send-verify-email:
     post:
-      summary: Refuse ownership change request
+      summary: Resend verification link to registration email
+      operationId: resendEmailToVerifyRegistration
       tags:
-        - Video Ownership Change
-      security:
-        - OAuth2: []
-      parameters:
-        - $ref: '#/components/parameters/idOrUUID'
+        - Register
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: object
+              properties:
+                email:
+                  type: string
+                  description: Registration email
+              required:
+                - email
       responses:
         '204':
           description: successful operation
-        '403':
-          description: cannot terminate an ownership change of another user
-        '404':
-          description: video ownership change not found
 
-  '/videos/{id}/give-ownership':
+  /api/v1/users/{id}/verify-email:
     post:
-      summary: Request ownership change
+      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:
-        - Video Ownership Change
-      security:
-        - OAuth2: []
+        - Users
+        - Register
       parameters:
-        - $ref: '#/components/parameters/idOrUUID'
+        - $ref: '#/components/parameters/id'
       requestBody:
-        required: true
         content:
-          application/x-www-form-urlencoded:
+          application/json:
             schema:
               type: object
               properties:
-                username:
+                verificationString:
                   type: string
+                  format: url
+                isPendingEmail:
+                  type: boolean
               required:
-                - username
+                - verificationString
       responses:
         '204':
           description: successful operation
-        '400':
-          description: changing video ownership to a remote account is not supported yet
+        '403':
+          description: invalid verification string
         '404':
-          description: video not found
+          description: user not found
 
-  /videos:
-    get:
-      summary: List videos
-      operationId: getVideos
+  /api/v1/users/registrations/{registrationId}/verify-email:
+    post:
+      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:
-        - Video
+        - Register
       parameters:
-        - $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/registrationId'
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: object
+              properties:
+                verificationString:
+                  type: string
+                  format: url
+              required:
+                - verificationString
       responses:
-        '200':
+        '204':
           description: successful operation
-          content:
-            application/json:
-              schema:
-                $ref: '#/components/schemas/VideoListResponse'
+        '403':
+          description: invalid verification string
+        '404':
+          description: registration not found
 
-  /videos/categories:
-    get:
-      summary: List available video categories
-      operationId: getCategories
+  /api/v1/users/{id}/two-factor/request:
+    post:
+      summary: Request two factor auth
+      operationId: requestTwoFactor
+      description: Request two factor authentication for a user
       tags:
-        - Video
+        - 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
@@ -1711,36 +1550,79 @@ paths:
               schema:
                 type: array
                 items:
-                  type: string
-              examples:
-                nightly:
-                  externalValue: https://peertube2.cpy.re/api/v1/videos/categories
+                  $ref: '#/components/schemas/RequestTwoFactorResponse'
+        '403':
+          description: invalid password
+        '404':
+          description: user not found
 
-  /videos/licences:
-    get:
-      summary: List available video licences
-      operationId: getLicences
+  /api/v1/users/{id}/two-factor/confirm-request:
+    post:
+      summary: Confirm two factor auth
+      operationId: confirmTwoFactorRequest
+      description: Confirm a two factor authentication request
       tags:
-        - Video
+        - 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:
-        '200':
+        '204':
           description: successful operation
-          content:
-            application/json:
-              schema:
-                type: array
-                items:
+        '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
-              examples:
-                nightly:
-                  externalValue: https://peertube2.cpy.re/api/v1/videos/licences
+                  description: Password of the currently authenticated user
+      responses:
+        '204':
+          description: successful operation
+        '403':
+          description: invalid password
+        '404':
+          description: user not found
 
-  /videos/languages:
+  /api/v1/users/me:
     get:
-      summary: List available video languages
-      operationId: getLanguages
+      summary: Get my user information
+      operationId: getUserInfo
+      security:
+        - OAuth2:
+          - user
       tags:
-        - Video
+        - My User
       responses:
         '200':
           description: successful operation
@@ -1749,670 +1631,2213 @@ paths:
               schema:
                 type: array
                 items:
-                  type: string
-              examples:
-                nightly:
-                  externalValue: https://peertube2.cpy.re/api/v1/videos/languages
-
-  /videos/privacies:
-    get:
-      summary: List available video privacy policies
-      operationId: getPrivacyPolicies
-      tags:
-        - Video
-      responses:
-        '200':
-          description: successful operation
-          content:
-            application/json:
-              schema:
-                type: array
-                items:
-                  type: string
-              examples:
-                nightly:
-                  externalValue: https://peertube2.cpy.re/api/v1/videos/privacies
-
-  '/videos/{id}':
+                  $ref: '#/components/schemas/User'
     put:
-      summary: Update a video
-      operationId: putVideo
+      summary: Update my user information
+      operationId: putUserInfo
       security:
-        - OAuth2: []
+        - OAuth2:
+          - user
       tags:
-        - Video
-      parameters:
-        - $ref: '#/components/parameters/idOrUUID'
+        - My User
       responses:
         '204':
           description: successful operation
       requestBody:
         content:
-          multipart/form-data:
+          application/json:
             schema:
-              type: object
-              properties:
-                thumbnailfile:
-                  description: Video thumbnail file
-                  type: string
-                  format: binary
-                previewfile:
-                  description: Video preview file
-                  type: string
-                  format: binary
-                category:
-                  $ref: '#/components/schemas/VideoCategorySet'
-                licence:
-                  $ref: '#/components/schemas/VideoLicenceSet'
-                language:
-                  $ref: '#/components/schemas/VideoLanguageSet'
-                privacy:
-                  $ref: '#/components/schemas/VideoPrivacySet'
-                description:
-                  description: Video description
-                  type: string
-                waitTranscoding:
-                  description: Whether or not we wait transcoding before publish the video
-                  type: string
-                support:
-                  description: A text tell the audience how to support the video creator
-                  example: Please support our work on https://soutenir.framasoft.org/en/ <3
-                  type: string
-                nsfw:
-                  description: Whether or not this video contains sensitive content
-                  type: boolean
-                name:
-                  description: Video name
-                  type: string
-                  minLength: 3
-                  maxLength: 120
-                tags:
-                  description: Video tags (maximum 5 tags each between 2 and 30 characters)
-                  type: array
-                  minItems: 1
-                  maxItems: 5
-                  items:
-                    type: string
-                    minLength: 2
-                    maxLength: 30
-                commentsEnabled:
-                  description: Enable or disable comments for this video
-                  type: boolean
-                downloadEnabled:
-                  description: Enable or disable downloading for this video
-                  type: boolean
-                originallyPublishedAt:
-                  description: Date when the content was originally published
-                  type: string
-                  format: date-time
-                scheduleUpdate:
-                  $ref: '#/components/schemas/VideoScheduledUpdate'
-            encoding:
-              thumbnailfile:
-                contentType: image/jpeg
-              previewfile:
-                contentType: image/jpeg
+              $ref: '#/components/schemas/UpdateMe'
+        required: true
+
+  /api/v1/users/me/videos/imports:
     get:
-      summary: Get a video
-      operationId: getVideo
+      summary: Get video imports of my user
+      security:
+        - OAuth2:
+          - user
       tags:
-        - Video
+        - Videos
+        - My User
       parameters:
-        - $ref: '#/components/parameters/idOrUUID'
+        - $ref: '#/components/parameters/start'
+        - $ref: '#/components/parameters/count'
+        - $ref: '#/components/parameters/sort'
+        -
+          name: targetUrl
+          in: query
+          required: false
+          description: Filter on import target URL
+          schema:
+            type: string
+        -
+          name: videoChannelSyncId
+          in: query
+          required: false
+          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
           content:
             application/json:
               schema:
-                $ref: '#/components/schemas/VideoDetails'
-    delete:
-      summary: Delete a video
-      operationId: delVideo
+                $ref: '#/components/schemas/VideoImportsList'
+
+  /api/v1/users/me/video-quota-used:
+    get:
+      summary: Get my user used quota
+      security:
+        - OAuth2:
+          - user
+      tags:
+        - My User
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                type: object
+                properties:
+                  videoQuotaUsed:
+                    type: number
+                    description: The user video quota used so far in bytes
+                    example: 16810141515
+                  videoQuotaUsedDaily:
+                    type: number
+                    description: The user video quota used today in bytes
+                    example: 1681014151
+
+  '/api/v1/users/me/videos/{videoId}/rating':
+    get:
+      summary: Get rate of my user for a video
       security:
         - OAuth2: []
       tags:
-        - Video
+        - My User
+        - Video Rates
       parameters:
-        - $ref: '#/components/parameters/idOrUUID'
+        - name: videoId
+          in: path
+          required: true
+          description: The video id
+          schema:
+            $ref: '#/components/schemas/Video/properties/id'
       responses:
-        '204':
+        '200':
           description: successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/GetMeVideoRating'
 
-  '/videos/{id}/description':
+  /api/v1/users/me/videos:
     get:
-      summary: Get complete video description
-      operationId: getVideoDesc
+      summary: Get videos of my user
+      security:
+        - OAuth2:
+          - user
       tags:
-        - Video
+        - My User
+        - Videos
       parameters:
-        - $ref: '#/components/parameters/idOrUUID'
+        - $ref: '#/components/parameters/start'
+        - $ref: '#/components/parameters/count'
+        - $ref: '#/components/parameters/sort'
       responses:
         '200':
           description: successful operation
           content:
             application/json:
               schema:
-                nullable: true
-                type: string
-                minLength: 3
-                maxLength: 10000
-                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)**
+                $ref: '#/components/schemas/VideoListResponse'
 
-  '/videos/{id}/views':
-    post:
-      summary: Add a view to a video
-      operationId: addView
+  /api/v1/users/me/subscriptions:
+    get:
+      summary: Get my user subscriptions
+      security:
+        - OAuth2:
+          - user
       tags:
-        - Video
+        - My Subscriptions
       parameters:
-        - $ref: '#/components/parameters/idOrUUID'
+        - $ref: '#/components/parameters/start'
+        - $ref: '#/components/parameters/count'
+        - $ref: '#/components/parameters/sort'
       responses:
-        '204':
+        '200':
           description: successful operation
-
-  '/videos/{id}/watching':
-    put:
-      summary: Set watching progress of a video
-      operationId: setProgress
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/VideoChannelList'
+    post:
       tags:
-        - Video
+        - My Subscriptions
+      summary: Add subscription to my user
       security:
-        - OAuth2: []
-      parameters:
-        - $ref: '#/components/parameters/idOrUUID'
+        - OAuth2:
+          - user
       requestBody:
         content:
           application/json:
             schema:
-              $ref: '#/components/schemas/UserWatchingVideo'
-        required: true
+              type: object
+              properties:
+                uri:
+                  type: string
+                  format: uri
+                  description: uri of the video channels to subscribe to
+              required:
+                - uri
+            examples:
+              default:
+                value:
+                  uri: 008a0e54-375d-49d0-8379-143202e24152@video.lqdn.fr
       responses:
-        '204':
+        '200':
           description: successful operation
 
-  /videos/upload:
-    post:
-      summary: Upload a video
-      description: Uses a single request to upload a video.
-      operationId: uploadLegacy
+  /api/v1/users/me/subscriptions/exist:
+    get:
+      summary: Get if subscriptions exist for my user
       security:
-        - OAuth2: []
+        - OAuth2:
+          - user
       tags:
-        - Video
-        - Video Upload
+        - My Subscriptions
+      parameters:
+        - $ref: '#/components/parameters/subscriptionsUris'
       responses:
         '200':
           description: successful operation
           content:
             application/json:
               schema:
-                $ref: '#/components/schemas/VideoUploadResponse'
-        '403':
-          description: video didn't pass upload filter
-        '408':
-          description: upload has timed out
-        '413':
-          x-summary: video file too large, due to quota or max body size limit set by the reverse-proxy
-          description: |
-            If the response has no body, it means the reverse-proxy didn't let it through. Otherwise disambiguate via `type`:
-            - `quota_reached` for quota limits wether daily or global
-          headers:
-            X-File-Maximum-Size:
+                type: object
+
+  /api/v1/users/me/subscriptions/videos:
+    get:
+      summary: List videos of subscriptions of my user
+      security:
+        - OAuth2:
+          - user
+      tags:
+        - My Subscriptions
+        - Videos
+      parameters:
+        - $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:
-                type: string
-                format: Nginx size
-              description: Maximum file size for the video
-        '415':
-          description: video type unsupported
-        '422':
-          description: video unreadable
+                $ref: '#/components/schemas/VideoListResponse'
+
+  '/api/v1/users/me/subscriptions/{subscriptionHandle}':
+    get:
+      summary: Get subscription of my user
+      security:
+        - OAuth2:
+          - user
+      tags:
+        - My Subscriptions
+      parameters:
+        - $ref: '#/components/parameters/subscriptionHandle'
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/VideoChannel'
+    delete:
+      summary: Delete subscription of my user
+      security:
+        - OAuth2:
+          - user
+      tags:
+        - My Subscriptions
+      parameters:
+        - $ref: '#/components/parameters/subscriptionHandle'
+      responses:
+        '200':
+          description: successful operation
+
+  /api/v1/users/me/notifications:
+    get:
+      summary: List my notifications
+      security:
+        - OAuth2: []
+      tags:
+        - My Notifications
+      parameters:
+        - name: unread
+          in: query
+          description: only list unread notifications
+          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/NotificationListResponse'
+
+  /api/v1/users/me/notifications/read:
+    post:
+      summary: Mark notifications as read by their id
+      security:
+        - OAuth2: []
+      tags:
+        - My Notifications
       requestBody:
         content:
-          multipart/form-data:
+          application/json:
             schema:
-              $ref: '#/components/schemas/VideoUploadRequestLegacy'
-            encoding:
-              videofile:
-                contentType: video/mp4, video/webm, video/ogg, video/avi, video/quicktime, video/x-msvideo, video/x-flv, video/x-matroska, application/octet-stream
-              thumbnailfile:
-                contentType: image/jpeg
-              previewfile:
-                contentType: image/jpeg
-      x-codeSamples:
-        - lang: Shell
-          source: |
-            ## DEPENDENCIES: jq
-            USERNAME="<your_username>"
-            PASSWORD="<your_password>"
-            FILE_PATH="<your_file_path>"
-            CHANNEL_ID="<your_channel_id>"
-            NAME="<video_name>"
-            API="https://peertube2.cpy.re/api/v1"
-
-            ## AUTH
-            client_id=$(curl -s "$API/oauth-clients/local" | jq -r ".client_id")
-            client_secret=$(curl -s "$API/oauth-clients/local" | jq -r ".client_secret")
-            token=$(curl -s "$API/users/token" \
-              --data client_id="$client_id" \
-              --data client_secret="$client_secret" \
-              --data grant_type=password \
-              --data username="$USERNAME" \
-              --data password="$PASSWORD" \
-              | jq -r ".access_token")
-
-            ## VIDEO UPLOAD
-            curl -s "$API/videos/upload" \
-              -H "Authorization: Bearer $token" \
-              --max-time 600 \
-              --form videofile=@"$FILE_PATH" \
-              --form channelId=$CHANNEL_ID \
-              --form name="$NAME"
+              type: object
+              properties:
+                ids:
+                  type: array
+                  description: ids of the notifications to mark as read
+                  items:
+                    type: integer
+              required:
+                - ids
+      responses:
+        '204':
+          description: successful operation
 
-  /videos/upload-resumable:
+  /api/v1/users/me/notifications/read-all:
     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
-      operationId: uploadResumableInit
+      summary: Mark all my notification as read
       security:
         - OAuth2: []
       tags:
-        - Video
-        - Video Upload
-      parameters:
-        - name: X-Upload-Content-Length
-          in: header
-          schema:
-            type: number
-            example: 2469036
-          required: true
-          description: Number of bytes that will be uploaded in subsequent requests. Set this value to the size of the file you are uploading.
-        - name: X-Upload-Content-Type
-          in: header
-          schema:
-            type: string
-            format: mimetype
-            example: video/mp4
-          required: true
-          description: MIME type of the file that you are uploading. Depending on your instance settings, acceptable values might vary.
+        - My Notifications
+      responses:
+        '204':
+          description: successful operation
+
+  /api/v1/users/me/notification-settings:
+    put:
+      summary: Update my notification settings
+      security:
+        - OAuth2: []
+      tags:
+        - My Notifications
       requestBody:
         content:
           application/json:
             schema:
-              $ref: '#/components/schemas/VideoUploadRequestResumable'
+              type: object
+              properties:
+                newVideoFromSubscription:
+                  $ref: '#/components/schemas/NotificationSettingValue'
+                newCommentOnMyVideo:
+                  $ref: '#/components/schemas/NotificationSettingValue'
+                abuseAsModerator:
+                  $ref: '#/components/schemas/NotificationSettingValue'
+                videoAutoBlacklistAsModerator:
+                  $ref: '#/components/schemas/NotificationSettingValue'
+                blacklistOnMyVideo:
+                  $ref: '#/components/schemas/NotificationSettingValue'
+                myVideoPublished:
+                  $ref: '#/components/schemas/NotificationSettingValue'
+                myVideoImportFinished:
+                  $ref: '#/components/schemas/NotificationSettingValue'
+                newFollow:
+                  $ref: '#/components/schemas/NotificationSettingValue'
+                newUserRegistration:
+                  $ref: '#/components/schemas/NotificationSettingValue'
+                commentMention:
+                  $ref: '#/components/schemas/NotificationSettingValue'
+                newInstanceFollower:
+                  $ref: '#/components/schemas/NotificationSettingValue'
+                autoInstanceFollowing:
+                  $ref: '#/components/schemas/NotificationSettingValue'
+      responses:
+        '204':
+          description: successful operation
+
+  /api/v1/users/me/history/videos:
+    get:
+      summary: List watched videos history
+      security:
+        - OAuth2: []
+      tags:
+        - My History
+      parameters:
+        - $ref: '#/components/parameters/start'
+        - $ref: '#/components/parameters/count'
+        - $ref: '#/components/parameters/search'
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/VideoListResponse'
+
+  /api/v1/users/me/history/videos/{videoId}:
+    delete:
+      summary: Delete history element
+      security:
+        - OAuth2: []
+      tags:
+        - My History
+      parameters:
+        - name: videoId
+          in: path
+          required: true
+          schema:
+            $ref: '#/components/schemas/Video/properties/id'
+      responses:
+        '204':
+          description: successful operation
+
+  /api/v1/users/me/history/videos/remove:
+    post:
+      summary: Clear video history
+      security:
+        - OAuth2: []
+      tags:
+        - My History
+      requestBody:
+        content:
+          multipart/form-data:
+            schema:
+              type: object
+              properties:
+                beforeDate:
+                  description: history before this date will be deleted
+                  type: string
+                  format: date-time
+      responses:
+        '204':
+          description: successful operation
+
+  /api/v1/users/me/avatar/pick:
+    post:
+      summary: Update my user avatar
+      security:
+        - OAuth2: []
+      tags:
+        - My User
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                type: object
+                properties:
+                  avatars:
+                    type: array
+                    items:
+                      $ref: '#/components/schemas/ActorImage'
+        '413':
+          description: image file too large
+          headers:
+            X-File-Maximum-Size:
+              schema:
+                type: string
+                format: Nginx size
+              description: Maximum file size for the avatar
+      requestBody:
+        content:
+          multipart/form-data:
+            schema:
+              type: object
+              properties:
+                avatarfile:
+                  description: The file to upload
+                  type: string
+                  format: binary
+            encoding:
+              avatarfile:
+                contentType: image/png, image/jpeg
+
+  /api/v1/users/me/avatar:
+    delete:
+      summary: Delete my avatar
+      security:
+        - OAuth2: []
+      tags:
+        - My User
+      responses:
+        '204':
+          description: successful operation
+
+  /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:
+        - Video Ownership Change
+      security:
+        - OAuth2: []
+      responses:
+        '200':
+          description: successful operation
+
+  '/api/v1/videos/ownership/{id}/accept':
+    post:
+      summary: Accept ownership change request
+      tags:
+        - Video Ownership Change
+      security:
+        - OAuth2: []
+      parameters:
+        - $ref: '#/components/parameters/idOrUUID'
+      responses:
+        '204':
+          description: successful operation
+        '403':
+          description: cannot terminate an ownership change of another user
+        '404':
+          description: video ownership change not found
+
+  '/api/v1/videos/ownership/{id}/refuse':
+    post:
+      summary: Refuse ownership change request
+      tags:
+        - Video Ownership Change
+      security:
+        - OAuth2: []
+      parameters:
+        - $ref: '#/components/parameters/idOrUUID'
+      responses:
+        '204':
+          description: successful operation
+        '403':
+          description: cannot terminate an ownership change of another user
+        '404':
+          description: video ownership change not found
+
+  '/api/v1/videos/{id}/give-ownership':
+    post:
+      summary: Request ownership change
+      tags:
+        - Video Ownership Change
+      security:
+        - OAuth2: []
+      parameters:
+        - $ref: '#/components/parameters/idOrUUID'
+      requestBody:
+        required: true
+        content:
+          application/x-www-form-urlencoded:
+            schema:
+              type: object
+              properties:
+                username:
+                  type: string
+              required:
+                - username
+      responses:
+        '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: incorrect parameters
+        '404':
+          description: video not found
+
+  /api/v1/videos/{id}/studio/edit:
+    post:
+      summary: Create a studio task
+      tags:
+        - Video Transcoding
+        - Video
+      description: Create a task to edit a video  (cut, add intro/outro etc)
+      security:
+        - OAuth2: []
+      parameters:
+        - $ref: '#/components/parameters/idOrUUID'
+      requestBody:
+        required: true
+        content:
+          application/x-www-form-urlencoded:
+            schema:
+              $ref: '#/components/schemas/VideoStudioCreateTask'
+      responses:
+        '204':
+          description: successful operation
+        '400':
+          description: incorrect parameters
+        '404':
+          description: video not found
+
+  /api/v1/videos:
+    get:
+      summary: List videos
+      operationId: getVideos
+      tags:
+        - Video
+      parameters:
+        - $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'
+
+  /api/v1/videos/categories:
+    get:
+      summary: List available video categories
+      operationId: getCategories
+      tags:
+        - Video
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  type: string
+              examples:
+                nightly:
+                  externalValue: https://peertube2.cpy.re/api/v1/videos/categories
+
+  /api/v1/videos/licences:
+    get:
+      summary: List available video licences
+      operationId: getLicences
+      tags:
+        - Video
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  type: string
+              examples:
+                nightly:
+                  externalValue: https://peertube2.cpy.re/api/v1/videos/licences
+
+  /api/v1/videos/languages:
+    get:
+      summary: List available video languages
+      operationId: getLanguages
+      tags:
+        - Video
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  type: string
+              examples:
+                nightly:
+                  externalValue: https://peertube2.cpy.re/api/v1/videos/languages
+
+  /api/v1/videos/privacies:
+    get:
+      summary: List available video privacy policies
+      operationId: getVideoPrivacyPolicies
+      tags:
+        - Video
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  type: string
+              examples:
+                nightly:
+                  externalValue: https://peertube2.cpy.re/api/v1/videos/privacies
+
+  '/api/v1/videos/{id}':
+    put:
+      summary: Update a video
+      operationId: putVideo
+      security:
+        - OAuth2: []
+      tags:
+        - Video
+      parameters:
+        - $ref: '#/components/parameters/idOrUUID'
+      responses:
+        '204':
+          description: successful operation
+      requestBody:
+        content:
+          multipart/form-data:
+            schema:
+              type: object
+              properties:
+                thumbnailfile:
+                  description: Video thumbnail file
+                  type: string
+                  format: binary
+                previewfile:
+                  description: Video preview file
+                  type: string
+                  format: binary
+                category:
+                  $ref: '#/components/schemas/VideoCategorySet'
+                licence:
+                  $ref: '#/components/schemas/VideoLicenceSet'
+                language:
+                  $ref: '#/components/schemas/VideoLanguageSet'
+                privacy:
+                  $ref: '#/components/schemas/VideoPrivacySet'
+                description:
+                  description: Video description
+                  type: string
+                waitTranscoding:
+                  description: Whether or not we wait transcoding before publish the video
+                  type: string
+                support:
+                  description: A text tell the audience how to support the video creator
+                  example: Please support our work on https://soutenir.framasoft.org/en/ <3
+                  type: string
+                nsfw:
+                  description: Whether or not this video contains sensitive content
+                  type: boolean
+                name:
+                  description: Video name
+                  type: string
+                  minLength: 3
+                  maxLength: 120
+                tags:
+                  description: Video tags (maximum 5 tags each between 2 and 30 characters)
+                  type: array
+                  minItems: 1
+                  maxItems: 5
+                  items:
+                    type: string
+                    minLength: 2
+                    maxLength: 30
+                commentsEnabled:
+                  description: Enable or disable comments for this video
+                  type: boolean
+                downloadEnabled:
+                  description: Enable or disable downloading for this video
+                  type: boolean
+                originallyPublishedAt:
+                  description: Date when the content was originally published
+                  type: string
+                  format: date-time
+                scheduleUpdate:
+                  $ref: '#/components/schemas/VideoScheduledUpdate'
+            encoding:
+              thumbnailfile:
+                contentType: image/jpeg
+              previewfile:
+                contentType: image/jpeg
+    get:
+      summary: Get a video
+      operationId: getVideo
+      tags:
+        - Video
+      parameters:
+        - $ref: '#/components/parameters/idOrUUID'
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/VideoDetails'
+    delete:
+      summary: Delete a video
+      operationId: delVideo
+      security:
+        - OAuth2: []
+      tags:
+        - Video
+      parameters:
+        - $ref: '#/components/parameters/idOrUUID'
+      responses:
+        '204':
+          description: successful operation
+
+  '/api/v1/videos/{id}/description':
+    get:
+      summary: Get complete video description
+      operationId: getVideoDesc
+      tags:
+        - Video
+      parameters:
+        - $ref: '#/components/parameters/idOrUUID'
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                nullable: true
+                type: string
+                minLength: 3
+                maxLength: 10000
+                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)**
+
+  '/api/v1/videos/{id}/source':
+    post:
+      summary: Get video source file metadata
+      operationId: getVideoSource
+      tags:
+        - Video
+      parameters:
+        - $ref: '#/components/parameters/idOrUUID'
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/VideoSource'
+
+  '/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.
+      operationId: addView
+      tags:
+        - Video
+      parameters:
+        - $ref: '#/components/parameters/idOrUUID'
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/UserViewingVideo'
+        required: true
+      responses:
+        '204':
+          description: successful operation
+
+  '/api/v1/videos/{id}/watching':
+    put:
+      summary: Set watching progress of a video
+      deprecated: true
+      description: This endpoint has been deprecated. Use `/videos/{id}/views` instead
+      tags:
+        - Video
+      security:
+        - OAuth2: []
+      parameters:
+        - $ref: '#/components/parameters/idOrUUID'
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/UserViewingVideo'
+        required: true
+      responses:
+        '204':
+          description: successful operation
+
+  '/api/v1/videos/{id}/stats/overall':
+    get:
+      summary: Get overall stats of a video
+      tags:
+        - Video Stats
+      security:
+        - OAuth2: []
+      parameters:
+        - $ref: '#/components/parameters/idOrUUID'
+        - name: startDate
+          in: query
+          description: Filter stats by start date
+          schema:
+            type: string
+            format: date-time
+        - name: endDate
+          in: query
+          description: Filter stats by end date
+          schema:
+            type: string
+            format: date-time
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/VideoStatsOverall'
+
+  '/api/v1/videos/{id}/stats/retention':
+    get:
+      summary: Get retention stats of a video
+      tags:
+        - Video Stats
+      security:
+        - OAuth2: []
+      parameters:
+        - $ref: '#/components/parameters/idOrUUID'
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/VideoStatsRetention'
+
+  '/api/v1/videos/{id}/stats/timeseries/{metric}':
+    get:
+      summary: Get timeserie stats of a video
+      tags:
+        - Video Stats
+      security:
+        - OAuth2: []
+      parameters:
+        - $ref: '#/components/parameters/idOrUUID'
+        -
+          name: metric
+          in: path
+          required: true
+          description: The metric to get
+          schema:
+            type: string
+            enum:
+              - 'viewers'
+              - 'aggregateWatchTime'
+        - name: startDate
+          in: query
+          description: Filter stats by start date
+          schema:
+            type: string
+            format: date-time
+        - name: endDate
+          in: query
+          description: Filter stats by end date
+          schema:
+            type: string
+            format: date-time
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/VideoStatsTimeserie'
+
+  /api/v1/videos/upload:
+    post:
+      summary: Upload a video
+      description: Uses a single request to upload a video.
+      operationId: uploadLegacy
+      security:
+        - OAuth2: []
+      tags:
+        - Video
+        - Video Upload
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/VideoUploadResponse'
+        '403':
+          description: video didn't pass upload filter
+        '408':
+          description: upload has timed out
+        '413':
+          x-summary: video file too large, due to quota or max body size limit set by the reverse-proxy
+          description: |
+            If the response has no body, it means the reverse-proxy didn't let it through. Otherwise disambiguate via `type`:
+            - `quota_reached` for quota limits whether daily or global
+          headers:
+            X-File-Maximum-Size:
+              schema:
+                type: string
+                format: Nginx size
+              description: Maximum file size for the video
+        '415':
+          description: video type unsupported
+        '422':
+          description: video unreadable
+      requestBody:
+        content:
+          multipart/form-data:
+            schema:
+              $ref: '#/components/schemas/VideoUploadRequestLegacy'
+            encoding:
+              videofile:
+                contentType: video/mp4, video/webm, video/ogg, video/avi, video/quicktime, video/x-msvideo, video/x-flv, video/x-matroska, application/octet-stream
+              thumbnailfile:
+                contentType: image/jpeg
+              previewfile:
+                contentType: image/jpeg
+      x-codeSamples:
+        - lang: Shell
+          source: |
+            ## DEPENDENCIES: jq
+            USERNAME="<your_username>"
+            PASSWORD="<your_password>"
+            FILE_PATH="<your_file_path>"
+            CHANNEL_ID="<your_channel_id>"
+            NAME="<video_name>"
+            API="https://peertube2.cpy.re/api/v1"
+
+            ## AUTH
+            client_id=$(curl -s "$API/oauth-clients/local" | jq -r ".client_id")
+            client_secret=$(curl -s "$API/oauth-clients/local" | jq -r ".client_secret")
+            token=$(curl -s "$API/users/token" \
+              --data client_id="$client_id" \
+              --data client_secret="$client_secret" \
+              --data grant_type=password \
+              --data username="$USERNAME" \
+              --data password="$PASSWORD" \
+              | jq -r ".access_token")
+
+            ## VIDEO UPLOAD
+            curl -s "$API/videos/upload" \
+              -H "Authorization: Bearer $token" \
+              --max-time 600 \
+              --form videofile=@"$FILE_PATH" \
+              --form channelId=$CHANNEL_ID \
+              --form name="$NAME"
+
+  /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
+      operationId: uploadResumableInit
+      security:
+        - OAuth2: []
+      tags:
+        - Video
+        - Video Upload
+      parameters:
+        - name: X-Upload-Content-Length
+          in: header
+          schema:
+            type: number
+            example: 2469036
+          required: true
+          description: Number of bytes that will be uploaded in subsequent requests. Set this value to the size of the file you are uploading.
+        - name: X-Upload-Content-Type
+          in: header
+          schema:
+            type: string
+            format: mimetype
+            example: video/mp4
+          required: true
+          description: MIME type of the file that you are uploading. Depending on your instance settings, acceptable values might vary.
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/VideoUploadRequestResumable'
+      responses:
+        '200':
+          description: file already exists, send a [`resume`](https://github.com/kukhariev/node-uploadx/blob/master/proto.md) request instead
+        '201':
+          description: created
+          headers:
+            Location:
+              schema:
+                type: string
+                format: url
+                example: /api/v1/videos/upload-resumable?upload_id=471e97554f21dec3b8bb5d4602939c51
+            Content-Length:
+              schema:
+                type: number
+                example: 0
+        '413':
+          x-summary: video file too large, due to quota, absolute max file size or concurrent partial upload limit
+          description: |
+            Disambiguate via `type`:
+            - `max_file_size_reached` for the absolute file size limit
+            - `quota_reached` for quota limits whether daily or global
+        '415':
+          description: video type unsupported
+    put:
+      summary: Send chunk for the resumable upload of a video
+      description: Uses [a resumable protocol](https://github.com/kukhariev/node-uploadx/blob/master/proto.md) to continue, pause or resume the upload of a video
+      operationId: uploadResumable
+      security:
+        - OAuth2: []
+      tags:
+        - Video
+        - Video Upload
+      parameters:
+        - name: upload_id
+          in: query
+          required: true
+          description: |
+            Created session id to proceed with. If you didn't send chunks in the last hour, it is
+            not valid anymore and you need to initialize a new upload.
+          schema:
+            type: string
+        - name: Content-Range
+          in: header
+          schema:
+            type: string
+            example: bytes 0-262143/2469036
+          required: true
+          description: |
+            Specifies the bytes in the file that the request is uploading.
+
+            For example, a value of `bytes 0-262143/1000000` shows that the request is sending the first
+            262144 bytes (256 x 1024) in a 2,469,036 byte file.
+        - name: Content-Length
+          in: header
+          schema:
+            type: number
+            example: 262144
+          required: true
+          description: |
+            Size of the chunk that the request is sending.
+
+            Remember that larger chunks are more efficient. PeerTube's web client uses chunks varying from
+            1048576 bytes (~1MB) and increases or reduces size depending on connection health.
+      requestBody:
+        content:
+          application/octet-stream:
+            schema:
+              type: string
+              format: binary
+      responses:
+        '200':
+          description: last chunk received
+          headers:
+            Content-Length:
+              schema:
+                type: number
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/VideoUploadResponse'
+        '308':
+          description: resume incomplete
+          headers:
+            Range:
+              schema:
+                type: string
+                example: bytes=0-262143
+            Content-Length:
+              schema:
+                type: number
+                example: 0
+        '403':
+          description: video didn't pass upload filter
+        '404':
+          description: upload not found
+        '409':
+          description: chunk doesn't match range
+        '422':
+          description: video unreadable
+        '429':
+          description: too many concurrent requests
+        '503':
+          description: upload is already being processed
+          headers:
+            'Retry-After':
+              schema:
+                type: number
+                example: 300
+    delete:
+      summary: Cancel the resumable upload of a video, deleting any data uploaded so far
+      description: Uses [a resumable protocol](https://github.com/kukhariev/node-uploadx/blob/master/proto.md) to cancel the upload of a video
+      operationId: uploadResumableCancel
+      security:
+        - OAuth2: []
+      tags:
+        - Video
+        - Video Upload
+      parameters:
+        - name: upload_id
+          in: query
+          required: true
+          description: |
+            Created session id to proceed with. If you didn't send chunks in the last 12 hours, it is
+            not valid anymore and the upload session has already been deleted with its data ;-)
+          schema:
+            type: string
+        - name: Content-Length
+          in: header
+          required: true
+          schema:
+            type: number
+            example: 0
+      responses:
+        '204':
+          description: upload cancelled
+          headers:
+            Content-Length:
+              schema:
+                type: number
+                example: 0
+        '404':
+          description: upload not found
+
+  /api/v1/videos/imports:
+    post:
+      summary: Import a video
+      description: Import a torrent or magnetURI or HTTP resource (if enabled by the instance administrator)
+      operationId: importVideo
+      security:
+        - OAuth2: []
+      tags:
+        - Video Imports
+        - Video Upload
+      requestBody:
+        content:
+          multipart/form-data:
+            schema:
+              $ref: '#/components/schemas/VideoCreateImport'
+            encoding:
+              torrentfile:
+                contentType: application/x-bittorrent
+              thumbnailfile:
+                contentType: image/jpeg
+              previewfile:
+                contentType: image/jpeg
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/VideoUploadResponse'
+        '400':
+          description: '`magnetUri` or `targetUrl` or a torrent file missing'
+        '403':
+          description: video didn't pass pre-import filter
+        '409':
+          description: HTTP or Torrent/magnetURI import not enabled
+
+  /api/v1/videos/imports/{id}/cancel:
+    post:
+      summary: Cancel video import
+      description: Cancel a pending video import
+      security:
+        - OAuth2: []
+      tags:
+        - Video Imports
+      parameters:
+        - $ref: '#/components/parameters/id'
+      responses:
+        '204':
+          description: successful operation
+
+  /api/v1/videos/imports/{id}:
+    delete:
+      summary: Delete video import
+      description: Delete ended video import
+      security:
+        - OAuth2: []
+      tags:
+        - Video Imports
+      parameters:
+        - $ref: '#/components/parameters/id'
+      responses:
+        '204':
+          description: successful operation
+
+  /api/v1/videos/live:
+    post:
+      summary: Create a live
+      operationId: addLive
+      security:
+        - OAuth2: []
+      tags:
+        - Live Videos
+        - Video
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/VideoUploadResponse'
+        '400':
+          x-summary: validation error, or conflicting `saveReplay` and `permanentLive` parameter set
+          description: |
+            Disambiguate via `type`:
+            - default type for a validation error
+            - `live_conflicting_permanent_and_save_replay` for conflicting parameters set
+        '403':
+          x-summary: live is not enabled, allow replay is not enabled, or max instance/user live videos limit is exceeded
+          description: |
+            Disambiguate via `type`:
+            - `live_not_enabled` for a disabled live feature
+            - `live_not_allowing_replay` for a disabled replay feature
+            - `max_instance_lives_limit_reached` for the absolute concurrent live limit
+            - `max_user_lives_limit_reached` for the user concurrent live limit
+      requestBody:
+        content:
+          multipart/form-data:
+            schema:
+              type: object
+              properties:
+                channelId:
+                  description: Channel id that will contain this live video
+                  type: integer
+                saveReplay:
+                  type: boolean
+                replaySettings:
+                  $ref: '#/components/schemas/LiveVideoReplaySettings'
+                permanentLive:
+                  description: User can stream multiple times in a permanent live
+                  type: boolean
+                latencyMode:
+                  description: User can select live latency mode if enabled by the instance
+                  $ref: '#/components/schemas/LiveVideoLatencyMode'
+                thumbnailfile:
+                  description: Live video/replay thumbnail file
+                  type: string
+                  format: binary
+                previewfile:
+                  description: Live video/replay preview file
+                  type: string
+                  format: binary
+                privacy:
+                  $ref: '#/components/schemas/VideoPrivacySet'
+                category:
+                  $ref: '#/components/schemas/VideoCategorySet'
+                licence:
+                  $ref: '#/components/schemas/VideoLicenceSet'
+                language:
+                  $ref: '#/components/schemas/VideoLanguageSet'
+                description:
+                  description: Live video/replay description
+                  type: string
+                support:
+                  description: A text tell the audience how to support the creator
+                  example: Please support our work on https://soutenir.framasoft.org/en/ <3
+                  type: string
+                nsfw:
+                  description: Whether or not this live video/replay contains sensitive content
+                  type: boolean
+                name:
+                  description: Live video/replay name
+                  type: string
+                  minLength: 3
+                  maxLength: 120
+                tags:
+                  description: Live video/replay tags (maximum 5 tags each between 2 and 30 characters)
+                  type: array
+                  minItems: 1
+                  maxItems: 5
+                  items:
+                    type: string
+                    minLength: 2
+                    maxLength: 30
+                commentsEnabled:
+                  description: Enable or disable comments for this live video/replay
+                  type: boolean
+                downloadEnabled:
+                  description: Enable or disable downloading for the replay of this live video
+                  type: boolean
+              required:
+                - channelId
+                - name
+            encoding:
+              thumbnailfile:
+                contentType: image/jpeg
+              previewfile:
+                contentType: image/jpeg
+
+  /api/v1/videos/live/{id}:
+    get:
+      summary: Get information about a live
+      operationId: getLiveId
+      security:
+        - OAuth2: []
+      tags:
+        - Live Videos
+        - Video
+      parameters:
+        - $ref: '#/components/parameters/idOrUUID'
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/LiveVideoResponse'
+    put:
+      summary: Update information about a live
+      operationId: updateLiveId
+      security:
+        - OAuth2: []
+      tags:
+        - Live Videos
+        - Video
+      parameters:
+        - $ref: '#/components/parameters/idOrUUID'
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/LiveVideoUpdate'
+      responses:
+        '204':
+          description: successful operation
+        '400':
+          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
+  /api/v1/videos/live/{id}/sessions:
+    get:
+      summary: List live sessions
+      description: List all sessions created in a particular live
+      security:
+        - OAuth2: []
+      tags:
+        - Live Videos
+      parameters:
+        - $ref: '#/components/parameters/idOrUUID'
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                type: object
+                properties:
+                  total:
+                    type: integer
+                    example: 1
+                  data:
+                    type: array
+                    items:
+                      $ref: '#/components/schemas/LiveVideoSessionResponse'
+  /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
+      security:
+        - OAuth2: []
+      tags:
+        - Live Videos
+      parameters:
+        - $ref: '#/components/parameters/idOrUUID'
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/LiveVideoSessionResponse'
+
+  /api/v1/users/me/abuses:
+    get:
+      summary: List my abuses
+      operationId: getMyAbuses
+      security:
+        - OAuth2: []
+      tags:
+        - Abuses
+        - My User
+      parameters:
+        - name: id
+          in: query
+          description: only list the report with this id
+          schema:
+            type: integer
+        - name: state
+          in: query
+          schema:
+            $ref: '#/components/schemas/AbuseStateSet'
+        - $ref: '#/components/parameters/abusesSort'
+        - $ref: '#/components/parameters/start'
+        - $ref: '#/components/parameters/count'
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                type: object
+                properties:
+                  total:
+                    type: integer
+                    example: 1
+                  data:
+                    type: array
+                    items:
+                      $ref: '#/components/schemas/Abuse'
+
+  /api/v1/abuses:
+    get:
+      summary: List abuses
+      operationId: getAbuses
+      security:
+        - OAuth2:
+          - admin
+          - moderator
+      tags:
+        - Abuses
+      parameters:
+        - name: id
+          in: query
+          description: only list the report with this id
+          schema:
+            type: integer
+        - name: predefinedReason
+          in: query
+          description: predefined reason the listed reports should contain
+          schema:
+            $ref: '#/components/schemas/PredefinedAbuseReasons'
+        - name: search
+          in: query
+          description: plain search that will match with video titles, reporter names and more
+          schema:
+            type: string
+        - name: state
+          in: query
+          schema:
+            $ref: '#/components/schemas/AbuseStateSet'
+        - name: searchReporter
+          in: query
+          description: only list reports of a specific reporter
+          schema:
+            type: string
+        - name: searchReportee
+          description: only list reports of a specific reportee
+          in: query
+          schema:
+            type: string
+        - name: searchVideo
+          in: query
+          description: only list reports of a specific video
+          schema:
+            type: string
+        - name: searchVideoChannel
+          in: query
+          description: only list reports of a specific video channel
+          schema:
+            type: string
+        - name: videoIs
+          in: query
+          description: only list deleted or blocklisted videos
+          schema:
+            type: string
+            enum:
+            - 'deleted'
+            - 'blacklisted'
+        - name: filter
+          in: query
+          description: only list account, comment or video reports
+          schema:
+            type: string
+            enum:
+            - 'video'
+            - 'comment'
+            - 'account'
+        - $ref: '#/components/parameters/start'
+        - $ref: '#/components/parameters/count'
+        - $ref: '#/components/parameters/abusesSort'
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                type: object
+                properties:
+                  total:
+                    type: integer
+                    example: 1
+                  data:
+                    type: array
+                    items:
+                      $ref: '#/components/schemas/Abuse'
+    post:
+      summary: Report an abuse
+      security:
+        - OAuth2: []
+      tags:
+        - Abuses
+      requestBody:
+        required: true
+        content:
+          application/json:
+            schema:
+              type: object
+              properties:
+                reason:
+                  description: Reason why the user reports this video
+                  type: string
+                  minLength: 2
+                  maxLength: 3000
+                predefinedReasons:
+                  $ref: '#/components/schemas/PredefinedAbuseReasons'
+                video:
+                  type: object
+                  properties:
+                    id:
+                      description: Video id to report
+                      allOf:
+                        - $ref: '#/components/schemas/Video/properties/id'
+                    startAt:
+                      type: integer
+                      format: seconds
+                      description: Timestamp in the video that marks the beginning of the report
+                      minimum: 0
+                    endAt:
+                      type: integer
+                      format: seconds
+                      description: Timestamp in the video that marks the ending of the report
+                      minimum: 0
+                comment:
+                  type: object
+                  properties:
+                    id:
+                      description: Comment id to report
+                      allOf:
+                        - $ref: '#/components/schemas/VideoComment/properties/id'
+                account:
+                  type: object
+                  properties:
+                    id:
+                      description: Account id to report
+                      type: integer
+              required:
+                - reason
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                type: object
+                properties:
+                  abuse:
+                    type: object
+                    properties:
+                      id:
+                        $ref: '#/components/schemas/id'
+        '400':
+          description: incorrect request parameters
+
+  '/api/v1/abuses/{abuseId}':
+    put:
+      summary: Update an abuse
+      security:
+        - OAuth2:
+          - admin
+          - moderator
+      tags:
+        - Abuses
+      parameters:
+        - $ref: '#/components/parameters/abuseId'
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: object
+              properties:
+                state:
+                  $ref: '#/components/schemas/AbuseStateSet'
+                moderationComment:
+                  type: string
+                  description: Update the report comment visible only to the moderation team
+                  minLength: 2
+                  maxLength: 3000
+      responses:
+        '204':
+          description: successful operation
+        '404':
+          description: abuse not found
+    delete:
+      tags:
+        - Abuses
+      summary: Delete an abuse
+      security:
+        - OAuth2:
+          - admin
+          - moderator
+      parameters:
+        - $ref: '#/components/parameters/abuseId'
+      responses:
+        '204':
+          description: successful operation
+        '404':
+          description: block not found
+
+  '/api/v1/abuses/{abuseId}/messages':
+    get:
+      summary: List messages of an abuse
+      security:
+        - OAuth2: []
+      tags:
+        - Abuses
+      parameters:
+        - $ref: '#/components/parameters/abuseId'
       responses:
         '200':
-          description: file already exists, send a [`resume`](https://github.com/kukhariev/node-uploadx/blob/master/proto.md) request instead
-        '201':
-          description: created
-          headers:
-            Location:
-              schema:
-                type: string
-                format: url
-                example: /api/v1/videos/upload-resumable?upload_id=471e97554f21dec3b8bb5d4602939c51
-            Content-Length:
+          description: successful operation
+          content:
+            application/json:
               schema:
-                type: number
-                example: 0
-        '413':
-          x-summary: video file too large, due to quota, absolute max file size or concurrent partial upload limit
-          description: |
-            Disambiguate via `type`:
-            - `max_file_size_reached` for the absolute file size limit
-            - `quota_reached` for quota limits whether daily or global
-        '415':
-          description: video type unsupported
-    put:
-      summary: Send chunk for the resumable upload of a video
-      description: Uses [a resumable protocol](https://github.com/kukhariev/node-uploadx/blob/master/proto.md) to continue, pause or resume the upload of a video
-      operationId: uploadResumable
+                type: object
+                properties:
+                  total:
+                    type: integer
+                    example: 1
+                  data:
+                    type: array
+                    items:
+                      $ref: '#/components/schemas/AbuseMessage'
+    post:
+      summary: Add message to an abuse
       security:
         - OAuth2: []
       tags:
-        - Video
-        - Video Upload
+        - Abuses
       parameters:
-        - name: upload_id
-          in: query
-          required: true
-          description: |
-            Created session id to proceed with. If you didn't send chunks in the last 12 hours, it is
-            not valid anymore and you need to initialize a new upload.
-          schema:
-            type: string
-        - name: Content-Range
-          in: header
-          schema:
-            type: string
-            example: bytes 0-262143/2469036
-          required: true
-          description: |
-            Specifies the bytes in the file that the request is uploading.
-
-            For example, a value of `bytes 0-262143/1000000` shows that the request is sending the first
-            262144 bytes (256 x 1024) in a 2,469,036 byte file.
-        - name: Content-Length
-          in: header
-          schema:
-            type: number
-            example: 262144
-          required: true
-          description: |
-            Size of the chunk that the request is sending.
-
-            The chunk size __must be a multiple of 256 KB__, and unlike [Google Resumable](https://developers.google.com/youtube/v3/guides/using_resumable_upload_protocol)
-            doesn't mandate for chunks to have the same size throughout the upload sequence.
-
-            Remember that larger chunks are more efficient. PeerTube's web client uses chunks varying from
-            1048576 bytes (~1MB) and increases or reduces size depending on connection health.
+        - $ref: '#/components/parameters/abuseId'
       requestBody:
+        required: true
         content:
-          application/octet-stream:
+          application/json:
             schema:
-              type: string
-              format: binary
+              type: object
+              properties:
+                message:
+                  description: Message to send
+                  type: string
+                  minLength: 2
+                  maxLength: 3000
+              required:
+                - message
       responses:
         '200':
-          description: last chunk received
-          headers:
-            Content-Length:
-              schema:
-                type: number
-          content:
-            application/json:
-              schema:
-                $ref: '#/components/schemas/VideoUploadResponse'
-        '308':
-          description: resume incomplete
-          headers:
-            Range:
-              schema:
-                type: string
-                example: bytes=0-262143
-            Content-Length:
-              schema:
-                type: number
-                example: 0
-        '403':
-          description: video didn't pass upload filter
-        '404':
-          description: upload not found
-        '409':
-          description: chunk doesn't match range
-        '422':
-          description: video unreadable
-        '429':
-          description: too many concurrent requests
-        '503':
-          description: upload is already being processed
-          headers:
-            'Retry-After':
-              schema:
-                type: number
-                example: 300
+          description: successful operation
+        '400':
+          description: incorrect request parameters
+
+  '/api/v1/abuses/{abuseId}/messages/{abuseMessageId}':
     delete:
-      summary: Cancel the resumable upload of a video, deleting any data uploaded so far
-      description: Uses [a resumable protocol](https://github.com/kukhariev/node-uploadx/blob/master/proto.md) to cancel the upload of a video
-      operationId: uploadResumableCancel
+      summary: Delete an abuse message
       security:
         - OAuth2: []
       tags:
-        - Video
-        - Video Upload
+        - Abuses
       parameters:
-        - name: upload_id
-          in: query
-          required: true
-          description: |
-            Created session id to proceed with. If you didn't send chunks in the last 12 hours, it is
-            not valid anymore and the upload session has already been deleted with its data ;-)
-          schema:
-            type: string
-        - name: Content-Length
-          in: header
-          required: true
-          schema:
-            type: number
-            example: 0
+        - $ref: '#/components/parameters/abuseId'
+        - $ref: '#/components/parameters/abuseMessageId'
       responses:
         '204':
-          description: upload cancelled
-          headers:
-            Content-Length:
-              schema:
-                type: number
-                example: 0
-        '404':
-          description: upload not found
+          description: successful operation
 
-  /videos/imports:
+  '/api/v1/videos/{id}/blacklist':
     post:
-      summary: Import a video
-      description: Import a torrent or magnetURI or HTTP resource (if enabled by the instance administrator)
-      operationId: importVideo
+      summary: Block a video
+      operationId: addVideoBlock
       security:
-        - OAuth2: []
+        - OAuth2:
+          - admin
+          - moderator
       tags:
-        - Video Imports
-        - Video Upload
-      requestBody:
-        content:
-          multipart/form-data:
-            schema:
-              $ref: '#/components/schemas/VideoCreateImport'
-            encoding:
-              torrentfile:
-                contentType: application/x-bittorrent
-              thumbnailfile:
-                contentType: image/jpeg
-              previewfile:
-                contentType: image/jpeg
+        - Video Blocks
+      parameters:
+        - $ref: '#/components/parameters/idOrUUID'
+      responses:
+        '204':
+          description: successful operation
+    delete:
+      summary: Unblock a video by its id
+      operationId: delVideoBlock
+      security:
+        - OAuth2:
+          - admin
+          - moderator
+      tags:
+        - Video Blocks
+      parameters:
+        - $ref: '#/components/parameters/idOrUUID'
+      responses:
+        '204':
+          description: successful operation
+        '404':
+          description: block not found
+
+  /api/v1/videos/blacklist:
+    get:
+      tags:
+        - Video Blocks
+      summary: List video blocks
+      operationId: getVideoBlocks
+      security:
+        - OAuth2:
+          - admin
+          - moderator
+      parameters:
+        - name: type
+          in: query
+          description: >
+            list only blocks that match this type:
+
+            - `1`: manual block
+
+            - `2`: automatic block that needs review
+          schema:
+            type: integer
+            enum:
+              - 1
+              - 2
+        - name: search
+          in: query
+          description: plain search that will match with video titles, and more
+          schema:
+            type: string
+        - $ref: '#/components/parameters/start'
+        - $ref: '#/components/parameters/count'
+        - $ref: '#/components/parameters/blacklistsSort'
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                type: object
+                properties:
+                  total:
+                    type: integer
+                    example: 1
+                  data:
+                    type: array
+                    items:
+                      $ref: '#/components/schemas/VideoBlacklist'
+
+  /api/v1/videos/{id}/captions:
+    get:
+      summary: List captions of a video
+      operationId: getVideoCaptions
+      tags:
+        - Video Captions
+      parameters:
+        - $ref: '#/components/parameters/idOrUUID'
       responses:
         '200':
           description: successful operation
           content:
             application/json:
               schema:
-                $ref: '#/components/schemas/VideoUploadResponse'
-        '400':
-          description: '`magnetUri` or `targetUrl` or a torrent file missing'
-        '403':
-          description: video didn't pass pre-import filter
-        '409':
-          description: HTTP or Torrent/magnetURI import not enabled
+                type: object
+                properties:
+                  total:
+                    type: integer
+                    example: 1
+                  data:
+                    type: array
+                    items:
+                      $ref: '#/components/schemas/VideoCaption'
 
-  /videos/imports/{id}/cancel:
-    post:
-      summary: Cancel video import
-      description: Cancel a pending video import
+  /api/v1/videos/{id}/captions/{captionLanguage}:
+    put:
+      summary: Add or replace a video caption
+      operationId: addVideoCaption
       security:
-        - OAuth2: []
+        - OAuth2:
+          - user
       tags:
-        - Video Imports
+        - Video Captions
       parameters:
-        - $ref: '#/components/parameters/id'
+        - $ref: '#/components/parameters/idOrUUID'
+        - $ref: '#/components/parameters/captionLanguage'
+      requestBody:
+        content:
+          multipart/form-data:
+            schema:
+              type: object
+              properties:
+                captionfile:
+                  description: The file to upload.
+                  type: string
+                  format: binary
+            encoding:
+              captionfile:
+                contentType: text/vtt, application/x-subrip, text/plain
       responses:
         '204':
           description: successful operation
-
-  /videos/imports/{id}:
+        '404':
+          description: video or language not found
     delete:
-      summary: Delete video import
-      description: Delete ended video import
+      summary: Delete a video caption
+      operationId: delVideoCaption
       security:
-        - OAuth2: []
+        - OAuth2:
+          - user
       tags:
-        - Video Imports
+        - Video Captions
       parameters:
-        - $ref: '#/components/parameters/id'
+        - $ref: '#/components/parameters/idOrUUID'
+        - $ref: '#/components/parameters/captionLanguage'
       responses:
         '204':
           description: successful operation
+        '404':
+          description: video or language or caption for that language not found
 
-  /videos/live:
+  /api/v1/video-channels:
+    get:
+      summary: List video channels
+      operationId: getVideoChannels
+      tags:
+        - Video Channels
+      parameters:
+        - $ref: '#/components/parameters/start'
+        - $ref: '#/components/parameters/count'
+        - $ref: '#/components/parameters/sort'
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/VideoChannelList'
     post:
-      summary: Create a live
-      operationId: addLive
+      summary: Create a video channel
+      operationId: addVideoChannel
       security:
         - OAuth2: []
       tags:
-        - Live Videos
-        - Video
+        - Video Channels
       responses:
         '200':
           description: successful operation
           content:
             application/json:
               schema:
-                $ref: '#/components/schemas/VideoUploadResponse'
-        '400':
-          x-summary: validation error, or conflicting `saveReplay` and `permanentLive` parameter set
-          description: |
-            Disambiguate via `type`:
-            - default type for a validation error
-            - `live_conflicting_permanent_and_save_replay` for conflicting parameters set
-        '403':
-          x-summary: live is not enabled, allow replay is not enabled, or max instance/user live videos limit is exceeded
-          description: |
-            Disambiguate via `type`:
-            - `live_not_enabled` for a disabled live feature
-            - `live_not_allowing_replay` for a disabled replay feature
-            - `max_instance_lives_limit_reached` for the absolute concurrent live limit
-            - `max_user_lives_limit_reached` for the user concurrent live limit
+                type: object
+                properties:
+                  videoChannel:
+                    type: object
+                    properties:
+                      id:
+                        $ref: '#/components/schemas/id'
       requestBody:
         content:
-          multipart/form-data:
+          application/json:
             schema:
-              type: object
-              properties:
-                channelId:
-                  description: Channel id that will contain this live video
-                  type: integer
-                saveReplay:
-                  type: boolean
-                permanentLive:
-                  description: User can stream multiple times in a permanent live
-                  type: boolean
-                thumbnailfile:
-                  description: Live video/replay thumbnail file
-                  type: string
-                  format: binary
-                previewfile:
-                  description: Live video/replay preview file
-                  type: string
-                  format: binary
-                privacy:
-                  $ref: '#/components/schemas/VideoPrivacySet'
-                category:
-                  $ref: '#/components/schemas/VideoCategorySet'
-                licence:
-                  $ref: '#/components/schemas/VideoLicenceSet'
-                language:
-                  $ref: '#/components/schemas/VideoLanguageSet'
-                description:
-                  description: Live video/replay description
-                  type: string
-                support:
-                  description: A text tell the audience how to support the creator
-                  example: Please support our work on https://soutenir.framasoft.org/en/ <3
-                  type: string
-                nsfw:
-                  description: Whether or not this live video/replay contains sensitive content
-                  type: boolean
-                name:
-                  description: Live video/replay name
-                  type: string
-                  minLength: 3
-                  maxLength: 120
-                tags:
-                  description: Live video/replay tags (maximum 5 tags each between 2 and 30 characters)
-                  type: array
-                  minItems: 1
-                  maxItems: 5
-                  items:
-                    type: string
-                    minLength: 2
-                    maxLength: 30
-                commentsEnabled:
-                  description: Enable or disable comments for this live video/replay
-                  type: boolean
-                downloadEnabled:
-                  description: Enable or disable downloading for the replay of this live video
-                  type: boolean
-              required:
-                - channelId
-                - name
-            encoding:
-              thumbnailfile:
-                contentType: image/jpeg
-              previewfile:
-                contentType: image/jpeg
+              $ref: '#/components/schemas/VideoChannelCreate'
 
-  /videos/live/{id}:
+  '/api/v1/video-channels/{channelHandle}':
     get:
-      summary: Get information about a live
-      operationId: getLiveId
-      security:
-        - OAuth2: []
+      summary: Get a video channel
+      operationId: getVideoChannel
       tags:
-        - Live Videos
-        - Video
+        - Video Channels
       parameters:
-        - $ref: '#/components/parameters/idOrUUID'
+        - $ref: '#/components/parameters/channelHandle'
       responses:
         '200':
           description: successful operation
           content:
             application/json:
               schema:
-                $ref: '#/components/schemas/LiveVideoResponse'
+                $ref: '#/components/schemas/VideoChannel'
     put:
-      summary: Update information about a live
-      operationId: updateLiveId
+      summary: Update a video channel
+      operationId: putVideoChannel
       security:
         - OAuth2: []
       tags:
-        - Live Videos
-        - Video
+        - Video Channels
       parameters:
-        - $ref: '#/components/parameters/idOrUUID'
+        - $ref: '#/components/parameters/channelHandle'
+      responses:
+        '204':
+          description: successful operation
       requestBody:
         content:
           application/json:
             schema:
-              $ref: '#/components/schemas/LiveVideoUpdate'
+              $ref: '#/components/schemas/VideoChannelUpdate'
+    delete:
+      summary: Delete a video channel
+      operationId: delVideoChannel
+      security:
+        - OAuth2: []
+      tags:
+        - Video Channels
+      parameters:
+        - $ref: '#/components/parameters/channelHandle'
       responses:
         '204':
           description: successful operation
-        '400':
-          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
 
-  /users/me/abuses:
+  '/api/v1/video-channels/{channelHandle}/videos':
     get:
-      summary: List my abuses
-      operationId: getMyAbuses
-      security:
-        - OAuth2: []
+      summary: List videos of a video channel
+      operationId: getVideoChannelVideos
+      tags:
+        - Video
+        - Video Channels
+      parameters:
+        - $ref: '#/components/parameters/channelHandle'
+        - $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'
+
+  '/api/v1/video-channels/{channelHandle}/video-playlists':
+    get:
+      summary: List playlists of a channel
       tags:
-        - Abuses
-        - My User
+        - Video Playlists
+        - Video Channels
       parameters:
-        - name: id
-          in: query
-          description: only list the report with this id
-          schema:
-            type: integer
-        - name: state
-          in: query
-          schema:
-            $ref: '#/components/schemas/AbuseStateSet'
-        - $ref: '#/components/parameters/abusesSort'
+        - $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
@@ -2427,78 +3852,22 @@ paths:
                   data:
                     type: array
                     items:
-                      $ref: '#/components/schemas/Abuse'
+                      $ref: '#/components/schemas/VideoPlaylist'
 
-  /abuses:
+  '/api/v1/video-channels/{channelHandle}/followers':
     get:
-      summary: List abuses
-      operationId: getAbuses
-      security:
-        - OAuth2:
-          - admin
-          - moderator
       tags:
-        - Abuses
+        - Video Channels
+      summary: 'List followers of a video channel'
+      security:
+        - OAuth2: []
+      operationId: getVideoChannelFollowers
       parameters:
-        - name: id
-          in: query
-          description: only list the report with this id
-          schema:
-            type: integer
-        - name: predefinedReason
-          in: query
-          description: predefined reason the listed reports should contain
-          schema:
-            $ref: '#/components/schemas/PredefinedAbuseReasons'
-        - name: search
-          in: query
-          description: plain search that will match with video titles, reporter names and more
-          schema:
-            type: string
-        - name: state
-          in: query
-          schema:
-            $ref: '#/components/schemas/AbuseStateSet'
-        - name: searchReporter
-          in: query
-          description: only list reports of a specific reporter
-          schema:
-            type: string
-        - name: searchReportee
-          description: only list reports of a specific reportee
-          in: query
-          schema:
-            type: string
-        - name: searchVideo
-          in: query
-          description: only list reports of a specific video
-          schema:
-            type: string
-        - name: searchVideoChannel
-          in: query
-          description: only list reports of a specific video channel
-          schema:
-            type: string
-        - name: videoIs
-          in: query
-          description: only list deleted or blocklisted videos
-          schema:
-            type: string
-            enum:
-            - 'deleted'
-            - 'blacklisted'
-        - name: filter
-          in: query
-          description: only list account, comment or video reports
-          schema:
-            type: string
-            enum:
-            - 'video'
-            - 'comment'
-            - 'account'
+        - $ref: '#/components/parameters/channelHandle'
         - $ref: '#/components/parameters/start'
         - $ref: '#/components/parameters/count'
-        - $ref: '#/components/parameters/abusesSort'
+        - $ref: '#/components/parameters/followersSort'
+        - $ref: '#/components/parameters/search'
       responses:
         '200':
           description: successful operation
@@ -2513,59 +3882,17 @@ paths:
                   data:
                     type: array
                     items:
-                      $ref: '#/components/schemas/Abuse'
+                      $ref: '#/components/schemas/Follow'
+
+  '/api/v1/video-channels/{channelHandle}/avatar/pick':
     post:
-      summary: Report an abuse
+      summary: Update channel avatar
       security:
         - OAuth2: []
       tags:
-        - Abuses
-      requestBody:
-        required: true
-        content:
-          application/json:
-            schema:
-              type: object
-              properties:
-                reason:
-                  description: Reason why the user reports this video
-                  type: string
-                  minLength: 2
-                  maxLength: 3000
-                predefinedReasons:
-                  $ref: '#/components/schemas/PredefinedAbuseReasons'
-                video:
-                  type: object
-                  properties:
-                    id:
-                      description: Video id to report
-                      allOf:
-                        - $ref: '#/components/schemas/Video/properties/id'
-                    startAt:
-                      type: integer
-                      format: seconds
-                      description: Timestamp in the video that marks the beginning of the report
-                      minimum: 0
-                    endAt:
-                      type: integer
-                      format: seconds
-                      description: Timestamp in the video that marks the ending of the report
-                      minimum: 0
-                comment:
-                  type: object
-                  properties:
-                    id:
-                      description: Comment id to report
-                      allOf:
-                        - $ref: '#/components/schemas/VideoComment/properties/id'
-                account:
-                  type: object
-                  properties:
-                    id:
-                      description: Account id to report
-                      type: integer
-              required:
-                - reason
+        - Video Channels
+      parameters:
+        - $ref: '#/components/parameters/channelHandle'
       responses:
         '200':
           description: successful operation
@@ -2574,68 +3901,54 @@ paths:
               schema:
                 type: object
                 properties:
-                  abuse:
-                    type: object
-                    properties:
-                      id:
-                        $ref: '#/components/schemas/id'
-        '400':
-          description: incorrect request parameters
-
-  '/abuses/{abuseId}':
-    put:
-      summary: Update an abuse
-      security:
-        - OAuth2:
-          - admin
-          - moderator
-      tags:
-        - Abuses
-      parameters:
-        - $ref: '#/components/parameters/abuseId'
+                  avatars:
+                    type: array
+                    items:
+                      $ref: '#/components/schemas/ActorImage'
+        '413':
+          description: image file too large
+          headers:
+            X-File-Maximum-Size:
+              schema:
+                type: string
+                format: Nginx size
+              description: Maximum file size for the avatar
       requestBody:
         content:
-          application/json:
+          multipart/form-data:
             schema:
               type: object
               properties:
-                state:
-                  $ref: '#/components/schemas/AbuseStateSet'
-                moderationComment:
+                avatarfile:
+                  description: The file to upload.
                   type: string
-                  description: Update the report comment visible only to the moderation team
-                  minLength: 2
-                  maxLength: 3000
-      responses:
-        '204':
-          description: successful operation
-        '404':
-          description: abuse not found
+                  format: binary
+            encoding:
+              avatarfile:
+                contentType: image/png, image/jpeg
+
+  '/api/v1/video-channels/{channelHandle}/avatar':
     delete:
-      tags:
-        - Abuses
-      summary: Delete an abuse
+      summary: Delete channel avatar
       security:
-        - OAuth2:
-          - admin
-          - moderator
+        - OAuth2: []
+      tags:
+        - Video Channels
       parameters:
-        - $ref: '#/components/parameters/abuseId'
+        - $ref: '#/components/parameters/channelHandle'
       responses:
         '204':
           description: successful operation
-        '404':
-          description: block not found
 
-  '/abuses/{abuseId}/messages':
-    get:
-      summary: List messages of an abuse
+  '/api/v1/video-channels/{channelHandle}/banner/pick':
+    post:
+      summary: Update channel banner
       security:
         - OAuth2: []
       tags:
-        - Abuses
+        - Video Channels
       parameters:
-        - $ref: '#/components/parameters/abuseId'
+        - $ref: '#/components/parameters/channelHandle'
       responses:
         '200':
           description: successful operation
@@ -2644,119 +3957,78 @@ paths:
               schema:
                 type: object
                 properties:
-                  total:
-                    type: integer
-                    example: 1
-                  data:
+                  banners:
                     type: array
                     items:
-                      $ref: '#/components/schemas/AbuseMessage'
-    post:
-      summary: Add message to an abuse
-      security:
-        - OAuth2: []
-      tags:
-        - Abuses
-      parameters:
-        - $ref: '#/components/parameters/abuseId'
+                      $ref: '#/components/schemas/ActorImage'
+        '413':
+          description: image file too large
+          headers:
+            X-File-Maximum-Size:
+              schema:
+                type: string
+                format: Nginx size
+              description: Maximum file size for the banner
       requestBody:
-        required: true
         content:
-          application/json:
+          multipart/form-data:
             schema:
               type: object
               properties:
-                message:
-                  description: Message to send
-                  type: string
-                  minLength: 2
-                  maxLength: 3000
-              required:
-                - message
-      responses:
-        '200':
-          description: successful operation
-        '400':
-          description: incorrect request parameters
+                bannerfile:
+                  description: The file to upload.
+                  type: string
+                  format: binary
+            encoding:
+              bannerfile:
+                contentType: image/png, image/jpeg
 
-  '/abuses/{abuseId}/messages/{abuseMessageId}':
+  '/api/v1/video-channels/{channelHandle}/banner':
     delete:
-      summary: Delete an abuse message
+      summary: Delete channel banner
       security:
         - OAuth2: []
       tags:
-        - Abuses
+        - Video Channels
       parameters:
-        - $ref: '#/components/parameters/abuseId'
-        - $ref: '#/components/parameters/abuseMessageId'
+        - $ref: '#/components/parameters/channelHandle'
       responses:
         '204':
           description: successful operation
 
-  '/videos/{id}/blacklist':
+  '/api/v1/video-channels/{channelHandle}/import-videos':
     post:
-      summary: Block a video
-      operationId: addVideoBlock
-      security:
-        - OAuth2:
-          - admin
-          - moderator
-      tags:
-        - Video Blocks
-      parameters:
-        - $ref: '#/components/parameters/idOrUUID'
-      responses:
-        '204':
-          description: successful operation
-    delete:
-      summary: Unblock a video by its id
-      operationId: delVideoBlock
+      summary: Import videos in channel
+      description: Import a remote channel/playlist videos into a channel
       security:
-        - OAuth2:
-          - admin
-          - moderator
+        - OAuth2: []
       tags:
-        - Video Blocks
+        - Video Channels
+        - Channels Sync
       parameters:
-        - $ref: '#/components/parameters/idOrUUID'
+        - $ref: '#/components/parameters/channelHandle'
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/ImportVideosInChannelCreate'
       responses:
         '204':
           description: successful operation
-        '404':
-          description: block not found
 
-  /videos/blacklist:
-    get:
-      tags:
-        - Video Blocks
-      summary: List video blocks
-      operationId: getVideoBlocks
+  '/api/v1/video-channel-syncs':
+    post:
+      summary: Create a synchronization for a video channel
+      operationId: addVideoChannelSync
       security:
-        - OAuth2:
-          - admin
-          - moderator
-      parameters:
-        - name: type
-          in: query
-          description: >
-            list only blocks that match this type:
-
-            - `1`: manual block
-
-            - `2`: automatic block that needs review
-          schema:
-            type: integer
-            enum:
-              - 1
-              - 2
-        - name: search
-          in: query
-          description: plain search that will match with video titles, and more
-          schema:
-            type: string
-        - $ref: '#/components/parameters/start'
-        - $ref: '#/components/parameters/count'
-        - $ref: '#/components/parameters/blacklistsSort'
+        - OAuth2: []
+      tags:
+        - Channels Sync
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/VideoChannelSyncCreate'
       responses:
         '200':
           description: successful operation
@@ -2765,198 +4037,216 @@ paths:
               schema:
                 type: object
                 properties:
-                  total:
-                    type: integer
-                    example: 1
-                  data:
-                    type: array
-                    items:
-                      $ref: '#/components/schemas/VideoBlacklist'
+                  videoChannelSync:
+                    $ref: "#/components/schemas/VideoChannelSync"
 
-  /videos/{id}/captions:
-    get:
-      summary: List captions of a video
-      operationId: getVideoCaptions
+  '/api/v1/video-channel-syncs/{channelSyncId}':
+    delete:
+      summary: Delete a video channel synchronization
+      operationId: delVideoChannelSync
+      security:
+        - OAuth2: []
       tags:
-        - Video Captions
+        - Channels Sync
       parameters:
-        - $ref: '#/components/parameters/idOrUUID'
+        - $ref: '#/components/parameters/channelSyncId'
       responses:
-        '200':
+        '204':
           description: successful operation
-          content:
-            application/json:
-              schema:
-                type: object
-                properties:
-                  total:
-                    type: integer
-                    example: 1
-                  data:
-                    type: array
-                    items:
-                      $ref: '#/components/schemas/VideoCaption'
 
-  /videos/{id}/captions/{captionLanguage}:
-    put:
-      summary: Add or replace a video caption
-      operationId: addVideoCaption
+  '/api/v1/video-channel-syncs/{channelSyncId}/sync':
+    post:
+      summary: Triggers the channel synchronization job, fetching all the videos from the remote channel
+      operationId: triggerVideoChannelSync
       security:
-        - OAuth2:
-          - user
+        - OAuth2: []
       tags:
-        - Video Captions
+        - Channels Sync
       parameters:
-        - $ref: '#/components/parameters/idOrUUID'
-        - $ref: '#/components/parameters/captionLanguage'
-      requestBody:
-        content:
-          multipart/form-data:
-            schema:
-              type: object
-              properties:
-                captionfile:
-                  description: The file to upload.
-                  type: string
-                  format: binary
-            encoding:
-              captionfile:
-                contentType: text/vtt, application/x-subrip, text/plain
+        - $ref: '#/components/parameters/channelSyncId'
       responses:
         '204':
           description: successful operation
-        '404':
-          description: video or language not found
-    delete:
-      summary: Delete a video caption
-      operationId: delVideoCaption
-      security:
-        - OAuth2:
-          - user
+
+
+  /api/v1/video-playlists/privacies:
+    get:
+      summary: List available playlist privacy policies
+      operationId: getPlaylistPrivacyPolicies
       tags:
-        - Video Captions
-      parameters:
-        - $ref: '#/components/parameters/idOrUUID'
-        - $ref: '#/components/parameters/captionLanguage'
+        - Video Playlists
       responses:
-        '204':
+        '200':
           description: successful operation
-        '404':
-          description: video or language or caption for that language not found
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  type: string
+              examples:
+                nightly:
+                  externalValue: https://peertube2.cpy.re/api/v1/video-playlists/privacies
 
-  /video-channels:
+  /api/v1/video-playlists:
     get:
-      summary: List video channels
-      operationId: getVideoChannels
+      summary: List video playlists
+      operationId: getPlaylists
       tags:
-        - Video Channels
+        - Video Playlists
       parameters:
         - $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:
-                $ref: '#/components/schemas/VideoChannelList'
+                type: object
+                properties:
+                  total:
+                    type: integer
+                    example: 1
+                  data:
+                    type: array
+                    items:
+                      $ref: '#/components/schemas/VideoPlaylist'
     post:
-      summary: Create a video channel
-      operationId: addVideoChannel
+      summary: Create a video playlist
+      description: If the video playlist is set as public, `videoChannelId` is mandatory.
+      operationId: addPlaylist
       security:
         - OAuth2: []
       tags:
-        - Video Channels
+        - Video Playlists
       responses:
-        '204':
+        '200':
           description: successful operation
           content:
             application/json:
               schema:
                 type: object
                 properties:
-                  videoChannel:
+                  videoPlaylist:
                     type: object
                     properties:
                       id:
-                        $ref: '#/components/schemas/id'
+                        $ref: '#/components/schemas/VideoPlaylist/properties/id'
+                      uuid:
+                        $ref: '#/components/schemas/VideoPlaylist/properties/uuid'
+                      shortUUID:
+                        $ref: '#/components/schemas/VideoPlaylist/properties/shortUUID'
       requestBody:
         content:
-          application/json:
+          multipart/form-data:
             schema:
-              $ref: '#/components/schemas/VideoChannelCreate'
+              type: object
+              properties:
+                displayName:
+                  description: Video playlist display name
+                  type: string
+                  minLength: 1
+                  maxLength: 120
+                thumbnailfile:
+                  description: Video playlist thumbnail file
+                  type: string
+                  format: binary
+                privacy:
+                  $ref: '#/components/schemas/VideoPlaylistPrivacySet'
+                description:
+                  description: Video playlist description
+                  type: string
+                  minLength: 3
+                  maxLength: 1000
+                videoChannelId:
+                  allOf:
+                    - $ref: '#/components/schemas/id'
+                  description: Video channel in which the playlist will be published
+              required:
+                - displayName
+            encoding:
+              thumbnailfile:
+                contentType: image/jpeg
 
-  '/video-channels/{channelHandle}':
+  /api/v1/video-playlists/{playlistId}:
     get:
-      summary: Get a video channel
-      operationId: getVideoChannel
+      summary: Get a video playlist
       tags:
-        - Video Channels
+        - Video Playlists
       parameters:
-        - $ref: '#/components/parameters/channelHandle'
+        - $ref: '#/components/parameters/playlistId'
       responses:
         '200':
           description: successful operation
           content:
             application/json:
               schema:
-                $ref: '#/components/schemas/VideoChannel'
+                $ref: '#/components/schemas/VideoPlaylist'
     put:
-      summary: Update a video channel
-      operationId: putVideoChannel
+      summary: Update a video playlist
+      description: 'If the video playlist is set as public, the playlist must have a assigned channel.'
       security:
         - OAuth2: []
       tags:
-        - Video Channels
-      parameters:
-        - $ref: '#/components/parameters/channelHandle'
+        - Video Playlists
       responses:
         '204':
           description: successful operation
+      parameters:
+        - $ref: '#/components/parameters/playlistId'
       requestBody:
         content:
-          application/json:
+          multipart/form-data:
             schema:
-              $ref: '#/components/schemas/VideoChannelUpdate'
+              type: object
+              properties:
+                displayName:
+                  description: Video playlist display name
+                  type: string
+                  minLength: 1
+                  maxLength: 120
+                thumbnailfile:
+                  description: Video playlist thumbnail file
+                  type: string
+                  format: binary
+                privacy:
+                  $ref: '#/components/schemas/VideoPlaylistPrivacySet'
+                description:
+                  description: Video playlist description
+                  type: string
+                videoChannelId:
+                  allOf:
+                    - $ref: '#/components/schemas/id'
+                  description: Video channel in which the playlist will be published
+            encoding:
+              thumbnailfile:
+                contentType: image/jpeg
     delete:
-      summary: Delete a video channel
-      operationId: delVideoChannel
+      summary: Delete a video playlist
       security:
         - OAuth2: []
       tags:
-        - Video Channels
+        - Video Playlists
       parameters:
-        - $ref: '#/components/parameters/channelHandle'
+        - $ref: '#/components/parameters/playlistId'
       responses:
         '204':
           description: successful operation
 
-  '/video-channels/{channelHandle}/videos':
+  /api/v1/video-playlists/{playlistId}/videos:
     get:
-      summary: List videos of a video channel
-      operationId: getVideoChannelVideos
+      summary: 'List videos of a playlist'
+      operationId: getVideoPlaylistVideos
       tags:
-        - Video
-        - Video Channels
+        - Videos
+        - Video Playlists
       parameters:
-        - $ref: '#/components/parameters/channelHandle'
-        - $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/playlistId'
         - $ref: '#/components/parameters/start'
         - $ref: '#/components/parameters/count'
-        - $ref: '#/components/parameters/videosSort'
       responses:
         '200':
           description: successful operation
@@ -2964,21 +4254,16 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/VideoListResponse'
-
-  '/video-channels/{channelHandle}/followers':
-    get:
-      tags:
-        - Video Channels
-      summary: 'List followers of a video channel'
+    post:
+      summary: Add a video in a playlist
+      operationId: addVideoPlaylistVideo
       security:
         - OAuth2: []
-      operationId: getVideoChannelFollowers
+      tags:
+        - Videos
+        - Video Playlists
       parameters:
-        - $ref: '#/components/parameters/channelHandle'
-        - $ref: '#/components/parameters/start'
-        - $ref: '#/components/parameters/count'
-        - $ref: '#/components/parameters/followersSort'
-        - $ref: '#/components/parameters/search'
+        - $ref: '#/components/parameters/playlistId'
       responses:
         '200':
           description: successful operation
@@ -2987,79 +4272,127 @@ paths:
               schema:
                 type: object
                 properties:
-                  total:
-                    type: integer
-                    example: 1
-                  data:
-                    type: array
-                    items:
-                      $ref: '#/components/schemas/Follow'
+                  videoPlaylistElement:
+                    type: object
+                    properties:
+                      id:
+                        type: integer
+                        example: 2
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: object
+              properties:
+                videoId:
+                  oneOf:
+                    - $ref: '#/components/schemas/Video/properties/uuid'
+                    - $ref: '#/components/schemas/Video/properties/id'
+                  description: Video to add in the playlist
+                startTimestamp:
+                  type: integer
+                  format: seconds
+                  description: Start the video at this specific timestamp
+                stopTimestamp:
+                  type: integer
+                  format: seconds
+                  description: Stop the video at this specific timestamp
+              required:
+                - videoId
 
-  '/video-channels/{channelHandle}/avatar/pick':
+  /api/v1/video-playlists/{playlistId}/videos/reorder:
     post:
-      summary: Update channel avatar
+      summary: 'Reorder a playlist'
+      operationId: reorderVideoPlaylist
       security:
         - OAuth2: []
       tags:
-        - Video Channels
+        - Video Playlists
       parameters:
-        - $ref: '#/components/parameters/channelHandle'
+        - $ref: '#/components/parameters/playlistId'
       responses:
-        '200':
+        '204':
           description: successful operation
-          content:
-            application/json:
-              schema:
-                type: object
-                properties:
-                  avatars:
-                    type: array
-                    items:
-                      $ref: '#/components/schemas/ActorImage'
-        '413':
-          description: image file too large
-          headers:
-            X-File-Maximum-Size:
-              schema:
-                type: string
-                format: Nginx size
-              description: Maximum file size for the avatar
       requestBody:
         content:
-          multipart/form-data:
+          application/json:
             schema:
               type: object
               properties:
-                avatarfile:
-                  description: The file to upload.
-                  type: string
-                  format: binary
-            encoding:
-              avatarfile:
-                contentType: image/png, image/jpeg
+                startPosition:
+                  type: integer
+                  description: 'Start position of the element to reorder'
+                  minimum: 1
+                insertAfterPosition:
+                  type: integer
+                  description: 'New position for the block to reorder, to add the block before the first element'
+                  minimum: 0
+                reorderLength:
+                  type: integer
+                  description: 'How many element from `startPosition` to reorder'
+                  minimum: 1
+              required:
+                - startPosition
+                - insertAfterPosition
 
-  '/video-channels/{channelHandle}/avatar':
+  /api/v1/video-playlists/{playlistId}/videos/{playlistElementId}:
+    put:
+      summary: Update a playlist element
+      operationId: putVideoPlaylistVideo
+      security:
+        - OAuth2: []
+      tags:
+        - Video Playlists
+      parameters:
+        - $ref: '#/components/parameters/playlistId'
+        - $ref: '#/components/parameters/playlistElementId'
+      responses:
+        '204':
+          description: successful operation
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: object
+              properties:
+                startTimestamp:
+                  type: integer
+                  format: seconds
+                  description: Start the video at this specific timestamp
+                stopTimestamp:
+                  type: integer
+                  format: seconds
+                  description: Stop the video at this specific timestamp
     delete:
-      summary: Delete channel avatar
+      summary: Delete an element from a playlist
+      operationId: delVideoPlaylistVideo
       security:
         - OAuth2: []
       tags:
-        - Video Channels
+        - Video Playlists
       parameters:
-        - $ref: '#/components/parameters/channelHandle'
+        - $ref: '#/components/parameters/playlistId'
+        - $ref: '#/components/parameters/playlistElementId'
       responses:
         '204':
           description: successful operation
 
-  '/video-channels/{channelHandle}/banner/pick':
-    post:
-      summary: Update channel banner
+  '/api/v1/users/me/video-playlists/videos-exist':
+    get:
+      summary: Check video exists in my playlists
       security:
         - OAuth2: []
       tags:
-        - Video Channels
+        - Video Playlists
       parameters:
-        - $ref: '#/components/parameters/channelHandle'
+        - name: videoIds
+          in: query
+          required: true
+          description: The video ids to check
+          schema:
+            type: array
+            items:
+              $ref: '#/components/schemas/Video/properties/id'
       responses:
         '200':
           description: successful operation
@@ -3068,71 +4401,83 @@ paths:
               schema:
                 type: object
                 properties:
-                  banners:
+                  videoId:
                     type: array
                     items:
-                      $ref: '#/components/schemas/ActorImage'
-        '413':
-          description: image file too large
-          headers:
-            X-File-Maximum-Size:
-              schema:
-                type: string
-                format: Nginx size
-              description: Maximum file size for the banner
-      requestBody:
-        content:
-          multipart/form-data:
-            schema:
-              type: object
-              properties:
-                bannerfile:
-                  description: The file to upload.
-                  type: string
-                  format: binary
-            encoding:
-              bannerfile:
-                contentType: image/png, image/jpeg
+                      type: object
+                      properties:
+                        playlistElementId:
+                          type: integer
+                        playlistId:
+                          type: integer
+                        startTimestamp:
+                          type: integer
+                          format: seconds
+                        stopTimestamp:
+                          type: integer
 
-  '/video-channels/{channelHandle}/banner':
-    delete:
-      summary: Delete channel banner
-      security:
-        - OAuth2: []
+  '/api/v1/accounts/{name}/video-playlists':
+    get:
+      summary: List playlists of an account
       tags:
-        - Video Channels
+        - Video Playlists
+        - Accounts
       parameters:
-        - $ref: '#/components/parameters/channelHandle'
+        - $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:
-        '204':
+        '200':
           description: successful operation
+          content:
+            application/json:
+              schema:
+                type: object
+                properties:
+                  total:
+                    type: integer
+                    example: 1
+                  data:
+                    type: array
+                    items:
+                      $ref: '#/components/schemas/VideoPlaylist'
 
-  /video-playlists/privacies:
+  '/api/v1/accounts/{name}/video-channels':
     get:
-      summary: List available playlist privacy policies
-      operationId: getPlaylistPrivacyPolicies
+      summary: List video channels of an account
       tags:
-        - Video Playlists
+        - Video Channels
+        - Accounts
+      parameters:
+        - $ref: '#/components/parameters/name'
+        - name: withStats
+          in: query
+          description: include daily view statistics for the last 30 days and total views (only if authentified as the account user)
+          schema:
+            type: boolean
+        - $ref: '#/components/parameters/start'
+        - $ref: '#/components/parameters/count'
+        - $ref: '#/components/parameters/sort'
       responses:
         '200':
           description: successful operation
           content:
             application/json:
               schema:
-                type: array
-                items:
-                  type: string
-              examples:
-                nightly:
-                  externalValue: https://peertube2.cpy.re/api/v1/video-playlists/privacies
+                $ref: '#/components/schemas/VideoChannelList'
 
-  /video-playlists:
+  '/api/v1/accounts/{name}/video-channel-syncs':
     get:
-      summary: List video playlists
-      operationId: getPlaylists
+      summary: List the synchronizations of video channels of an account
       tags:
-        - Video Playlists
+        - Video Channels
+        - Channels Sync
+        - Accounts
       parameters:
+        - $ref: '#/components/parameters/name'
         - $ref: '#/components/parameters/start'
         - $ref: '#/components/parameters/count'
         - $ref: '#/components/parameters/sort'
@@ -3142,334 +4487,351 @@ paths:
           content:
             application/json:
               schema:
-                type: object
-                properties:
-                  total:
-                    type: integer
-                    example: 1
-                  data:
-                    type: array
-                    items:
-                      $ref: '#/components/schemas/VideoPlaylist'
-    post:
-      summary: Create a video playlist
-      description: If the video playlist is set as public, `videoChannelId` is mandatory.
-      operationId: addPlaylist
+                $ref: '#/components/schemas/VideoChannelSyncList'
+
+  '/api/v1/accounts/{name}/ratings':
+    get:
+      summary: List ratings of an account
       security:
         - OAuth2: []
       tags:
-        - Video Playlists
+        - Accounts
+      parameters:
+        - $ref: '#/components/parameters/name'
+        - $ref: '#/components/parameters/start'
+        - $ref: '#/components/parameters/count'
+        - $ref: '#/components/parameters/sort'
+        - name: rating
+          in: query
+          required: false
+          description: Optionally filter which ratings to retrieve
+          schema:
+            type: string
+            enum:
+              - like
+              - dislike
       responses:
         '200':
           description: successful operation
           content:
             application/json:
               schema:
-                type: object
-                properties:
-                  videoPlaylist:
-                    type: object
-                    properties:
-                      id:
-                        $ref: '#/components/schemas/VideoPlaylist/properties/id'
-                      uuid:
-                        $ref: '#/components/schemas/VideoPlaylist/properties/uuid'
-                      shortUUID:
-                        $ref: '#/components/schemas/VideoPlaylist/properties/shortUUID'
-      requestBody:
-        content:
-          multipart/form-data:
-            schema:
-              type: object
-              properties:
-                displayName:
-                  description: Video playlist display name
-                  type: string
-                  minLength: 1
-                  maxLength: 120
-                thumbnailfile:
-                  description: Video playlist thumbnail file
-                  type: string
-                  format: binary
-                privacy:
-                  $ref: '#/components/schemas/VideoPlaylistPrivacySet'
-                description:
-                  description: Video playlist description
-                  type: string
-                  minLength: 3
-                  maxLength: 1000
-                videoChannelId:
-                  allOf:
-                    - $ref: '#/components/schemas/id'
-                  description: Video channel in which the playlist will be published
-              required:
-                - displayName
-            encoding:
-              thumbnailfile:
-                contentType: image/jpeg
+                type: array
+                items:
+                  $ref: '#/components/schemas/VideoRating'
 
-  /video-playlists/{playlistId}:
+  '/api/v1/videos/{id}/comment-threads':
     get:
-      summary: Get a video playlist
+      summary: List threads of a video
       tags:
-        - Video Playlists
+        - Video Comments
       parameters:
-        - $ref: '#/components/parameters/playlistId'
+        - $ref: '#/components/parameters/idOrUUID'
+        - $ref: '#/components/parameters/start'
+        - $ref: '#/components/parameters/count'
+        - $ref: '#/components/parameters/commentsSort'
       responses:
         '200':
           description: successful operation
           content:
             application/json:
               schema:
-                $ref: '#/components/schemas/VideoPlaylist'
-    put:
-      summary: Update a video playlist
-      description: 'If the video playlist is set as public, the playlist must have a assigned channel.'
+                $ref: '#/components/schemas/CommentThreadResponse'
+    post:
+      summary: Create a thread
       security:
         - OAuth2: []
       tags:
-        - Video Playlists
+        - Video Comments
+      parameters:
+        - $ref: '#/components/parameters/idOrUUID'
       responses:
-        '204':
+        '200':
           description: successful operation
-      parameters:
-        - $ref: '#/components/parameters/playlistId'
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/CommentThreadPostResponse'
+        '404':
+          description: video does not exist
       requestBody:
         content:
-          multipart/form-data:
+          application/json:
             schema:
               type: object
               properties:
-                displayName:
-                  description: Video playlist display name
-                  type: string
-                  minLength: 1
-                  maxLength: 120
-                thumbnailfile:
-                  description: Video playlist thumbnail file
-                  type: string
-                  format: binary
-                privacy:
-                  $ref: '#/components/schemas/VideoPlaylistPrivacySet'
-                description:
-                  description: Video playlist description
-                  type: string
-                videoChannelId:
+                text:
                   allOf:
-                    - $ref: '#/components/schemas/id'
-                  description: Video channel in which the playlist will be published
-            encoding:
-              thumbnailfile:
-                contentType: image/jpeg
-    delete:
-      summary: Delete a video playlist
-      security:
-        - OAuth2: []
-      tags:
-        - Video Playlists
-      parameters:
-        - $ref: '#/components/parameters/playlistId'
-      responses:
-        '204':
-          description: successful operation
+                    - $ref: '#/components/schemas/VideoComment/properties/text'
+                  format: markdown
+                  maxLength: 10000
+              required:
+                - text
 
-  /video-playlists/{playlistId}/videos:
+  '/api/v1/videos/{id}/comment-threads/{threadId}':
     get:
-      summary: 'List videos of a playlist'
-      operationId: getVideoPlaylistVideos
+      summary: Get a thread
       tags:
-        - Videos
-        - Video Playlists
+        - Video Comments
       parameters:
-        - $ref: '#/components/parameters/playlistId'
-        - $ref: '#/components/parameters/start'
-        - $ref: '#/components/parameters/count'
+        - $ref: '#/components/parameters/idOrUUID'
+        - $ref: '#/components/parameters/threadId'
       responses:
         '200':
           description: successful operation
           content:
             application/json:
               schema:
-                $ref: '#/components/schemas/VideoListResponse'
+                $ref: '#/components/schemas/VideoCommentThreadTree'
+
+  '/api/v1/videos/{id}/comments/{commentId}':
     post:
-      summary: Add a video in a playlist
-      operationId: addVideoPlaylistVideo
+      summary: Reply to a thread of a video
       security:
         - OAuth2: []
       tags:
-        - Videos
-        - Video Playlists
+        - Video Comments
       parameters:
-        - $ref: '#/components/parameters/playlistId'
+        - $ref: '#/components/parameters/idOrUUID'
+        - $ref: '#/components/parameters/commentId'
       responses:
         '200':
           description: successful operation
           content:
             application/json:
               schema:
-                type: object
-                properties:
-                  videoPlaylistElement:
-                    type: object
-                    properties:
-                      id:
-                        type: integer
-                        example: 2
+                $ref: '#/components/schemas/CommentThreadPostResponse'
+        '404':
+          description: thread or video does not exist
       requestBody:
         content:
           application/json:
             schema:
               type: object
               properties:
-                videoId:
-                  oneOf:
-                    - $ref: '#/components/schemas/Video/properties/uuid'
-                    - $ref: '#/components/schemas/Video/properties/id'
-                  description: Video to add in the playlist
-                startTimestamp:
-                  type: integer
-                  format: seconds
-                  description: Start the video at this specific timestamp
-                stopTimestamp:
-                  type: integer
-                  format: seconds
-                  description: Stop the video at this specific timestamp
+                text:
+                  allOf:
+                    - $ref: '#/components/schemas/VideoComment/properties/text'
+                  format: markdown
+                  maxLength: 10000
               required:
-                - videoId
+                - text
+    delete:
+      summary: Delete a comment or a reply
+      security:
+        - OAuth2: []
+      tags:
+        - Video Comments
+      parameters:
+        - $ref: '#/components/parameters/idOrUUID'
+        - $ref: '#/components/parameters/commentId'
+      responses:
+        '204':
+          description: successful operation
+        '403':
+          description: cannot remove comment of another user
+        '404':
+          description: comment or video does not exist
+        '409':
+          description: comment is already deleted
 
-  /video-playlists/{playlistId}/videos/reorder:
-    post:
-      summary: 'Reorder a playlist'
-      operationId: reorderVideoPlaylist
+  '/api/v1/videos/{id}/rate':
+    put:
+      summary: Like/dislike a video
       security:
         - OAuth2: []
       tags:
-        - Video Playlists
+        - Video Rates
       parameters:
-        - $ref: '#/components/parameters/playlistId'
-      responses:
-        '204':
-          description: successful operation
+        - $ref: '#/components/parameters/idOrUUID'
       requestBody:
         content:
           application/json:
             schema:
               type: object
               properties:
-                startPosition:
-                  type: integer
-                  description: 'Start position of the element to reorder'
-                  minimum: 1
-                insertAfterPosition:
-                  type: integer
-                  description: 'New position for the block to reorder, to add the block before the first element'
-                  minimum: 0
-                reorderLength:
-                  type: integer
-                  description: 'How many element from `startPosition` to reorder'
-                  minimum: 1
+                rating:
+                  type: string
+                  enum:
+                    - like
+                    - dislike
               required:
-                - startPosition
-                - insertAfterPosition
+                - rating
+      responses:
+        '204':
+          description: successful operation
+        '404':
+          description: video does not exist
 
-  /video-playlists/{playlistId}/videos/{playlistElementId}:
-    put:
-      summary: Update a playlist element
-      operationId: putVideoPlaylistVideo
+  '/api/v1/videos/{id}/hls':
+    delete:
+      summary: Delete video HLS files
       security:
-        - OAuth2: []
+        - OAuth2:
+          - admin
       tags:
-        - Video Playlists
+        - Video Files
+      operationId: delVideoHLS
       parameters:
-        - $ref: '#/components/parameters/playlistId'
-        - $ref: '#/components/parameters/playlistElementId'
+        - $ref: '#/components/parameters/idOrUUID'
       responses:
         '204':
           description: successful operation
-      requestBody:
-        content:
-          application/json:
-            schema:
-              type: object
-              properties:
-                startTimestamp:
-                  type: integer
-                  format: seconds
-                  description: Start the video at this specific timestamp
-                stopTimestamp:
-                  type: integer
-                  format: seconds
-                  description: Stop the video at this specific timestamp
+        '404':
+          description: video does not exist
+  '/api/v1/videos/{id}/webtorrent':
     delete:
-      summary: Delete an element from a playlist
-      operationId: delVideoPlaylistVideo
+      summary: Delete video WebTorrent files
       security:
-        - OAuth2: []
+        - OAuth2:
+          - admin
       tags:
-        - Video Playlists
+        - Video Files
+      operationId: delVideoWebTorrent
       parameters:
-        - $ref: '#/components/parameters/playlistId'
-        - $ref: '#/components/parameters/playlistElementId'
+        - $ref: '#/components/parameters/idOrUUID'
       responses:
         '204':
           description: successful operation
+        '404':
+          description: video does not exist
 
-  '/users/me/video-playlists/videos-exist':
-    get:
-      summary: Check video exists in my playlists
+  '/api/v1/videos/{id}/transcoding':
+    post:
+      summary: Create a transcoding job
       security:
-        - OAuth2: []
+        - OAuth2:
+          - admin
       tags:
-        - Video Playlists
+        - Video Transcoding
+      operationId: createVideoTranscoding
       parameters:
-        - name: videoIds
+        - $ref: '#/components/parameters/idOrUUID'
+      requestBody:
+          content:
+            application/json:
+              schema:
+                type: object
+                properties:
+                  transcodingType:
+                    type: string
+                    enum:
+                      - hls
+                      - webtorrent
+                required:
+                  - transcodingType
+      responses:
+        '204':
+          description: successful operation
+        '404':
+          description: video does not exist
+
+  /api/v1/search/videos:
+    get:
+      tags:
+        - Search
+      summary: Search videos
+      operationId: searchVideos
+      parameters:
+        - name: search
           in: query
           required: true
-          description: The video ids to check
+          allowEmptyValue: false
+          description: >
+            String to search. If the user can make a remote URI search, and the string is an URI then the
+            PeerTube instance will fetch the remote object and add it to its database. Then,
+            you can use the REST API to fetch the complete video information and interact with it.
           schema:
-            type: array
-            items:
-              $ref: '#/components/schemas/Video/properties/id'
+            type: string
+        - $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/uuids'
+        - $ref: '#/components/parameters/hasHLSFiles'
+        - $ref: '#/components/parameters/hasWebtorrentFiles'
+        - $ref: '#/components/parameters/skipCount'
+        - $ref: '#/components/parameters/start'
+        - $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
+          schema:
+            type: string
+            format: date-time
+        - name: endDate
+          in: query
+          description: Get videos that are published before this date
+          schema:
+            type: string
+            format: date-time
+        - name: originallyPublishedStartDate
+          in: query
+          description: Get videos that are originally published after this date
+          schema:
+            type: string
+            format: date-time
+        - name: originallyPublishedEndDate
+          in: query
+          description: Get videos that are originally published before this date
+          schema:
+            type: string
+            format: date-time
+        - name: durationMin
+          in: query
+          description: Get videos that have this minimum duration
+          schema:
+            type: integer
+        - name: durationMax
+          in: query
+          description: Get videos that have this maximum duration
+          schema:
+            type: integer
+      callbacks:
+        'searchTarget === search-index':
+          $ref: '#/components/callbacks/searchIndex'
       responses:
         '200':
           description: successful operation
           content:
             application/json:
               schema:
-                type: object
-                properties:
-                  videoId:
-                    type: array
-                    items:
-                      type: object
-                      properties:
-                        playlistElementId:
-                          type: integer
-                        playlistId:
-                          type: integer
-                        startTimestamp:
-                          type: integer
-                          format: seconds
-                        stopTimestamp:
-                          type: integer
-                          format: seconds
+                $ref: '#/components/schemas/VideoListResponse'
+        '500':
+          description: search index unavailable
 
-  '/accounts/{name}/video-channels':
+  /api/v1/search/video-channels:
     get:
-      summary: List video channels of an account
       tags:
-        - Video Channels
-        - Accounts
+        - Search
+      summary: Search channels
+      operationId: searchChannels
       parameters:
-        - $ref: '#/components/parameters/name'
-        - name: withStats
+        - name: search
           in: query
-          description: include view statistics for the last 30 days (only if authentified as the account user)
+          required: true
+          description: >
+            String to search. If the user can make a remote URI search, and the string is an URI then the
+            PeerTube instance will fetch the remote object and add it to its database. Then,
+            you can use the REST API to fetch the complete channel information and interact with it.
           schema:
-            type: boolean
+            type: string
         - $ref: '#/components/parameters/start'
         - $ref: '#/components/parameters/count'
+        - $ref: '#/components/parameters/searchTarget'
         - $ref: '#/components/parameters/sort'
+      callbacks:
+        'searchTarget === search-index':
+          $ref: '#/components/callbacks/searchIndex'
       responses:
         '200':
           description: successful operation
@@ -3477,451 +4839,458 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/VideoChannelList'
+        '500':
+          description: search index unavailable
+
+  /api/v1/search/video-playlists:
+    get:
+      tags:
+        - Search
+      summary: Search playlists
+      operationId: searchPlaylists
+      parameters:
+        - name: search
+          in: query
+          required: true
+          description: >
+            String to search. If the user can make a remote URI search, and the string is an URI then the
+            PeerTube instance will fetch the remote object and add it to its database. Then,
+            you can use the REST API to fetch the complete playlist information and interact with it.
+          schema:
+            type: string
+        - $ref: '#/components/parameters/start'
+        - $ref: '#/components/parameters/count'
+        - $ref: '#/components/parameters/searchTarget'
+        - $ref: '#/components/parameters/sort'
+      callbacks:
+        'searchTarget === search-index':
+          $ref: '#/components/callbacks/searchIndex'
+      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'
+        '500':
+          description: search index unavailable
 
-  '/accounts/{name}/ratings':
+  /api/v1/blocklist/status:
     get:
-      summary: List ratings of an account
-      security:
-        - OAuth2: []
       tags:
-        - Accounts
+        - Account Blocks
+        - Server Blocks
+      summary: Get block status of accounts/hosts
       parameters:
-        - $ref: '#/components/parameters/name'
-        - $ref: '#/components/parameters/start'
-        - $ref: '#/components/parameters/count'
-        - $ref: '#/components/parameters/sort'
-        - name: rating
+        -
+          name: 'accounts'
           in: query
-          required: false
-          description: Optionally filter which ratings to retrieve
+          description: 'Check if these accounts are blocked'
+          example: [ 'goofy@example.com', 'donald@example.com' ]
           schema:
-            type: string
-            enum:
-              - like
-              - dislike
+            type: array
+            items:
+              type: string
+        -
+          name: 'hosts'
+          in: query
+          description: 'Check if these hosts are blocked'
+          example: [ 'example.com' ]
+          schema:
+            type: array
+            items:
+              type: string
       responses:
         '200':
           description: successful operation
           content:
-            application/json:
+            'application/json':
               schema:
-                type: array
-                items:
-                  $ref: '#/components/schemas/VideoRating'
+                $ref: '#/components/schemas/BlockStatus'
 
-  '/videos/{id}/comment-threads':
+  /api/v1/server/blocklist/accounts:
     get:
-      summary: List threads of a video
       tags:
-        - Video Comments
+        - Account Blocks
+      summary: List account blocks
+      security:
+        - OAuth2:
+          - admin
       parameters:
-        - $ref: '#/components/parameters/idOrUUID'
         - $ref: '#/components/parameters/start'
         - $ref: '#/components/parameters/count'
-        - $ref: '#/components/parameters/commentsSort'
+        - $ref: '#/components/parameters/sort'
       responses:
         '200':
           description: successful operation
-          content:
-            application/json:
-              schema:
-                $ref: '#/components/schemas/CommentThreadResponse'
     post:
-      summary: Create a thread
-      security:
-        - OAuth2: []
       tags:
-        - Video Comments
-      parameters:
-        - $ref: '#/components/parameters/idOrUUID'
-      responses:
-        '200':
-          description: successful operation
-          content:
-            application/json:
-              schema:
-                $ref: '#/components/schemas/CommentThreadPostResponse'
-        '404':
-          description: video does not exist
+        - Account Blocks
+      summary: Block an account
+      security:
+        - OAuth2:
+          - admin
       requestBody:
         content:
           application/json:
             schema:
               type: object
               properties:
-                text:
-                  allOf:
-                    - $ref: '#/components/schemas/VideoComment/properties/text'
-                  format: markdown
-                  maxLength: 10000
+                accountName:
+                  type: string
+                  example: chocobozzz@example.org
+                  description: account to block, in the form `username@domain`
               required:
-                - text
+                - accountName
+      responses:
+        '200':
+          description: successful operation
+        '409':
+          description: self-blocking forbidden
 
-  '/videos/{id}/comment-threads/{threadId}':
-    get:
-      summary: Get a thread
+  '/api/v1/server/blocklist/accounts/{accountName}':
+    delete:
       tags:
-        - Video Comments
+        - Account Blocks
+      summary: Unblock an account by its handle
+      security:
+        - OAuth2:
+          - admin
       parameters:
-        - $ref: '#/components/parameters/idOrUUID'
-        - $ref: '#/components/parameters/threadId'
+        - name: accountName
+          in: path
+          required: true
+          description: account to unblock, in the form `username@domain`
+          schema:
+            type: string
       responses:
-        '200':
+        '201':
           description: successful operation
-          content:
-            application/json:
-              schema:
-                $ref: '#/components/schemas/VideoCommentThreadTree'
+        '404':
+          description: account or account block does not exist
 
-  '/videos/{id}/comments/{commentId}':
-    post:
-      summary: Reply to a thread of a video
-      security:
-        - OAuth2: []
+  /api/v1/server/blocklist/servers:
+    get:
       tags:
-        - Video Comments
+        - Server Blocks
+      summary: List server blocks
+      security:
+        - OAuth2:
+          - admin
       parameters:
-        - $ref: '#/components/parameters/idOrUUID'
-        - $ref: '#/components/parameters/commentId'
+        - $ref: '#/components/parameters/start'
+        - $ref: '#/components/parameters/count'
+        - $ref: '#/components/parameters/sort'
       responses:
         '200':
           description: successful operation
-          content:
-            application/json:
-              schema:
-                $ref: '#/components/schemas/CommentThreadPostResponse'
-        '404':
-          description: thread or video does not exist
+    post:
+      tags:
+        - Server Blocks
+      summary: Block a server
+      security:
+        - OAuth2:
+          - admin
       requestBody:
         content:
           application/json:
             schema:
               type: object
               properties:
-                text:
-                  allOf:
-                    - $ref: '#/components/schemas/VideoComment/properties/text'
-                  format: markdown
-                  maxLength: 10000
+                host:
+                  type: string
+                  format: hostname
+                  description: server domain to block
               required:
-                - text
+                - host
+      responses:
+        '204':
+          description: successful operation
+        '409':
+          description: self-blocking forbidden
+
+  '/api/v1/server/blocklist/servers/{host}':
     delete:
-      summary: Delete a comment or a reply
-      security:
-        - OAuth2: []
       tags:
-        - Video Comments
+        - Server Blocks
+      summary: Unblock a server by its domain
+      security:
+        - OAuth2:
+          - admin
       parameters:
-        - $ref: '#/components/parameters/idOrUUID'
-        - $ref: '#/components/parameters/commentId'
+        - name: host
+          in: path
+          required: true
+          description: server domain to unblock
+          schema:
+            type: string
+            format: hostname
       responses:
         '204':
           description: successful operation
-        '403':
-          description: cannot remove comment of another user
         '404':
-          description: comment or video does not exist
-        '409':
-          description: comment is already deleted
+          description: account block does not exist
 
-  '/videos/{id}/rate':
+  /api/v1/server/redundancy/{host}:
     put:
-      summary: Like/dislike a video
+      tags:
+        - Instance Redundancy
+      summary: Update a server redundancy policy
+      security:
+        - OAuth2:
+          - admin
+      parameters:
+        - name: host
+          in: path
+          required: true
+          description: server domain to mirror
+          schema:
+            type: string
+            format: hostname
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: object
+              properties:
+                redundancyAllowed:
+                  type: boolean
+                  description: allow mirroring of the host's local videos
+              required:
+                - redundancyAllowed
+      responses:
+        '204':
+          description: successful operation
+        '404':
+          description: server is not already known
+
+  /api/v1/server/redundancy/videos:
+    get:
+      tags:
+        - Video Mirroring
+      summary: List videos being mirrored
+      operationId: getMirroredVideos
+      security:
+        - OAuth2:
+          - admin
+      parameters:
+        - name: target
+          in: query
+          required: true
+          description: direction of the mirror
+          schema:
+            type: string
+            enum:
+              - my-videos
+              - remote-videos
+        - $ref: '#/components/parameters/start'
+        - $ref: '#/components/parameters/count'
+        - $ref: '#/components/parameters/videoRedundanciesSort'
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  $ref: '#/components/schemas/VideoRedundancy'
+    post:
+      tags:
+        - Video Mirroring
+      summary: Mirror a video
+      operationId: putMirroredVideo
       security:
-        - OAuth2: []
-      tags:
-        - Video Rates
-      parameters:
-        - $ref: '#/components/parameters/idOrUUID'
+        - OAuth2:
+          - admin
       requestBody:
         content:
           application/json:
             schema:
               type: object
               properties:
-                rating:
-                  type: string
-                  enum:
-                    - like
-                    - dislike
+                videoId:
+                  $ref: '#/components/schemas/Video/properties/id'
               required:
-                - rating
+                - videoId
       responses:
         '204':
           description: successful operation
+        '400':
+          description: cannot mirror a local video
         '404':
           description: video does not exist
+        '409':
+          description: video is already mirrored
 
-  '/videos/{id}/hls':
+  /api/v1/server/redundancy/videos/{redundancyId}:
     delete:
-      summary: Delete video HLS files
+      tags:
+        - Video Mirroring
+      summary: Delete a mirror done on a video
+      operationId: delMirroredVideo
       security:
         - OAuth2:
           - admin
-      tags:
-        - Video Files
-      operationId: delVideoHLS
       parameters:
-        - $ref: '#/components/parameters/idOrUUID'
+        - 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 does not exist
-  '/videos/{id}/webtorrent':
-    delete:
-      summary: Delete video WebTorrent files
-      security:
-        - OAuth2:
-          - admin
+          description: video redundancy not found
+
+  /api/v1/server/stats:
+    get:
       tags:
-        - Video Files
-      operationId: delVideoWebTorrent
-      parameters:
-        - $ref: '#/components/parameters/idOrUUID'
+        - Stats
+      summary: Get instance stats
+      description: Get instance public statistics. This endpoint is cached.
+      operationId: getInstanceStats
       responses:
-        '204':
+        '200':
           description: successful operation
-        '404':
-          description: video does not exist
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ServerStats'
 
-  '/videos/{id}/transcoding':
+  /api/v1/server/logs/client:
     post:
-      summary: Create a transcoding job
-      security:
-        - OAuth2:
-          - admin
       tags:
-        - Video Transcoding
-      operationId: createVideoTranscoding
-      parameters:
-        - $ref: '#/components/parameters/idOrUUID'
+        - Logs
+      summary: Send client log
+      operationId: sendClientLog
       requestBody:
-          content:
-            application/json:
-              schema:
-                type: object
-                properties:
-                  transcodingType:
-                    type: string
-                    enum:
-                      - hls
-                      - webtorrent
-                required:
-                  - transcodingType
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/SendClientLog'
       responses:
         '204':
           description: successful operation
-        '404':
-          description: video does not exist
 
-  /search/videos:
+  /api/v1/server/logs:
     get:
       tags:
-        - Search
-      summary: Search videos
-      operationId: searchVideos
-      parameters:
-        - name: search
-          in: query
-          required: true
-          allowEmptyValue: false
-          description: >
-            String to search. If the user can make a remote URI search, and the string is an URI then the
-            PeerTube instance will fetch the remote object and add it to its database. Then,
-            you can use the REST API to fetch the complete video information and interact with it.
-          schema:
-            type: string
-        - $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/searchTarget'
-        - $ref: '#/components/parameters/videosSearchSort'
-        - name: startDate
-          in: query
-          description: Get videos that are published after this date
-          schema:
-            type: string
-            format: date-time
-        - name: endDate
-          in: query
-          description: Get videos that are published before this date
-          schema:
-            type: string
-            format: date-time
-        - name: originallyPublishedStartDate
-          in: query
-          description: Get videos that are originally published after this date
-          schema:
-            type: string
-            format: date-time
-        - name: originallyPublishedEndDate
-          in: query
-          description: Get videos that are originally published before this date
-          schema:
-            type: string
-            format: date-time
-        - name: durationMin
-          in: query
-          description: Get videos that have this minimum duration
-          schema:
-            type: integer
-        - name: durationMax
-          in: query
-          description: Get videos that have this maximum duration
-          schema:
-            type: integer
-      callbacks:
-        'searchTarget === search-index':
-          $ref: '#/components/callbacks/searchIndex'
+        - Logs
+      summary: Get instance logs
+      operationId: getInstanceLogs
+      security:
+        - OAuth2:
+          - admin
       responses:
         '200':
           description: successful operation
           content:
             application/json:
               schema:
-                $ref: '#/components/schemas/VideoListResponse'
-        '500':
-          description: search index unavailable
+                type: array
+                items:
+                  type: string
 
-  /search/video-channels:
+  /api/v1/server/audit-logs:
     get:
       tags:
-        - Search
-      summary: Search channels
-      operationId: searchChannels
-      parameters:
-        - name: search
-          in: query
-          required: true
-          description: >
-            String to search. If the user can make a remote URI search, and the string is an URI then the
-            PeerTube instance will fetch the remote object and add it to its database. Then,
-            you can use the REST API to fetch the complete channel information and interact with it.
-          schema:
-            type: string
-        - $ref: '#/components/parameters/start'
-        - $ref: '#/components/parameters/count'
-        - $ref: '#/components/parameters/searchTarget'
-        - $ref: '#/components/parameters/sort'
-      callbacks:
-        'searchTarget === search-index':
-          $ref: '#/components/callbacks/searchIndex'
+        - Logs
+      summary: Get instance audit logs
+      operationId: getInstanceAuditLogs
+      security:
+        - OAuth2:
+          - admin
       responses:
         '200':
           description: successful operation
           content:
             application/json:
               schema:
-                $ref: '#/components/schemas/VideoChannelList'
-        '500':
-          description: search index unavailable
+                type: array
+                items:
+                  type: string
 
-  /search/video-playlists:
+  /api/v1/plugins:
     get:
       tags:
-        - Search
-      summary: Search playlists
-      operationId: searchPlaylists
+        - Plugins
+      summary: List plugins
+      operationId: getPlugins
+      security:
+        - OAuth2:
+          - admin
       parameters:
-        - name: search
+        - name: pluginType
           in: query
-          required: true
-          description: >
-            String to search. If the user can make a remote URI search, and the string is an URI then the
-            PeerTube instance will fetch the remote object and add it to its database. Then,
-            you can use the REST API to fetch the complete playlist information and interact with it.
           schema:
-            type: string
+            type: integer
+        - name: uninstalled
+          in: query
+          schema:
+            type: boolean
         - $ref: '#/components/parameters/start'
         - $ref: '#/components/parameters/count'
-        - $ref: '#/components/parameters/searchTarget'
         - $ref: '#/components/parameters/sort'
-      callbacks:
-        'searchTarget === search-index':
-          $ref: '#/components/callbacks/searchIndex'
       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'
-        '500':
-          description: search index unavailable
-
-  /blocklist/status:
-    get:
-      tags:
-        - Account Blocks
-        - Server Blocks
-      summary: Get block status of accounts/hosts
-      parameters:
-        -
-          name: 'accounts'
-          in: query
-          description: 'Check if these accounts are blocked'
-          example: [ 'goofy@example.com', 'donald@example.com' ]
-          schema:
-            type: array
-            items:
-              type: string
-        -
-          name: 'hosts'
-          in: query
-          description: 'Check if these hosts are blocked'
-          example: [ 'example.com' ]
-          schema:
-            type: array
-            items:
-              type: string
-      responses:
-        '200':
-          description: successful operation
-          content:
-            'application/json':
-              schema:
-                $ref: '#/components/schemas/BlockStatus'
+                $ref: '#/components/schemas/PluginResponse'
 
-  /server/blocklist/accounts:
+  /api/v1/plugins/available:
     get:
       tags:
-        - Account Blocks
-      summary: List account blocks
+        - 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:
-        - Account Blocks
-      summary: Block an account
+        - Plugins
+      summary: Install a plugin
+      operationId: addPlugin
       security:
         - OAuth2:
           - admin
@@ -3929,60 +5298,71 @@ paths:
         content:
           application/json:
             schema:
-              type: object
-              properties:
-                accountName:
-                  type: string
-                  example: chocobozzz@example.org
-                  description: account to block, in the form `username@domain`
-              required:
-                - accountName
+              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:
-        '200':
+        '204':
           description: successful operation
-        '409':
-          description: self-blocking forbidden
+        '400':
+          description: should have either `npmName` or `path` set
 
-  '/server/blocklist/accounts/{accountName}':
-    delete:
+  /api/v1/plugins/update:
+    post:
       tags:
-        - Account Blocks
-      summary: Unblock an account by its handle
+        - Plugins
+      summary: Update a plugin
+      operationId: updatePlugin
       security:
         - OAuth2:
           - admin
-      parameters:
-        - name: accountName
-          in: path
-          required: true
-          description: account to unblock, in the form `username@domain`
-          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:
-        '201':
+        '204':
           description: successful operation
+        '400':
+          description: should have either `npmName` or `path` set
         '404':
-          description: account or account block does not exist
+          description: existing plugin not found
 
-  /server/blocklist/servers:
-    get:
-      tags:
-        - Server Blocks
-      summary: List server blocks
-      security:
-        - OAuth2:
-          - admin
-      parameters:
-        - $ref: '#/components/parameters/start'
-        - $ref: '#/components/parameters/count'
-        - $ref: '#/components/parameters/sort'
-      responses:
-        '200':
-          description: successful operation
+  /api/v1/plugins/uninstall:
     post:
       tags:
-        - Server Blocks
-      summary: Block a server
+        - Plugins
+      summary: Uninstall a plugin
+      operationId: uninstallPlugin
       security:
         - OAuth2:
           - admin
@@ -3992,646 +5372,539 @@ paths:
             schema:
               type: object
               properties:
-                host:
+                npmName:
                   type: string
-                  format: hostname
-                  description: server domain to block
+                  description: name of the plugin/theme in its package.json
+                  example: peertube-plugin-auth-ldap
               required:
-                - host
+                - npmName
       responses:
         '204':
           description: successful operation
-        '409':
-          description: self-blocking forbidden
+        '404':
+          description: existing plugin not found
 
-  '/server/blocklist/servers/{host}':
-    delete:
+  /api/v1/plugins/{npmName}:
+    get:
       tags:
-        - Server Blocks
-      summary: Unblock a server by its domain
+        - Plugins
+      summary: Get a plugin
+      operationId: getPlugin
       security:
         - OAuth2:
           - admin
       parameters:
-        - name: host
-          in: path
-          required: true
-          description: server domain to unblock
-          schema:
-            type: string
-            format: hostname
+        - $ref: '#/components/parameters/npmName'
       responses:
-        '204':
+        '200':
           description: successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/Plugin'
         '404':
-          description: account block does not exist
+          description: plugin not found
 
-  /server/redundancy/{host}:
+  /api/v1/plugins/{npmName}/settings:
     put:
       tags:
-        - Instance Redundancy
-      summary: Update a server redundancy policy
+        - Plugins
+      summary: Set a plugin's settings
       security:
         - OAuth2:
           - admin
       parameters:
-        - name: host
-          in: path
-          required: true
-          description: server domain to mirror
-          schema:
-            type: string
-            format: hostname
+        - $ref: '#/components/parameters/npmName'
       requestBody:
         content:
           application/json:
             schema:
               type: object
               properties:
-                redundancyAllowed:
-                  type: boolean
-                  description: allow mirroring of the host's local videos
-              required:
-                - redundancyAllowed
+                settings:
+                  type: object
+                  additionalProperties: true
       responses:
         '204':
           description: successful operation
         '404':
-          description: server is not already known
+          description: plugin not found
 
-  /server/redundancy/videos:
+  /api/v1/plugins/{npmName}/public-settings:
     get:
       tags:
-        - Video Mirroring
-      summary: List videos being mirrored
-      operationId: getMirroredVideos
+        - Plugins
+      summary: Get a plugin's public settings
+      parameters:
+        - $ref: '#/components/parameters/npmName'
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                type: object
+                additionalProperties: true
+        '404':
+          description: plugin not found
+
+  /api/v1/plugins/{npmName}/registered-settings:
+    get:
+      tags:
+        - Plugins
+      summary: Get a plugin's registered settings
       security:
         - OAuth2:
           - admin
       parameters:
-        - name: target
-          in: query
-          required: true
-          description: direction of the mirror
-          schema:
-            type: string
-            enum:
-              - my-videos
-              - remote-videos
-        - $ref: '#/components/parameters/start'
-        - $ref: '#/components/parameters/count'
-        - $ref: '#/components/parameters/videoRedundanciesSort'
+        - $ref: '#/components/parameters/npmName'
       responses:
         '200':
           description: successful operation
           content:
             application/json:
               schema:
-                type: array
-                items:
-                  $ref: '#/components/schemas/VideoRedundancy'
+                type: object
+                additionalProperties: true
+        '404':
+          description: plugin not found
+
+  /api/v1/metrics/playback:
     post:
+      summary: Create playback metrics
+      description: These metrics are exposed by OpenTelemetry metrics exporter if enabled.
       tags:
-        - Video Mirroring
-      summary: Mirror a video
-      operationId: putMirroredVideo
-      security:
-        - OAuth2:
-          - admin
+        - Stats
       requestBody:
         content:
           application/json:
             schema:
-              type: object
-              properties:
-                videoId:
-                  $ref: '#/components/schemas/Video/properties/id'
-              required:
-                - videoId
+              $ref: '#/components/schemas/PlaybackMetricCreate'
       responses:
         '204':
           description: successful operation
-        '400':
-          description: cannot mirror a local video
-        '404':
-          description: video does not exist
-        '409':
-          description: video is already mirrored
 
-  /server/redundancy/videos/{redundancyId}:
-    delete:
+  /api/v1/runners/registration-tokens/generate:
+    post:
+      summary: Generate registration token
+      description: Generate a new runner registration token
+      security:
+        - OAuth2:
+          - admin
       tags:
-        - Video Mirroring
-      summary: Delete a mirror done on a video
-      operationId: delMirroredVideo
+        - 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:
-        - name: redundancyId
-          in: path
-          required: true
-          description: id of an existing redundancy on a video
-          schema:
-            type: string
+        - $ref: '#/components/parameters/registrationTokenId'
       responses:
         '204':
           description: successful operation
-        '404':
-          description: video redundancy not found
 
-  '/feeds/video-comments.{format}':
+  /api/v1/runners/registration-tokens:
     get:
+      summary: List registration tokens
+      security:
+        - OAuth2:
+          - admin
       tags:
-        - Feeds
-      summary: List comments on videos
-      operationId: getSyndicatedComments
+        - Runner Registration Token
       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/start'
+        - $ref: '#/components/parameters/count'
+        - $ref: '#/components/parameters/registrationTokenSort'
       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/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
+                properties:
+                  total:
+                    type: integer
+                    example: 1
+                  data:
+                    type: array
+                    items:
+                      $ref: '#/components/schemas/RunnerRegistrationToken'
 
-  '/feeds/videos.{format}':
-    get:
+  /api/v1/runners/register:
+    post:
+      summary: Register a new runner
+      description: API used by PeerTube runners
       tags:
-        - 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'
+        - Runners
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: object
+              properties:
+                registrationToken:
+                  type: string
+                name:
+                  type: string
+                description:
+                  type: string
+              required:
+                - registrationToken
+                - name
       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
-        '404':
-          description: video channel or account not found
-        '406':
-          description: accept header unsupported
+                properties:
+                  id:
+                    type: integer
+                    description: Runner id
+                  runnerToken:
+                    type: string
 
-  '/feeds/subscriptions.{format}':
-    get:
+  /api/v1/runners/unregister:
+    post:
+      summary: Unregister a runner
+      description: API used by PeerTube runners
       tags:
-        - Feeds
-        - Account
-      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'
+        - 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
-          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
 
-  /plugins:
+  /api/v1/runners:
     get:
-      tags:
-        - Plugins
-      summary: List plugins
-      operationId: getPlugins
+      summary: List runners
       security:
         - OAuth2:
           - admin
+      tags:
+        - Runners
       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/runnerSort'
       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/Runner'
 
-  /plugins/available:
-    get:
+
+  /api/v1/runners/jobs/request:
+    post:
+      summary: Request a new job
+      description: API used by PeerTube runners
       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'
+        - 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
@@ -4639,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:
@@ -4709,23 +5987,31 @@ components:
       name: sort
       in: query
       required: false
-      description: Sort videos by criteria
       schema:
         type: string
         enum:
-        - name
-        - -duration
-        - -createdAt
-        - -publishedAt
-        - -views
-        - -likes
-        - -trending
-        - -hot
+          - name
+          - -duration
+          - -createdAt
+          - -publishedAt
+          - -views
+          - -likes
+          - -trending
+          - -hot
+          - -best
+        description: >
+          Sort videos by criteria (prefixing with `-` means `DESC` order):
+            * `hot` - Adaptation of Reddit "hot" algorithm taking into account video views, likes, dislikes and comments and publication date
+            * `best` - Same than `hot`, but also takes into account user video history
+            * `trending` - Sort videos by recent views ("recent" is defined by the admin)
+            * `views` - Sort videos using their `views` counter
+            * `publishedAt` - Sort by video publication date (when it became publicly available)
     videosSearchSort:
       name: sort
       in: query
       required: false
-      description: Sort videos by criteria
+      description: >
+        Sort videos by criteria (prefixing with `-` means `DESC` order):
       schema:
         type: string
         enum:
@@ -4816,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
@@ -4831,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
@@ -4884,6 +6209,13 @@ components:
       schema:
         type: string
         example: my_username | my_username@example.com
+    channelSyncId:
+      name: channelSyncId
+      in: path
+      required: true
+      description: Channel Sync id
+      schema:
+        $ref: '#/components/schemas/Abuse/properties/id'
     subscriptionHandle:
       name: subscriptionHandle
       in: path
@@ -5028,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
@@ -5090,6 +6436,7 @@ components:
           - activitypub-refresher
           - video-redundancy
           - video-live-ending
+          - video-channel-import
     followState:
       name: state
       in: query
@@ -5109,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: |
@@ -5121,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:
@@ -5131,7 +6524,7 @@ components:
             moderator: Moderator scope
             user: User scope
   schemas:
-    # Resuable core properties
+    # Reusable core properties
     id:
       type: integer
       minimum: 1
@@ -5209,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:
@@ -5237,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:
@@ -5291,6 +6684,22 @@ components:
       description: 'Admin flags for the user (None = `0`, Bypass video blocklist = `1`)'
       example: 1
 
+    LiveVideoLatencyMode:
+      type: integer
+      enum:
+        - 1
+        - 2
+        - 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:
@@ -5299,7 +6708,23 @@ components:
             - 1
             - 2
             - 3
-          description: 'The video state (Published = `1`, to transcode = `2`, to import = `3`)'
+            - 4
+            - 5
+            - 6
+            - 7
+            - 8
+            - 9
+          description: |
+            The video state:
+            - `1`: Published
+            - `2`: To transcode
+            - `3`: To import
+            - `4`: Waiting for live stream
+            - `5`: Live ended
+            - `6`: To move to an external storage (object storage...)
+            - `7`: Transcoding failed
+            - `8`: Moving to an external storage failed
+            - `9`: To edit using studio edition feature
         label:
           type: string
 
@@ -5409,6 +6834,8 @@ components:
     VideoFile:
       readOnly: true
       properties:
+        id:
+          $ref: '#/components/schemas/id'
         magnetUri:
           type: string
           format: uri
@@ -5971,6 +7398,10 @@ components:
           $ref: '#/components/schemas/VideoConstantString-Language'
         captionPath:
           type: string
+    VideoSource:
+      properties:
+        filename:
+          type: string
     ActorImage:
       properties:
         path:
@@ -6046,13 +7477,68 @@ components:
             description:
               type: string
               description: text or bio displayed on the account's profile
-    UserWatchingVideo:
+    UserViewingVideo:
+      required:
+        - currentTime
       properties:
         currentTime:
           type: integer
           format: seconds
           description: timestamp within the video, in seconds
           example: 5
+        viewEvent:
+          type: string
+          enum:
+            - seek
+          description: >
+            Event since last viewing call:
+             * `seek` - If the user seeked the video
+
+    VideoStatsOverall:
+      properties:
+        averageWatchTime:
+          type: number
+        totalWatchTime:
+          type: number
+        viewersPeak:
+          type: number
+        viewersPeakDate:
+          type: string
+          format: date-time
+        countries:
+          type: array
+          items:
+            type: object
+            properties:
+              isoCode:
+                type: string
+              viewers:
+                type: number
+
+    VideoStatsRetention:
+      properties:
+        data:
+          type: array
+          items:
+            type: object
+            properties:
+              second:
+                type: number
+              retentionPercent:
+                type: number
+
+    VideoStatsTimeserie:
+      properties:
+        data:
+          type: array
+          items:
+            type: object
+            properties:
+              date:
+                type: string
+              value:
+                type: number
+
     ServerConfig:
       properties:
         instance:
@@ -6155,6 +7641,11 @@ components:
                   properties:
                     enabled:
                       type: boolean
+            videoChannelSynchronization:
+              type: object
+              properties:
+                enabled:
+                  type: boolean
         autoBlacklist:
           type: object
           properties:
@@ -6258,6 +7749,96 @@ components:
             enabled:
               type: boolean
 
+    SendClientLog:
+      properties:
+        message:
+          type: string
+        url:
+          type: string
+          description: URL of the current user page
+        level:
+          enum:
+            - error
+            - warn
+        stackTrace:
+          type: string
+          description: Stack trace of the error if there is one
+        userAgent:
+          type: string
+          description: User agent of the web browser that sends the message
+        meta:
+          type: string
+          description: Additional information regarding this log
+      required:
+        - message
+        - url
+        - level
+
+    ServerStats:
+      properties:
+        totalUsers:
+          type: number
+        totalDailyActiveUsers:
+          type: number
+        totalWeeklyActiveUsers:
+          type: number
+        totalMonthlyActiveUsers:
+          type: number
+        totalLocalVideos:
+          type: number
+        totalLocalVideoViews:
+          type: number
+          description: Total video views made on the instance
+        totalLocalVideoComments:
+          type: number
+          description: Total comments made by local users
+        totalLocalVideoFilesSize:
+          type: number
+        totalVideos:
+          type: number
+        totalVideoComments:
+          type: number
+        totalLocalVideoChannels:
+          type: number
+        totalLocalDailyActiveVideoChannels:
+          type: number
+        totalLocalWeeklyActiveVideoChannels:
+          type: number
+        totalLocalMonthlyActiveVideoChannels:
+          type: number
+        totalLocalPlaylists:
+          type: number
+        totalInstanceFollowers:
+          type: number
+        totalInstanceFollowing:
+          type: number
+        videosRedundancy:
+          type: array
+          items:
+            type: object
+            properties:
+                strategy:
+                  type: string
+                totalSize:
+                  type: number
+                totalUsed:
+                  type: number
+                totalVideoFiles:
+                  type: number
+                totalVideos:
+                  type: number
+        totalActivityPubMessagesProcessed:
+          type: number
+        totalActivityPubMessagesSuccesses:
+          type: number
+        totalActivityPubMessagesErrors:
+          type: number
+
+        activityPubMessagesProcessedPerSecond:
+          type: number
+        totalActivityPubMessagesWaiting:
+          type: number
+
     ServerConfigAbout:
       properties:
         instance:
@@ -6429,6 +8010,11 @@ components:
                   properties:
                     enabled:
                       type: boolean
+            video_channel_synchronization:
+              type: object
+              properties:
+                enabled:
+                  type: boolean
         autoBlacklist:
           type: object
           properties:
@@ -6521,6 +8107,7 @@ components:
             - videos-views-stats
             - activitypub-refresher
             - video-redundancy
+            - video-channel-import
         data:
           type: object
           additionalProperties: true
@@ -6676,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:
@@ -6731,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
@@ -6806,8 +8406,6 @@ components:
         - username
         - password
         - email
-        - videoQuota
-        - videoQuotaDaily
         - role
     UpdateUser:
       properties:
@@ -6914,6 +8512,7 @@ components:
       required:
         - video
         - rating
+
     RegisterUser:
       properties:
         username:
@@ -6928,21 +8527,92 @@ components:
           description: email of the user, used for login or service communications
         displayName:
           type: string
-          description: editable name of the user, displayed in its representations
-          minLength: 1
-          maxLength: 120
-        channel:
+          description: editable name of the user, displayed in its representations
+          minLength: 1
+          maxLength: 120
+        channel:
+          type: object
+          description: channel base information used to create the first channel of the user
+          properties:
+            name:
+              $ref: '#/components/schemas/usernameChannel'
+            displayName:
+              type: string
+      required:
+        - username
+        - 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
-          description: channel base information used to create the first channel of the user
+          nullable: true
+          description: If the registration has been accepted, this is a partial user object created by the registration
           properties:
-            name:
-              $ref: '#/components/schemas/usernameChannel'
-            displayName:
-              type: string
-      required:
-        - username
-        - password
-        - email
+            id:
+              $ref: '#/components/schemas/id'
 
     OAuthClient:
       properties:
@@ -7041,9 +8711,19 @@ components:
                   type: integer
                 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
@@ -7054,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:
@@ -7071,6 +8752,63 @@ 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:
+        id:
+          $ref: '#/components/schemas/id'
+        state:
+          type: object
+          properties:
+            id:
+              type: integer
+              example: 2
+            label:
+              type: string
+              example: PROCESSING
+        externalChannelUrl:
+          type: string
+          example: 'https://youtube.com/c/UC_myfancychannel'
+        createdAt:
+          type: string
+          format: date-time
+        lastSyncAt:
+          type: string
+          format: date-time
+          nullable: true
+        channel:
+          $ref: '#/components/schemas/VideoChannel'
+    VideoChannelSyncList:
+      type: object
+      properties:
+        total:
+          type: integer
+          example: 1
+        data:
+          type: array
+          items:
+            allOf:
+              - $ref: '#/components/schemas/VideoChannelSync'
+    VideoChannelSyncCreate:
+      type: object
+      properties:
+        externalChannelUrl:
+          type: string
+          example: https://youtube.com/c/UC_myfancychannel
+        videoChannelId:
+          $ref: '#/components/schemas/id'
     MRSSPeerLink:
       type: object
       xml:
@@ -7260,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:
@@ -7479,26 +9213,384 @@ components:
       properties:
         saveReplay:
           type: boolean
+        replaySettings:
+          $ref: '#/components/schemas/LiveVideoReplaySettings'
         permanentLive:
           description: User can stream multiple times in a permanent live
           type: boolean
+        latencyMode:
+          description: User can select live latency mode if enabled by the instance
+          $ref: '#/components/schemas/LiveVideoLatencyMode'
 
     LiveVideoResponse:
       properties:
         rtmpUrl:
           type: string
+          description: Included in the response if an appropriate token is provided
         rtmpsUrl:
           type: string
+          description: Included in the response if an appropriate token is provided
         streamKey:
           type: string
-          description: RTMP stream key to use to stream into this live video
+          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
+        latencyMode:
+          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:
+        anyOf:
+          -
+            title: cut
+            type: object
+            properties:
+              name:
+                type: string
+                enum:
+                  - 'cut'
+              options:
+                type: object
+                properties:
+                  start:
+                    type: integer
+                  end:
+                    type: integer
+          -
+            title: add-intro
+            type: object
+            properties:
+              name:
+                type: string
+                enum:
+                  - 'add-intro'
+              options:
+                type: object
+                properties:
+                  file:
+                    type: string
+                    format: binary
+          -
+            title: add-outro
+            type: object
+            properties:
+              name:
+                type: string
+                enum:
+                  - 'add-outro'
+              options:
+                type: object
+                properties:
+                  file:
+                    type: string
+                    format: binary
+          -
+            title: add-watermark
+            type: object
+            properties:
+              name:
+                type: string
+                enum:
+                  - 'add-watermark'
+              options:
+                type: object
+                properties:
+                  file:
+                    type: string
+                    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'
+
+    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: