]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blobdiff - support/doc/api/openapi.yaml
Merge branch 'release/3.2.0' into develop
[github/Chocobozzz/PeerTube.git] / support / doc / api / openapi.yaml
index fd227353d91251ec3617a37178645ff73c2ec4eb..0762e590ada0f35a9f3abba6509515f7576fffe1 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,40 +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"
     }
     ```
 
-    Validation errors benefit from a more detailed error type and return the HTTP `400 Bad Request` status code.
+    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.
@@ -85,9 +103,33 @@ info:
     | `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,
@@ -205,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
@@ -235,6 +283,9 @@ x-tagGroups:
   - name: Search
     tags:
       - Search
+  - name: Custom pages
+    tags:
+      - Homepage
   - name: Moderation
     tags:
       - Abuses
@@ -256,6 +307,7 @@ paths:
       tags:
         - Accounts
       summary: Get an account
+      operationId: getAccount
       parameters:
         - $ref: '#/components/parameters/name'
       responses:
@@ -267,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'
@@ -328,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'
@@ -346,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
@@ -361,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:
@@ -376,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:
@@ -393,6 +455,7 @@ paths:
                 $ref: '#/components/schemas/ServerConfigCustom'
     put:
       summary: Set instance runtime configuration
+      operationId: putCustomConfig
       tags:
         - Config
       security:
@@ -409,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:
@@ -417,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
@@ -459,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'
@@ -528,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
@@ -555,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
@@ -572,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':
@@ -599,6 +771,7 @@ paths:
         required: true
     get:
       summary: List users
+      operationId: getUsers
       security:
         - OAuth2:
           - admin
@@ -619,6 +792,7 @@ paths:
                 type: array
                 items:
                   $ref: '#/components/schemas/User'
+
   '/users/{id}':
     parameters:
       - $ref: '#/components/parameters/id'
@@ -629,7 +803,7 @@ paths:
           - admin
       tags:
         - Users
-      operationId: delUserId
+      operationId: delUser
       responses:
         '204':
           description: successful operation
@@ -639,7 +813,7 @@ paths:
         - OAuth2: []
       tags:
         - Users
-      operationId: getUserId
+      operationId: getUser
       parameters:
         - name: withStats
           in: query
@@ -664,7 +838,7 @@ paths:
         - OAuth2: []
       tags:
         - Users
-      operationId: putUserId
+      operationId: putUser
       responses:
         '204':
           description: successful operation
@@ -674,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
@@ -688,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
@@ -707,6 +1036,7 @@ paths:
                   $ref: '#/components/schemas/User'
     put:
       summary: Update my user information
+      operationId: putUserInfo
       security:
         - OAuth2:
           - user
@@ -721,6 +1051,7 @@ paths:
             schema:
               $ref: '#/components/schemas/UpdateMe'
         required: true
+
   /users/me/videos/imports:
     get:
       summary: Get video imports of my user
@@ -741,6 +1072,7 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/VideoImportsList'
+
   /users/me/video-quota-used:
     get:
       summary: Get my user used quota
@@ -765,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
@@ -787,6 +1120,7 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/GetMeVideoRating'
+
   /users/me/videos:
     get:
       summary: Get videos of my user
@@ -807,6 +1141,7 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/VideoListResponse'
+
   /users/me/subscriptions:
     get:
       summary: Get my user subscriptions
@@ -852,6 +1187,7 @@ paths:
       responses:
         '200':
           description: successful operation
+
   /users/me/subscriptions/exist:
     get:
       summary: Get if subscriptions exist for my user
@@ -869,6 +1205,7 @@ paths:
             application/json:
               schema:
                 type: object
+
   /users/me/subscriptions/videos:
     get:
       summary: List videos of subscriptions of my user
@@ -898,6 +1235,7 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/VideoListResponse'
+
   '/users/me/subscriptions/{subscriptionHandle}':
     get:
       summary: Get subscription of my user
@@ -927,6 +1265,7 @@ paths:
       responses:
         '200':
           description: successful operation
+
   /users/me/notifications:
     get:
       summary: List my notifications
@@ -950,6 +1289,7 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/NotificationListResponse'
+
   /users/me/notifications/read:
     post:
       summary: Mark notifications as read by their id
@@ -973,6 +1313,7 @@ paths:
       responses:
         '204':
           description: successful operation
+
   /users/me/notifications/read-all:
     post:
       summary: Mark all my notification as read
@@ -983,6 +1324,7 @@ paths:
       responses:
         '204':
           description: successful operation
+
   /users/me/notification-settings:
     put:
       summary: Update my notification settings
@@ -1023,6 +1365,7 @@ paths:
       responses:
         '204':
           description: successful operation
+
   /users/me/history/videos:
     get:
       summary: List watched videos history
@@ -1041,6 +1384,7 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/VideoListResponse'
+
   /users/me/history/videos/remove:
     post:
       summary: Clear video history
@@ -1061,6 +1405,7 @@ paths:
       responses:
         '204':
           description: successful operation
+
   /users/me/avatar/pick:
     post:
       summary: Update my user avatar
@@ -1099,6 +1444,7 @@ paths:
             encoding:
               avatarfile:
                 contentType: image/png, image/jpeg
+
   /users/me/avatar:
     delete:
       summary: Delete my avatar
@@ -1120,6 +1466,7 @@ paths:
       responses:
         '200':
           description: successful operation
+
   '/videos/ownership/{id}/accept':
     post:
       summary: Accept ownership change request
@@ -1136,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
@@ -1152,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
@@ -1179,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:
@@ -1204,6 +1555,7 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/VideoListResponse'
+
   /videos/categories:
     get:
       summary: List available video categories
@@ -1222,6 +1574,7 @@ paths:
               examples:
                 nightly:
                   externalValue: https://peertube2.cpy.re/api/v1/videos/categories
+
   /videos/licences:
     get:
       summary: List available video licences
@@ -1240,6 +1593,7 @@ paths:
               examples:
                 nightly:
                   externalValue: https://peertube2.cpy.re/api/v1/videos/licences
+
   /videos/languages:
     get:
       summary: List available video languages
@@ -1258,6 +1612,7 @@ paths:
               examples:
                 nightly:
                   externalValue: https://peertube2.cpy.re/api/v1/videos/languages
+
   /videos/privacies:
     get:
       summary: List available video privacy policies
@@ -1276,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:
@@ -1353,6 +1710,7 @@ paths:
                 contentType: image/jpeg
     get:
       summary: Get a video
+      operationId: getVideo
       tags:
         - Video
       parameters:
@@ -1366,6 +1724,7 @@ paths:
                 $ref: '#/components/schemas/VideoDetails'
     delete:
       summary: Delete a video
+      operationId: delVideo
       security:
         - OAuth2: []
       tags:
@@ -1375,9 +1734,11 @@ paths:
       responses:
         '204':
           description: successful operation
+
   '/videos/{id}/description':
     get:
       summary: Get complete video description
+      operationId: getVideoDesc
       tags:
         - Video
       parameters:
@@ -1394,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
@@ -1404,6 +1766,7 @@ paths:
       responses:
         '204':
           description: successful operation
+
   '/videos/{id}/watching':
     put:
       summary: Set watching progress of a video
@@ -1422,6 +1785,7 @@ paths:
       responses:
         '204':
           description: successful operation
+
   /videos/upload:
     post:
       summary: Upload a video
@@ -1478,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
@@ -1561,7 +1926,7 @@ paths:
         - Video Upload
       parameters:
         - name: upload_id
-          in: path
+          in: query
           required: true
           description: |
             Created session id to proceed with. If you didn't send chunks in the last 12 hours, it is
@@ -1638,7 +2003,7 @@ paths:
         - Video Upload
       parameters:
         - name: upload_id
-          in: path
+          in: query
           required: true
           description: |
             Created session id to proceed with. If you didn't send chunks in the last 12 hours, it is
@@ -1659,6 +2024,7 @@ paths:
               schema:
                 type: number
                 example: 0
+
   /videos/imports:
     post:
       summary: Import a video
@@ -1698,7 +2064,7 @@ paths:
   /videos/live:
     post:
       summary: Create a live
-      operationId: createLive
+      operationId: addLive
       security:
         - OAuth2: []
       tags:
@@ -1946,7 +2312,6 @@ paths:
                     type: array
                     items:
                       $ref: '#/components/schemas/Abuse'
-
     post:
       summary: Report an abuse
       security:
