X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=support%2Fdoc%2Fapi%2Fopenapi.yaml;h=9bf5024bb02610df5ea3a5a3f21e3acbcb510060;hb=597da8dd814a1e4b4dc69dd3ebed50c11619045d;hp=bfe3c6da4b9418851ef35fd43b268b7ec40325e9;hpb=985ece57551515e3b10a83c4a826bf35913a992a;p=github%2FChocobozzz%2FPeerTube.git diff --git a/support/doc/api/openapi.yaml b/support/doc/api/openapi.yaml index bfe3c6da4..9bf5024bb 100644 --- a/support/doc/api/openapi.yaml +++ b/support/doc/api/openapi.yaml @@ -1,15 +1,15 @@ openapi: 3.0.0 info: title: PeerTube - version: 3.1.0 + version: 4.0.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,28 +38,91 @@ 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, completed by a [RFC7807-compliant](https://tools.ietf.org/html/rfc7807) response body. ``` + HTTP 1.1 404 Not Found + Content-Type: application/problem+json; charset=utf-8 + + { + "detail": "Video not found", + "docs": "https://docs.joinpeertube.org/api-rest-reference.html#operation/getVideo", + "status": 404, + "title": "Not Found", + "type": "about:blank" + } + ``` + + We provide error `type` values 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. Types are used to disambiguate errors that bear the same status code + and are non-obvious: + + ``` + HTTP 1.1 403 Forbidden + Content-Type: application/problem+json; charset=utf-8 + + { + "detail": "Cannot get this video regarding follow constraints", + "docs": "https://docs.joinpeertube.org/api-rest-reference.html#operation/getVideo", + "status": 403, + "title": "Forbidden", + "type": "https://docs.joinpeertube.org/api-rest-reference.html#section/Errors/does_not_respect_follow_constraints" + } + ``` + + Here a 403 error could otherwise mean that the video is private or blocklisted. + + ### 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 description: + + ``` + HTTP 1.1 400 Bad Request + Content-Type: application/problem+json; charset=utf-8 + { - "code": "unauthorized_request", // example inner error code - "error": "Token is invalid." // example exposed error message + "detail": "Incorrect request parameters: id", + "docs": "https://docs.joinpeertube.org/api-rest-reference.html#operation/getVideo", + "instance": "/api/v1/videos/9c9de5e8-0a1e-484a-b099-e80766180", + "invalid-params": { + "id": { + "location": "params", + "msg": "Invalid value", + "param": "id", + "value": "9c9de5e8-0a1e-484a-b099-e80766180" + } + }, + "status": 400, + "title": "Bad Request", + "type": "about:blank" } ``` + Where `id` is the name of the field concerned by the error, within the route definition. + `invalid-params..location` can be either 'params', 'body', 'header', 'query' or 'cookies', and + `invalid-params..value` reports the value that didn't pass validation whose `invalid-params..msg` + is about. + + ### Deprecated error fields + + Some fields could be included with previous versions. They are still included but their use is deprecated: + - `error`: superseded by `detail` + - `code`: superseded by `type` (which is now an URI) + # 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* | 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, *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 +130,37 @@ info: | Header | Description | |-------------------------|------------------------------------------------------------| - | X-RateLimit-Limit | Number of max requests allowed in the current time period | - | X-RateLimit-Remaining | Number of remaining requests in the current time period | - | X-RateLimit-Reset | Timestamp of end of current time period as UNIX timestamp | - | Retry-After | Seconds to delay after the first `429` is received | + | `X-RateLimit-Limit` | Number of max requests allowed in the current time period | + | `X-RateLimit-Remaining` | Number of remaining requests in the current time period | + | `X-RateLimit-Reset` | Timestamp of end of current time period as UNIX timestamp | + | `Retry-After` | Seconds to delay after the first `429` is received | + + # CORS + + This API features [Cross-Origin Resource Sharing (CORS)](https://fetch.spec.whatwg.org/), + allowing cross-domain communication from the browser for some routes: + + | Endpoint | + |------------------------- ---| + | `/api/*` | + | `/download/*` | + | `/lazy-static/*` | + | `/live/segments-sha256/*` | + | `/.well-known/webfinger` | + + In addition, all routes serving ActivityPub are CORS-enabled for all origins. externalDocs: url: https://docs.joinpeertube.org/api-rest-reference.html tags: + - name: Register + description: | + As a visitor, you can use this API to open an account (if registrations are open on + that PeerTube instance). As an admin, you should use the dedicated [User creation + API](#operation/addUser) instead. + - name: Session + x-displayName: Login/Logout + description: | + Sessions deal with access tokens over time. Only __one session token can currently be used at a time__. - name: Accounts description: > Accounts encompass remote accounts discovered across the federation, @@ -180,6 +267,10 @@ tags: description: Like/dislike a video. - name: Video Playlists description: Operations dealing with playlists of videos. Playlists are bound to users and/or channels. + - name: Video Files + description: Operations on video files + - name: Video Transcoding + description: Video transcoding related operations - name: Feeds description: Server syndication feeds - name: Search @@ -191,12 +282,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](#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 @@ -216,11 +313,16 @@ x-tagGroups: - Video Playlists - Video Ownership Change - Video Mirroring + - Video Files + - Video Transcoding - Live Videos - Feeds - name: Search tags: - Search + - name: Custom pages + tags: + - Homepage - name: Moderation tags: - Abuses @@ -242,6 +344,7 @@ paths: tags: - Accounts summary: Get an account + operationId: getAccount parameters: - $ref: '#/components/parameters/name' responses: @@ -253,12 +356,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' @@ -268,7 +373,11 @@ paths: - $ref: '#/components/parameters/licenceOneOf' - $ref: '#/components/parameters/languageOneOf' - $ref: '#/components/parameters/nsfw' - - $ref: '#/components/parameters/filter' + - $ref: '#/components/parameters/isLocal' + - $ref: '#/components/parameters/include' + - $ref: '#/components/parameters/privacyOneOf' + - $ref: '#/components/parameters/hasHLSFiles' + - $ref: '#/components/parameters/hasWebtorrentFiles' - $ref: '#/components/parameters/skipCount' - $ref: '#/components/parameters/start' - $ref: '#/components/parameters/count' @@ -314,11 +423,43 @@ paths: json = r.json() print(json) + + '/accounts/{name}/followers': + get: + tags: + - Accounts + summary: 'List followers of an account' + security: + - OAuth2: [] + operationId: getAccountFollowers + parameters: + - $ref: '#/components/parameters/name' + - $ref: '#/components/parameters/start' + - $ref: '#/components/parameters/count' + - $ref: '#/components/parameters/followersSort' + - $ref: '#/components/parameters/search' + responses: + '200': + description: successful operation + content: + application/json: + schema: + type: object + properties: + total: + type: integer + example: 1 + data: + type: array + items: + $ref: '#/components/schemas/Follow' + /accounts: get: tags: - Accounts summary: List accounts + operationId: getAccounts parameters: - $ref: '#/components/parameters/start' - $ref: '#/components/parameters/count' @@ -332,11 +473,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 @@ -347,9 +490,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: @@ -362,9 +507,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: @@ -379,6 +526,7 @@ paths: $ref: '#/components/schemas/ServerConfigCustom' put: summary: Set instance runtime configuration + operationId: putCustomConfig tags: - Config security: @@ -395,6 +543,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: @@ -403,9 +552,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 @@ -445,66 +630,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' @@ -514,16 +741,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 actors (PeerTube instance, channel or account) responses: '204': description: successful operation @@ -541,9 +774,37 @@ paths: type: string format: hostname uniqueItems: true + handles: + type: array + items: + type: string + uniqueItems: true + + '/server/following/{hostOrHandle}': + delete: + summary: Unfollow an actor (PeerTube instance, channel or account) + security: + - OAuth2: + - admin + tags: + - Instance Follows + parameters: + - name: hostOrHandle + in: path + required: true + description: The hostOrHandle to unfollow + schema: + type: string + responses: + '204': + description: successful operation + '404': + description: host or handle not found + /users: post: summary: Create a user + operationId: addUser security: - OAuth2: - admin @@ -558,18 +819,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': @@ -579,10 +840,13 @@ 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 + operationId: getUsers security: - OAuth2: - admin @@ -603,6 +867,7 @@ paths: type: array items: $ref: '#/components/schemas/User' + '/users/{id}': parameters: - $ref: '#/components/parameters/id' @@ -613,7 +878,7 @@ paths: - admin tags: - Users - operationId: delUserId + operationId: delUser responses: '204': description: successful operation @@ -623,7 +888,7 @@ paths: - OAuth2: [] tags: - Users - operationId: getUserId + operationId: getUser parameters: - name: withStats in: query @@ -648,7 +913,7 @@ paths: - OAuth2: [] tags: - Users - operationId: putUserId + operationId: putUser responses: '204': description: successful operation @@ -658,11 +923,132 @@ 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 + '400': + x-summary: client or credentials are invalid + description: | + Disambiguate via `type`: + - `invalid_client` for an unmatched `client_id` + - `invalid_grant` for unmatched credentials + '401': + x-summary: token expired + description: | + Disambiguate via `type`: + - default value for a regular authentication failure + - `invalid_token` for an expired token + x-codeSamples: + - lang: Shell + source: | + ## DEPENDENCIES: jq + API="https://peertube2.cpy.re/api/v1" + USERNAME="" + 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 @@ -672,9 +1058,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 @@ -691,6 +1123,7 @@ paths: $ref: '#/components/schemas/User' put: summary: Update my user information + operationId: putUserInfo security: - OAuth2: - user @@ -705,6 +1138,7 @@ paths: schema: $ref: '#/components/schemas/UpdateMe' required: true + /users/me/videos/imports: get: summary: Get video imports of my user @@ -725,6 +1159,7 @@ paths: application/json: schema: $ref: '#/components/schemas/VideoImportsList' + /users/me/video-quota-used: get: summary: Get my user used quota @@ -743,10 +1178,13 @@ 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: summary: Get rate of my user for a video @@ -759,9 +1197,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 @@ -769,6 +1207,7 @@ paths: application/json: schema: $ref: '#/components/schemas/GetMeVideoRating' + /users/me/videos: get: summary: Get videos of my user @@ -789,6 +1228,7 @@ paths: application/json: schema: $ref: '#/components/schemas/VideoListResponse' + /users/me/subscriptions: get: summary: Get my user subscriptions @@ -804,6 +1244,10 @@ paths: responses: '200': description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/VideoChannelList' post: tags: - My Subscriptions @@ -830,6 +1274,7 @@ paths: responses: '200': description: successful operation + /users/me/subscriptions/exist: get: summary: Get if subscriptions exist for my user @@ -847,6 +1292,7 @@ paths: application/json: schema: type: object + /users/me/subscriptions/videos: get: summary: List videos of subscriptions of my user @@ -864,7 +1310,11 @@ paths: - $ref: '#/components/parameters/licenceOneOf' - $ref: '#/components/parameters/languageOneOf' - $ref: '#/components/parameters/nsfw' - - $ref: '#/components/parameters/filter' + - $ref: '#/components/parameters/isLocal' + - $ref: '#/components/parameters/include' + - $ref: '#/components/parameters/privacyOneOf' + - $ref: '#/components/parameters/hasHLSFiles' + - $ref: '#/components/parameters/hasWebtorrentFiles' - $ref: '#/components/parameters/skipCount' - $ref: '#/components/parameters/start' - $ref: '#/components/parameters/count' @@ -876,6 +1326,7 @@ paths: application/json: schema: $ref: '#/components/schemas/VideoListResponse' + '/users/me/subscriptions/{subscriptionHandle}': get: summary: Get subscription of my user @@ -905,6 +1356,7 @@ paths: responses: '200': description: successful operation + /users/me/notifications: get: summary: List my notifications @@ -928,6 +1380,7 @@ paths: application/json: schema: $ref: '#/components/schemas/NotificationListResponse' + /users/me/notifications/read: post: summary: Mark notifications as read by their id @@ -951,6 +1404,7 @@ paths: responses: '204': description: successful operation + /users/me/notifications/read-all: post: summary: Mark all my notification as read @@ -961,6 +1415,7 @@ paths: responses: '204': description: successful operation + /users/me/notification-settings: put: summary: Update my notification settings @@ -1001,6 +1456,7 @@ paths: responses: '204': description: successful operation + /users/me/history/videos: get: summary: List watched videos history @@ -1019,6 +1475,7 @@ paths: application/json: schema: $ref: '#/components/schemas/VideoListResponse' + /users/me/history/videos/remove: post: summary: Clear video history @@ -1039,6 +1496,7 @@ paths: responses: '204': description: successful operation + /users/me/avatar/pick: post: summary: Update my user avatar @@ -1071,12 +1529,13 @@ paths: type: object properties: avatarfile: - description: The file to upload. + description: The file to upload type: string format: binary encoding: avatarfile: contentType: image/png, image/jpeg + /users/me/avatar: delete: summary: Delete my avatar @@ -1098,6 +1557,7 @@ paths: responses: '200': description: successful operation + '/videos/ownership/{id}/accept': post: summary: Accept ownership change request @@ -1114,6 +1574,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 @@ -1130,6 +1591,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 @@ -1157,9 +1619,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: @@ -1170,7 +1634,11 @@ paths: - $ref: '#/components/parameters/licenceOneOf' - $ref: '#/components/parameters/languageOneOf' - $ref: '#/components/parameters/nsfw' - - $ref: '#/components/parameters/filter' + - $ref: '#/components/parameters/isLocal' + - $ref: '#/components/parameters/include' + - $ref: '#/components/parameters/privacyOneOf' + - $ref: '#/components/parameters/hasHLSFiles' + - $ref: '#/components/parameters/hasWebtorrentFiles' - $ref: '#/components/parameters/skipCount' - $ref: '#/components/parameters/start' - $ref: '#/components/parameters/count' @@ -1182,6 +1650,7 @@ paths: application/json: schema: $ref: '#/components/schemas/VideoListResponse' + /videos/categories: get: summary: List available video categories @@ -1200,6 +1669,7 @@ paths: examples: nightly: externalValue: https://peertube2.cpy.re/api/v1/videos/categories + /videos/licences: get: summary: List available video licences @@ -1218,6 +1688,7 @@ paths: examples: nightly: externalValue: https://peertube2.cpy.re/api/v1/videos/licences + /videos/languages: get: summary: List available video languages @@ -1236,6 +1707,7 @@ paths: examples: nightly: externalValue: https://peertube2.cpy.re/api/v1/videos/languages + /videos/privacies: get: summary: List available video privacy policies @@ -1254,9 +1726,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: @@ -1296,7 +1770,7 @@ paths: type: string support: description: A text tell the audience how to support the video creator - example: Please support my work on ! <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 @@ -1318,6 +1792,9 @@ paths: commentsEnabled: description: Enable or disable comments for this video type: boolean + downloadEnabled: + description: Enable or disable downloading for this video + type: boolean originallyPublishedAt: description: Date when the content was originally published type: string @@ -1331,6 +1808,7 @@ paths: contentType: image/jpeg get: summary: Get a video + operationId: getVideo tags: - Video parameters: @@ -1344,6 +1822,7 @@ paths: $ref: '#/components/schemas/VideoDetails' delete: summary: Delete a video + operationId: delVideo security: - OAuth2: [] tags: @@ -1353,9 +1832,11 @@ paths: responses: '204': description: successful operation + '/videos/{id}/description': get: summary: Get complete video description + operationId: getVideoDesc tags: - Video parameters: @@ -1366,10 +1847,17 @@ 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 + operationId: addView tags: - Video parameters: @@ -1377,9 +1865,11 @@ paths: responses: '204': description: successful operation + '/videos/{id}/watching': put: summary: Set watching progress of a video + operationId: setProgress tags: - Video security: @@ -1395,6 +1885,7 @@ paths: responses: '204': description: successful operation + /videos/upload: post: summary: Upload a video @@ -1412,14 +1903,15 @@ paths: application/json: schema: $ref: '#/components/schemas/VideoUploadResponse' - '400': - description: invalid file field, schedule date or parameter '403': description: video didn't pass upload filter '408': description: upload has timed out '413': - description: video file too large, due to quota or max body size limit set by the reverse-proxy + x-summary: video file too large, due to quota or max body size limit set by the reverse-proxy + description: | + If the response has no body, it means the reverse-proxy didn't let it through. Otherwise disambiguate via `type`: + - `quota_reached` for quota limits wether daily or global headers: X-File-Maximum-Size: schema: @@ -1451,26 +1943,27 @@ paths: FILE_PATH="" CHANNEL_ID="" 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 @@ -1517,10 +2010,12 @@ paths: schema: type: number example: 0 - '400': - description: invalid file field, schedule date or parameter '413': - description: video file too large, due to quota, absolute max file size or concurrent partial upload limit + x-summary: video file too large, due to quota, absolute max file size or concurrent partial upload limit + description: | + Disambiguate via `type`: + - `max_file_size_reached` for the absolute file size limit + - `quota_reached` for quota limits whether daily or global '415': description: video type unsupported put: @@ -1534,7 +2029,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 @@ -1596,10 +2091,21 @@ paths: example: 0 '403': description: video didn't pass upload filter - '413': - description: video file too large, due to quota or max body size limit set by the reverse-proxy + '404': + description: upload not found + '409': + description: chunk doesn't match range '422': description: video unreadable + '429': + description: too many concurrent requests + '503': + description: upload is already being processed + headers: + 'Retry-After': + schema: + type: number + example: 300 delete: summary: Cancel the resumable upload of a video, deleting any data uploaded so far description: Uses [a resumable protocol](https://github.com/kukhariev/node-uploadx/blob/master/proto.md) to cancel the upload of a video @@ -1611,7 +2117,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 @@ -1632,6 +2138,9 @@ paths: schema: type: number example: 0 + '404': + description: upload not found + /videos/imports: post: summary: Import a video @@ -1646,75 +2155,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: - $ref: '#/components/schemas/VideoCategorySet' - licence: - $ref: '#/components/schemas/VideoLicenceSet' - language: - $ref: '#/components/schemas/VideoLanguageSet' - 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 ! <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 @@ -1739,7 +2180,7 @@ paths: /videos/live: post: summary: Create a live - operationId: createLive + operationId: addLive security: - OAuth2: [] tags: @@ -1752,8 +2193,20 @@ paths: application/json: schema: $ref: '#/components/schemas/VideoUploadResponse' + '400': + x-summary: validation error, or conflicting `saveReplay` and `permanentLive` parameter set + description: | + Disambiguate via `type`: + - default type for a validation error + - `live_conflicting_permanent_and_save_replay` for conflicting parameters set '403': - description: Live is not enabled, allow replay is not enabled, or max instance/user live videos limit is exceeded + x-summary: live is not enabled, allow replay is not enabled, or max instance/user live videos limit is exceeded + description: | + Disambiguate via `type`: + - `live_not_enabled` for a disabled live feature + - `live_not_allowing_replay` for a disabled replay feature + - `max_instance_lives_limit_reached` for the absolute concurrent live limit + - `max_user_lives_limit_reached` for the user concurrent live limit requestBody: content: multipart/form-data: @@ -1789,7 +2242,7 @@ paths: type: string support: description: A text tell the audience how to support the creator - example: Please support my work on ! <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,7 +2265,7 @@ paths: description: Enable or disable comments for this live video/replay type: boolean downloadEnabled: - description: Enable or disable downloading for the replay of this live + description: Enable or disable downloading for the replay of this live video type: boolean required: - channelId @@ -1858,11 +2311,11 @@ 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: @@ -1954,7 +2407,7 @@ paths: type: string - name: videoIs in: query - description: only list blacklisted or deleted videos + description: only list deleted or blocklisted videos schema: type: string enum: @@ -1987,7 +2440,6 @@ paths: type: array items: $ref: '#/components/schemas/Abuse' - post: summary: Report an abuse security: @@ -2013,13 +2465,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: @@ -2027,20 +2482,32 @@ 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: - '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 @@ -2085,6 +2552,7 @@ paths: description: successful operation '404': description: block not found + '/abuses/{abuseId}/messages': get: summary: List messages of an abuse @@ -2100,10 +2568,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: @@ -2131,6 +2604,7 @@ paths: description: successful operation '400': description: incorrect request parameters + '/abuses/{abuseId}/messages/{abuseMessageId}': delete: summary: Delete an abuse message @@ -2148,6 +2622,7 @@ paths: '/videos/{id}/blacklist': post: summary: Block a video + operationId: addVideoBlock security: - OAuth2: - admin @@ -2161,6 +2636,7 @@ paths: description: successful operation delete: summary: Unblock a video by its id + operationId: delVideoBlock security: - OAuth2: - admin @@ -2174,11 +2650,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 @@ -2220,9 +2698,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: @@ -2242,9 +2722,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 @@ -2273,6 +2755,7 @@ paths: description: video or language not found delete: summary: Delete a video caption + operationId: delVideoCaption security: - OAuth2: - user @@ -2286,9 +2769,11 @@ paths: description: successful operation '404': description: video or language or caption for that language not found + /video-channels: get: summary: List video channels + operationId: getVideoChannels tags: - Video Channels parameters: @@ -2301,17 +2786,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: addVideoChannel security: - OAuth2: [] tags: @@ -2319,14 +2797,26 @@ paths: responses: '204': description: successful operation + content: + application/json: + schema: + type: object + properties: + videoChannel: + type: object + properties: + id: + $ref: '#/components/schemas/VideoChannel/properties/id' requestBody: content: application/json: schema: $ref: '#/components/schemas/VideoChannelCreate' + '/video-channels/{channelHandle}': get: summary: Get a video channel + operationId: getVideoChannel tags: - Video Channels parameters: @@ -2340,6 +2830,7 @@ paths: $ref: '#/components/schemas/VideoChannel' put: summary: Update a video channel + operationId: putVideoChannel security: - OAuth2: [] tags: @@ -2356,6 +2847,7 @@ paths: $ref: '#/components/schemas/VideoChannelUpdate' delete: summary: Delete a video channel + operationId: delVideoChannel security: - OAuth2: [] tags: @@ -2365,33 +2857,70 @@ paths: responses: '204': description: successful operation + '/video-channels/{channelHandle}/videos': get: - summary: List videos of a video channel + summary: List videos of a video channel + operationId: getVideoChannelVideos + tags: + - Video + - Video Channels + parameters: + - $ref: '#/components/parameters/channelHandle' + - $ref: '#/components/parameters/categoryOneOf' + - $ref: '#/components/parameters/isLive' + - $ref: '#/components/parameters/tagsOneOf' + - $ref: '#/components/parameters/tagsAllOf' + - $ref: '#/components/parameters/licenceOneOf' + - $ref: '#/components/parameters/languageOneOf' + - $ref: '#/components/parameters/nsfw' + - $ref: '#/components/parameters/isLocal' + - $ref: '#/components/parameters/include' + - $ref: '#/components/parameters/privacyOneOf' + - $ref: '#/components/parameters/hasHLSFiles' + - $ref: '#/components/parameters/hasWebtorrentFiles' + - $ref: '#/components/parameters/skipCount' + - $ref: '#/components/parameters/start' + - $ref: '#/components/parameters/count' + - $ref: '#/components/parameters/videosSort' + responses: + '200': + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/VideoListResponse' + + '/video-channels/{channelHandle}/followers': + get: tags: - - Video - Video Channels + summary: 'List followers of a video channel' + security: + - OAuth2: [] + operationId: getVideoChannelFollowers parameters: - $ref: '#/components/parameters/channelHandle' - - $ref: '#/components/parameters/categoryOneOf' - - $ref: '#/components/parameters/isLive' - - $ref: '#/components/parameters/tagsOneOf' - - $ref: '#/components/parameters/tagsAllOf' - - $ref: '#/components/parameters/licenceOneOf' - - $ref: '#/components/parameters/languageOneOf' - - $ref: '#/components/parameters/nsfw' - - $ref: '#/components/parameters/filter' - - $ref: '#/components/parameters/skipCount' - $ref: '#/components/parameters/start' - $ref: '#/components/parameters/count' - - $ref: '#/components/parameters/videosSort' + - $ref: '#/components/parameters/followersSort' + - $ref: '#/components/parameters/search' responses: '200': description: successful operation content: application/json: schema: - $ref: '#/components/schemas/VideoListResponse' + type: object + properties: + total: + type: integer + example: 1 + data: + type: array + items: + $ref: '#/components/schemas/Follow' + '/video-channels/{channelHandle}/avatar/pick': post: summary: Update channel avatar @@ -2432,6 +2961,7 @@ paths: encoding: avatarfile: contentType: image/png, image/jpeg + '/video-channels/{channelHandle}/avatar': delete: summary: Delete channel avatar @@ -2445,7 +2975,6 @@ paths: '204': description: successful operation - '/video-channels/{channelHandle}/banner/pick': post: summary: Update channel banner @@ -2486,6 +3015,7 @@ paths: encoding: bannerfile: contentType: image/png, image/jpeg + '/video-channels/{channelHandle}/banner': delete: summary: Delete channel banner @@ -2545,8 +3075,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.' - operationId: createPlaylist + description: If the video playlist is set as public, `videoChannelId` is mandatory. + operationId: addPlaylist security: - OAuth2: [] tags: @@ -2563,9 +3093,11 @@ paths: type: object properties: id: - type: integer + $ref: '#/components/schemas/VideoPlaylist/properties/id' uuid: - $ref: '#/components/schemas/UUIDv4' + $ref: '#/components/schemas/VideoPlaylist/properties/uuid' + shortUUID: + $ref: '#/components/schemas/VideoPlaylist/properties/shortUUID' requestBody: content: multipart/form-data: @@ -2586,22 +3118,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 @@ -2620,7 +3155,7 @@ paths: '204': description: successful operation parameters: - - $ref: '#/components/parameters/idOrUUID' + - $ref: '#/components/parameters/playlistId' requestBody: content: multipart/form-data: @@ -2642,8 +3177,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 @@ -2654,19 +3190,22 @@ 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' + - $ref: '#/components/parameters/start' + - $ref: '#/components/parameters/count' responses: '200': description: successful operation @@ -2675,14 +3214,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 @@ -2696,6 +3236,7 @@ paths: properties: id: type: integer + example: 2 requestBody: content: application/json: @@ -2703,26 +3244,31 @@ 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' + operationId: reorderVideoPlaylist security: - OAuth2: [] tags: - Video Playlists parameters: - - $ref: '#/components/parameters/idOrUUID' + - $ref: '#/components/parameters/playlistId' responses: '204': description: successful operation @@ -2748,15 +3294,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': @@ -2769,18 +3316,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': @@ -2788,7 +3338,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: @@ -2801,7 +3351,7 @@ paths: schema: type: array items: - type: integer + $ref: '#/components/schemas/Video/properties/id' responses: '200': description: successful operation @@ -2821,8 +3371,10 @@ paths: type: integer startTimestamp: type: integer + format: seconds stopTimestamp: type: integer + format: seconds '/accounts/{name}/video-channels': get: @@ -2846,14 +3398,8 @@ 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 @@ -2884,6 +3430,7 @@ paths: type: array items: $ref: '#/components/schemas/VideoRating' + '/videos/{id}/comment-threads': get: summary: List threads of a video @@ -2925,8 +3472,10 @@ paths: type: object properties: text: - type: string - description: 'Text comment' + allOf: + - $ref: '#/components/schemas/VideoComment/properties/text' + format: markdown + maxLength: 10000 required: - text @@ -2945,6 +3494,7 @@ paths: application/json: schema: $ref: '#/components/schemas/VideoCommentThreadTree' + '/videos/{id}/comments/{commentId}': post: summary: Reply to a thread of a video @@ -2971,11 +3521,12 @@ paths: type: object properties: text: - type: string - description: 'Text comment' + allOf: + - $ref: '#/components/schemas/VideoComment/properties/text' + format: markdown + maxLength: 10000 required: - text - delete: summary: Delete a comment or a reply security: @@ -2994,6 +3545,7 @@ paths: description: comment or video does not exist '409': description: comment is already deleted + '/videos/{id}/rate': put: summary: Like/dislike a video @@ -3003,16 +3555,94 @@ paths: - Video Rates parameters: - $ref: '#/components/parameters/idOrUUID' + requestBody: + content: + application/json: + schema: + type: object + properties: + rating: + type: string + enum: + - like + - dislike + required: + - rating + responses: + '204': + description: successful operation + '404': + description: video does not exist + + '/videos/{id}/hls': + delete: + summary: Delete video HLS files + security: + - OAuth2: + - admin + tags: + - Video Files + operationId: delVideoHLS + parameters: + - $ref: '#/components/parameters/idOrUUID' + responses: + '204': + description: successful operation + '404': + description: video does not exist + '/videos/{id}/webtorrent': + delete: + summary: Delete video WebTorrent files + security: + - OAuth2: + - admin + tags: + - Video Files + operationId: delVideoWebTorrent + parameters: + - $ref: '#/components/parameters/idOrUUID' + responses: + '204': + description: successful operation + '404': + description: video does not exist + + '/videos/{id}/transcoding': + post: + summary: Create a transcoding job + security: + - OAuth2: + - admin + tags: + - Video Transcoding + operationId: createVideoTranscoding + parameters: + - $ref: '#/components/parameters/idOrUUID' + requestBody: + content: + application/json: + schema: + type: object + properties: + transcodingType: + type: string + enum: + - hls + - webtorrent + required: + - transcodingType responses: '204': description: successful operation '404': description: video does not exist + /search/videos: get: tags: - Search summary: Search videos + operationId: searchVideos parameters: - name: search in: query @@ -3031,7 +3661,11 @@ paths: - $ref: '#/components/parameters/licenceOneOf' - $ref: '#/components/parameters/languageOneOf' - $ref: '#/components/parameters/nsfw' - - $ref: '#/components/parameters/filter' + - $ref: '#/components/parameters/isLocal' + - $ref: '#/components/parameters/include' + - $ref: '#/components/parameters/privacyOneOf' + - $ref: '#/components/parameters/hasHLSFiles' + - $ref: '#/components/parameters/hasWebtorrentFiles' - $ref: '#/components/parameters/skipCount' - $ref: '#/components/parameters/start' - $ref: '#/components/parameters/count' @@ -3083,11 +3717,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 @@ -3111,12 +3747,85 @@ paths: content: application/json: schema: - type: array - items: - $ref: '#/components/schemas/VideoChannel' + $ref: '#/components/schemas/VideoChannelList' + '500': + description: search index unavailable + + /search/video-playlists: + get: + tags: + - Search + summary: Search playlists + operationId: searchPlaylists + parameters: + - name: search + in: query + required: true + description: > + String to search. If the user can make a remote URI search, and the string is an URI then the + PeerTube instance will fetch the remote object and add it to its database. Then, + you can use the REST API to fetch the complete playlist information and interact with it. + schema: + type: string + - $ref: '#/components/parameters/start' + - $ref: '#/components/parameters/count' + - $ref: '#/components/parameters/searchTarget' + - $ref: '#/components/parameters/sort' + callbacks: + 'searchTarget === search-index': + $ref: '#/components/callbacks/searchIndex' + responses: + '200': + description: successful operation + content: + application/json: + schema: + type: object + properties: + total: + type: integer + example: 1 + data: + type: array + items: + $ref: '#/components/schemas/VideoPlaylist' '500': description: search index unavailable - /blocklist/accounts: + + /blocklist/status: + get: + tags: + - Account Blocks + - Server Blocks + summary: Get block status of accounts/hosts + parameters: + - + name: 'accounts' + in: query + description: 'Check if these accounts are blocked' + example: [ 'goofy@example.com', 'donald@example.com' ] + schema: + type: array + items: + type: string + - + name: 'hosts' + in: query + description: 'Check if these hosts are blocked' + example: [ 'example.com' ] + schema: + type: array + items: + type: string + responses: + '200': + description: successful operation + content: + 'application/json': + schema: + $ref: '#/components/schemas/BlockStatus' + + /server/blocklist/accounts: get: tags: - Account Blocks @@ -3155,7 +3864,8 @@ paths: description: successful operation '409': description: self-blocking forbidden - '/blocklist/accounts/{accountName}': + + '/server/blocklist/accounts/{accountName}': delete: tags: - Account Blocks @@ -3175,7 +3885,8 @@ paths: description: successful operation '404': description: account or account block does not exist - /blocklist/servers: + + /server/blocklist/servers: get: tags: - Server Blocks @@ -3210,11 +3921,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 @@ -3231,11 +3943,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 @@ -3267,11 +3980,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 @@ -3301,6 +4016,7 @@ paths: tags: - Video Mirroring summary: Mirror a video + operationId: putMirroredVideo security: - OAuth2: - admin @@ -3311,7 +4027,7 @@ paths: type: object properties: videoId: - type: integer + $ref: '#/components/schemas/Video/properties/id' required: - videoId responses: @@ -3323,11 +4039,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 @@ -3343,11 +4061,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 @@ -3436,11 +4156,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 @@ -3478,7 +4200,11 @@ paths: type: string - $ref: '#/components/parameters/sort' - $ref: '#/components/parameters/nsfw' - - $ref: '#/components/parameters/filter' + - $ref: '#/components/parameters/isLocal' + - $ref: '#/components/parameters/include' + - $ref: '#/components/parameters/privacyOneOf' + - $ref: '#/components/parameters/hasHLSFiles' + - $ref: '#/components/parameters/hasWebtorrentFiles' responses: '204': description: successful operation @@ -3522,12 +4248,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 @@ -3557,7 +4285,11 @@ paths: required: true - $ref: '#/components/parameters/sort' - $ref: '#/components/parameters/nsfw' - - $ref: '#/components/parameters/filter' + - $ref: '#/components/parameters/isLocal' + - $ref: '#/components/parameters/include' + - $ref: '#/components/parameters/privacyOneOf' + - $ref: '#/components/parameters/hasHLSFiles' + - $ref: '#/components/parameters/hasWebtorrentFiles' responses: '204': description: successful operation @@ -3584,11 +4316,13 @@ paths: type: object '406': description: accept header unsupported + /plugins: get: tags: - Plugins summary: List plugins + operationId: getPlugins security: - OAuth2: - admin @@ -3611,11 +4345,13 @@ paths: application/json: schema: $ref: '#/components/schemas/PluginResponse' + /plugins/available: get: tags: - Plugins summary: List available plugins + operationId: getAvailablePlugins security: - OAuth2: - admin @@ -3644,11 +4380,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 @@ -3677,11 +4415,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 @@ -3712,11 +4452,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 @@ -3737,11 +4479,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 @@ -3756,6 +4500,7 @@ paths: $ref: '#/components/schemas/Plugin' '404': description: plugin not found + /plugins/{npmName}/settings: put: tags: @@ -3780,6 +4525,7 @@ paths: description: successful operation '404': description: plugin not found + /plugins/{npmName}/public-settings: get: tags: @@ -3797,6 +4543,7 @@ paths: additionalProperties: true '404': description: plugin not found + /plugins/{npmName}/registered-settings: get: tags: @@ -3817,6 +4564,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) @@ -3924,7 +4672,7 @@ components: name: sort in: query required: false - description: Sort blacklists by criteria + description: Sort blocklists by criteria schema: type: string enum: @@ -3981,6 +4729,15 @@ components: type: string enum: - name + followersSort: + name: sort + in: query + required: false + description: Sort followers by criteria + schema: + type: string + enum: + - createdAt name: name: name in: path @@ -3995,48 +4752,52 @@ components: required: true description: The user id schema: - type: integer - minimum: 0 - example: 42 + $ref: '#/components/schemas/id' idOrUUID: name: id in: path required: true - description: The object id or uuid + description: The object id, uuid or short uuid schema: oneOf: - - type: integer - minimum: 0 - example: 42 + - $ref: '#/components/schemas/id' - $ref: '#/components/schemas/UUIDv4' + - $ref: '#/components/schemas/shortUUID' + 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 @@ -4066,7 +4827,7 @@ components: required: true description: The comment id schema: - type: integer + $ref: '#/components/schemas/VideoComment/properties/id' isLive: name: isLive in: query @@ -4081,10 +4842,10 @@ components: 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: @@ -4121,10 +4882,10 @@ components: 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: @@ -4134,10 +4895,10 @@ components: 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: @@ -4161,20 +4922,58 @@ components: enum: - 'true' - 'false' - filter: - name: filter + isLocal: + name: isLocal in: query required: false - description: > - Special filters which might require special rights: - * `local` - only videos local to the instance - * `all-local` - only videos local to the instance, but showing private and unlisted videos (requires Admin privileges) - * `all` - all videos, showing private and unlisted videos (requires Admin privileges) schema: - type: string + type: boolean + description: '**PeerTube >= 4.0** Display only local or remote videos' + hasHLSFiles: + name: hasHLSFiles + in: query + required: false + schema: + type: boolean + description: '**PeerTube >= 4.0** Display only videos that have HLS files' + hasWebtorrentFiles: + name: hasWebtorrentFiles + in: query + required: false + schema: + type: boolean + description: '**PeerTube >= 4.0** Display only videos that have WebTorrent files' + privacyOneOf: + name: privacyOneOf + in: query + required: false + schema: + $ref: '#/components/schemas/VideoPrivacySet' + description: '**PeerTube >= 4.0** Display only videos in this specific privacy/privacies' + include: + name: include + in: query + required: false + schema: + type: integer enum: - - local - - all-local + - 0 + - 1 + - 2 + - 4 + - 8 + description: > + **PeerTube >= 4.0** Include additional videos in results (can be combined using bitwise or operator) + + - `0` NONE + + - `1` NOT_PUBLISHED_STATE + + - `2` BLACKLISTED + + - `4` BLOCKED_OWNER + + - `8` FILES subscriptionsUris: name: uris in: query @@ -4209,70 +5008,122 @@ components: - video-transcoding - video-file-import - video-import - - videos-views + - videos-views-stats - 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 * + - [Generate] an access token for that account at `/api/v1/users/token`. + - Make requests with the *Authorization: Bearer * 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 + shortUUID: + type: string + description: translation of a uuid v4 with a bigger alphabet to have a shorter uuid + example: 2y84q2MQUMWPbiEcxNXMgC + 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: $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: $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: $ref: '#/components/schemas/VideoLanguageSet' label: type: string + example: English VideoPlaylistPrivacySet: type: integer @@ -4316,6 +5167,29 @@ components: label: type: string + BlockStatus: + properties: + accounts: + type: object + additionalProperties: + x-additionalPropertiesName: account + type: object + properties: + blockedByServer: + type: boolean + blockedByUser: + type: boolean + hosts: + type: object + additionalProperties: + x-additionalPropertiesName: host + type: object + properties: + blockedByServer: + type: boolean + blockedByUser: + type: boolean + NSFWPolicy: type: string enum: @@ -4336,7 +5210,7 @@ components: enum: - 0 - 1 - description: 'Admin flags for the user (None = `0`, Bypass video blacklist = `1`)' + description: 'Admin flags for the user (None = `0`, Bypass video blocklist = `1`)' example: 1 VideoStateConstant: @@ -4387,6 +5261,7 @@ components: `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: $ref: '#/components/schemas/VideoResolutionSet' @@ -4424,7 +5299,7 @@ components: VideoChannelSummary: properties: id: - type: integer + $ref: '#/components/schemas/id' name: type: string displayName: @@ -4445,21 +5320,27 @@ 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 + 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 @@ -4478,15 +5359,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: @@ -4522,20 +5405,24 @@ 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' + shortUUID: + allOf: + - $ref: '#/components/schemas/shortUUID' isLive: type: boolean createdAt: @@ -4559,13 +5446,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: | @@ -4579,11 +5474,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 @@ -4611,7 +5508,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: @@ -4637,6 +5536,9 @@ components: - $ref: '#/components/schemas/Video' - type: object properties: + viewers: + type: integer + description: If the video is a live, you have the amount of current viewers descriptionPath: type: string example: /api/v1/videos/9c9de5e8-0a1e-484a-b099-e80766180a6d/description @@ -4644,7 +5546,7 @@ components: support: type: string description: A text tell the audience how to support the video creator - example: Please support my work on ! <3 + example: Please support our work on https://soutenir.framasoft.org/en/ <3 minLength: 3 maxLength: 1000 channel: @@ -4669,6 +5571,9 @@ components: items: type: string format: url + example: + - https://peertube2.cpy.re/tracker/announce + - wss://peertube2.cpy.re/tracker/socket files: type: array items: @@ -4690,7 +5595,7 @@ components: FileRedundancyInformation: properties: id: - type: integer + $ref: '#/components/schemas/id' fileUrl: type: string format: url @@ -4715,7 +5620,7 @@ components: VideoRedundancy: properties: id: - type: integer + $ref: '#/components/schemas/id' name: type: string url: @@ -4746,33 +5651,71 @@ 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 - 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 + description: magnet URI allowing to resolve the import's source video + 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: @@ -4786,8 +5729,7 @@ components: Abuse: properties: id: - type: integer - example: 7 + $ref: '#/components/schemas/id' reason: type: string example: The video is a spam @@ -4812,7 +5754,7 @@ components: AbuseMessage: properties: id: - type: integer + $ref: '#/components/schemas/id' message: type: string minLength: 2 @@ -4827,9 +5769,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 @@ -4856,29 +5798,15 @@ 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' + shortUUID: + allOf: + - $ref: '#/components/schemas/shortUUID' createdAt: type: string format: date-time @@ -4889,8 +5817,6 @@ components: type: string minLength: 3 maxLength: 1000 - uuid: - $ref: '#/components/schemas/UUIDv4' displayName: type: string minLength: 1 @@ -4899,6 +5825,7 @@ components: type: boolean videoLength: type: integer + minimum: 0 thumbnailPath: type: string privacy: @@ -4912,30 +5839,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: @@ -4965,8 +5906,7 @@ components: ActorInfo: properties: id: - type: integer - example: 11 + $ref: '#/components/schemas/id' name: type: string displayName: @@ -4983,20 +5923,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 @@ -5010,16 +5959,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: @@ -5192,8 +6147,10 @@ components: properties: videoQuota: type: integer + example: 16810141515 videoQuotaDaily: type: integer + example: 1681014151 trending: type: object properties: @@ -5219,6 +6176,12 @@ components: indexUrl: type: string format: url + homepage: + type: object + properties: + enabled: + type: boolean + ServerConfigAbout: properties: instance: @@ -5312,8 +6275,10 @@ components: properties: videoQuota: type: integer + example: 16810141515 videoQuotaDaily: type: integer + example: 1681014151 transcoding: type: object description: Settings pertaining to transcoding jobs @@ -5344,6 +6309,8 @@ components: properties: 0p: type: boolean + 144p: + type: boolean 240p: type: boolean 360p: @@ -5407,10 +6374,16 @@ components: type: boolean manualApproval: type: boolean + + CustomHomepage: + properties: + content: + type: string + Follow: properties: id: - type: integer + $ref: '#/components/schemas/id' follower: $ref: '#/components/schemas/Actor' following: @@ -5449,9 +6422,7 @@ components: Job: properties: id: - type: integer - minimum: 0 - example: 42 + $ref: '#/components/schemas/id' state: type: string enum: @@ -5471,7 +6442,7 @@ components: - video-transcoding - email - video-import - - videos-views + - videos-views-stats - activitypub-refresher - video-redundancy data: @@ -5495,22 +6466,25 @@ 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: @@ -5522,12 +6496,14 @@ components: 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 ! <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 @@ -5538,6 +6514,9 @@ components: minItems: 1 maxItems: 5 uniqueItems: true + example: + - framasoft + - peertube items: type: string minLength: 2 @@ -5587,6 +6566,7 @@ components: description: Video filename including extension type: string format: filename + example: what_is_peertube.mp4 thumbnailfile: description: Video thumbnail file type: string @@ -5601,10 +6581,11 @@ 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' + shortUUID: + $ref: '#/components/schemas/Video/properties/shortUUID' CommentThreadResponse: properties: total: @@ -5656,7 +6637,8 @@ components: type: boolean description: Has the user confirmed their email address? id: - type: integer + allOf: + - $ref: '#/components/schemas/id' readOnly: true pluginAuth: type: string @@ -5666,6 +6648,8 @@ components: format: date-time noInstanceConfigWarningModal: type: boolean + noAccountSetupWarningModal: + type: boolean noWelcomeModal: type: boolean nsfwPolicy: @@ -5682,10 +6666,7 @@ components: type: string description: Theme enabled by this user username: - type: string - description: The user username - minLength: 1 - maxLength: 50 + $ref: '#/components/schemas/username' videoChannels: type: array items: @@ -5698,7 +6679,7 @@ components: type: integer description: The user daily video quota in bytes example: -1 - webtorrentEnabled: + p2pEnabled: type: boolean description: Enable P2P in the player UserWithStats: @@ -5708,7 +6689,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 @@ -5724,31 +6705,23 @@ components: AddUser: properties: username: - type: string - description: The user username - minLength: 1 - maxLength: 50 - pattern: '/^[a-z0-9._]{1,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 - pattern: '/^[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\\-_.:]+$/' + $ref: '#/components/schemas/usernameChannel' role: $ref: '#/components/schemas/UserRole' adminFlags: @@ -5762,22 +6735,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 @@ -5787,40 +6757,61 @@ 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 + p2pEnabled: + 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 + noAccountSetupWarningModal: + type: boolean + noWelcomeModal: + type: boolean GetMeVideoRating: properties: id: - type: string - description: Id of the video + $ref: '#/components/schemas/id' rating: type: string enum: @@ -5848,77 +6839,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 ! <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 @@ -6119,11 +7191,11 @@ components: enum: - 0 - 1 - - 3 + - 2 Notification: properties: id: - type: integer + $ref: '#/components/schemas/id' type: type: integer description: > @@ -6156,6 +7228,14 @@ components: - `13` NEW_INSTANCE_FOLLOWER - `14` AUTO_INSTANCE_FOLLOWING + + - `15` ABUSE_STATE_CHANGE + + - `16` ABUSE_NEW_MESSAGE + + - `17` NEW_PLUGIN_VERSION + + - `18` NEW_PEERTUBE_VERSION read: type: boolean video: @@ -6171,7 +7251,7 @@ components: type: object properties: id: - type: integer + $ref: '#/components/schemas/id' video: nullable: true $ref: '#/components/schemas/VideoInfo' @@ -6179,9 +7259,7 @@ components: type: string nullable: true magnetUri: - type: string - format: uri - nullable: true + $ref: '#/components/schemas/VideoImport/properties/magnetUri' targetUri: type: string format: uri @@ -6191,7 +7269,7 @@ components: type: object properties: id: - type: integer + $ref: '#/components/schemas/id' threadId: type: integer video: @@ -6203,7 +7281,7 @@ components: type: object properties: id: - type: integer + $ref: '#/components/schemas/id' video: allOf: - $ref: '#/components/schemas/VideoInfo' @@ -6212,7 +7290,7 @@ components: type: object properties: id: - type: integer + $ref: '#/components/schemas/id' video: allOf: - $ref: '#/components/schemas/VideoInfo' @@ -6225,7 +7303,7 @@ components: nullable: true properties: id: - type: integer + $ref: '#/components/schemas/id' follower: $ref: '#/components/schemas/ActorInfo' state: @@ -6330,6 +7408,8 @@ components: properties: rtmpUrl: type: string + rtmpsUrl: + type: string streamKey: type: string description: RTMP stream key to use to stream into this live video