From 4aabcf8d57b35fa29ef58efeb3c9cadaa47b10ba Mon Sep 17 00:00:00 2001 From: Eliot Berriot Date: Tue, 26 Mar 2019 11:40:53 +0100 Subject: [PATCH 1/4] Libraries endpoint documentation --- docs/swagger.yml | 218 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 193 insertions(+), 25 deletions(-) diff --git a/docs/swagger.yml b/docs/swagger.yml index de809242d..c4b413414 100644 --- a/docs/swagger.yml +++ b/docs/swagger.yml @@ -1,3 +1,16 @@ +# Undocumented endpoints: +# /api/v1/settings +# /api/v1/activity +# /api/v1/uploads +# /api/v1/listen +# /api/v1/playlists +# /api/v1/playlist-tracks +# /api/v1/favorites +# /api/v1/search +# /api/v1/radios +# /api/v1/history +# /api/v1/users + openapi: "3.0.0" info: description: "Documentation for [Funkwhale](https://funkwhale.audio) API. The API is **not** stable yet." @@ -30,11 +43,21 @@ components: security: - jwt: [] +tags: + - name: Auth and security + description: Login, logout and authorization endpoints + - name: Library and metadata + description: Information and metadata about musical and audio entities (albums, tracks, artists, etc.) + - name: Uploads and audio content + description: Manipulation and uploading of audio files + externalDocs: + url: https://docs.funkwhale.audio/users/managing.html + paths: /token/: post: tags: - - "auth" + - "Auth and security" description: Obtain a JWT token you can use for authenticating your next requests. security: [] @@ -61,7 +84,7 @@ paths: get: summary: List artists tags: - - "artists" + - "Library and metadata" parameters: - name: "q" in: "query" @@ -106,7 +129,7 @@ paths: - $ref: "#/parameters/ObjectId" tags: - - "artists" + - "Library and metadata" responses: 200: content: @@ -127,8 +150,7 @@ paths: - $ref: "#/parameters/PageSize" tags: - - "artists" - - "libraries" + - "Library and metadata" responses: 200: content: @@ -145,7 +167,7 @@ paths: get: summary: List albums tags: - - "albums" + - "Library and metadata" parameters: - name: "q" in: "query" @@ -198,7 +220,7 @@ paths: - $ref: "#/parameters/ObjectId" tags: - - "albums" + - "Library and metadata" responses: 200: content: @@ -220,8 +242,7 @@ paths: - $ref: "#/parameters/PageSize" tags: - - "albums" - - "libraries" + - "Library and metadata" responses: 200: content: @@ -238,7 +259,7 @@ paths: get: summary: List tracks tags: - - "tracks" + - "Library and metadata" parameters: - name: "q" in: "query" @@ -302,12 +323,12 @@ paths: $ref: "#/definitions/Track" /tracks/{id}/: get: - summary: Retrieve a single track parameters: - $ref: "#/parameters/ObjectId" + summary: Retrieve a single track tags: - - "tracks" + - "Library and metadata" responses: 200: content: @@ -329,8 +350,7 @@ paths: - $ref: "#/parameters/PageSize" tags: - - "tracks" - - "libraries" + - "Library and metadata" responses: 200: content: @@ -347,7 +367,7 @@ paths: get: summary: List licenses tags: - - "licenses" + - "Library and metadata" parameters: - $ref: "#/parameters/PageNumber" - $ref: "#/parameters/PageSize" @@ -366,19 +386,19 @@ paths: $ref: "#/definitions/License" /licenses/{code}/: + parameters: + - name: code + in: path + description: License code + required: true + schema: + type: string + example: cc0-1.0 get: summary: Retrieve a single license - parameters: - - name: code - in: path - description: License code - required: true - schema: - type: string - example: cc0-1.0 tags: - - "licenses" + - "Library and metadata" responses: 200: content: @@ -391,6 +411,89 @@ paths: schema: $ref: "#/definitions/ResourceNotFound" + /libraries/: + get: + summary: List owned libraries + tags: + - "Uploads and audio content" + parameters: + - $ref: "#/parameters/PageNumber" + - $ref: "#/parameters/PageSize" + responses: + 200: + content: + application/json: + schema: + allOf: + - $ref: "#/definitions/ResultPage" + - type: "object" + properties: + results: + type: "array" + items: + $ref: "#/definitions/OwnedLibrary" + post: + tags: + - "Uploads and audio content" + description: + Create a new library + security: [] + responses: + 201: + $ref: "#/responses/201" + 400: + $ref: "#/responses/400" + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/definitions/OwnedLibraryCreate" + + /libraries/{uuid}/: + parameters: + - name: uuid + in: path + required: true + schema: + type: "string" + format: "uuid" + get: + summary: Retrieve a library + tags: + - "Uploads and audio content" + responses: + 200: + content: + application/json: + schema: + $ref: "#/definitions/OwnedLibrary" + post: + summary: Update a library + tags: + - "Uploads and audio content" + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/definitions/OwnedLibraryCreate" + responses: + 200: + content: + application/json: + schema: + $ref: "#/definitions/OwnedLibrary" + delete: + summary: Delete a library and all associated uploads + description: | + This will delete the library, all associated uploads, follows, and broadcast + the event on the federation. + tags: + - "Uploads and audio content" + responses: + 204: + $ref: "#/responses/204" parameters: ObjectId: @@ -434,11 +537,35 @@ parameters: required: false type: "boolean" +responses: + 201: + description: Successfully created + 204: + description: Successfully deleted + 400: + description: Bad request + properties: mbid: type: "string" - formats: "uuid" + format: "uuid" description: "A musicbrainz ID" + creation_date: + type: "string" + format: "date-time" + privacy_level: + type: string + example: "me" + description: "'me' means private, 'instance' means viewable by local users, 'everyone' means public" + enum: + - "me" + - "instance" + - "everyone" + fid: + type: "string" + format: "uri" + description: "Federation ID" + example: "https://my.instance/federation/music/libraries/3fa85f64-5717-4562-b3fc-2c963f66afa6" definitions: ResultPage: @@ -793,6 +920,47 @@ definitions: format: "uri" description: "URL to stream the upload" + OwnedLibraryCreate: + type: "object" + properties: + password: + type: "name" + example: "My new library" + description: + required: false + type: "string" + example: "Lots of interesting content" + privacy_level: + $ref: "#/properties/privacy_level" + + OwnedLibrary: + type: "object" + properties: + uuid: + type: string + format: uuid + fid: + $ref: "#/properties/fid" + name: + type: "string" + example: "My Creative Commons library" + description: + type: "string" + example: "All content is under CC-BY" + creation_date: + $ref: "#/properties/creation_date" + privacy_level: + $ref: "#/properties/privacy_level" + uploads_count: + type: "integer" + format: "int64" + example: 34 + size: + type: "integer" + format: "int64" + example: 678917000 + description: "Total size of uploads in the library, in bytes" + ResourceNotFound: type: "object" properties: From 5b74448e665ab139b88ff1f73de5789951e2780f Mon Sep 17 00:00:00 2001 From: Eliot Berriot Date: Tue, 26 Mar 2019 12:32:04 +0100 Subject: [PATCH 2/4] Documented /uploads endpoint --- docs/swagger.yml | 149 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 138 insertions(+), 11 deletions(-) diff --git a/docs/swagger.yml b/docs/swagger.yml index c4b413414..45ca6246d 100644 --- a/docs/swagger.yml +++ b/docs/swagger.yml @@ -1,7 +1,6 @@ # Undocumented endpoints: # /api/v1/settings # /api/v1/activity -# /api/v1/uploads # /api/v1/listen # /api/v1/playlists # /api/v1/playlist-tracks @@ -437,7 +436,6 @@ paths: - "Uploads and audio content" description: Create a new library - security: [] responses: 201: $ref: "#/responses/201" @@ -495,6 +493,96 @@ paths: 204: $ref: "#/responses/204" + /uploads/: + get: + summary: List owned uploads + tags: + - "Uploads and audio content" + parameters: + - name: "q" + in: "query" + default: null + description: "Search query used to filter uploads" + schema: + required: false + type: "string" + example: "Dire straits" + - $ref: "#/parameters/PageNumber" + - $ref: "#/parameters/PageSize" + responses: + 200: + content: + application/json: + schema: + allOf: + - $ref: "#/definitions/ResultPage" + - type: "object" + properties: + results: + type: "array" + items: + $ref: "#/definitions/OwnedUpload" + post: + tags: + - "Uploads and audio content" + description: + Upload a new file in a library. The event will be broadcasted on federation, + according to the library visibility and followers. + responses: + 201: + $ref: "#/responses/201" + 400: + $ref: "#/responses/400" + requestBody: + required: true + content: + multipart/form-data: + schema: + type: object + properties: + library: + type: string + format: uuid + description: "The library in which the audio should be stored" + import_reference: + type: string + example: "Import launched via API client on 04/19" + source: + type: string + example: "upload://filename.mp3" + audio_file: + type: string + format: binary + + /uploads/{uuid}/: + parameters: + - name: uuid + in: path + required: true + schema: + type: "string" + format: "uuid" + get: + summary: Retrieve an upload + tags: + - "Uploads and audio content" + responses: + 200: + content: + application/json: + schema: + $ref: "#/definitions/OwnedUpload" + delete: + summary: Delete an upload + description: | + This will delete the upload from the server and broadcast the event + on the federation. + tags: + - "Uploads and audio content" + responses: + 204: + $ref: "#/responses/204" + parameters: ObjectId: name: id @@ -556,7 +644,10 @@ properties: privacy_level: type: string example: "me" - description: "'me' means private, 'instance' means viewable by local users, 'everyone' means public" + description: > + * `me`: private + * `instance`: accessible by local users + * `everyone`: public (including over federation) enum: - "me" - "instance" @@ -566,6 +657,27 @@ properties: format: "uri" description: "Federation ID" example: "https://my.instance/federation/music/libraries/3fa85f64-5717-4562-b3fc-2c963f66afa6" + audio_mimetype: + type: string + example: "audio/ogg" + enum: + - "audio/ogg" + - "audio/mpeg" + - "audio/x-flac" + - "audio/flac" + import_status: + type: string + example: "finished" + enum: + - "pending" + - "finished" + - "errored" + - "skipped" + description: > + * `pending`: waiting to be processed by the server + * `finished`: successfully processed by the server + * `errored`: couldn't be processed by the server (e.g because of a tagging issue) + * `skipped`: processed by the server but skipped, because considered as a duplicate of an existing upload definitions: ResultPage: @@ -903,18 +1015,14 @@ definitions: example: 128000 description: "Bitrate of the file, in bytes/s" mimetype: - type: string - example: "audio/ogg" - enum: - - "audio/ogg" - - "audio/mpeg" - - "audio/x-flac" - - "audio/flac" + $ref: "#/properties/audio_mimetype" extension: type: string example: "ogg" description: "File extension of the upload" - + filename: + type: "string" + example: "Myfile.mp3" listen_url: type: "string" format: "uri" @@ -961,6 +1069,25 @@ definitions: example: 678917000 description: "Total size of uploads in the library, in bytes" + OwnedUpload: + type: "object" + allOf: + - $ref: "#/definitions/Upload" + - type: "object" + properties: + import_status: + $ref: "#/properties/import_status" + track: + $ref: "#/definitions/Track" + library: + $ref: "#/definitions/OwnedLibrary" + source: + type: "string" + example: "upload://myfile.mp3" + import_reference: + type: "string" + example: "Import launched via web UI on 03/18" + ResourceNotFound: type: "object" properties: From 800dd5ba182d99756518ca4c1bbf4af5b60d867b Mon Sep 17 00:00:00 2001 From: Eliot Berriot Date: Tue, 26 Mar 2019 13:58:47 +0100 Subject: [PATCH 3/4] Documented /favorites endpoint --- docs/swagger.yml | 166 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 158 insertions(+), 8 deletions(-) diff --git a/docs/swagger.yml b/docs/swagger.yml index 45ca6246d..94bf33c4f 100644 --- a/docs/swagger.yml +++ b/docs/swagger.yml @@ -4,7 +4,6 @@ # /api/v1/listen # /api/v1/playlists # /api/v1/playlist-tracks -# /api/v1/favorites # /api/v1/search # /api/v1/radios # /api/v1/history @@ -12,7 +11,15 @@ openapi: "3.0.0" info: - description: "Documentation for [Funkwhale](https://funkwhale.audio) API. The API is **not** stable yet." + description: | + Interactive documentation for [Funkwhale](https://funkwhale.audio) API. + + The API is **not** freezed yet, but we will document breaking changes in our changelog, + and try to avoid those as much as possible. + + For more targeted guides regarding API usage, and especially authentication, please + refer to [https://docs.funkwhale.audio/api.html](https://docs.funkwhale.audio/api.html) + version: "1.0.0" title: "Funkwhale API" @@ -51,6 +58,8 @@ tags: description: Manipulation and uploading of audio files externalDocs: url: https://docs.funkwhale.audio/users/managing.html + - name: Content curation + description: Favorites, playlists, radios paths: /token/: @@ -92,7 +101,6 @@ paths: schema: required: false type: "string" - example: "carpenter" - allOf: - $ref: "#/parameters/Ordering" - default: "-creation_date" @@ -175,7 +183,6 @@ paths: schema: required: false type: "string" - example: "carpenter" - name: "artist" in: "query" default: null @@ -267,7 +274,6 @@ paths: schema: required: false type: "string" - example: "carpenter" - name: "artist" in: "query" default: null @@ -276,6 +282,13 @@ paths: required: false type: "integer" format: "int64" + - name: "favorites" + in: "query" + default: null + description: "filter/exclude tracks favorited by the current user" + schema: + required: false + type: "boolean" - name: "album" in: "query" default: null @@ -477,7 +490,7 @@ paths: schema: $ref: "#/definitions/OwnedLibraryCreate" responses: - 200: + 201: content: application/json: schema: @@ -583,6 +596,91 @@ paths: 204: $ref: "#/responses/204" + /favorites/tracks/: + get: + tags: + - "Content curation" + parameters: + - name: "q" + in: "query" + default: null + description: "Search query used to filter favorites" + schema: + required: false + type: "string" + - name: "user" + in: "query" + default: null + description: "Limit results to favorites belonging to the given user" + schema: + $ref: "#/parameters/ObjectId" + - $ref: "#/parameters/PageNumber" + - $ref: "#/parameters/PageSize" + responses: + 200: + content: + application/json: + schema: + allOf: + - $ref: "#/definitions/ResultPage" + - type: "object" + properties: + results: + type: "array" + items: + $ref: "#/definitions/TrackFavorite" + post: + summary: Mark the given track as favorite + tags: + - "Content curation" + requestBody: + required: true + content: + application/json: + schema: + type: "object" + properties: + track: + type: "integer" + format: "int64" + example: 98 + responses: + 201: + content: + application/json: + schema: + type: "object" + properties: + id: + type: "integer" + format: "int64" + example: 876 + track: + type: "integer" + format: "int64" + example: 98 + creation_date: + $ref: "#/properties/creation_date" + /favorites/tracks/remove/: + post: + summary: Remove the given track from favorites + tags: + - "Content curation" + requestBody: + required: true + content: + application/json: + schema: + type: "object" + properties: + track: + type: "integer" + format: "int64" + example: 98 + responses: + 204: + $ref: "#/responses/204" + parameters: ObjectId: name: id @@ -644,7 +742,7 @@ properties: privacy_level: type: string example: "me" - description: > + description: | * `me`: private * `instance`: accessible by local users * `everyone`: public (including over federation) @@ -673,7 +771,7 @@ properties: - "finished" - "errored" - "skipped" - description: > + description: | * `pending`: waiting to be processed by the server * `finished`: successfully processed by the server * `errored`: couldn't be processed by the server (e.g because of a tagging issue) @@ -1087,6 +1185,58 @@ definitions: import_reference: type: "string" example: "Import launched via web UI on 03/18" + TrackFavorite: + type: "object" + properties: + id: + type: "integer" + format: "int64" + example: 876 + track: + $ref: "#/definitions/Track" + user: + $ref: "#/definitions/User" + creation_date: + $ref: "#/properties/creation_date" + User: + type: "object" + properties: + id: + type: "integer" + format: "int64" + example: 23 + username: + type: "string" + example: "alice" + name: + type: "string" + example: "Alice Kingsley" + avatar: + $ref: "#/definitions/Avatar" + + Avatar: + type: "object" + properties: + original: + type: "string" + format: "uri" + description: "Original image URL" + example: "http://yourinstance/media/users/avatars/92/49/60/b3c-4736-43b3-bb5c-ed7a99ac6996.jpg" + square_crop: + type: "string" + format: "uri" + description: "400x400 thumbnail URL" + example: "http://yourinstance/media/__sized__/users/avatars/92/49/60/b3c-4736-43b3-bb5c-ed7a99ac6996-crop-c0-5__0-5-400x400-70.jpg" + small_square_crop: + type: "string" + format: "uri" + description: "50x50 thumbnail URL" + example: "http://yourinstance/media/__sized__/users/avatars/92/49/60/b3c-4736-43b3-bb5c-ed7a99ac6996-crop-c0-5__0-5-50x50-70.jpg" + medium_square_crop: + type: "string" + format: "uri" + description: "200x200 thumbnail URL" + example: "http://yourinstance/media/__sized__/users/avatars/92/49/60/b3c-4736-43b3-bb5c-ed7a99ac6996-crop-c0-5__0-5-200x200-70.jpg" ResourceNotFound: type: "object" From a1817f6473341cfa9c455cecde4539ce9141db9f Mon Sep 17 00:00:00 2001 From: Eliot Berriot Date: Tue, 26 Mar 2019 15:01:00 +0100 Subject: [PATCH 4/4] Documented /listen endpoint --- docs/swagger.yml | 66 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/docs/swagger.yml b/docs/swagger.yml index 94bf33c4f..4ef60de6f 100644 --- a/docs/swagger.yml +++ b/docs/swagger.yml @@ -1,7 +1,6 @@ # Undocumented endpoints: # /api/v1/settings # /api/v1/activity -# /api/v1/listen # /api/v1/playlists # /api/v1/playlist-tracks # /api/v1/search @@ -374,7 +373,66 @@ paths: application/json: schema: $ref: "#/definitions/ResourceNotFound" + /listen/{uuid}/: + get: + summary: Download the audio file matching the given track uuid + description: | + Given a track uuid (and not ID), return the first found audio file + accessible by the user making the request. + In case of a remote upload, this endpoint will fetch the audio file from the remote + and cache it before sending the response. + + parameters: + - name: uuid + in: path + required: true + description: Track uuid + schema: + type: "string" + format: "uuid" + - name: to + in: query + required: false + description: | + If specified, the endpoint will return a transcoded version of the original + audio file. + + Since transcoding happens on the fly, it can significantly increase response time, + and it's recommended to request transcoding only for files that are not playable + by the client. + + This endpoint support bytess-range requests. + schema: + $ref: "#/properties/transcode_options" + - name: upload + in: query + required: false + summary: An upload uuid + description: | + If specified, will return the audio for the given upload uuid. + + This is useful for tracks that have multiple uploads available. + + schema: + type: string + format: uuid + + tags: + - "Library and metadata" + responses: + 200: + content: + '*/*': + description: "Audio file, as binary data" + schema: + type: string + format: binary + 404: + content: + application/json: + schema: + $ref: "#/definitions/ResourceNotFound" /licenses/: get: summary: List licenses @@ -777,6 +835,12 @@ properties: * `errored`: couldn't be processed by the server (e.g because of a tagging issue) * `skipped`: processed by the server but skipped, because considered as a duplicate of an existing upload + transcode_options: + type: string + enum: + - "ogg" + - "mp3" + definitions: ResultPage: type: "object"