]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blobdiff - support/doc/api/openapi.yaml
more faithful error description in openapi spec
[github/Chocobozzz/PeerTube.git] / support / doc / api / openapi.yaml
index a71b571b87ea1cea8032e0903c5f93240ad5ef37..6e82864a0187ed7dfc0034d0d5e0518fe1f51ac4 100644 (file)
@@ -1,15 +1,15 @@
 openapi: 3.0.0
 info:
   title: PeerTube
-  version: 3.1.0
+  version: 3.2.0-rc.1
   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
@@ -27,8 +27,8 @@ info:
     # 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,28 +38,60 @@ 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
-    format.
+    of the API call.
 
     ```
+    HTTP 1.1 404 Not Found
+    Content-Type: application/json
+
+    {
+      "errorCode": 1
+      "error": "Account not found"
+    }
+    ```
+
+    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
+
     {
-      "code": "unauthorized_request", // example inner error code
-      "error": "Token is invalid." // example exposed error message
+      "errors": {
+        "id": { // 
+          "value": "a117eb-c6a9-4756-bb09-2a956239f",
+          "msg": "Should have a valid id",
+          "param": "id",
+          "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¹               | 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, ¹failed requests are not taken into account. A service
+    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.
 
     You can get details about the current state of your rate limit by reading the
@@ -67,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/createUser) 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,
@@ -144,8 +200,8 @@ tags:
 
       ### Upload
 
-      - [_legacy_](#tag/Video-Upload/paths/~1videos~1upload/post), where the video file is sent in a single request
-      - [_resumable_](#tag/Video-Upload/paths/~1videos~1upload-resumable/post), where the video file is sent in chunks
+      - [_legacy_](#operation/uploadLegacy), where the video file is sent in a single request
+      - [_resumable_](#operation/uploadResumableInit), where the video file is sent in chunks
 
       You can upload videos more reliably by using the resumable variant. Its protocol lets
       you resume an upload operation after a network interruption or other transmission failure,
@@ -195,8 +251,12 @@ tags:
     description: |
       PeerTube instances can mirror videos from one another, and help distribute some videos.
 
-      For importing videos as your own, refer to [video imports](#tag/Video-Upload/paths/~1videos~1imports/post).
+      For importing videos as your own, refer to [video imports](#operation/importVideo).
 x-tagGroups:
+  - name: Auth
+    tags:
+      - Register
+      - Session
   - name: Accounts
     tags:
       - Accounts
@@ -280,7 +340,7 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/VideoListResponse'
-      x-code-samples:
+      x-codeSamples:
         - lang: JavaScript
           source: |
             fetch('https://peertube2.cpy.re/api/v1/accounts/{name}/videos')
@@ -344,6 +404,9 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/ServerConfig'
+              examples:
+                nightly:
+                  externalValue: https://peertube2.cpy.re/api/v1/config
   /config/about:
     get:
       summary: Get instance "About" information
@@ -356,6 +419,9 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/ServerConfigAbout'
+              examples:
+                nightly:
+                  externalValue: https://peertube2.cpy.re/api/v1/config/about
   /config/custom:
     get:
       summary: Get instance runtime configuration
@@ -538,6 +604,7 @@ paths:
   /users:
     post:
       summary: Create a user
+      operationId: createUser
       security:
         - OAuth2:
           - admin
@@ -573,7 +640,9 @@ paths:
           application/json:
             schema:
               $ref: '#/components/schemas/AddUser'
-        description: User to create
+        description: |
+          If the smtp server is configured, you can leave the password empty and an email will be sent
+          asking the user to set it first.
         required: true
     get:
       summary: List users
@@ -618,13 +687,24 @@ paths:
       tags:
         - Users
       operationId: getUserId
+      parameters:
+        - name: withStats
+          in: query
+          description: include statistics about the user (only available as a moderator/admin)
+          schema:
+            type: boolean
       responses:
         '200':
-          description: successful operation
+          x-summary: successful operation
+          description: |
+            As an admin/moderator, you can request a response augmented with statistics about the user's
+            moderation relations and videos usage, by using the `withStats` parameter.
           content:
             application/json:
               schema:
-                $ref: '#/components/schemas/User'
+                oneOf:
+                  - $ref: '#/components/schemas/User'
+                  - $ref: '#/components/schemas/UserWithStats'
     put:
       summary: Update a user
       security:
@@ -641,11 +721,92 @@ 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'
+  /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
+  /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
       tags:
         - Users
+        - Register
       responses:
         '204':
           description: successful operation
@@ -655,6 +816,47 @@ paths:
             schema:
               $ref: '#/components/schemas/RegisterUser'
         required: true
+  /users/{id}/verify-email:
+    post:
+      summary: Verify a user
+      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
+      tags:
+        - Users
+        - Register
+      responses:
+        '204':
+          description: successful operation
+
   /users/me:
     get:
       summary: Get my user information
@@ -707,7 +909,7 @@ paths:
           content:
             application/json:
               schema:
-                $ref: '#/components/schemas/VideoImport'
+                $ref: '#/components/schemas/VideoImportsList'
   /users/me/video-quota-used:
     get:
       summary: Get my user used quota
@@ -726,9 +928,11 @@ paths:
                 properties:
                   videoQuotaUsed:
                     type: number
+                    description: The user video quota used so far in bytes
                     example: 16810141515
                   videoQuotaUsedDaily:
                     type: number
+                    description: The user video quota used today in bytes
                     example: 1681014151
   '/users/me/videos/{videoId}/rating':
     get:
@@ -742,9 +946,9 @@ paths:
         - name: videoId
           in: path
           required: true
-          description: 'The video id '
+          description: The video id
           schema:
-            type: string
+            $ref: '#/components/schemas/Video/properties/id'
       responses:
         '200':
           description: successful operation
@@ -787,6 +991,10 @@ paths:
       responses:
         '200':
           description: successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/VideoChannelList'
     post:
       tags:
         - My Subscriptions
@@ -1054,7 +1262,7 @@ paths:
               type: object
               properties:
                 avatarfile:
-                  description: The file to upload.
+                  description: The file to upload
                   type: string
                   format: binary
             encoding:
@@ -1168,6 +1376,7 @@ paths:
   /videos/categories:
     get:
       summary: List available video categories
+      operationId: getCategories
       tags:
         - Video
       responses:
@@ -1185,6 +1394,7 @@ paths:
   /videos/licences:
     get:
       summary: List available video licences
+      operationId: getLicences
       tags:
         - Video
       responses:
@@ -1202,6 +1412,7 @@ paths:
   /videos/languages:
     get:
       summary: List available video languages
+      operationId: getLanguages
       tags:
         - Video
       responses:
@@ -1218,7 +1429,8 @@ paths:
                   externalValue: https://peertube2.cpy.re/api/v1/videos/languages
   /videos/privacies:
     get:
-      summary: List available video privacies
+      summary: List available video privacy policies
+      operationId: getPrivacyPolicies
       tags:
         - Video
       responses:
@@ -1260,16 +1472,11 @@ paths:
                   type: string
                   format: binary
                 category:
-                  description: Video category
-                  type: integer
-                  example: 4
+                  $ref: '#/components/schemas/VideoCategorySet'
                 licence:
-                  description: Video licence
-                  type: integer
-                  example: 2
+                  $ref: '#/components/schemas/VideoLicenceSet'
                 language:
-                  description: Video language
-                  type: string
+                  $ref: '#/components/schemas/VideoLanguageSet'
                 privacy:
                   $ref: '#/components/schemas/VideoPrivacySet'
                 description:
@@ -1280,7 +1487,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
@@ -1350,7 +1557,12 @@ paths:
           content:
             application/json:
               schema:
+                nullable: true
                 type: string
+                minLength: 3
+                maxLength: 10000
+                example: |
+                  **[Want to help to translate this video?](https://weblate.framasoft.org/projects/what-is-peertube-video/)**\r\n\r\n**Take back the control of your videos! [#JoinPeertube](https://joinpeertube.org)**
   '/videos/{id}/views':
     post:
       summary: Add a view to a video
@@ -1383,6 +1595,7 @@ paths:
     post:
       summary: Upload a video
       description: Uses a single request to upload a video.
+      operationId: uploadLegacy
       security:
         - OAuth2: []
       tags:
@@ -1425,7 +1638,7 @@ paths:
                 contentType: image/jpeg
               previewfile:
                 contentType: image/jpeg
-      x-code-samples:
+      x-codeSamples:
         - lang: Shell
           source: |
             ## DEPENDENCIES: jq
@@ -1458,6 +1671,7 @@ paths:
     post:
       summary: Initialize the resumable upload of a video
       description: Uses [a resumable protocol](https://github.com/kukhariev/node-uploadx/blob/master/proto.md) to initialize the upload of a video
+      operationId: uploadResumableInit
       security:
         - OAuth2: []
       tags:
@@ -1508,6 +1722,7 @@ paths:
     put:
       summary: Send chunk for the resumable upload of a video
       description: Uses [a resumable protocol](https://github.com/kukhariev/node-uploadx/blob/master/proto.md) to continue, pause or resume the upload of a video
+      operationId: uploadResumable
       security:
         - OAuth2: []
       tags:
@@ -1584,6 +1799,7 @@ paths:
     delete:
       summary: Cancel the resumable upload of a video, deleting any data uploaded so far
       description: Uses [a resumable protocol](https://github.com/kukhariev/node-uploadx/blob/master/proto.md) to cancel the upload of a video
+      operationId: uploadResumableCancel
       security:
         - OAuth2: []
       tags:
@@ -1616,6 +1832,7 @@ paths:
     post:
       summary: Import a video
       description: Import a torrent or magnetURI or HTTP resource (if enabled by the instance administrator)
+      operationId: importVideo
       security:
         - OAuth2: []
       tags:
@@ -1625,80 +1842,7 @@ paths:
         content:
           multipart/form-data:
             schema:
-              type: object
-              properties:
-                torrentfile:
-                  description: Torrent File
-                  type: string
-                  format: binary
-                targetUrl:
-                  description: HTTP target URL
-                  type: string
-                magnetUri:
-                  description: Magnet URI
-                  type: string
-                channelId:
-                  description: Channel id that will contain this video
-                  type: integer
-                thumbnailfile:
-                  description: Video thumbnail file
-                  type: string
-                  format: binary
-                previewfile:
-                  description: Video preview file
-                  type: string
-                  format: binary
-                privacy:
-                  $ref: '#/components/schemas/VideoPrivacySet'
-                category:
-                  description: Video category
-                  type: integer
-                  example: 4
-                licence:
-                  description: Video licence
-                  type: integer
-                  example: 2
-                language:
-                  description: Video language
-                  type: string
-                description:
-                  description: Video description
-                  type: string
-                waitTranscoding:
-                  description: Whether or not we wait transcoding before publish the video
-                  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
-                  type: string
-                nsfw:
-                  description: Whether or not this video contains sensitive content
-                  type: boolean
-                name:
-                  description: Video name
-                  type: string
-                  minLength: 3
-                  maxLength: 120
-                tags:
-                  description: Video tags (maximum 5 tags each between 2 and 30 characters)
-                  type: array
-                  minItems: 1
-                  maxItems: 5
-                  items:
-                    type: string
-                    minLength: 2
-                    maxLength: 30
-                commentsEnabled:
-                  description: Enable or disable comments for this video
-                  type: boolean
-                downloadEnabled:
-                  description: Enable or disable downloading for this video
-                  type: boolean
-                scheduleUpdate:
-                  $ref: '#/components/schemas/VideoScheduledUpdate'
-              required:
-                - channelId
-                - name
+              $ref: '#/components/schemas/VideoCreateImport'
             encoding:
               torrentfile:
                 contentType: application/x-bittorrent
@@ -1723,6 +1867,7 @@ paths:
   /videos/live:
     post:
       summary: Create a live
+      operationId: createLive
       security:
         - OAuth2: []
       tags:
@@ -1736,7 +1881,7 @@ paths:
               schema:
                 $ref: '#/components/schemas/VideoUploadResponse'
         '403':
-          description: Live is not enabled, allow replay is not enabled, or max instance/user live videos limit is exceeded
+          description: live is not enabled, allow replay is not enabled, or max instance/user live videos limit is exceeded
       requestBody:
         content:
           multipart/form-data:
@@ -1762,20 +1907,17 @@ paths:
                 privacy:
                   $ref: '#/components/schemas/VideoPrivacySet'
                 category:
-                  description: Live video/replay category
-                  type: string
+                  $ref: '#/components/schemas/VideoCategorySet'
                 licence:
-                  description: Live video/replay licence
-                  type: string
+                  $ref: '#/components/schemas/VideoLicenceSet'
                 language:
-                  description: Live video/replay language
-                  type: string
+                  $ref: '#/components/schemas/VideoLanguageSet'
                 description:
                   description: Live video/replay description
                   type: string
                 support:
                   description: A text tell the audience how to support the creator
-                  example: Please support 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
@@ -1812,6 +1954,7 @@ paths:
   /videos/live/{id}:
     get:
       summary: Get information about a live
+      operationId: getLiveId
       security:
         - OAuth2: []
       tags:
@@ -1828,6 +1971,7 @@ paths:
                 $ref: '#/components/schemas/LiveVideoResponse'
     put:
       summary: Update information about a live
+      operationId: updateLiveId
       security:
         - OAuth2: []
       tags:
@@ -1842,15 +1986,16 @@ paths:
               $ref: '#/components/schemas/LiveVideoUpdate'
       responses:
         '204':
-          description: Successful operation
+          description: successful operation
         '400':
-          description: Bad parameters or trying to update a live that has already started
+          description: bad parameters or trying to update a live that has already started
         '403':
-          description: Trying to save replay of the live but saving replay is not enabled on the instance
+          description: trying to save replay of the live but saving replay is not enabled on the instance
 
   /users/me/abuses:
     get:
       summary: List my abuses
+      operationId: getMyAbuses
       security:
         - OAuth2: []
       tags:
@@ -1866,22 +2011,29 @@ paths:
           in: query
           schema:
             $ref: '#/components/schemas/AbuseStateSet'
+        - $ref: '#/components/parameters/abusesSort'
         - $ref: '#/components/parameters/start'
         - $ref: '#/components/parameters/count'
-        - $ref: '#/components/parameters/abusesSort'
       responses:
         '200':
           description: successful operation
           content:
             application/json:
               schema:
-                type: array
-                items:
-                  $ref: '#/components/schemas/Abuse'
+                type: object
+                properties:
+                  total:
+                    type: integer
+                    example: 1
+                  data:
+                    type: array
+                    items:
+                      $ref: '#/components/schemas/Abuse'
 
   /abuses:
     get:
       summary: List abuses
+      operationId: getAbuses
       security:
         - OAuth2:
           - admin
@@ -1954,9 +2106,15 @@ paths:
           content:
             application/json:
               schema:
-                type: array
-                items:
-                  $ref: '#/components/schemas/Abuse'
+                type: object
+                properties:
+                  total:
+                    type: integer
+                    example: 1
+                  data:
+                    type: array
+                    items:
+                      $ref: '#/components/schemas/Abuse'
 
     post:
       summary: Report an abuse
@@ -1983,13 +2141,16 @@ paths:
                   properties:
                     id:
                       description: Video id to report
-                      type: number
+                      allOf:
+                        - $ref: '#/components/schemas/Video/properties/id'
                     startAt:
                       type: integer
+                      format: seconds
                       description: Timestamp in the video that marks the beginning of the report
                       minimum: 0
                     endAt:
                       type: integer
+                      format: seconds
                       description: Timestamp in the video that marks the ending of the report
                       minimum: 0
                 comment:
@@ -1997,13 +2158,14 @@ paths:
                   properties:
                     id:
                       description: Comment id to report
-                      type: number
+                      allOf:
+                        - $ref: '#/components/schemas/VideoComment/properties/id'
                 account:
                   type: object
                   properties:
                     id:
                       description: Account id to report
-                      type: number
+                      type: integer
               required:
                 - reason
       responses:
@@ -2259,6 +2421,7 @@ paths:
   /video-channels:
     get:
       summary: List video channels
+      operationId: getVideoChannels
       tags:
         - Video Channels
       parameters:
@@ -2271,17 +2434,10 @@ paths:
           content:
             application/json:
               schema:
-                type: object
-                properties:
-                  total:
-                    type: integer
-                    example: 1
-                  data:
-                    type: array
-                    items:
-                      $ref: '#/components/schemas/VideoChannel'
+                $ref: '#/components/schemas/VideoChannelList'
     post:
       summary: Create a video channel
+      operationId: createVideoChannel
       security:
         - OAuth2: []
       tags:
@@ -2289,6 +2445,16 @@ 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:
@@ -2297,6 +2463,7 @@ paths:
   '/video-channels/{channelHandle}':
     get:
       summary: Get a video channel
+      operationId: getVideoChannel
       tags:
         - Video Channels
       parameters:
@@ -2471,7 +2638,8 @@ paths:
 
   /video-playlists/privacies:
     get:
-      summary: List available playlist privacies
+      summary: List available playlist privacy policies
+      operationId: getPlaylistPrivacyPolicies
       tags:
         - Video Playlists
       responses:
@@ -2490,6 +2658,7 @@ paths:
   /video-playlists:
     get:
       summary: List video playlists
+      operationId: getPlaylists
       tags:
         - Video Playlists
       parameters:
@@ -2513,7 +2682,8 @@ paths:
                       $ref: '#/components/schemas/VideoPlaylist'
     post:
       summary: Create a video playlist
-      description: 'If the video playlist is set as public, the videoChannelId is mandatory.'
+      description: If the video playlist is set as public, `videoChannelId` is mandatory.
+      operationId: createPlaylist
       security:
         - OAuth2: []
       tags:
@@ -2530,9 +2700,9 @@ paths:
                     type: object
                     properties:
                       id:
-                        type: integer
+                        $ref: '#/components/schemas/VideoPlaylist/properties/id'
                       uuid:
-                        $ref: '#/components/schemas/UUIDv4'
+                        $ref: '#/components/schemas/VideoPlaylist/properties/uuid'
       requestBody:
         content:
           multipart/form-data:
@@ -2553,22 +2723,25 @@ paths:
                 description:
                   description: Video playlist description
                   type: string
+                  minLength: 3
+                  maxLength: 1000
                 videoChannelId:
+                  allOf:
+                    - $ref: '#/components/schemas/id'
                   description: Video channel in which the playlist will be published
-                  type: integer
               required:
                 - displayName
             encoding:
               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
@@ -2587,7 +2760,7 @@ paths:
         '204':
           description: successful operation
       parameters:
-        - $ref: '#/components/parameters/idOrUUID'
+        - $ref: '#/components/parameters/playlistId'
       requestBody:
         content:
           multipart/form-data:
@@ -2609,8 +2782,9 @@ paths:
                   description: Video playlist description
                   type: string
                 videoChannelId:
+                  allOf:
+                    - $ref: '#/components/schemas/id'
                   description: Video channel in which the playlist will be published
-                  type: integer
             encoding:
               thumbnailfile:
                 contentType: image/jpeg
@@ -2621,19 +2795,19 @@ 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'
       tags:
         - Videos
         - Video Playlists
       parameters:
-        - $ref: '#/components/parameters/idOrUUID'
+        - $ref: '#/components/parameters/playlistId'
       responses:
         '200':
           description: successful operation
@@ -2642,14 +2816,14 @@ paths:
               schema:
                 $ref: '#/components/schemas/VideoListResponse'
     post:
-      summary: 'Add a video in a playlist'
+      summary: Add a video in a playlist
       security:
         - OAuth2: []
       tags:
         - Videos
         - Video Playlists
       parameters:
-        - $ref: '#/components/parameters/idOrUUID'
+        - $ref: '#/components/parameters/playlistId'
       responses:
         '200':
           description: successful operation
@@ -2663,6 +2837,7 @@ paths:
                     properties:
                       id:
                         type: integer
+                        example: 2
       requestBody:
         content:
           application/json:
@@ -2670,18 +2845,22 @@ paths:
               type: object
               properties:
                 videoId:
-                  type: integer
-                  description: 'Video to add in the playlist'
+                  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'
       security:
@@ -2689,7 +2868,7 @@ paths:
       tags:
         - Video Playlists
       parameters:
-        - $ref: '#/components/parameters/idOrUUID'
+        - $ref: '#/components/parameters/playlistId'
       responses:
         '204':
           description: successful operation
@@ -2715,15 +2894,15 @@ paths:
                 - startPosition
                 - insertAfterPosition
 
-  /video-playlists/{id}/videos/{playlistElementId}:
+  /video-playlists/{playlistId}/videos/{playlistElementId}:
     put:
-      summary: 'Update a playlist element'
+      summary: Update a playlist element
       security:
         - OAuth2: []
       tags:
         - Video Playlists
       parameters:
-        - $ref: '#/components/parameters/idOrUUID'
+        - $ref: '#/components/parameters/playlistId'
         - $ref: '#/components/parameters/playlistElementId'
       responses:
         '204':
@@ -2736,18 +2915,20 @@ 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
       security:
         - OAuth2: []
       tags:
         - Video Playlists
       parameters:
-        - $ref: '#/components/parameters/idOrUUID'
+        - $ref: '#/components/parameters/playlistId'
         - $ref: '#/components/parameters/playlistElementId'
       responses:
         '204':
@@ -2755,7 +2936,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:
@@ -2768,7 +2949,7 @@ paths:
           schema:
             type: array
             items:
-              type: integer
+              $ref: '#/components/schemas/Video/properties/id'
       responses:
         '200':
           description: successful operation
@@ -2788,8 +2969,10 @@ paths:
                           type: integer
                         startTimestamp:
                           type: integer
+                          format: seconds
                         stopTimestamp:
                           type: integer
+                          format: seconds
 
   '/accounts/{name}/video-channels':
     get:
@@ -2813,14 +2996,7 @@ paths:
           content:
             application/json:
               schema:
-                properties:
-                  total:
-                    type: integer
-                    example: 1
-                  data:
-                    type: array
-                    items:
-                      $ref: '#/components/schemas/VideoChannel'
+                $ref: '#/components/schemas/VideoChannelList'
   '/accounts/{name}/ratings':
     get:
       summary: List ratings of an account
@@ -2892,8 +3068,10 @@ paths:
               type: object
               properties:
                 text:
-                  type: string
-                  description: 'Text comment'
+                  allOf:
+                    - $ref: '#/components/schemas/VideoComment/properties/text'
+                  format: markdown
+                  maxLength: 10000
               required:
                 - text
 
@@ -2938,8 +3116,10 @@ paths:
               type: object
               properties:
                 text:
-                  type: string
-                  description: 'Text comment'
+                  allOf:
+                    - $ref: '#/components/schemas/VideoComment/properties/text'
+                  format: markdown
+                  maxLength: 10000
               required:
                 - text
 
@@ -2970,6 +3150,19 @@ 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
@@ -3078,9 +3271,7 @@ paths:
           content:
             application/json:
               schema:
-                type: array
-                items:
-                  $ref: '#/components/schemas/VideoChannel'
+                $ref: '#/components/schemas/VideoChannelList'
         '500':
           description: search index unavailable
   /blocklist/accounts:
@@ -3278,7 +3469,7 @@ paths:
               type: object
               properties:
                 videoId:
-                  type: integer
+                  $ref: '#/components/schemas/Video/properties/id'
               required:
                 - videoId
       responses:
@@ -3962,9 +4153,7 @@ components:
       required: true
       description: The user id
       schema:
-        type: integer
-        minimum: 0
-        example: 42
+        $ref: '#/components/schemas/id'
     idOrUUID:
       name: id
       in: path
@@ -3972,38 +4161,43 @@ components:
       description: The object id or uuid
       schema:
         oneOf:
-          - type: integer
-            minimum: 0
-            example: 42
+          - $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
       required: true
       description: Playlist element id
       schema:
-        type: integer
+        $ref: '#/components/schemas/id'
     abuseId:
       name: abuseId
       in: path
       required: true
       description: Abuse id
       schema:
-        type: integer
+        $ref: '#/components/schemas/Abuse/properties/id'
     abuseMessageId:
       name: abuseMessageId
       in: path
       required: true
       description: Abuse message id
       schema:
-        type: integer
+        $ref: '#/components/schemas/AbuseMessage/properties/id'
     captionLanguage:
       name: captionLanguage
       in: path
       required: true
       description: The caption language
       schema:
-        type: string
+        $ref: '#/components/schemas/VideoLanguageSet'
     channelHandle:
       name: channelHandle
       in: path
@@ -4026,14 +4220,14 @@ components:
       required: true
       description: The thread id (root comment id)
       schema:
-        type: integer
+        $ref: '#/components/schemas/VideoCommentThreadTree/properties/comment/properties/id'
     commentId:
       name: commentId
       in: path
       required: true
       description: The comment id
       schema:
-        type: integer
+        $ref: '#/components/schemas/VideoComment/properties/id'
     isLive:
       name: isLive
       in: query
@@ -4045,13 +4239,13 @@ components:
       name: categoryOneOf
       in: query
       required: false
-      description: category id of the video (see [/videos/categories](#tag/Video/paths/~1videos~1categories/get))
+      description: category id of the video (see [/videos/categories](#operation/getCategories))
       schema:
         oneOf:
-        - type: integer
+        - $ref: '#/components/schemas/VideoCategorySet'
         - type: array
           items:
-            type: integer
+            $ref: '#/components/schemas/VideoCategorySet'
       style: form
       explode: false
     tagsOneOf:
@@ -4085,26 +4279,26 @@ components:
       name: languageOneOf
       in: query
       required: false
-      description: language id of the video (see [/videos/languages](#tag/Video/paths/~1videos~1languages/get)). Use `_unknown` to filter on videos that don't have a video language
+      description: language id of the video (see [/videos/languages](#operation/getLanguages)). Use `_unknown` to filter on videos that don't have a video language
       schema:
         oneOf:
-        - type: string
+        - $ref: '#/components/schemas/VideoLanguageSet'
         - type: array
           items:
-            type: string
+            $ref: '#/components/schemas/VideoLanguageSet'
       style: form
       explode: false
     licenceOneOf:
       name: licenceOneOf
       in: query
       required: false
-      description: licence id of the video (see [/videos/licences](#tag/Video/paths/~1videos~1licences/get))
+      description: licence id of the video (see [/videos/licences](#operation/getLicences))
       schema:
         oneOf:
-        - type: integer
+        - $ref: '#/components/schemas/VideoLicenceSet'
         - type: array
           items:
-            type: integer
+            $ref: '#/components/schemas/VideoLicenceSet'
       style: form
       explode: false
     skipCount:
@@ -4185,53 +4379,90 @@ components:
       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
             user: User scope
   schemas:
+    # Resuable core properties
+    id:
+      type: integer
+      minimum: 1
+      example: 42
     UUIDv4:
       type: string
       format: uuid
       example: 9c9de5e8-0a1e-484a-b099-e80766180a6d
       pattern: '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$'
-      # the regex above limits the length;
-      # however, some tools might require explicit settings:
       minLength: 36
       maxLength: 36
+    username:
+      type: string
+      description: immutable name of the user, used to find or mention its actor
+      example: chocobozzz
+      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: '/^[a-zA-Z0-9\\-_.:]+$/'
+      minLength: 1
+      maxLength: 50
+    password:
+      type: string
+      format: password
+      minLength: 6
+      maxLength: 255
 
+    VideoCategorySet:
+      type: integer
+      description: category id of the video (see [/videos/categories](#operation/getCategories))
+      example: 15
     VideoConstantNumber-Category:
       properties:
         id:
-          type: integer
-          description: category id of the video (see [/videos/categories](#tag/Video/paths/~1videos~1categories/get))
+          $ref: '#/components/schemas/VideoCategorySet'
         label:
           type: string
+          example: Science & Technology
+
+    VideoLicenceSet:
+      type: integer
+      description: licence id of the video (see [/videos/licences](#operation/getLicences))
+      example: 2
     VideoConstantNumber-Licence:
       properties:
         id:
-          type: integer
-          description: licence id of the video (see [/videos/licences](#tag/Video/paths/~1videos~1licences/get))
+          $ref: '#/components/schemas/VideoLicenceSet'
         label:
           type: string
+          example: Attribution - Share Alike
+
+    VideoLanguageSet:
+      type: string
+      description: language id of the video (see [/videos/languages](#operation/getLanguages))
+      example: en
     VideoConstantString-Language:
       properties:
         id:
-          type: string
-          description: language id of the video (see [/videos/languages](#tag/Video/paths/~1videos~1languages/get))
+          $ref: '#/components/schemas/VideoLanguageSet'
         label:
           type: string
+          example: English
 
     VideoPlaylistPrivacySet:
       type: integer
@@ -4239,7 +4470,7 @@ components:
         - 1
         - 2
         - 3
-      description: 'The video playlist privacy (Public = `1`, Unlisted = `2`, Private = `3`)'
+      description: Video playlist privacy policy (see [/video-playlists/privacies])
     VideoPlaylistPrivacyConstant:
       properties:
         id:
@@ -4252,7 +4483,7 @@ components:
       enum:
         - 1
         - 2
-      description: 'The video playlist type (Regular = `1`, Watch Later = `2`)'
+      description: The video playlist type (Regular = `1`, Watch Later = `2`)
     VideoPlaylistTypeConstant:
       properties:
         id:
@@ -4267,7 +4498,7 @@ components:
         - 2
         - 3
         - 4
-      description: 'The video privacy (Public = `1`, Unlisted = `2`, Private = `3`, Internal = `4`)'
+      description: privacy id of the video (see [/videos/privacies](#operation/getPrivacyPolicies))
     VideoPrivacyConstant:
       properties:
         id:
@@ -4338,12 +4569,18 @@ components:
         - captions
       example: [spamOrMisleading]
 
+    VideoResolutionSet:
+      type: integer
+      description: |
+        Video resolution (`0`, `240`, `360`, `720`, `1080`, `1440` or `2160`)
+
+        `0` is used as a special value for stillimage videos dedicated to audio, a.k.a. audio-only videos.
+      example: 240
     VideoResolutionConstant:
+      description: resolutions and their labels for the video
       properties:
         id:
-          type: integer
-          description: 'Video resolution (240, 360, 720, 1080, 1440 or 2160)'
-          example: 240
+          $ref: '#/components/schemas/VideoResolutionSet'
         label:
           type: string
           example: 240p
@@ -4378,7 +4615,7 @@ components:
     VideoChannelSummary:
       properties:
         id:
-          type: integer
+          $ref: '#/components/schemas/id'
         name:
           type: string
         displayName:
@@ -4399,21 +4636,28 @@ components:
           type: integer
         startTimestamp:
           type: integer
+          format: seconds
         stopTimestamp:
           type: integer
+          format: seconds
         video:
           nullable: true
           allOf:
             - $ref: '#/components/schemas/Video'
     VideoFile:
+      readOnly: true
       properties:
         magnetUri:
           type: string
+          format: uri
+          description: magnet URI allowing to resolve the video via BitTorrent without a metainfo file
+          example: magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-240.torrent&xt=urn:btih:38b4747ff788b30bf61f59d1965cd38f9e48e01f&dn=What+is+PeerTube%3F&tr=wss%3A%2F%2Fframatube.org%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fwebseed%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-240.mp4
+          pattern: /magnet:\?xt=urn:[a-z0-9]+:[a-z0-9]{32}/i
         resolution:
           $ref: '#/components/schemas/VideoResolutionConstant'
         size:
           type: integer
-          description: 'Video file size in bytes'
+          description: Video file size in bytes
         torrentUrl:
           type: string
           description: Direct URL of the torrent file
@@ -4432,15 +4676,17 @@ components:
           format: url
         fps:
           type: number
+          description: Frames per second of the video file
         metadataUrl:
           type: string
           format: url
+          description: URL dereferencing the output of ffprobe on the file
     VideoStreamingPlaylists:
       allOf:
         - type: object
           properties:
             id:
-              type: integer
+              $ref: '#/components/schemas/id'
             type:
               type: integer
               enum:
@@ -4476,20 +4722,21 @@ components:
     VideoInfo:
       properties:
         id:
-          type: integer
+          $ref: '#/components/schemas/Video/properties/id'
         uuid:
-          $ref: '#/components/schemas/UUIDv4'
+          $ref: '#/components/schemas/Video/properties/uuid'
         name:
-          type: string
-          minLength: 3
-          maxLength: 120
+          $ref: '#/components/schemas/Video/properties/name'
     Video:
       properties:
         id:
-          type: integer
-          example: 8
+          description: object id for the video
+          allOf:
+            - $ref: '#/components/schemas/id'
         uuid:
-          $ref: '#/components/schemas/UUIDv4'
+          description: universal identifier for the video, that can be used across instances
+          allOf:
+            - $ref: '#/components/schemas/UUIDv4'
         isLive:
           type: boolean
         createdAt:
@@ -4513,13 +4760,21 @@ components:
           example: 2010-10-01T10:52:46.396Z
           description: used to represent a date of first publication, prior to the practical publication date of `publishedAt`
         category:
-          $ref: '#/components/schemas/VideoConstantNumber-Category'
+          allOf:
+            - $ref: '#/components/schemas/VideoConstantNumber-Category'
+          description: category in which the video is classified
         licence:
-          $ref: '#/components/schemas/VideoConstantNumber-Licence'
+          allOf:
+            - $ref: '#/components/schemas/VideoConstantNumber-Licence'
+          description: licence under which the video is distributed
         language:
-          $ref: '#/components/schemas/VideoConstantString-Language'
+          allOf:
+            - $ref: '#/components/schemas/VideoConstantString-Language'
+          description: main language used in the video
         privacy:
-          $ref: '#/components/schemas/VideoPrivacyConstant'
+          allOf:
+            - $ref: '#/components/schemas/VideoPrivacyConstant'
+          description: privacy policy used to distribute the video
         description:
           type: string
           example: |
@@ -4533,11 +4788,13 @@ components:
         duration:
           type: integer
           example: 1419
+          format: seconds
           description: duration of the video in seconds
         isLocal:
           type: boolean
         name:
           type: string
+          description: title of the video
           example: What is PeerTube?
           minLength: 3
           maxLength: 120
@@ -4565,7 +4822,9 @@ components:
           type: boolean
           nullable: true
         state:
-          $ref: '#/components/schemas/VideoStateConstant'
+          allOf:
+            - $ref: '#/components/schemas/VideoStateConstant'
+          description: represents the internal state of the video processing within the PeerTube instance
         scheduledUpdate:
           nullable: true
           allOf:
@@ -4598,7 +4857,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:
@@ -4623,6 +4882,9 @@ components:
               items:
                 type: string
                 format: url
+              example:
+                - https://peertube2.cpy.re/tracker/announce
+                - wss://peertube2.cpy.re/tracker/socket
             files:
               type: array
               items:
@@ -4644,7 +4906,7 @@ components:
     FileRedundancyInformation:
       properties:
         id:
-          type: integer
+          $ref: '#/components/schemas/id'
         fileUrl:
           type: string
           format: url
@@ -4669,7 +4931,7 @@ components:
     VideoRedundancy:
       properties:
         id:
-          type: integer
+          $ref: '#/components/schemas/id'
         name:
           type: string
         url:
@@ -4700,38 +4962,86 @@ components:
         label:
           type: string
           example: Pending
+    VideoCreateImport:
+      allOf:
+        - type: object
+          additionalProperties: false
+          oneOf:
+            - properties:
+                targetUrl:
+                  $ref: '#/components/schemas/VideoImport/properties/targetUrl'
+              required: [targetUrl]
+            - properties:
+                magnetUri:
+                  $ref: '#/components/schemas/VideoImport/properties/magnetUri'
+              required: [magnetUri]
+            - properties:
+                torrentfile:
+                  $ref: '#/components/schemas/VideoImport/properties/torrentfile'
+              required: [torrentfile]
+        - $ref: '#/components/schemas/VideoUploadRequestCommon'
+      required:
+        - channelId
+        - name
     VideoImport:
       properties:
         id:
-          type: integer
-          example: 2
+          readOnly: true
+          allOf:
+            - $ref: '#/components/schemas/id'
         targetUrl:
           type: string
           format: url
+          description: remote URL where to find the import's source video
           example: https://framatube.org/videos/watch/9c9de5e8-0a1e-484a-b099-e80766180a6d
         magnetUri:
           type: string
           format: uri
+          description: magnet URI allowing to resolve the import's source video
           example: magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-240.torrent&xt=urn:btih:38b4747ff788b30bf61f59d1965cd38f9e48e01f&dn=What+is+PeerTube%3F&tr=wss%3A%2F%2Fframatube.org%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fwebseed%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-240.mp4
+          pattern: /magnet:\?xt=urn:[a-z0-9]+:[a-z0-9]{32}/i
+        torrentfile:
+          writeOnly: true
+          type: string
+          format: binary
+          description: Torrent file containing only the video file
         torrentName:
+          readOnly: true
           type: string
         state:
-          $ref: '#/components/schemas/VideoImportStateConstant'
+          readOnly: true
+          allOf:
+            - $ref: '#/components/schemas/VideoImportStateConstant'
         error:
+          readOnly: true
           type: string
         createdAt:
+          readOnly: true
           type: string
           format: date-time
         updatedAt:
+          readOnly: true
           type: string
           format: date-time
         video:
-          $ref: '#/components/schemas/Video'
+          readOnly: true
+          nullable: true
+          allOf:
+            - $ref: '#/components/schemas/Video'
+    VideoImportsList:
+      properties:
+        total:
+          type: integer
+          example: 1
+        data:
+          type: array
+          maxItems: 100
+          items:
+            $ref: '#/components/schemas/VideoImport'
     Abuse:
       properties:
         id:
-          type: integer
-          example: 7
+          $ref: '#/components/schemas/id'
         reason:
           type: string
           example: The video is a spam
@@ -4756,7 +5066,7 @@ components:
     AbuseMessage:
       properties:
         id:
-          type: integer
+          $ref: '#/components/schemas/id'
         message:
           type: string
           minLength: 2
@@ -4771,9 +5081,9 @@ components:
     VideoBlacklist:
       properties:
         id:
-          type: integer
+          $ref: '#/components/schemas/id'
         videoId:
-          type: integer
+          $ref: '#/components/schemas/Video/properties/id'
         createdAt:
           type: string
           format: date-time
@@ -4800,29 +5110,12 @@ components:
           type: integer
         nsfw:
           type: boolean
-    VideoChannel:
-      properties:
-        displayName:
-          type: string
-          minLength: 1
-          maxLength: 120
-        description:
-          type: string
-          minLength: 3
-          maxLength: 1000
-        isLocal:
-          type: boolean
-        ownerAccount:
-          type: object
-          properties:
-            id:
-              type: integer
-            uuid:
-              $ref: '#/components/schemas/UUIDv4'
     VideoPlaylist:
       properties:
         id:
-          type: integer
+          $ref: '#/components/schemas/id'
+        uuid:
+          $ref: '#/components/schemas/UUIDv4'
         createdAt:
           type: string
           format: date-time
@@ -4833,8 +5126,6 @@ components:
           type: string
           minLength: 3
           maxLength: 1000
-        uuid:
-          $ref: '#/components/schemas/UUIDv4'
         displayName:
           type: string
           minLength: 1
@@ -4843,6 +5134,7 @@ components:
           type: boolean
         videoLength:
           type: integer
+          minimum: 0
         thumbnailPath:
           type: string
         privacy:
@@ -4856,30 +5148,44 @@ components:
     VideoComment:
       properties:
         id:
-          type: integer
+          $ref: '#/components/schemas/id'
         url:
           type: string
           format: url
         text:
           type: string
+          format: html
+          description: Text of the comment
           minLength: 1
-          maxLength: 10000
+          example: This video is wonderful!
         threadId:
-          type: integer
+          $ref: '#/components/schemas/id'
         inReplyToCommentId:
-          type: integer
+          nullable: true
+          allOf:
+            - $ref: '#/components/schemas/id'
         videoId:
-          type: integer
+          $ref: '#/components/schemas/Video/properties/id'
         createdAt:
           type: string
           format: date-time
         updatedAt:
           type: string
           format: date-time
+        deletedAt:
+          nullable: true
+          type: string
+          format: date-time
+          default: null
+        isDeleted:
+          type: boolean
+          default: false
         totalRepliesFromVideoAuthor:
           type: integer
+          minimum: 0
         totalReplies:
           type: integer
+          minimum: 0
         account:
           $ref: '#/components/schemas/Account'
     VideoCommentThreadTree:
@@ -4909,8 +5215,7 @@ components:
     ActorInfo:
       properties:
         id:
-          type: integer
-          example: 11
+          $ref: '#/components/schemas/id'
         name:
           type: string
         displayName:
@@ -4927,20 +5232,29 @@ components:
     Actor:
       properties:
         id:
-          type: integer
-          example: 11
+          $ref: '#/components/schemas/id'
         url:
           type: string
           format: url
         name:
-          type: string
+          description: immutable name of the actor, used to find or mention it
+          allOf:
+            - $ref: '#/components/schemas/username'
         host:
           type: string
           format: hostname
+          description: server on which the actor is resident
+        hostRedundancyAllowed:
+          type: boolean
+          description: whether this actor's host allows redundancy of its videos
         followingCount:
           type: integer
+          minimum: 0
+          description: number of actors subscribed to by this actor, as seen by this instance
         followersCount:
           type: integer
+          minimum: 0
+          description: number of followers of this actor, as seen by this instance
         createdAt:
           type: string
           format: date-time
@@ -4954,16 +5268,22 @@ components:
         - $ref: '#/components/schemas/Actor'
         - properties:
             userId:
-              type: string
-              example: 2
+              description: object id for the user tied to this account
+              allOf:
+                - $ref: '#/components/schemas/User/properties/id'
             displayName:
               type: string
+              description: editable name of the account, displayed in its representations
+              minLength: 3
+              maxLength: 120
             description:
               type: string
+              description: text or bio displayed on the account's profile
     UserWatchingVideo:
       properties:
         currentTime:
           type: integer
+          format: seconds
           description: timestamp within the video, in seconds
           example: 5
     ServerConfig:
@@ -5051,7 +5371,7 @@ components:
             enabledResolutions:
               type: array
               items:
-                type: integer
+                $ref: '#/components/schemas/VideoResolutionSet'
         import:
           type: object
           properties:
@@ -5136,8 +5456,10 @@ components:
           properties:
             videoQuota:
               type: integer
+              example: 16810141515
             videoQuotaDaily:
               type: integer
+              example: 1681014151
         trending:
           type: object
           properties:
@@ -5252,25 +5574,44 @@ components:
               type: boolean
         user:
           type: object
+          description: Settings that apply to new users, if registration is enabled
           properties:
             videoQuota:
               type: integer
+              example: 16810141515
             videoQuotaDaily:
               type: integer
+              example: 1681014151
         transcoding:
           type: object
+          description: Settings pertaining to transcoding jobs
           properties:
             enabled:
               type: boolean
             allowAdditionalExtensions:
               type: boolean
+              description: Allow your users to upload .mkv, .mov, .avi, .wmv, .flv, .f4v, .3g2, .3gp, .mts, m2ts, .mxf, .nut videos
             allowAudioFiles:
               type: boolean
+              description: If a user uploads an audio file, PeerTube will create a video by merging the preview file and the audio file
             threads:
               type: integer
+              description: Amount of threads used by ffmpeg for 1 transcoding job
+            concurrency:
+              type: number
+              description: Amount of transcoding jobs to execute in parallel
+            profile:
+              type: string
+              enum:
+                - default
+              description: |
+                New profiles can be added by plugins ; available in core PeerTube: 'default'.
             resolutions:
               type: object
+              description: Resolutions to transcode _new videos_ to
               properties:
+                0p:
+                  type: boolean
                 240p:
                   type: boolean
                 360p:
@@ -5285,8 +5626,15 @@ components:
                   type: boolean
                 2160p:
                   type: boolean
+            webtorrent:
+              type: object
+              description: WebTorrent-specific settings
+              properties:
+                enabled:
+                  type: boolean
             hls:
               type: object
+              description: HLS-specific settings
               properties:
                 enabled:
                   type: boolean
@@ -5330,7 +5678,7 @@ components:
     Follow:
       properties:
         id:
-          type: integer
+          $ref: '#/components/schemas/id'
         follower:
           $ref: '#/components/schemas/Actor'
         following:
@@ -5369,9 +5717,7 @@ components:
     Job:
       properties:
         id:
-          type: integer
-          minimum: 0
-          example: 42
+          $ref: '#/components/schemas/id'
         state:
           type: string
           enum:
@@ -5415,44 +5761,44 @@ components:
           type: object
           properties:
             id:
-              type: integer
-              example: 8
+              $ref: '#/components/schemas/id'
             account:
               type: object
               properties:
                 id:
-                  type: integer
-                  example: 37
+                  $ref: '#/components/schemas/id'
     VideoUploadRequestCommon:
       properties:
         name:
           description: Video name
           type: string
+          example: What is PeerTube?
+          minLength: 3
+          maxLength: 120
         channelId:
           description: Channel id that will contain this video
           type: integer
+          example: 3
+          minimum: 1
         privacy:
           $ref: '#/components/schemas/VideoPrivacySet'
         category:
-          description: Video category
-          type: integer
-          example: 4
+          $ref: '#/components/schemas/VideoCategorySet'
         licence:
-          description: Video licence
-          type: integer
-          example: 2
+          $ref: '#/components/schemas/VideoLicenceSet'
         language:
-          description: Video language
-          type: string
+          $ref: '#/components/schemas/VideoLanguageSet'
         description:
           description: Video description
           type: string
+          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)**
         waitTranscoding:
           description: Whether or not we wait transcoding before publish the video
           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
@@ -5463,6 +5809,9 @@ components:
           minItems: 1
           maxItems: 5
           uniqueItems: true
+          example:
+            - framasoft
+            - peertube
           items:
             type: string
             minLength: 2
@@ -5512,6 +5861,7 @@ components:
               description: Video filename including extension
               type: string
               format: filename
+              example: what_is_peertube.mp4
             thumbnailfile:
               description: Video thumbnail file
               type: string
@@ -5526,10 +5876,9 @@ components:
           type: object
           properties:
             id:
-              type: integer
-              example: 8
+              $ref: '#/components/schemas/Video/properties/id'
             uuid:
-              $ref: '#/components/schemas/UUIDv4'
+              $ref: '#/components/schemas/Video/properties/uuid'
     CommentThreadResponse:
       properties:
         total:
@@ -5556,35 +5905,46 @@ components:
             $ref: '#/components/schemas/Video'
     User:
       properties:
-        id:
-          type: integer
-          readOnly: true
-        username:
+        account:
+          $ref: '#/components/schemas/Account'
+        autoPlayNextVideo:
+          type: boolean
+          description: Automatically start playing the upcoming video after the currently playing video
+        autoPlayNextVideoPlaylist:
+          type: boolean
+          description: Automatically start playing the video on the playlist after the currently playing video
+        autoPlayVideo:
+          type: boolean
+          description: Automatically start playing the video on the watch page
+        blocked:
+          type: boolean
+        blockedReason:
+          type: string
+        createdAt:
           type: string
-          description: The user username
-          minLength: 1
-          maxLength: 50
         email:
           type: string
           format: email
           description: The user email
+        emailVerified:
+          type: boolean
+          description: Has the user confirmed their email address?
+        id:
+          allOf:
+            - $ref: '#/components/schemas/id'
+          readOnly: true
         pluginAuth:
           type: string
           description: Auth plugin to use to authenticate the user
-        theme:
+        lastLoginDate:
           type: string
-          description: Theme enabled by this user
-        emailVerified:
+          format: date-time
+        noInstanceConfigWarningModal:
+          type: boolean
+        noWelcomeModal:
           type: boolean
-          description: Has the user confirmed their email address?
         nsfwPolicy:
           $ref: '#/components/schemas/NSFWPolicy'
-        webtorrentEnabled:
-          type: boolean
-          description: Enable P2P in the player
-        autoPlayVideo:
-          type: boolean
-          description: Automatically start playing the video on the watch page
         role:
           $ref: '#/components/schemas/UserRole'
         roleLabel:
@@ -5593,64 +5953,66 @@ components:
             - User
             - Moderator
             - Administrator
-        videoQuota:
-          type: integer
-          description: The user video quota
-        videoQuotaDaily:
-          type: integer
-          description: The user daily video quota
-        videosCount:
-          type: integer
-        abusesCount:
-          type: integer
-        abusesAcceptedCount:
-          type: integer
-        abusesCreatedCount:
-          type: integer
-        videoCommentsCount:
-          type: integer
-        noInstanceConfigWarningModal:
-          type: boolean
-        noWelcomeModal:
-          type: boolean
-        blocked:
-          type: boolean
-        blockedReason:
-          type: string
-        createdAt:
+        theme:
           type: string
-        account:
-          $ref: '#/components/schemas/Account'
+          description: Theme enabled by this user
+        username:
+          $ref: '#/components/schemas/username'
         videoChannels:
           type: array
           items:
             $ref: '#/components/schemas/VideoChannel'
+        videoQuota:
+          type: integer
+          description: The user video quota in bytes
+          example: -1
+        videoQuotaDaily:
+          type: integer
+          description: The user daily video quota in bytes
+          example: -1
+        webtorrentEnabled:
+          type: boolean
+          description: Enable P2P in the player
+    UserWithStats:
+      allOf:
+        - $ref: '#/components/schemas/User'
+        - properties:
+            # optionally present fields: they require WITH_STATS scope
+            videosCount:
+              type: integer
+              description: Count of videos published 
+            abusesCount:
+              type: integer
+              description: Count of reports/abuses of which the user is a target
+            abusesAcceptedCount:
+              type: integer
+              description: Count of reports/abuses created by the user and accepted/acted upon by the moderation team
+            abusesCreatedCount:
+              type: integer
+              description: Count of reports/abuses created by the user
+            videoCommentsCount:
+              type: integer
+              description: Count of comments published
     AddUser:
       properties:
         username:
-          type: string
-          description: The user username
-          minLength: 1
-          maxLength: 50
+          $ref: '#/components/schemas/username'
         password:
-          type: string
-          format: password
-          description: The user password. If the smtp server is configured, you can leave empty and an email will be sent
-          minLength: 6
-          maxLength: 255
+          $ref: '#/components/schemas/password'
         email:
           type: string
           format: email
           description: The user email
         videoQuota:
           type: integer
-          description: The user video quota
+          description: The user video quota in bytes
+          example: -1
         videoQuotaDaily:
           type: integer
-          description: The user daily video quota
+          description: The user daily video quota in bytes
+          example: -1
         channelName:
-          type: string
-          description: The user default channel username
+          $ref: '#/components/schemas/usernameChannel'
         role:
           $ref: '#/components/schemas/UserRole'
         adminFlags:
@@ -5664,22 +6026,19 @@ components:
         - role
     UpdateUser:
       properties:
-        id:
-          type: string
-          description: The user id
         email:
-          type: string
-          format: email
           description: The updated email of the user
+          allOf:
+            - $ref: '#/components/schemas/User/properties/email'
         emailVerified:
           type: boolean
           description: Set the email as verified
         videoQuota:
           type: integer
-          description: The updated video quota of the user
+          description: The updated video quota of the user in bytes
         videoQuotaDaily:
           type: integer
-          description: The updated daily video quota of the user
+          description: The updated daily video quota of the user in bytes
         pluginAuth:
           type: string
           nullable: true
@@ -5689,40 +6048,59 @@ components:
           $ref: '#/components/schemas/UserRole'
         adminFlags:
           $ref: '#/components/schemas/UserAdminFlags'
-      required:
-        - id
     UpdateMe:
+      # see shared/models/users/user-update-me.model.ts:
       properties:
         password:
-          type: string
-          format: password
-          description: Your new password
-          minLength: 6
-          maxLength: 255
+          $ref: '#/components/schemas/password'
+        currentPassword:
+          $ref: '#/components/schemas/password'
         email:
+          description: new email used for login and service communications
+          allOf:
+            - $ref: '#/components/schemas/User/properties/email'
+        displayName:
           type: string
-          format: email
-          description: Your new email
+          description: new name of the user in its representations
+          minLength: 3
+          maxLength: 120
         displayNSFW:
           type: string
-          description: Your new displayNSFW
+          description: new NSFW display policy
           enum:
             - 'true'
             - 'false'
             - both
+        webTorrentEnabled:
+          type: boolean
+          description: whether to enable P2P in the player or not
         autoPlayVideo:
           type: boolean
-          description: Your new autoPlayVideo
-      required:
-        - password
-        - email
-        - displayNSFW
-        - autoPlayVideo
+          description: new preference regarding playing videos automatically
+        autoPlayNextVideo:
+          type: boolean
+          description: new preference regarding playing following videos automatically
+        autoPlayNextVideoPlaylist:
+          type: boolean
+          description: new preference regarding playing following playlist videos automatically
+        videosHistoryEnabled:
+          type: boolean
+          description: whether to keep track of watched history or not
+        videoLanguages:
+          type: array
+          items:
+            type: string
+          description: list of languages to filter videos down to
+        theme:
+          type: string
+        noInstanceConfigWarningModal:
+          type: boolean
+        noWelcomeModal:
+          type: boolean
     GetMeVideoRating:
       properties:
         id:
-          type: string
-          description: Id of the video
+          $ref: '#/components/schemas/id'
         rating:
           type: string
           enum:
@@ -5750,77 +6128,158 @@ components:
     RegisterUser:
       properties:
         username:
-          type: string
-          description: The username of the user
-          minLength: 1
-          maxLength: 50
-          pattern: '/^[a-z0-9._]{1,50}$/'
+          description: immutable name of the user, used to find or mention its actor
+          allOf:
+            - $ref: '#/components/schemas/username'
         password:
-          type: string
-          format: password
-          description: The password of the user
-          minLength: 6
-          maxLength: 255
+          $ref: '#/components/schemas/password'
         email:
           type: string
           format: email
-          description: The email of the user
+          description: email of the user, used for login or service communications
         displayName:
           type: string
-          description: The user display name
+          description: editable name of the user, displayed in its representations
           minLength: 1
           maxLength: 120
         channel:
           type: object
+          description: channel base information used to create the first channel of the user
           properties:
             name:
-              type: string
-              description: The username for the default channel
-              pattern: '/^[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\\-_.:]+$/'
+              $ref: '#/components/schemas/usernameChannel'
             displayName:
-              type: string
-              description: The display name for the default channel
-              minLength: 1
-              maxLength: 120
+              $ref: '#/components/schemas/VideoChannel/properties/displayName'
       required:
         - username
         - password
         - email
 
-    VideoChannelCommon:
+    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
         displayName:
           type: string
+          description: editable name of the channel, displayed in its representations
+          example: Videos of Framasoft
           minLength: 1
           maxLength: 120
         description:
           type: string
+          example: Videos made with <3 by Framasoft
           minLength: 3
           maxLength: 1000
         support:
           type: string
-          description: 'A 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
+          description: text shown by default on all videos of this channel, to tell the audience how to support it
+          example: Please support our work on https://soutenir.framasoft.org/en/ <3
           minLength: 3
           maxLength: 1000
+        # GET-only properties
+        id:
+          readOnly: true
+          allOf:
+            - $ref: '#/components/schemas/id'
+        isLocal:
+          readOnly: true
+          type: boolean
+        updatedAt:
+          readOnly: true
+          type: string
+          format: date-time
+        ownerAccount:
+          readOnly: true
+          nullable: true
+          type: object
+          properties:
+            id:
+              type: integer
+            uuid:
+              $ref: '#/components/schemas/UUIDv4'
     VideoChannelCreate:
       allOf:
-        - $ref: '#/components/schemas/VideoChannelCommon'
+        - $ref: '#/components/schemas/VideoChannel'
         - properties:
             name:
-              type: string
-              minLength: 1
-              maxLength: 120
+              description: username of the channel to create
+              allOf:
+                - $ref: '#/components/schemas/usernameChannel'
       required:
         - name
         - displayName
     VideoChannelUpdate:
       allOf:
-        - $ref: '#/components/schemas/VideoChannelCommon'
+        - $ref: '#/components/schemas/VideoChannel'
         - properties:
             bulkVideosSupportUpdate:
               type: boolean
-              description: 'Update the support field for all videos of this channel'
+              description: Update the support field for all videos of this channel
+    VideoChannelList:
+      properties:
+        total:
+          type: integer
+          example: 1
+        data:
+          type: array
+          items:
+            allOf:
+              - $ref: '#/components/schemas/VideoChannel'
+              - $ref: '#/components/schemas/Actor'
 
     MRSSPeerLink:
       type: object
@@ -6025,7 +6484,7 @@ components:
     Notification:
       properties:
         id:
-          type: integer
+          $ref: '#/components/schemas/id'
         type:
           type: integer
           description: >
@@ -6073,7 +6532,7 @@ components:
           type: object
           properties:
             id:
-              type: integer
+              $ref: '#/components/schemas/id'
             video:
               nullable: true
               $ref: '#/components/schemas/VideoInfo'
@@ -6081,9 +6540,7 @@ components:
               type: string
               nullable: true
             magnetUri:
-              type: string
-              format: uri
-              nullable: true
+              $ref: '#/components/schemas/VideoImport/properties/magnetUri'
             targetUri:
               type: string
               format: uri
@@ -6093,7 +6550,7 @@ components:
           type: object
           properties:
             id:
-              type: integer
+              $ref: '#/components/schemas/id'
             threadId:
               type: integer
             video:
@@ -6105,7 +6562,7 @@ components:
           type: object
           properties:
             id:
-              type: integer
+              $ref: '#/components/schemas/id'
             video:
               allOf:
                 - $ref: '#/components/schemas/VideoInfo'
@@ -6114,7 +6571,7 @@ components:
           type: object
           properties:
             id:
-              type: integer
+              $ref: '#/components/schemas/id'
             video:
               allOf:
                 - $ref: '#/components/schemas/VideoInfo'
@@ -6127,7 +6584,7 @@ components:
           nullable: true
           properties:
             id:
-              type: integer
+              $ref: '#/components/schemas/id'
             follower:
               $ref: '#/components/schemas/ActorInfo'
             state: