]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blobdiff - support/doc/api/openapi.yaml
Instance homepage support (#4007)
[github/Chocobozzz/PeerTube.git] / support / doc / api / openapi.yaml
index c201b52baf4cd33458470eeffa549e480ac9cc1d..74910c3133eb7df54fe89aa6526bddd08ede8731 100644 (file)
@@ -1,15 +1,15 @@
 openapi: 3.0.0
 info:
   title: PeerTube
-  version: 3.2.0-rc.1
+  version: 3.2.0
   contact:
     name: PeerTube Community
-    url: 'https://joinpeertube.org'
+    url: https://joinpeertube.org
   license:
     name: AGPLv3.0
-    url: 'https://github.com/Chocobozzz/PeerTube/blob/master/LICENSE'
+    url: https://github.com/Chocobozzz/PeerTube/blob/master/LICENSE
   x-logo:
-    url: 'https://joinpeertube.org/img/brand.png'
+    url: https://joinpeertube.org/img/brand.png
     altText: PeerTube Project Homepage
   description: |
     The PeerTube API is built on HTTP(S) and is RESTful. You can use your favorite
@@ -22,13 +22,13 @@ info:
     - [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
-    examples of using with the PeerTube API.
+    examples of using the PeerTube API.
 
     # Authentication
 
     When you sign up for an account on a PeerTube instance, you are given the possibility
-    to generate sessions on it, and authenticate there using a session token. Only __one
-    session token can currently be used at a time__.
+    to generate sessions on it, and authenticate there using an access token. Only __one
+    access token can currently be used at a time__.
 
     ## Roles
 
@@ -38,39 +38,58 @@ info:
     # Errors
 
     The API uses standard HTTP status codes to indicate the success or failure
-    of the API call. The body of the response will be JSON in the following
-    formats.
+    of the API call.
 
     ```
+    HTTP 1.1 404 Not Found
+    Content-Type: application/json
+
     {
-      "error": "Account not found" // error debug message
+      "errorCode": 1
+      "error": "Account not found"
     }
     ```
 
-    Some errors benefit from a more detailed message:
+    We provide error codes for [a growing number of cases](https://github.com/Chocobozzz/PeerTube/blob/develop/shared/models/server/server-error-code.enum.ts),
+    but it is still optional.
+
+    ### Validation errors
+
+    Each parameter is evaluated on its own against a set of rules before the route validator
+    proceeds with potential testing involving parameter combinations. Errors coming from Validation
+    errors appear earlier and benefit from a more detailed error type:
+
     ```
+    HTTP 1.1 400 Bad Request
+    Content-Type: application/json
+
     {
       "errors": {
-        "id": { // where 'id' is the name of the parameter concerned by the error.
-          "value": "a117eb-c6a9-4756-bb09-2a956239f", // value that triggered the error.
-          "msg": "Should have an valid id",  // error debug message
+        "id": {
+          "value": "a117eb-c6a9-4756-bb09-2a956239f",
+          "msg": "Should have a valid id",
           "param": "id",
-          "location": "params" // 'params', 'body', 'header', 'query' or 'cookies'
+          "location": "params"
         }
       }
     }
     ```
 
+    Where `id` is the name of the field concerned by the error, within the route definition.
+    `errors.<field>.location` can be either 'params', 'body', 'header', 'query' or 'cookies', and
+    `errors.<field>.value` reports the value that didn't pass validation whose `errors.<field>.msg`
+    is about.
+
     # Rate limits
 
     We are rate-limiting all endpoints of PeerTube's API. Custom values can be set by administrators:
 
-    | Endpoint                | Calls            | Time frame                |
-    |-------------------------|------------------|---------------------------|
-    | `/*`                    | 50               | 10 seconds                |
-    | `POST /users/token`     | 15               | 5 minutes                 |
-    | `POST /users/register`  | 2<sup>*</sup>    | 5 minutes                 |
-    | `POST /users/ask-send-verify-email` | 3    | 5 minutes                 |
+    | Endpoint (prefix: `/api/v1`) | Calls         | Time frame   |
+    |------------------------------|---------------|--------------|
+    | `/*`                         | 50            | 10 seconds   |
+    | `POST /users/token`          | 15            | 5 minutes    |
+    | `POST /users/register`       | 2<sup>*</sup> | 5 minutes    |
+    | `POST /users/ask-send-verify-email` | 3      | 5 minutes    |
 
     Depending on the endpoint, <sup>*</sup>failed requests are not taken into account. A service
     limit is announced by a `429 Too Many Requests` status code.
@@ -80,13 +99,37 @@ info:
 
     | Header                  | Description                                                |
     |-------------------------|------------------------------------------------------------|
-    | X-RateLimit-Limit       | Number of max requests allowed in the current time period  |
-    | X-RateLimit-Remaining   | Number of remaining requests in the current time period    |
-    | X-RateLimit-Reset       | Timestamp of end of current time period as UNIX timestamp  |
-    | Retry-After             | Seconds to delay after the first `429` is received         |
+    | `X-RateLimit-Limit`     | Number of max requests allowed in the current time period  |
+    | `X-RateLimit-Remaining` | Number of remaining requests in the current time period    |
+    | `X-RateLimit-Reset`     | Timestamp of end of current time period as UNIX timestamp  |
+    | `Retry-After`           | Seconds to delay after the first `429` is received         |
+
+    # CORS
+
+    This API features [Cross-Origin Resource Sharing (CORS)](https://fetch.spec.whatwg.org/),
+    allowing cross-domain communication from the browser for some routes:
+
+    | Endpoint                    |
+    |------------------------- ---|
+    | `/api/*`                    |
+    | `/download/*`               |
+    | `/lazy-static/*`            |
+    | `/live/segments-sha256/*`   |
+    | `/.well-known/webfinger`    |
+
+    In addition, all routes serving ActivityPub are CORS-enabled for all origins.
 externalDocs:
   url: https://docs.joinpeertube.org/api-rest-reference.html
 tags:
+  - name: Register
+    description: |
+      As a visitor, you can use this API to open an account (if registrations are open on
+      that PeerTube instance). As an admin, you should use the dedicated [User creation
+      API](#operation/addUser) instead.
+  - name: Session
+    x-displayName: Login/Logout
+    description: |
+      Sessions deal with access tokens over time. Only __one session token can currently be used at a time__.
   - name: Accounts
     description: >
       Accounts encompass remote accounts discovered across the federation,
@@ -204,12 +247,18 @@ tags:
 
       Administrators can also enable the use of a remote search system, indexing
       videos and channels not could be not federated by the instance.
+  - name: Homepage
+    description: Get and update the custom homepage
   - name: Video Mirroring
     description: |
       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).
 x-tagGroups:
+  - name: Auth
+    tags:
+      - Register
+      - Session
   - name: Accounts
     tags:
       - Accounts
@@ -234,6 +283,9 @@ x-tagGroups:
   - name: Search
     tags:
       - Search
+  - name: Custom pages
+    tags:
+      - Homepage
   - name: Moderation
     tags:
       - Abuses
@@ -255,6 +307,7 @@ paths:
       tags:
         - Accounts
       summary: Get an account
+      operationId: getAccount
       parameters:
         - $ref: '#/components/parameters/name'
       responses:
@@ -266,12 +319,14 @@ paths:
                 $ref: '#/components/schemas/Account'
         '404':
           description: account not found
+
   '/accounts/{name}/videos':
     get:
       tags:
         - Accounts
         - Video
       summary: 'List videos of an account'
+      operationId: getAccountVideos
       parameters:
         - $ref: '#/components/parameters/name'
         - $ref: '#/components/parameters/categoryOneOf'
@@ -327,11 +382,13 @@ paths:
             json = r.json()
 
             print(json)
+
   /accounts:
     get:
       tags:
         - Accounts
       summary: List accounts
+      operationId: getAccounts
       parameters:
         - $ref: '#/components/parameters/start'
         - $ref: '#/components/parameters/count'
@@ -345,11 +402,13 @@ paths:
                 type: array
                 items:
                   $ref: '#/components/schemas/Account'
+
   /config:
     get:
       tags:
         - Config
       summary: Get instance public configuration
+      operationId: getConfig
       responses:
         '200':
           description: successful operation
@@ -360,9 +419,11 @@ paths:
               examples:
                 nightly:
                   externalValue: https://peertube2.cpy.re/api/v1/config
+
   /config/about:
     get:
       summary: Get instance "About" information
+      operationId: getAbout
       tags:
         - Config
       responses:
@@ -375,9 +436,11 @@ paths:
               examples:
                 nightly:
                   externalValue: https://peertube2.cpy.re/api/v1/config/about
+
   /config/custom:
     get:
       summary: Get instance runtime configuration
+      operationId: getCustomConfig
       tags:
         - Config
       security:
@@ -392,6 +455,7 @@ paths:
                 $ref: '#/components/schemas/ServerConfigCustom'
     put:
       summary: Set instance runtime configuration
+      operationId: putCustomConfig
       tags:
         - Config
       security:
@@ -408,6 +472,7 @@ paths:
               - webtorrent and hls are disabled with transcoding enabled - you need at least one enabled
     delete:
       summary: Delete instance runtime configuration
+      operationId: delCustomConfig
       tags:
         - Config
       security:
@@ -416,9 +481,45 @@ paths:
       responses:
         '200':
           description: successful operation
+
+  /custom-pages/homepage/instance:
+    get:
+      summary: Get instance custom homepage
+      tags:
+        - Homepage
+      responses:
+        '404':
+          description: No homepage set
+        '200':
+          description: successful operation
+          content:
+            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/{state}:
     get:
       summary: List instance jobs
+      operationId: getJobs
       security:
         - OAuth2:
           - admin
@@ -458,66 +559,108 @@ paths:
                     maxItems: 100
                     items:
                       $ref: '#/components/schemas/Job'
-  '/server/following/{host}':
+
+  /server/followers:
+    get:
+      tags:
+        - 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
+          content:
+            application/json:
+              schema:
+                type: object
+                properties:
+                  total:
+                    type: integer
+                    example: 1
+                  data:
+                    type: array
+                    items:
+                      $ref: '#/components/schemas/Follow'
+
+  '/server/followers/{nameWithHost}':
     delete:
+      summary: Remove or reject a follower to your server
       security:
         - OAuth2:
           - admin
       tags:
         - Instance Follows
-      summary: Unfollow a server
       parameters:
-        - name: host
+        - name: nameWithHost
           in: path
           required: true
-          description: 'The host to unfollow '
+          description: The remote actor handle to remove from your followers
           schema:
             type: string
-            format: hostname
+            format: email
       responses:
-        '201':
+        '204':
           description: successful operation
-  /server/followers:
-    get:
+        '404':
+          description: follower not found
+
+  '/server/followers/{nameWithHost}/reject':
+    post:
+      summary: Reject a pending follower to your server
+      security:
+        - OAuth2:
+          - admin
       tags:
         - Instance Follows
-      summary: List instance followers
       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:
-                type: array
-                items:
-                  $ref: '#/components/schemas/Follow'
+        '404':
+          description: follower not found
+
+  '/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
+
   /server/following:
     get:
       tags:
         - Instance Follows
       summary: List instances followed by the server
       parameters:
-        - name: state
-          in: query
-          schema:
-            type: string
-            enum:
-              - pending
-              - accepted
-        - name: actorType
-          in: query
-          schema:
-            type: string
-            enum:
-              - Person
-              - Application
-              - Group
-              - Service
-              - Organization
+        - $ref: '#/components/parameters/followState'
+        - $ref: '#/components/parameters/actorType'
         - $ref: '#/components/parameters/start'
         - $ref: '#/components/parameters/count'
         - $ref: '#/components/parameters/sort'
@@ -527,16 +670,22 @@ paths:
           content:
             application/json:
               schema:
-                type: array
-                items:
-                  $ref: '#/components/schemas/Follow'
+                type: object
+                properties:
+                  total:
+                    type: integer
+                    example: 1
+                  data:
+                    type: array
+                    items:
+                      $ref: '#/components/schemas/Follow'
     post:
       security:
         - OAuth2:
           - admin
       tags:
         - Instance Follows
-      summary: Follow a server
+      summary: Follow a list of servers
       responses:
         '204':
           description: successful operation
@@ -554,9 +703,33 @@ paths:
                     type: string
                     format: hostname
                   uniqueItems: true
+
+  '/server/following/{host}':
+    delete:
+      summary: Unfollow a server
+      security:
+        - OAuth2:
+          - admin
+      tags:
+        - Instance Follows
+      parameters:
+        - name: host
+          in: path
+          required: true
+          description: The host to unfollow
+          schema:
+            type: string
+            format: hostname
+      responses:
+        '204':
+          description: successful operation
+        '404':
+          description: host not found
+
   /users:
     post:
       summary: Create a user
+      operationId: addUser
       security:
         - OAuth2:
           - admin
@@ -571,18 +744,18 @@ paths:
                 $ref: '#/components/schemas/AddUserResponse'
           links:
             # GET /users/{id}
-            GetUserId:
-              operationId: getUserId
+            GetUser:
+              operationId: getUser
               parameters:
                 id: '$response.body#/user/id'
             # PUT /users/{id}
-            PutUserId:
-              operationId: putUserId
+            PutUser:
+              operationId: putUser
               parameters:
                 id: '$response.body#/user/id'
             # DELETE /users/{id}
-            DelUserId:
-              operationId: delUserId
+            DelUser:
+              operationId: delUser
               parameters:
                 id: '$response.body#/user/id'
         '403':
@@ -598,6 +771,7 @@ paths:
         required: true
     get:
       summary: List users
+      operationId: getUsers
       security:
         - OAuth2:
           - admin
@@ -618,6 +792,7 @@ paths:
                 type: array
                 items:
                   $ref: '#/components/schemas/User'
+
   '/users/{id}':
     parameters:
       - $ref: '#/components/parameters/id'
@@ -628,7 +803,7 @@ paths:
           - admin
       tags:
         - Users
-      operationId: delUserId
+      operationId: delUser
       responses:
         '204':
           description: successful operation
@@ -638,7 +813,7 @@ paths:
         - OAuth2: []
       tags:
         - Users
-      operationId: getUserId
+      operationId: getUser
       parameters:
         - name: withStats
           in: query
@@ -663,7 +838,7 @@ paths:
         - OAuth2: []
       tags:
         - Users
-      operationId: putUserId
+      operationId: putUser
       responses:
         '204':
           description: successful operation
@@ -673,11 +848,120 @@ paths:
             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
+      tags:
+        - Session
+      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.
+      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'
+      responses:
+        '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
+      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
+      tags:
+        - Session
+      security:
+        - OAuth2: []
+      responses:
+        '200':
+          description: successful operation
+
   /users/register:
     post:
       summary: Register a user
+      operationId: registerUser
       tags:
         - Users
+        - Register
       responses:
         '204':
           description: successful operation
@@ -687,9 +971,55 @@ paths:
             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'
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: object
+              properties:
+                verificationString:
+                  type: string
+                  format: url
+                isPendingEmail:
+                  type: boolean
+              required:
+                - verificationString
+      responses:
+        '204':
+          description: successful operation
+        '403':
+          description: invalid verification string
+        '404':
+          description: user not found
+
+  /users/ask-send-verify-email:
+    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
       security:
         - OAuth2:
           - user
@@ -706,6 +1036,7 @@ paths:
                   $ref: '#/components/schemas/User'
     put:
       summary: Update my user information
+      operationId: putUserInfo
       security:
         - OAuth2:
           - user
@@ -720,6 +1051,7 @@ paths:
             schema:
               $ref: '#/components/schemas/UpdateMe'
         required: true
+
   /users/me/videos/imports:
     get:
       summary: Get video imports of my user
@@ -740,6 +1072,7 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/VideoImportsList'
+
   /users/me/video-quota-used:
     get:
       summary: Get my user used quota
@@ -764,6 +1097,7 @@ paths:
                     type: number
                     description: The user video quota used today in bytes
                     example: 1681014151
+
   '/users/me/videos/{videoId}/rating':
     get:
       summary: Get rate of my user for a video
@@ -786,6 +1120,7 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/GetMeVideoRating'
+
   /users/me/videos:
     get:
       summary: Get videos of my user
@@ -806,6 +1141,7 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/VideoListResponse'
+
   /users/me/subscriptions:
     get:
       summary: Get my user subscriptions
@@ -851,6 +1187,7 @@ paths:
       responses:
         '200':
           description: successful operation
+
   /users/me/subscriptions/exist:
     get:
       summary: Get if subscriptions exist for my user
@@ -868,6 +1205,7 @@ paths:
             application/json:
               schema:
                 type: object
+
   /users/me/subscriptions/videos:
     get:
       summary: List videos of subscriptions of my user
@@ -897,6 +1235,7 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/VideoListResponse'
+
   '/users/me/subscriptions/{subscriptionHandle}':
     get:
       summary: Get subscription of my user
@@ -926,6 +1265,7 @@ paths:
       responses:
         '200':
           description: successful operation
+
   /users/me/notifications:
     get:
       summary: List my notifications
@@ -949,6 +1289,7 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/NotificationListResponse'
+
   /users/me/notifications/read:
     post:
       summary: Mark notifications as read by their id
@@ -972,6 +1313,7 @@ paths:
       responses:
         '204':
           description: successful operation
+
   /users/me/notifications/read-all:
     post:
       summary: Mark all my notification as read
@@ -982,6 +1324,7 @@ paths:
       responses:
         '204':
           description: successful operation
+
   /users/me/notification-settings:
     put:
       summary: Update my notification settings
@@ -1022,6 +1365,7 @@ paths:
       responses:
         '204':
           description: successful operation
+
   /users/me/history/videos:
     get:
       summary: List watched videos history
@@ -1040,6 +1384,7 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/VideoListResponse'
+
   /users/me/history/videos/remove:
     post:
       summary: Clear video history
@@ -1060,6 +1405,7 @@ paths:
       responses:
         '204':
           description: successful operation
+
   /users/me/avatar/pick:
     post:
       summary: Update my user avatar
@@ -1098,6 +1444,7 @@ paths:
             encoding:
               avatarfile:
                 contentType: image/png, image/jpeg
+
   /users/me/avatar:
     delete:
       summary: Delete my avatar
@@ -1119,6 +1466,7 @@ paths:
       responses:
         '200':
           description: successful operation
+
   '/videos/ownership/{id}/accept':
     post:
       summary: Accept ownership change request
@@ -1135,6 +1483,7 @@ paths:
           description: cannot terminate an ownership change of another user
         '404':
           description: video owneship change not found
+
   '/videos/ownership/{id}/refuse':
     post:
       summary: Refuse ownership change request
@@ -1151,6 +1500,7 @@ paths:
           description: cannot terminate an ownership change of another user
         '404':
           description: video owneship change not found
+
   '/videos/{id}/give-ownership':
     post:
       summary: Request ownership change
@@ -1178,9 +1528,11 @@ paths:
           description: changing video ownership to a remote account is not supported yet
         '404':
           description: video not found
+
   /videos:
     get:
       summary: List videos
+      operationId: getVideos
       tags:
         - Video
       parameters:
@@ -1203,6 +1555,7 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/VideoListResponse'
+
   /videos/categories:
     get:
       summary: List available video categories
@@ -1221,6 +1574,7 @@ paths:
               examples:
                 nightly:
                   externalValue: https://peertube2.cpy.re/api/v1/videos/categories
+
   /videos/licences:
     get:
       summary: List available video licences
@@ -1239,6 +1593,7 @@ paths:
               examples:
                 nightly:
                   externalValue: https://peertube2.cpy.re/api/v1/videos/licences
+
   /videos/languages:
     get:
       summary: List available video languages
@@ -1257,6 +1612,7 @@ paths:
               examples:
                 nightly:
                   externalValue: https://peertube2.cpy.re/api/v1/videos/languages
+
   /videos/privacies:
     get:
       summary: List available video privacy policies
@@ -1275,9 +1631,11 @@ paths:
               examples:
                 nightly:
                   externalValue: https://peertube2.cpy.re/api/v1/videos/privacies
+
   '/videos/{id}':
     put:
       summary: Update a video
+      operationId: putVideo
       security:
         - OAuth2: []
       tags:
@@ -1317,7 +1675,7 @@ paths:
                   type: string
                 support:
                   description: A text tell the audience how to support the video creator
-                  example: Please support my work on <insert crowdfunding plateform>! <3
+                  example: Please support our work on https://soutenir.framasoft.org/en/ <3
                   type: string
                 nsfw:
                   description: Whether or not this video contains sensitive content
@@ -1352,6 +1710,7 @@ paths:
                 contentType: image/jpeg
     get:
       summary: Get a video
+      operationId: getVideo
       tags:
         - Video
       parameters:
@@ -1365,6 +1724,7 @@ paths:
                 $ref: '#/components/schemas/VideoDetails'
     delete:
       summary: Delete a video
+      operationId: delVideo
       security:
         - OAuth2: []
       tags:
@@ -1374,9 +1734,11 @@ paths:
       responses:
         '204':
           description: successful operation
+
   '/videos/{id}/description':
     get:
       summary: Get complete video description
+      operationId: getVideoDesc
       tags:
         - Video
       parameters:
@@ -1393,6 +1755,7 @@ paths:
                 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)**
+
   '/videos/{id}/views':
     post:
       summary: Add a view to a video
@@ -1403,6 +1766,7 @@ paths:
       responses:
         '204':
           description: successful operation
+
   '/videos/{id}/watching':
     put:
       summary: Set watching progress of a video
@@ -1421,6 +1785,7 @@ paths:
       responses:
         '204':
           description: successful operation
+
   /videos/upload:
     post:
       summary: Upload a video
@@ -1477,26 +1842,27 @@ paths:
             FILE_PATH="<your_file_path>"
             CHANNEL_ID="<your_channel_id>"
             NAME="<video_name>"
+            API="https://peertube2.cpy.re/api/v1"
 
-            API_PATH="https://peertube2.cpy.re/api/v1"
             ## AUTH
-            client_id=$(curl -s "$API_PATH/oauth-clients/local" | jq -r ".client_id")
-            client_secret=$(curl -s "$API_PATH/oauth-clients/local" | jq -r ".client_secret")
-            token=$(curl -s "$API_PATH/users/token" \
+            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 response_type=code \
               --data username="$USERNAME" \
               --data password="$PASSWORD" \
               | jq -r ".access_token")
+
             ## VIDEO UPLOAD
-            curl -s "$API_PATH/videos/upload" \
+            curl -s "$API/videos/upload" \
               -H "Authorization: Bearer $token" \
               --max-time 600 \
               --form videofile=@"$FILE_PATH" \
               --form channelId=$CHANNEL_ID \
               --form name="$NAME"
+
   /videos/upload-resumable:
     post:
       summary: Initialize the resumable upload of a video
@@ -1658,6 +2024,7 @@ paths:
               schema:
                 type: number
                 example: 0
+
   /videos/imports:
     post:
       summary: Import a video
@@ -1697,7 +2064,7 @@ paths:
   /videos/live:
     post:
       summary: Create a live
-      operationId: createLive
+      operationId: addLive
       security:
         - OAuth2: []
       tags:
@@ -1747,7 +2114,7 @@ paths:
                   type: string
                 support:
                   description: A text tell the audience how to support the creator
-                  example: Please support my work on <insert crowdfunding plateform>! <3
+                  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
@@ -1945,7 +2312,6 @@ paths:
                     type: array
                     items:
                       $ref: '#/components/schemas/Abuse'
-
     post:
       summary: Report an abuse
       security:
@@ -1975,10 +2341,12 @@ paths:
                         - $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:
@@ -1997,10 +2365,21 @@ paths:
               required:
                 - reason
       responses:
-        '204':
+        '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
+
   '/abuses/{abuseId}':
     put:
       summary: Update an abuse
@@ -2045,6 +2424,7 @@ paths:
           description: successful operation
         '404':
           description: block not found
+
   '/abuses/{abuseId}/messages':
     get:
       summary: List messages of an abuse
@@ -2060,10 +2440,15 @@ paths:
           content:
             application/json:
               schema:
-                type: array
-                items:
-                  $ref: '#/components/schemas/AbuseMessage'
-
+                type: object
+                properties:
+                  total:
+                    type: integer
+                    example: 1
+                  data:
+                    type: array
+                    items:
+                      $ref: '#/components/schemas/AbuseMessage'
     post:
       summary: Add message to an abuse
       security:
@@ -2091,6 +2476,7 @@ paths:
           description: successful operation
         '400':
           description: incorrect request parameters
+
   '/abuses/{abuseId}/messages/{abuseMessageId}':
     delete:
       summary: Delete an abuse message
@@ -2108,6 +2494,7 @@ paths:
   '/videos/{id}/blacklist':
     post:
       summary: Block a video
+      operationId: addVideoBlock
       security:
         - OAuth2:
           - admin
@@ -2121,6 +2508,7 @@ paths:
           description: successful operation
     delete:
       summary: Unblock a video by its id
+      operationId: delVideoBlock
       security:
         - OAuth2:
           - admin
@@ -2134,11 +2522,13 @@ paths:
           description: successful operation
         '404':
           description: block not found
+
   /videos/blacklist:
     get:
       tags:
         - Video Blocks
       summary: List video blocks
+      operationId: getVideoBlocks
       security:
         - OAuth2:
           - admin
@@ -2180,9 +2570,11 @@ paths:
                     type: array
                     items:
                       $ref: '#/components/schemas/VideoBlacklist'
+
   /videos/{id}/captions:
     get:
       summary: List captions of a video
+      operationId: getVideoCaptions
       tags:
         - Video Captions
       parameters:
@@ -2202,9 +2594,11 @@ paths:
                     type: array
                     items:
                       $ref: '#/components/schemas/VideoCaption'
+
   /videos/{id}/captions/{captionLanguage}:
     put:
       summary: Add or replace a video caption
+      operationId: addVideoCaption
       security:
         - OAuth2:
           - user
@@ -2233,6 +2627,7 @@ paths:
           description: video or language not found
     delete:
       summary: Delete a video caption
+      operationId: delVideoCaption
       security:
         - OAuth2:
           - user
@@ -2246,9 +2641,11 @@ paths:
           description: successful operation
         '404':
           description: video or language or caption for that language not found
+
   /video-channels:
     get:
       summary: List video channels
+      operationId: getVideoChannels
       tags:
         - Video Channels
       parameters:
@@ -2264,6 +2661,7 @@ paths:
                 $ref: '#/components/schemas/VideoChannelList'
     post:
       summary: Create a video channel
+      operationId: addVideoChannel
       security:
         - OAuth2: []
       tags:
@@ -2271,14 +2669,26 @@ paths:
       responses:
         '204':
           description: successful operation
+          content:
+            application/json:
+              schema:
+                type: object
+                properties:
+                  videoChannel:
+                    type: object
+                    properties:
+                      id:
+                        $ref: '#/components/schemas/VideoChannel/properties/id'
       requestBody:
         content:
           application/json:
             schema:
               $ref: '#/components/schemas/VideoChannelCreate'
+
   '/video-channels/{channelHandle}':
     get:
       summary: Get a video channel
+      operationId: getVideoChannel
       tags:
         - Video Channels
       parameters:
@@ -2292,6 +2702,7 @@ paths:
                 $ref: '#/components/schemas/VideoChannel'
     put:
       summary: Update a video channel
+      operationId: putVideoChannel
       security:
         - OAuth2: []
       tags:
@@ -2308,6 +2719,7 @@ paths:
               $ref: '#/components/schemas/VideoChannelUpdate'
     delete:
       summary: Delete a video channel
+      operationId: delVideoChannel
       security:
         - OAuth2: []
       tags:
@@ -2317,9 +2729,11 @@ paths:
       responses:
         '204':
           description: successful operation
+
   '/video-channels/{channelHandle}/videos':
     get:
       summary: List videos of a video channel
+      operationId: getVideoChannelVideos
       tags:
         - Video
         - Video Channels
@@ -2344,6 +2758,7 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/VideoListResponse'
+
   '/video-channels/{channelHandle}/avatar/pick':
     post:
       summary: Update channel avatar
@@ -2384,6 +2799,7 @@ paths:
             encoding:
               avatarfile:
                 contentType: image/png, image/jpeg
+
   '/video-channels/{channelHandle}/avatar':
     delete:
       summary: Delete channel avatar
@@ -2397,7 +2813,6 @@ paths:
         '204':
           description: successful operation
 
-
   '/video-channels/{channelHandle}/banner/pick':
     post:
       summary: Update channel banner
@@ -2438,6 +2853,7 @@ paths:
             encoding:
               bannerfile:
                 contentType: image/png, image/jpeg
+
   '/video-channels/{channelHandle}/banner':
     delete:
       summary: Delete channel banner
@@ -2498,7 +2914,7 @@ paths:
     post:
       summary: Create a video playlist
       description: If the video playlist is set as public, `videoChannelId` is mandatory.
-      operationId: createPlaylist
+      operationId: addPlaylist
       security:
         - OAuth2: []
       tags:
@@ -2550,13 +2966,13 @@ paths:
               thumbnailfile:
                 contentType: image/jpeg
 
-  /video-playlists/{id}:
+  /video-playlists/{playlistId}:
     get:
       summary: Get a video playlist
       tags:
         - Video Playlists
       parameters:
-        - $ref: '#/components/parameters/idOrUUID'
+        - $ref: '#/components/parameters/playlistId'
       responses:
         '200':
           description: successful operation
@@ -2575,7 +2991,7 @@ paths:
         '204':
           description: successful operation
       parameters:
-        - $ref: '#/components/parameters/idOrUUID'
+        - $ref: '#/components/parameters/playlistId'
       requestBody:
         content:
           multipart/form-data:
@@ -2610,19 +3026,20 @@ paths:
       tags:
         - Video Playlists
       parameters:
-        - $ref: '#/components/parameters/idOrUUID'
+        - $ref: '#/components/parameters/playlistId'
       responses:
         '204':
           description: successful operation
 
-  /video-playlists/{id}/videos:
+  /video-playlists/{playlistId}/videos:
     get:
       summary: 'List videos of a playlist'
+      operationId: getVideoPlaylistVideos
       tags:
         - Videos
         - Video Playlists
       parameters:
-        - $ref: '#/components/parameters/idOrUUID'
+        - $ref: '#/components/parameters/playlistId'
       responses:
         '200':
           description: successful operation
@@ -2631,14 +3048,15 @@ paths:
               schema:
                 $ref: '#/components/schemas/VideoListResponse'
     post:
-      summary: 'Add a video in a playlist'
+      summary: Add a video in a playlist
+      operationId: addVideoPlaylistVideo
       security:
         - OAuth2: []
       tags:
         - Videos
         - Video Playlists
       parameters:
-        - $ref: '#/components/parameters/idOrUUID'
+        - $ref: '#/components/parameters/playlistId'
       responses:
         '200':
           description: successful operation
@@ -2652,6 +3070,7 @@ paths:
                     properties:
                       id:
                         type: integer
+                        example: 2
       requestBody:
         content:
           application/json:
@@ -2659,27 +3078,31 @@ paths:
               type: object
               properties:
                 videoId:
-                  allOf:
+                  oneOf:
+                    - $ref: '#/components/schemas/Video/properties/uuid'
                     - $ref: '#/components/schemas/Video/properties/id'
                   description: Video to add in the playlist
                 startTimestamp:
                   type: integer
-                  description: Start the video at this specific timestamp (in seconds)
+                  format: seconds
+                  description: Start the video at this specific timestamp
                 stopTimestamp:
                   type: integer
-                  description: Stop the video at this specific timestamp (in seconds)
+                  format: seconds
+                  description: Stop the video at this specific timestamp
               required:
                 - videoId
 
-  /video-playlists/{id}/videos/reorder:
+  /video-playlists/{playlistId}/videos/reorder:
     post:
       summary: 'Reorder a playlist'
+      operationId: reorderVideoPlaylist
       security:
         - OAuth2: []
       tags:
         - Video Playlists
       parameters:
-        - $ref: '#/components/parameters/idOrUUID'
+        - $ref: '#/components/parameters/playlistId'
       responses:
         '204':
           description: successful operation
@@ -2705,15 +3128,16 @@ paths:
                 - startPosition
                 - insertAfterPosition
 
-  /video-playlists/{id}/videos/{playlistElementId}:
+  /video-playlists/{playlistId}/videos/{playlistElementId}:
     put:
-      summary: 'Update a playlist element'
+      summary: Update a playlist element
+      operationId: putVideoPlaylistVideo
       security:
         - OAuth2: []
       tags:
         - Video Playlists
       parameters:
-        - $ref: '#/components/parameters/idOrUUID'
+        - $ref: '#/components/parameters/playlistId'
         - $ref: '#/components/parameters/playlistElementId'
       responses:
         '204':
@@ -2726,18 +3150,21 @@ paths:
               properties:
                 startTimestamp:
                   type: integer
-                  description: 'Start the video at this specific timestamp (in seconds)'
+                  format: seconds
+                  description: Start the video at this specific timestamp
                 stopTimestamp:
                   type: integer
-                  description: 'Stop the video at this specific timestamp (in seconds)'
+                  format: seconds
+                  description: Stop the video at this specific timestamp
     delete:
-      summary: 'Delete an element from a playlist'
+      summary: Delete an element from a playlist
+      operationId: delVideoPlaylistVideo
       security:
         - OAuth2: []
       tags:
         - Video Playlists
       parameters:
-        - $ref: '#/components/parameters/idOrUUID'
+        - $ref: '#/components/parameters/playlistId'
         - $ref: '#/components/parameters/playlistElementId'
       responses:
         '204':
@@ -2745,7 +3172,7 @@ paths:
 
   '/users/me/video-playlists/videos-exist':
     get:
-      summary: 'Check video exists in my playlists'
+      summary: Check video exists in my playlists
       security:
         - OAuth2: []
       tags:
@@ -2778,8 +3205,10 @@ paths:
                           type: integer
                         startTimestamp:
                           type: integer
+                          format: seconds
                         stopTimestamp:
                           type: integer
+                          format: seconds
 
   '/accounts/{name}/video-channels':
     get:
@@ -2804,6 +3233,7 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/VideoChannelList'
+
   '/accounts/{name}/ratings':
     get:
       summary: List ratings of an account
@@ -2834,6 +3264,7 @@ paths:
                 type: array
                 items:
                   $ref: '#/components/schemas/VideoRating'
+
   '/videos/{id}/comment-threads':
     get:
       summary: List threads of a video
@@ -2897,6 +3328,7 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/VideoCommentThreadTree'
+
   '/videos/{id}/comments/{commentId}':
     post:
       summary: Reply to a thread of a video
@@ -2929,7 +3361,6 @@ paths:
                   maxLength: 10000
               required:
                 - text
-
     delete:
       summary: Delete a comment or a reply
       security:
@@ -2948,6 +3379,7 @@ paths:
           description: comment or video does not exist
         '409':
           description: comment is already deleted
+
   '/videos/{id}/rate':
     put:
       summary: Like/dislike a video
@@ -2957,16 +3389,31 @@ paths:
         - Video Rates
       parameters:
         - $ref: '#/components/parameters/idOrUUID'
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: object
+              properties:
+                rating:
+                  type: string
+                  enum:
+                    - like
+                    - dislike
+              required:
+                - rating
       responses:
         '204':
           description: successful operation
         '404':
           description: video does not exist
+
   /search/videos:
     get:
       tags:
         - Search
       summary: Search videos
+      operationId: searchVideos
       parameters:
         - name: search
           in: query
@@ -3037,11 +3484,13 @@ paths:
                 $ref: '#/components/schemas/VideoListResponse'
         '500':
           description: search index unavailable
+
   /search/video-channels:
     get:
       tags:
         - Search
       summary: Search channels
+      operationId: searchChannels
       parameters:
         - name: search
           in: query
@@ -3068,7 +3517,8 @@ paths:
                 $ref: '#/components/schemas/VideoChannelList'
         '500':
           description: search index unavailable
-  /blocklist/accounts:
+
+  /server/blocklist/accounts:
     get:
       tags:
         - Account Blocks
@@ -3107,7 +3557,8 @@ paths:
           description: successful operation
         '409':
           description: self-blocking forbidden
-  '/blocklist/accounts/{accountName}':
+
+  '/server/blocklist/accounts/{accountName}':
     delete:
       tags:
         - Account Blocks
@@ -3127,7 +3578,8 @@ paths:
           description: successful operation
         '404':
           description: account or account block does not exist
-  /blocklist/servers:
+
+  /server/blocklist/servers:
     get:
       tags:
         - Server Blocks
@@ -3162,11 +3614,12 @@ paths:
               required:
                 - host
       responses:
-        '200':
+        '204':
           description: successful operation
         '409':
           description: self-blocking forbidden
-  '/blocklist/servers/{host}':
+
+  '/server/blocklist/servers/{host}':
     delete:
       tags:
         - Server Blocks
@@ -3183,11 +3636,12 @@ paths:
             type: string
             format: hostname
       responses:
-        '201':
+        '204':
           description: successful operation
         '404':
           description: account block does not exist
-  /redundancy/{host}:
+
+  /server/redundancy/{host}:
     put:
       tags:
         - Instance Redundancy
@@ -3219,11 +3673,13 @@ paths:
           description: successful operation
         '404':
           description: server is not already known
-  /redundancy/videos:
+
+  /server/redundancy/videos:
     get:
       tags:
         - Video Mirroring
       summary: List videos being mirrored
+      operationId: getMirroredVideos
       security:
         - OAuth2:
           - admin
@@ -3253,6 +3709,7 @@ paths:
       tags:
         - Video Mirroring
       summary: Mirror a video
+      operationId: putMirroredVideo
       security:
         - OAuth2:
           - admin
@@ -3275,11 +3732,13 @@ paths:
           description: video does not exist
         '409':
           description: video is already mirrored
-  /redundancy/videos/{redundancyId}:
+
+  /server/redundancy/videos/{redundancyId}:
     delete:
       tags:
         - Video Mirroring
       summary: Delete a mirror done on a video
+      operationId: delMirroredVideo
       security:
         - OAuth2:
           - admin
@@ -3295,11 +3754,13 @@ paths:
           description: successful operation
         '404':
           description: video redundancy not found
+
   '/feeds/video-comments.{format}':
     get:
       tags:
         - Feeds
       summary: List comments on videos
+      operationId: getSyndicatedComments
       parameters:
         - name: format
           in: path
@@ -3388,11 +3849,13 @@ paths:
           description: video, video channel or account not found
         '406':
           description: accept header unsupported
+
   '/feeds/videos.{format}':
     get:
       tags:
         - Feeds
       summary: List videos
+      operationId: getSyndicatedVideos
       parameters:
         - name: format
           in: path
@@ -3474,12 +3937,14 @@ paths:
           description: video channel or account not found
         '406':
           description: accept header unsupported
+
   '/feeds/subscriptions.{format}':
     get:
       tags:
         - Feeds
         - Account
       summary: List videos of subscriptions tied to a token
+      operationId: getSyndicatedSubscriptionVideos
       parameters:
         - name: format
           in: path
@@ -3536,11 +4001,13 @@ paths:
                 type: object
         '406':
           description: accept header unsupported
+
   /plugins:
     get:
       tags:
         - Plugins
       summary: List plugins
+      operationId: getPlugins
       security:
         - OAuth2:
           - admin
@@ -3563,11 +4030,13 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/PluginResponse'
+
   /plugins/available:
     get:
       tags:
         - Plugins
       summary: List available plugins
+      operationId: getAvailablePlugins
       security:
         - OAuth2:
           - admin
@@ -3596,11 +4065,13 @@ paths:
                 $ref: '#/components/schemas/PluginResponse'
         '503':
           description: plugin index unavailable
+
   /plugins/install:
     post:
       tags:
         - Plugins
       summary: Install a plugin
+      operationId: addPlugin
       security:
         - OAuth2:
           - admin
@@ -3629,11 +4100,13 @@ paths:
           description: successful operation
         '400':
           description: should have either `npmName` or `path` set
+
   /plugins/update:
     post:
       tags:
         - Plugins
       summary: Update a plugin
+      operationId: updatePlugin
       security:
         - OAuth2:
           - admin
@@ -3664,11 +4137,13 @@ paths:
           description: should have either `npmName` or `path` set
         '404':
           description: existing plugin not found
+
   /plugins/uninstall:
     post:
       tags:
         - Plugins
       summary: Uninstall a plugin
+      operationId: uninstallPlugin
       security:
         - OAuth2:
           - admin
@@ -3689,11 +4164,13 @@ paths:
           description: successful operation
         '404':
           description: existing plugin not found
+
   /plugins/{npmName}:
     get:
       tags:
         - Plugins
       summary: Get a plugin
+      operationId: getPlugin
       security:
         - OAuth2:
           - admin
@@ -3708,6 +4185,7 @@ paths:
                 $ref: '#/components/schemas/Plugin'
         '404':
           description: plugin not found
+
   /plugins/{npmName}/settings:
     put:
       tags:
@@ -3732,6 +4210,7 @@ paths:
           description: successful operation
         '404':
           description: plugin not found
+
   /plugins/{npmName}/public-settings:
     get:
       tags:
@@ -3749,6 +4228,7 @@ paths:
                 additionalProperties: true
         '404':
           description: plugin not found
+
   /plugins/{npmName}/registered-settings:
     get:
       tags:
@@ -3769,6 +4249,7 @@ paths:
                 additionalProperties: true
         '404':
           description: plugin not found
+
 servers:
   - url: 'https://peertube2.cpy.re/api/v1'
     description: Live Test Server (live data - latest nightly version)
@@ -3957,6 +4438,13 @@ components:
         oneOf:
           - $ref: '#/components/schemas/id'
           - $ref: '#/components/schemas/UUIDv4'
+    playlistId:
+      name: playlistId
+      in: path
+      required: true
+      description: Playlist id
+      schema:
+        $ref: '#/components/schemas/VideoPlaylist/properties/id'
     playlistElementId:
       name: playlistElementId
       in: path
@@ -4007,7 +4495,7 @@ components:
       required: true
       description: The thread id (root comment id)
       schema:
-        $ref: '#/components/schemas/VideoCommentThreadTree/properties/comment/properties/id'
+        type: integer
     commentId:
       name: commentId
       in: path
@@ -4161,22 +4649,42 @@ components:
           - activitypub-refresher
           - video-redundancy
           - video-live-ending
+    followState:
+      name: state
+      in: query
+      schema:
+        type: string
+        enum:
+          - pending
+          - accepted
+    actorType:
+      name: actorType
+      in: query
+      schema:
+        type: string
+        enum:
+          - Person
+          - Application
+          - Group
+          - Service
+          - Organization
   securitySchemes:
     OAuth2:
       description: |
         Authenticating via OAuth requires the following steps:
         - Have an activated account
-        - [Generate](https://docs.joinpeertube.org/api-rest-getting-started) a
-        Bearer Token for that account at `/api/v1/users/token`
-        - Make authenticated requests, putting *Authorization: Bearer <token\>*
+        - [Generate] an access token for that account at `/api/v1/users/token`.
+        - Make requests with the *Authorization: Bearer <token\>* header
         - Profit, depending on the role assigned to the account
 
-        Note that the __access token is valid for 1 day__ and, and is given
+        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
       type: oauth2
       flows:
         password:
-          tokenUrl: 'https://peertube.example.com/api/v1/users/token'
+          tokenUrl: /api/v1/users/token
           scopes:
             admin: Admin scope
             moderator: Moderator scope
@@ -4198,14 +4706,16 @@ components:
       type: string
       description: immutable name of the user, used to find or mention its actor
       example: chocobozzz
-      pattern: '/^[a-z0-9._]{1,50}$/'
+      pattern: '/^[a-z0-9._]+$/'
       minLength: 1
       maxLength: 50
     usernameChannel:
       type: string
       description: immutable name of the channel, used to interact with its actor
-      example: The Capybara Channel
-      pattern: '/^[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\\-_.:]+$/'
+      example: framasoft_videos
+      pattern: '/^[a-zA-Z0-9\\-_.:]+$/'
+      minLength: 1
+      maxLength: 50
     password:
       type: string
       format: password
@@ -4420,8 +4930,10 @@ components:
           type: integer
         startTimestamp:
           type: integer
+          format: seconds
         stopTimestamp:
           type: integer
+          format: seconds
         video:
           nullable: true
           allOf:
@@ -4570,6 +5082,7 @@ components:
         duration:
           type: integer
           example: 1419
+          format: seconds
           description: duration of the video in seconds
         isLocal:
           type: boolean
@@ -4638,7 +5151,7 @@ components:
             support:
               type: string
               description: A text tell the audience how to support the video creator
-              example: Please support my work on <insert crowdfunding plateform>! <3
+              example: Please support our work on https://soutenir.framasoft.org/en/ <3
               minLength: 3
               maxLength: 1000
             channel:
@@ -5064,6 +5577,7 @@ components:
       properties:
         currentTime:
           type: integer
+          format: seconds
           description: timestamp within the video, in seconds
           example: 5
     ServerConfig:
@@ -5265,6 +5779,12 @@ components:
                     indexUrl:
                       type: string
                       format: url
+        homepage:
+          type: object
+          properties:
+            enabled:
+              type: boolean
+
     ServerConfigAbout:
       properties:
         instance:
@@ -5455,6 +5975,12 @@ components:
                   type: boolean
                 manualApproval:
                   type: boolean
+
+    CustomHomepage:
+      properties:
+        content:
+          type: string
+
     Follow:
       properties:
         id:
@@ -5578,7 +6104,7 @@ components:
           type: boolean
         support:
           description: A text tell the audience how to support the video creator
-          example: Please support my work on <insert crowdfunding plateform>! <3
+          example: Please support our work on https://soutenir.framasoft.org/en/ <3
           type: string
         nsfw:
           description: Whether or not this video contains sensitive content
@@ -5760,7 +6286,7 @@ components:
             # optionally present fields: they require WITH_STATS scope
             videosCount:
               type: integer
-              description: Count of videos published 
+              description: Count of videos published
             abusesCount:
               type: integer
               description: Count of reports/abuses of which the user is a target
@@ -5935,6 +6461,61 @@ components:
         - password
         - email
 
+    OAuthClient:
+      properties:
+        client_id:
+          type: string
+          pattern: /^[a-z0-9]$/
+          maxLength: 32
+          minLength: 32
+          example: v1ikx5hnfop4mdpnci8nsqh93c45rldf
+        client_secret:
+          type: string
+          pattern: /^[a-zA-Z0-9]$/
+          maxLength: 32
+          minLength: 32
+          example: AjWiOapPltI6EnsWQwlFarRtLh4u8tDt
+    OAuthToken-password:
+      allOf:
+        - $ref: '#/components/schemas/OAuthClient'
+        - type: object
+          properties:
+            grant_type:
+              type: string
+              enum:
+                - password
+                - refresh_token
+              default: password
+            username:
+              $ref: '#/components/schemas/User/properties/username'
+            password:
+              $ref: '#/components/schemas/password'
+      required:
+        - client_id
+        - client_secret
+        - grant_type
+        - username
+        - password
+    OAuthToken-refresh_token:
+      allOf:
+        - $ref: '#/components/schemas/OAuthClient'
+        - type: object
+          properties:
+            grant_type:
+              type: string
+              enum:
+                - password
+                - refresh_token
+              default: password
+            refresh_token:
+              type: string
+              example: 2e0d675df9fc96d2e4ec8a3ebbbf45eca9137bb7
+      required:
+        - client_id
+        - client_secret
+        - grant_type
+        - refresh_token
+
     VideoChannel:
       properties:
         # GET/POST/PUT properties
@@ -5952,7 +6533,7 @@ components:
         support:
           type: string
           description: text shown by default on all videos of this channel, to tell the audience how to support it
-          example: Please support my work on <insert crowdfunding plateform>! <3
+          example: Please support our work on https://soutenir.framasoft.org/en/ <3
           minLength: 3
           maxLength: 1000
         # GET-only properties