@@ -1976,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:
@@ -1998,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
@@ -2046,6 +2424,7 @@ paths:
           description: successful operation
         '404':
           description: block not found
+
   '/abuses/{abuseId}/messages':
     get:
       summary: List messages of an abuse
@@ -2061,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:
@@ -2092,6 +2476,7 @@ paths:
           description: successful operation
         '400':
           description: incorrect request parameters
+
   '/abuses/{abuseId}/messages/{abuseMessageId}':
     delete:
       summary: Delete an abuse message
@@ -2109,6 +2494,7 @@ paths:
   '/videos/{id}/blacklist':
     post:
       summary: Block a video
+      operationId: addVideoBlock
       security:
         - OAuth2:
           - admin
@@ -2122,6 +2508,7 @@ paths:
           description: successful operation
     delete:
       summary: Unblock a video by its id
+      operationId: delVideoBlock
       security:
         - OAuth2:
           - admin
@@ -2135,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
@@ -2181,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:
@@ -2203,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
@@ -2234,6 +2627,7 @@ paths:
           description: video or language not found
     delete:
       summary: Delete a video caption
+      operationId: delVideoCaption
       security:
         - OAuth2:
           - user
@@ -2247,6 +2641,7 @@ paths:
           description: successful operation
         '404':
           description: video or language or caption for that language not found
+
   /video-channels:
     get:
       summary: List video channels
@@ -2266,7 +2661,7 @@ paths:
                 $ref: '#/components/schemas/VideoChannelList'
     post:
       summary: Create a video channel
-      operationId: createVideoChannel
+      operationId: addVideoChannel
       security:
         - OAuth2: []
       tags:
@@ -2289,6 +2684,7 @@ paths:
           application/json:
             schema:
               $ref: '#/components/schemas/VideoChannelCreate'
+
   '/video-channels/{channelHandle}':
     get:
       summary: Get a video channel
@@ -2306,6 +2702,7 @@ paths:
                 $ref: '#/components/schemas/VideoChannel'
     put:
       summary: Update a video channel
+      operationId: putVideoChannel
       security:
         - OAuth2: []
       tags:
@@ -2322,6 +2719,7 @@ paths:
               $ref: '#/components/schemas/VideoChannelUpdate'
     delete:
       summary: Delete a video channel
+      operationId: delVideoChannel
       security:
         - OAuth2: []
       tags:
@@ -2331,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
@@ -2358,6 +2758,7 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/VideoListResponse'
+
   '/video-channels/{channelHandle}/avatar/pick':
     post:
       summary: Update channel avatar
@@ -2398,6 +2799,7 @@ paths:
             encoding:
               avatarfile:
                 contentType: image/png, image/jpeg
+
   '/video-channels/{channelHandle}/avatar':
     delete:
       summary: Delete channel avatar
@@ -2411,7 +2813,6 @@ paths:
         '204':
           description: successful operation
 
-
   '/video-channels/{channelHandle}/banner/pick':
     post:
       summary: Update channel banner
@@ -2452,6 +2853,7 @@ paths:
             encoding:
               bannerfile:
                 contentType: image/png, image/jpeg
+
   '/video-channels/{channelHandle}/banner':
     delete:
       summary: Delete channel banner
@@ -2512,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:
@@ -2564,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
@@ -2589,7 +2991,7 @@ paths:
         '204':
           description: successful operation
       parameters:
-        - $ref: '#/components/parameters/idOrUUID'
+        - $ref: '#/components/parameters/playlistId'
       requestBody:
         content:
           multipart/form-data:
@@ -2624,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
@@ -2645,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
@@ -2666,6 +3070,7 @@ paths:
                     properties:
                       id:
                         type: integer
+                        example: 2
       requestBody:
         content:
           application/json:
@@ -2673,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
@@ -2719,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':
@@ -2740,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':
@@ -2759,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:
@@ -2792,8 +3205,10 @@ paths:
                           type: integer
                         startTimestamp:
                           type: integer
+                          format: seconds
                         stopTimestamp:
                           type: integer
+                          format: seconds
 
   '/accounts/{name}/video-channels':
     get:
@@ -2818,6 +3233,7 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/VideoChannelList'
+
   '/accounts/{name}/ratings':
     get:
       summary: List ratings of an account
