Update API docs

This commit is contained in:
Ciarán Ainsworth 2022-10-20 16:38:24 +00:00
parent 9d2a1da039
commit 5dc7a33a2f
9 changed files with 307 additions and 163 deletions

View File

@ -0,0 +1 @@
Updated API developer documentation (#1912, #1909)

View File

@ -1,6 +0,0 @@
Funkwhale API
=============
Funkwhale API is still a work in progress and should not be considered as
stable. We offer an `interactive documentation using swagger </swagger/>`_
were you can browse available endpoints and try the API.

View File

@ -0,0 +1,137 @@
# API authentication
Funkwhale uses the OAuth [authorization grant flow](https://tools.ietf.org/html/rfc6749#section-4.1) for external apps. This flow is a secure way to authenticate apps that requires a user's explicit consent to perform actions.
```{mermaid}
%%{init: { 'sequence': {'mirrorActors': false} } }%%
sequenceDiagram
accTitle: "Funkwhale OAuth token flow"
accDescr: "A sequence diagram showing how apps authenticate with Funkwhale"
autonumber
actor User
participant A as Application
participant F as Funkwhale web interface
participant T as Token endpoint
User ->> A: Log in to Funkwhale
A ->> F: Direct to login screen
F -->> User: Authenticate this app?
User ->> F: Confirm
F -->> A: Authorization code
A ->> T: Authorization code and redirect URI
T -->> A: Access token and refresh token
loop Refresh
A ->> T: Refresh token
T -->> A: Access token
end
```
```{contents} Steps
:local:
```
## 1. Create an application
To connect to the Funkwhale API using OAuth, you need to create an **application**. This represents the entity credentials are related to.
When creating an application you need to define the [**scopes**](https://www.rfc-editor.org/rfc/rfc6749#section-3.3) the application has access to. Scopes define what information your application can access. Each scope can be granted with the following rights:
- `read:<scope>`: grants read-only access to the resource
- `write:<scope>`: grants write-only access to the resource
`read` rights are required to fetch information using a `GET` request. All other actions (`POST`, `PATCH`, `PUT`, and `DELETE`) require `write` priviliges. You may give an application **both** `read` and `write` access to any scope.
```{list-table}
:header-rows: 1
* - Scope
- Description
* - `read`
- Read-only access to all data
* - `write`
- Read-only access to all data
* - `<read/write>:profile`
- Access to profile data (email address, username, etc.)
* - `<read/write>:libraries`
- Access to library data (uploads, libraries, tracks, albums, artists, etc.)
* - `<read/write>:favorites`
- Access to favorites
* - `<read/write>:listenings`
- Access to history
* - `<read/write>:follows`
- Access to followers
* - `<read/write>:playlists`
- Access to playlists
* - `<read/write>:radios`
- Access to radios
* - `<read/write>:filters`
- Access to content filters
* - `<read/write>:notifications`
- Access to notifications
* - `<read/write>:edits`
- Access to metadata edits
```
Next, you need to define a [**Redirect URI**](https://www.rfc-editor.org/rfc/rfc6749#section-3.1.2). This is the location the user is redirected to once they authenticate your app. This can be any URI you want.
```{note}
Funkwhale supports the `urn:ietf:wg:oauth:2.0:oob` redirect URI for non-web applications. If you use this URI, the user is shown a token to copy and paste.
```
Once you've decided on your scopes and your redirect URI, you can create your app using one of the following methods:
1. Visit `/settings/applications/new` on your Funkwhale pod while logged in
2. Send a `POST` request to `/api/v1/oauth/apps`. See our [API documentation](https://docs.funkwhale.audio/swagger/) for more information
Both methods return a [**client ID**](https://www.rfc-editor.org/rfc/rfc6749#section-2.2) and a [**secret**](https://www.rfc-editor.org/rfc/rfc6749#section-2.3.1).
## 2. Get an authorization code
```{important}
Authorization codes are only valid for 5 minutes after the user approves the request.
```
You need an [**authorization code**](https://www.rfc-editor.org/rfc/rfc6749#section-1.3.1) to request an access token for your user. This code confirms to the server that a user has authorized access to their account.
To fetch an authorization code, you need to send the user to their Funkwhale pod to authenticate. This sends an [authorization request](https://www.rfc-editor.org/rfc/rfc6749#section-4.1.2) to the server.
To do this, call the `/authorize` endpoint with the following URL encoded query parameters:
- `client_id`* - Your application's client ID
- `response_type`* - Must be set to `code`.
- `redirect_uri` - Your redirect URI
- `scope` - A list of scopes
- `state` - Used to maintain state between the request and the callback to prevent cross-site request forgery. Typically corresponds with a location in the app (e.g. `/library`)
Here is an example URL: `https://demo.funkwhale.audio/authorize?response_type=code&scope=read%20write&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fauth%2Fcallback&state=/library&client_id=jDOUfhqLlrbuOkToDCanZmBKEiyorMb9ZUgD2tFQ`.
When the user authorizes your app, the server responds with an authorization code. See [the OAuth spec](https://www.rfc-editor.org/rfc/rfc6749#section-4.1.2) for more information about this response.
## 3. Get an access token
Once you receive your authorization code, you need to [request an access token](https://www.rfc-editor.org/rfc/rfc6749#section-4.1.3). To request an access token, call the `/api/v1/oauth/token` endpoint with the following information:
- `grant_type`* - Must be set to `authorization_code`
- `code`* - Your application's authorization code
- `redirect_uri`* - Your redirect URI
- `client_id`* Your application's client ID
The server responds with an [`access_token`](https://www.rfc-editor.org/rfc/rfc6749#section-1.4) and a [`refresh_token`](https://www.rfc-editor.org/rfc/rfc6749#section-1.5). See [the OAuth spec](https://www.rfc-editor.org/rfc/rfc6749#section-4.1.4) for more information about this response.
You can use this token to authenticate calls from your application to the Funkwhale API by passing it as a request header with the following format: `Authorization: Bearer <token>`.
## 4. Refresh your access token
```{important}
When you refresh your token the endpoint returns a new `refresh_token`. You must update your refresh token each time you request a new access token.
```
By default, Funkwhale access tokens are valid for **10 hours**. Pod admins can configure this by setting the `ACCESS_TOKEN_EXPIRE_SECONDS` variable in their `.env` file.
After the access token expires, you must request a new access token by calling the `/api/v1/oauth/token` endpoint with the following information:
- `grant_type`* - Must be set to `refresh_token`
- `refresh_token`* - Your current refresh token
- `scope` - A list of scopes
See [the OAuth spec](https://www.rfc-editor.org/rfc/rfc6749#section-6) for more information about this response.

View File

@ -0,0 +1,18 @@
# Funkwhale API
The Funkwhale API is a [REST API](https://developer.mozilla.org/en-US/docs/Glossary/REST) written in [Python](https://www.python.org/) using the [Django REST framework](https://www.django-rest-framework.org/). It is the central component of the project and houses the application's logic.
The current API (v1) is **stable**, meaning we are committed to not introducing breaking changes and to maintaining compatibility. We are currently working on Funkwhale API v2, but this is a work in progress and not yet ready for production use.
```{toctree}
---
caption: Resources
maxdepth: 1
---
API explorer<https://docs.funkwhale.audio/swagger/>
authentication
rate_limit
subsonic
```

View File

@ -0,0 +1,51 @@
# Rate limiting
Funkwhale supports rate-limiting as of version 0.2.0. Pod admins can choose to rate limit specific endpoints to prevent abuse and improve the stability of the service. If the server drops a request due to rate-limiting, it returns a `429` status code.
By default, rate limits follow these rules:
1. Anonymous (unauthenticated) requests are subject to lower limits than authenticated requests
2. `PUT`, `DELETE`, `PUT`, `POST`, and `PATCH` requests are subject to lower limits than `GET` requests
You can return a full list of scope with their corresponding rate-limits by making a `GET` request to `/api/v1/rate-limit`.
## HTTP headers
Each API call returns HTTP headers to pass the following information:
- What was the scope of the request
- What is the rate-limit associated with the request scope
- How many more requests in the scope can be made within the rate-limit timeframe
- How much time does the client need to wait to send another request
Here is a full list of supported headers
```{list-table}
:header-rows: 1
* - Header
- Example value
- Description
* - `X-RateLimit-Limit`
- 50
- The number of requests allowed within a given period
* - `X-RateLimit-Duration`
- 3600
- The time window, in seconds, during which the number of requests are measured
* - `X-RateLimit-Scope`
- `login`
- The name of the scope computed for the request
* - `X-RateLimit-Remaining`
- 42
- How many requests can be sent with the same scope before the rate-limit applies
* - `Retry-After`
- 3543
- How many seconds the client must wait before it can retry. Only applies if `X-RateLimit-Remaining` is `0`
* - `X-RateLimit-Reset`
- 1568126089
- A timestamp indicating when the `X-RateLimit-Remaining` value will reset
* - `X-RateLimit-ResetSeconds`
- 3599
- The number of seconds until the `X-RateLimit-Remaining` value resets
```

View File

@ -0,0 +1,71 @@
# Subsonic API
Funkwhale supports a subset of the [Subsonic API's](http://www.subsonic.org/pages/api.jsp) endpoints. This enables users to listen to music stored on their Funkwhale pod through a Subsonic-compatible app.
We aim to support as many endpoints as we can to give Subsonic users the best possible experience. However, some endpoints require a folder-based endpoint. This doesn't match Funkwhale's internal structure, which means emulating them is difficult.
## Supported endpoints
```{note}
We aim to keep this list up-to-date. If you think something is missing, you can see all supported endpoints in the [API views](https://dev.funkwhale.audio/funkwhale/funkwhale/blob/develop/api/funkwhale_api/subsonic/views.py).
```
Funkwhale supports both XML and JSON formats for the following Subsonic endpoints:
- [`createPlaylist`](http://www.subsonic.org/pages/api.jsp#createPlaylist)
- [`deletePlaylist`](http://www.subsonic.org/pages/api.jsp#deletePlaylist)
- [`getAlbum`](http://www.subsonic.org/pages/api.jsp#getAlbum)
- [`getAlbumList2`](http://www.subsonic.org/pages/api.jsp#getAlbumList2)
- [`getArtist`](http://www.subsonic.org/pages/api.jsp#getArtist)
- [`getArtistInfo2`](http://www.subsonic.org/pages/api.jsp#getArtistInfo2)
- [`getArtists`](http://www.subsonic.org/pages/api.jsp#getArtists)
- [`getAvatar`](http://www.subsonic.org/pages/api.jsp#getAvatar)
- [`getCoverArt`](http://www.subsonic.org/pages/api.jsp#getCoverArt)
- [`getIndexes`](http://www.subsonic.org/pages/api.jsp#getIndexes)
- [`getLicense`](http://www.subsonic.org/pages/api.jsp#getLicense)
- [`getMusicFolders`](http://www.subsonic.org/pages/api.jsp#getMusicFolders)
- [`getPlaylist`](http://www.subsonic.org/pages/api.jsp#getPlaylist)
- [`getPlaylists`](http://www.subsonic.org/pages/api.jsp#getPlaylists)
- [`getRandomSongs`](http://www.subsonic.org/pages/api.jsp#getRandomSongs)
- [`getSong`](http://www.subsonic.org/pages/api.jsp#getSong)
- [`getStarred`](http://www.subsonic.org/pages/api.jsp#getStarred)
- [`getStarred2`](http://www.subsonic.org/pages/api.jsp#getStarred2)
- [`getUser`](http://www.subsonic.org/pages/api.jsp#getUser)
- [`ping`](http://www.subsonic.org/pages/api.jsp#ping)
- [`scrobble`](http://www.subsonic.org/pages/api.jsp#scrobble)
- [`search3`](http://www.subsonic.org/pages/api.jsp#search3)
- [`star`](http://www.subsonic.org/pages/api.jsp#star)
- [`stream`](http://www.subsonic.org/pages/api.jsp#stream)
- [`unstar`](http://www.subsonic.org/pages/api.jsp#unstar)
- [`updatePlaylist`](http://www.subsonic.org/pages/api.jsp#updatePlaylist)
### Additional properties
Funkwhale returns some additional properties to Subsonic payloads. You can use these properties to adapt your client behavior if needed:
```{list-table}
* - Property
- Data type
- Description
* - `type`
- String
- The name of the app (`funkwhale`)
* - `funkwhaleVersion`
- String
- The Funkwhale version the pod is running
```
```{code-block} json
{
"subsonic-response": {
"type": "funkwhale",
"funkwhaleVersion": "1.3.0"
}
}
```
## Test a Subsonic app
We host a demo server at <https://demo.funkwhale.audio> which you can use to test your Subsonic app.
You can test the Subsonic API by logging in with a Subsonic client or by directly by calling an endpoint. For example, call this URL to test the `ping` endpoint: <https://demo.funkwhale.audio/rest/ping.view?f=json>

View File

@ -1,69 +0,0 @@
Subsonic API
============
Funkwhale implements a subset of the `Subsonic API <http://www.subsonic.org/pages/api.jsp>`_ that makes it compatible
with various apps in the Subsonic ecosystem (See `our list of supported apps <https://funkwhale.audio/en_US/apps>`_).
Supported endpoints
-------------------
We seek the best compatibility with existing apps and will eventually implement
all endpoints that match Funkwhale's feature set. However, the current implementation
do not include folder-based endpoints, as it does not match our internal model at all
and will require substantial effort to emulate.
We'll try to keep this list up-to-date, but you can also browse `the relevant code
<https://dev.funkwhale.audio/funkwhale/funkwhale/blob/develop/api/funkwhale_api/subsonic/views.py>`_
if needed.
As of today, the following endpoints are implemented:
- createPlaylist
- deletePlaylist
- getAlbum
- getAlbumList2
- getArtist
- getArtistInfo2
- getArtists
- getAvatar
- getCoverArt
- getIndexes
- getLicense
- getMusicFolders
- getPlaylist
- getPlaylists
- getRandomSongs
- getSong
- getStarred
- getStarred2
- getUser
- ping
- scrobble
- search3
- star
- stream
- unstar
- updatePlaylist
We support both XML and JSON formats for all those endpoints.
Additional properties
---------------------
Regardless of the endpoints, we always return those additional properties
in our payload, which you can use to adapt your client behaviour if needed:
.. code-block:: json
{
"subsonic-response": {
"type": "funkwhale",
"funkwhaleVersion": "0.17"
}
}
Testing a Subsonic app
----------------------
We maintain a demo server at https://demo.funkwhale.audio/, which you can use for
your tests. Example with the ping endpoint: https://demo.funkwhale.audio/rest/ping.view?f=json

View File

@ -74,6 +74,7 @@ developer_documentation/index
developer_documentation/setup/index developer_documentation/setup/index
developer_documentation/contribute/index developer_documentation/contribute/index
developer_documentation/workflows/index developer_documentation/workflows/index
developer_documentation/api/index
``` ```

View File

@ -1,117 +1,57 @@
openapi: "3.0.3" openapi: "3.0.3"
info: info:
description: | description: |
Interactive documentation for [Funkwhale](https://funkwhale.audio) API. API explorer for the [Funkwhale](https://funkwhale.audio) API.
Backward compatibility between minor versions (1.X to 1.Y) is guaranteed for all the Backward compatibility between minor versions (1.X to 1.Y) is guaranteed for all the
endpoints documented here. endpoints documented here.
Usage ## Usage
-----
Click on an endpoint name to inspect its properties, parameters and responses. Click on an endpoint name to inspect its properties, parameters and responses.
Use the "Try it out" button to send a real world payload to the endpoint and inspect Use the "Try it out" button to send a real world payload to the endpoint and inspect
the corresponding response. the corresponding response.
OAuth Authentication ## OAuth Authentication
--------------------
You can register your own OAuth app using the `/api/v1/oauth/apps/` endpoint. Proceed to the standard OAuth flow afterwards: Funkwhale uses the OAuth [authorization grant flow](https://tools.ietf.org/html/rfc6749#section-4.1) for external apps. This flow is
a secure way to authenticate apps that requires a user's explicit consent to perform actions. You can use our demo server at <https://demo.funkwhale.audio>
for testing purposes.
- Our authorize URL is at `/authorize` To authenticate with the Funkwhale API:
- Our token acquisition and refresh URL is at `/api/v1/oauth/token`
- The list of supported scopes is available by clicking the `Authorize` button in the Swagger UI documentation
- Use `urn:ietf:wg:oauth:2.0:oob` as your redirect URI if you want the user to get a copy-pastable authorization code
- At the moment, endpoints that deal with admin or moderator-level content are not accessible via OAuth, only through the Web UI
You can use our demo server at `https://demo.funkwhale.audio` for testing purposes. 1. Create an application by sending a `POST` request to `api/v1/oauth/apps`. Include your scopes and redirect URI (use `urn:ietf:wg:oauth:2.0:oob`
to get an authorization code you can copy)
2. Send an [authorization request](https://www.rfc-editor.org/rfc/rfc6749#section-4.1.2) to the `/authorize` endpoint to receive an authorization code
3. [Request an access token](https://www.rfc-editor.org/rfc/rfc6749#section-4.1.3) from `/api/v1/oauth/token`
4. Use your access token to authenticate your calls with the following format: `Authorization: Bearer <token>`
5. Refresh your access token by sending a refresh request to `/api/v1/oauth/token`
Application token authentication For more detailed instructions, see [our API authentication documentation](https://docs.funkwhale.audio/developer_documentation/api/authentication.html).
--------------------------------
If using OAuth isn't practical and you have an account on the Funkwhale pod, you can create an application by visiting `/settings`. ## Application token authentication
Once the application is created, you can authenticate using its access token in the `Authorization` header, like this: `Authorization: Bearer <token>`. If you have an account on your target pod, you can create an application at `/settings/applications/new`. Once you authorize the application you
can retrieve an access token. Use your access token to authenticate your calls with the following format: `Authorization: Bearer <token>`
Rate limiting ## Rate limiting
-------------
Depending on server configuration, pods running Funkwhale 0.20 and higher may rate-limit incoming Funkwhale supports rate-limiting as of version 0.2.0. Pod admins can choose to rate limit specific endpoints to prevent abuse and improve the stability of the service.
requests to prevent abuse and improve the stability of service. Requests that are dropped because of rate-limiting If the server drops a request due to rate-limiting, it returns a `429` status code.
receive a 429 HTTP response.
The limits themselves vary depending on: Each API call returns HTTP headers to pass the following information:
- The client: anonymous requests are subject to lower limits than authenticated requests - What was the scope of the request (`X-RateLimit-Scope`)
- The operation being performed: Write and delete operations, as performed with DELETE, POST, PUT and PATCH HTTP methods are subject to lower limits - What is the rate-limit associated with the request scope (`X-RateLimit-Limit`)
- How many more requests in the scope can be made within the rate-limit timeframe (`X-RateLimit-Remaining`)
- How much time does the client need to wait to send another request (`Retry-After`)
Those conditions are used to determine the scope of the request, which in turns determine the limit that is applied. For more information, check our [rate limit documentation](https://docs.funkwhale.audio/developer_documentation/api/rate-limit.html)
For instance, authenticated POST requests are bound to the `authenticated-create` scope, with a default limit of
1000 requests/hour, but anonymous POST requests are bound to the `anonymous-create` scope, with a lower limit of 1000 requests/day.
A full list of scopes with their corresponding description, and the current usage data for the client performing the request ## Resources
is available via the `/api/v1/rate-limit` endpoint.
Additionally, we include HTTP headers on all API response to ensure API clients can understand: For more information about API usage, refer to [our API documentation](https://docs.funkwhale.audio/developer_documentation/api/index.html).
- what scope was bound to a given request
- what is the corresponding limit
- how much similar requests can be sent before being limited
- and how much time they should wait if they have been limited
<table>
<caption>Rate limiting headers</caption>
<thead>
<th>Header</th>
<th>Example value</th>
<th>Description value</th>
</thead>
<tbody>
<tr>
<td><code>X-RateLimit-Limit</code></td>
<td>50</td>
<td>The number of allowed requests whithin a given period</td>
</tr>
<tr>
<td><code>X-RateLimit-Duration</code></td>
<td>3600</td>
<td>The time window, in seconds, during which those requests are accounted for.</td>
</tr>
<tr>
<td><code>X-RateLimit-Scope</code></td>
<td>login</td>
<td>The name of the scope as computed for the request</td>
</tr>
<tr>
<td><code>X-RateLimit-Remaining</code></td>
<td>42</td>
<td>How many requests can be sent with the same scope before the limit applies</td>
</tr>
<tr>
<td><code>Retry-After</code> (if <code>X-RateLimit-Remaining</code> is 0)</td>
<td>3543</td>
<td>How many seconds to wait before a retry</td>
</tr>
<tr>
<td><code>X-RateLimit-Reset</code></td>
<td>1568126089</td>
<td>A timestamp indicating when <code>X-RateLimit-Remaining</code> will return to its higher possible value</td>
</tr>
<tr>
<td><code>X-RateLimit-ResetSeconds</code></td>
<td>3599</td>
<td>How many seconds to wait before <code>X-RateLimit-Remaining</code> returns to its higher possible value</td>
</tr>
</tbody>
</table>
Resources
---------
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" version: "1.0.0"
title: "Funkwhale API" title: "Funkwhale API"