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/contribute/index
developer_documentation/workflows/index
developer_documentation/api/index
```

View File

@ -1,117 +1,57 @@
openapi: "3.0.3"
info:
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
endpoints documented here.
Usage
-----
## Usage
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
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`
- 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
To authenticate with the Funkwhale API:
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
requests to prevent abuse and improve the stability of service. Requests that are dropped because of rate-limiting
receive a 429 HTTP response.
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.
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
- The operation being performed: Write and delete operations, as performed with DELETE, POST, PUT and PATCH HTTP methods are subject to lower limits
- What was the scope of the request (`X-RateLimit-Scope`)
- 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 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.
For more information, check our [rate limit documentation](https://docs.funkwhale.audio/developer_documentation/api/rate-limit.html)
A full list of scopes with their corresponding description, and the current usage data for the client performing the request
is available via the `/api/v1/rate-limit` endpoint.
## Resources
Additionally, we include HTTP headers on all API response to ensure API clients can understand:
- 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)
For more information about API usage, refer to [our API documentation](https://docs.funkwhale.audio/developer_documentation/api/index.html).
version: "1.0.0"
title: "Funkwhale API"