@@ -2848,6 +3264,7 @@ paths:
                 type: array
                 items:
                   $ref: '#/components/schemas/VideoRating'
+
   '/videos/{id}/comment-threads':
     get:
       summary: List threads of a video
@@ -2911,6 +3328,7 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/VideoCommentThreadTree'
+
   '/videos/{id}/comments/{commentId}':
     post:
       summary: Reply to a thread of a video
@@ -2943,7 +3361,6 @@ paths:
                   maxLength: 10000
               required:
                 - text
-
     delete:
       summary: Delete a comment or a reply
       security:
@@ -2962,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
@@ -2989,11 +3407,13 @@ paths:
           description: successful operation
         '404':
           description: video does not exist
+
   /search/videos:
     get:
       tags:
         - Search
       summary: Search videos
+      operationId: searchVideos
       parameters:
         - name: search
           in: query
@@ -3064,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
@@ -3095,7 +3517,8 @@ paths:
                 $ref: '#/components/schemas/VideoChannelList'
         '500':
           description: search index unavailable
-  /blocklist/accounts:
+
+  /server/blocklist/accounts:
     get:
       tags:
         - Account Blocks
@@ -3134,7 +3557,8 @@ paths:
           description: successful operation
         '409':
           description: self-blocking forbidden
-  '/blocklist/accounts/{accountName}':
+
+  '/server/blocklist/accounts/{accountName}':
     delete:
       tags:
         - Account Blocks
@@ -3154,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
@@ -3189,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
@@ -3210,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
@@ -3246,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
@@ -3280,6 +3709,7 @@ paths:
       tags:
         - Video Mirroring
       summary: Mirror a video
+      operationId: putMirroredVideo
       security:
         - OAuth2:
           - admin
@@ -3302,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
@@ -3322,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
@@ -3415,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
@@ -3501,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
@@ -3563,11 +4001,13 @@ paths:
                 type: object
         '406':
           description: accept header unsupported
+
   /plugins:
     get:
       tags:
         - Plugins
       summary: List plugins
+      operationId: getPlugins
       security:
         - OAuth2:
           - admin
@@ -3590,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
@@ -3623,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
@@ -3656,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
@@ -3691,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
@@ -3716,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
@@ -3735,6 +4185,7 @@ paths:
                 $ref: '#/components/schemas/Plugin'
         '404':
           description: plugin not found
+
   /plugins/{npmName}/settings:
     put:
       tags:
@@ -3759,6 +4210,7 @@ paths:
           description: successful operation
         '404':
           description: plugin not found
+
   /plugins/{npmName}/public-settings:
     get:
       tags:
@@ -3776,6 +4228,7 @@ paths:
                 additionalProperties: true
         '404':
           description: plugin not found
+
   /plugins/{npmName}/registered-settings:
     get:
       tags:
@@ -3796,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)
@@ -3984,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
@@ -4034,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
@@ -4188,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
@@ -4225,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: framasoft_videos
-      pattern: '/^[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\\-_.:]+$/'
+      pattern: '/^[a-zA-Z0-9\\-_.:]+$/'
+      minLength: 1
+      maxLength: 50
     password:
       type: string
       format: password
@@ -4447,8 +4930,10 @@ components:
           type: integer
         startTimestamp:
           type: integer
+          format: seconds
         stopTimestamp:
           type: integer
+          format: seconds
         video:
           nullable: true
           allOf:
@@ -4597,6 +5082,7 @@ components:
         duration:
           type: integer
           example: 1419
+          format: seconds
           description: duration of the video in seconds
         isLocal:
           type: boolean
@@ -5091,6 +5577,7 @@ components:
       properties:
         currentTime:
           type: integer
+          format: seconds
           description: timestamp within the video, in seconds
           example: 5
     ServerConfig:
@@ -5292,6 +5779,12 @@ components:
                     indexUrl:
                       type: string
                       format: url
+        homepage:
+          type: object
+          properties:
+            enabled:
+              type: boolean
+
     ServerConfigAbout:
       properties:
         instance:
@@ -5482,6 +5975,12 @@ components:
                   type: boolean
                 manualApproval:
                   type: boolean
+
+    CustomHomepage:
+      properties:
+        content:
+          type: string
+
     Follow:
       properties:
         id:
@@ -5787,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
@@ -5962,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