swagger.yml 53.6 KB
Newer Older
1
openapi: "3.0.3"
2
info:
Eliot Berriot's avatar
Eliot Berriot committed
3
4
5
  description: |
    Interactive documentation for [Funkwhale](https://funkwhale.audio) API.

Agate's avatar
Agate committed
6
7
    Backward compatibility between minor versions (1.X to 1.Y) is guaranteed for all the
    endpoints documented here.
Eliot Berriot's avatar
Eliot Berriot committed
8

Eliot Berriot's avatar
Eliot Berriot committed
9
10
11
12
13
14
15
16
    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.

Agate's avatar
Agate committed
17
18
19
20
21
    OAuth Authentication
    --------------------
      
    You can register your own OAuth app using the `/api/v1/oauth/apps/` endpoint. Proceed to the standard OAuth flow afterwards:
      
Agate's avatar
Agate committed
22
23
24
25
26
    - 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
Agate's avatar
Agate committed
27
    
Agate's avatar
Agate committed
28
    You can use our demo server at `https://demo.funkwhale.audio` for testing purposes.
Agate's avatar
Agate committed
29
30
31
32
33
34
35
        
    Application token authentication
    --------------------------------
    
    If using OAuth isn't practical and you have an account on the Funkwhale pod, you can create an application by visiting `/settings`.

    Once the application is created, you can authenticate using its access token in the `Authorization` header, like this: `Authorization: Bearer <token>`. 
Eliot Berriot's avatar
Eliot Berriot committed
36

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
    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.

    The limits themselves vary depending on:

    - 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

    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.

    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.

    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>


Eliot Berriot's avatar
Eliot Berriot committed
110
111
112
    Resources
    ---------

Eliot Berriot's avatar
Eliot Berriot committed
113
114
115
    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)

116
117
118
119
  version: "1.0.0"
  title: "Funkwhale API"

servers:
120
  - url: https://demo.funkwhale.audio
121
    description: Demo server
122
123
  - url: https://open.audio
    description: Real server with real content
124
  - url: https://{domain}
125
126
127
128
129
130
131
132
133
134
    description: Custom server
    variables:
      domain:
        default: yourdomain
        description: Your Funkwhale Domain
      protocol:
        enum:
          - 'http'
          - 'https'
        default: 'https'
135
136
137

components:
  securitySchemes:
138
139
140
141
142
143
144
145
146
147
148
149
    oauth2:
      type: oauth2
      description: This API uses OAuth 2 with the Authorization Code flow. You can register an app using the /oauth/apps/ endpoint.
      flows:
        authorizationCode:
          authorizationUrl: /authorize
          tokenUrl: /api/v1/oauth/token/
          refreshUrl: /api/v1/oauth/token/
          scopes:
            "read": "Read-only access to all user data"
            "write": "Write-only access on all user data"
            "read:edits": "Read-only access to edits"
Agate's avatar
Agate committed
150
151
152
            "write:edits": "Write-only access to edits"
            "read:favorites": "Read-only access to favorites"
            "write:favorites": "Write-only access to favorits"
153
            "read:filters": "Read-only to to content filters"
Agate's avatar
Agate committed
154
155
            "write:filters": "Write-only access to content-filters"
            "read:follows": "Read-only to follows"
156
            "write:follows": "Write-only access to follows"
Agate's avatar
Agate committed
157
158
159
160
161
            "read:libraries": "Read-only access to library and uploads"
            "write:libraries": "Write-only access to libraries"
            "read:listenings": "Read-only access to listening history"
            "write:listenings": "Write-only access to listening history"
            "read:notifications": "Read-only access to notifications"
162
            "write:notifications": "Write-only access to notifications"
Agate's avatar
Agate committed
163
164
165
166
167
            "read:playlists": "Read-only access to playlists"
            "write:playlists": "Write-only access to playlists"
            "read:profile": "Read-only access to profile data"
            "write:profile": "Write-only access to profile data"
            "read:radios": "Read-only access to radios"
168
            "write:radios": "Write-only access to radios"
Agate's avatar
Agate committed
169
170
171
172
            "read:reports": "Read-only access to reports"
            "write:reports": "Write-only access to reports"
            "read:security": "Read-only access security settings"
            "write:security": "write-only access security settings"
173
174
175
176
177
178
179
180
    jwt:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: "You can get a token by using the /token endpoint"

security:
  - jwt: []
181
  - oauth2: []
182

183
184
tags:
  - name: Auth and security
185
    description: Login, logout, rate-limit and authorization endpoints
186
187
188
189
190
191
  - 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
Agate's avatar
Agate committed
192
193
194
195
  - name: Channels and subscriptions
    description: Channel management and subscription
    externalDocs:
      url: https://docs.funkwhale.audio/users/upload.html#using-a-channel
Eliot Berriot's avatar
Eliot Berriot committed
196
197
  - name: Content curation
    description: Favorites, playlists, radios
Agate's avatar
Agate committed
198
199
  - name: User activity
    description: Listenings
Eliot Berriot's avatar
Eliot Berriot committed
200
201
  - name: Other
    description: Other endpoints that don't fit in the categories above
202

203
paths:
204
205
206
  /api/v1/oauth/apps/:
    post:
      tags:
207
        - "Auth and security"
Agate's avatar
Agate committed
208
      summary:
209
210
211
212
213
214
215
216
        Register an OAuth application
      security: []
      responses:
        201:
          content:
            application/json:
              schema:
                allOf:
Agate's avatar
Agate committed
217
218
                  - $ref: "./api/definitions.yml#/OAuthApplication"
                  - $ref: "./api/definitions.yml#/OAuthApplicationCreation"
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: "object"
              properties:
                name:
                  type: "string"
                  example: "My Awesome Funkwhale Client"
                  summary: "A human readable name for your app"
                redirect_uris:
                  type: "string"
                  example: "https://myapp/oauth2/funkwhale"
                  summary: "A list of redirect uris, separated by spaces"
                scopes:
                  type: "string"
                  summary: "A list of scopes requested by your app, separated by spaces"
                  example: "read write:playlists write:favorites"
Agate's avatar
Agate committed
238
  /api/v1/oauth/token/:
239
240
    post:
      tags:
241
        - "Auth and security"
Agate's avatar
Agate committed
242
243
      summary:
        Request an OAuth bearer token in exchange of an authorization_code or a refresh_token
244
245
      security: []
      responses:
Agate's avatar
Agate committed
246
        200:
247

248
  /api/v1/auth/registration/:
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
    post:
      summary: Create an account
      description: |
        Register a new account on this instance. An invitation code will be required
        if sign up is disabled.
      tags:
        - "Auth and security"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: "object"
              properties:
                username:
                  type: "string"
                  example: "alice"
                email:
                  type: "string"
                  format: "email"
                invitation:
                  type: "string"
                  example: "INVITECODE"
                  required: false
                  description: An invitation code, required if signups are closed on the instance.
                password1:
                  type: "string"
                  example: "passw0rd"
                password2:
                  type: "string"
                  description: Must be identical to password1
                  example: "passw0rd"
      responses:
        201:
          $ref: "#/responses/201"
284
  /api/v1/auth/password/reset/:
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
    post:
      summary: Request a password reset
      description: |
        Request a password reset. An email with reset instructions will be sent to the provided email,
        if it's associated with a user account.
      tags:
        - "Auth and security"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: "object"
              properties:
                email:
                  type: "string"
                  format: "email"
      responses:
        200:
          $ref: "#/responses/200"
305
  /api/v1/users/me/:
306
307
308
309
310
311
312
313
314
315
316
317
    get:
      summary: Retrive profile information
      description: |
        Retrieve profile informations of the current user
      tags:
        - "Auth and security"

      responses:
        200:
          content:
            application/json:
              schema:
Agate's avatar
Agate committed
318
                $ref: "./api/definitions.yml#/Me"
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
    delete:
      summary: Delete the user account performing the request
      tags:
        - "Auth and security"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: "object"
              properties:
                confirm:
                  type: "boolean"
                  description: "Must be set to true, to avoid accidental deletion"
                password:
                  type: "string"
                  description: "The current password of the account"
      responses:
        200:
          content:
            application/json:
              schema:
                $ref: "./api/definitions.yml#/Me"
  /api/v1/users/users/change-email/:
    post:
      summary: Update the email address associated with a user account
      tags:
        - "Auth and security"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: "object"
              properties:
                email:
                  type: "string"
                  format: "email"
                password:
                  type: "string"
                  description: "The current password of the account"
      responses:
        200:
          content:
            application/json:
              schema:
                $ref: "./api/definitions.yml#/Me"
366

367
368
369
370
371
372
373
374
375
376
377
  /api/v1/rate-limit/:
    get:
      summary: Retrive rate-limit information and current usage status
      tags:
        - "Auth and security"

      responses:
        200:
          content:
            application/json:
              schema:
Agate's avatar
Agate committed
378
                $ref: "./api/definitions.yml#/RateLimitStatus"
379

380
  /api/v1/artists/:
381
    get:
Eliot Berriot's avatar
Eliot Berriot committed
382
      summary: List artists
383
      tags:
384
        - "Library and metadata"
385
386
387
      security:
        - oauth2:
          - "read:libraries"
388
      parameters:
Agate's avatar
Agate committed
389

Agate's avatar
Agate committed
390
        - $ref: "./api/parameters.yml#/Search"
Eliot Berriot's avatar
Eliot Berriot committed
391
        - allOf:
Agate's avatar
Agate committed
392
            - $ref: "./api/parameters.yml#/Ordering"
Eliot Berriot's avatar
Eliot Berriot committed
393
394
395
396
397
398
399
400
401
            - default: "-creation_date"
              schema:
                required: false
                type: "string"
                example: "creation_date"
                enum:
                  - creation_date
                  - id
                  - name
402
                  - random
Agate's avatar
Agate committed
403
        - $ref: "./api/parameters.yml#/Playable"
404
        - $ref: "./api/parameters.yml#/HasAlbums"
Agate's avatar
Agate committed
405
        - $ref: "./api/parameters.yml#/Library"
Agate's avatar
Agate committed
406
407
        - $ref: "./api/parameters.yml#/PageNumber"
        - $ref: "./api/parameters.yml#/PageSize"
Agate's avatar
Agate committed
408
        - $ref: "./api/parameters.yml#/Related"
Agate's avatar
Agate committed
409
        - $ref: "./api/parameters.yml#/Scope"
Eliot Berriot's avatar
Eliot Berriot committed
410
411
412
413
414
415
      responses:
        200:
          content:
            application/json:
              schema:
                allOf:
Agate's avatar
Agate committed
416
                  - $ref: "./api/definitions.yml#/ResultPage"
Eliot Berriot's avatar
Eliot Berriot committed
417
418
419
420
421
                  - type: "object"
                    properties:
                      results:
                        type: "array"
                        items:
Agate's avatar
Agate committed
422
                          $ref: "./api/definitions.yml#/Artist"
423
  /api/v1/artists/{id}/:
Eliot Berriot's avatar
Eliot Berriot committed
424
425
426
    get:
      summary: Retrieve a single artist
      parameters:
Agate's avatar
Agate committed
427
428
        - $ref: "./api/parameters.yml#/ObjectId"
        - $ref: "./api/parameters.yml#/Refresh"
429
430
431
      security:
        - oauth2:
          - "read:libraries"
Eliot Berriot's avatar
Eliot Berriot committed
432
      tags:
433
        - "Library and metadata"
Eliot Berriot's avatar
Eliot Berriot committed
434
435
436
437
438
      responses:
        200:
          content:
            application/json:
              schema:
Agate's avatar
Agate committed
439
                $ref: "./api/definitions.yml#/Artist"
Eliot Berriot's avatar
Eliot Berriot committed
440
441
442
443
        404:
          content:
            application/json:
              schema:
Agate's avatar
Agate committed
444
                $ref: "./api/definitions.yml#/ResourceNotFound"
445
  /api/v1/artists/{id}/libraries/:
Eliot Berriot's avatar
Eliot Berriot committed
446
447
    get:
      summary: List available user libraries containing work from this artist
448
449
450
      security:
        - oauth2:
          - "read:libraries"
Eliot Berriot's avatar
Eliot Berriot committed
451
      parameters:
Agate's avatar
Agate committed
452
453
454
        - $ref: "./api/parameters.yml#/ObjectId"
        - $ref: "./api/parameters.yml#/PageNumber"
        - $ref: "./api/parameters.yml#/PageSize"
Eliot Berriot's avatar
Eliot Berriot committed
455
456

      tags:
457
        - "Library and metadata"
Eliot Berriot's avatar
Eliot Berriot committed
458
459
460
461
462
      responses:
        200:
          content:
            application/json:
              schema:
Agate's avatar
Agate committed
463
                $ref: "./api/definitions.yml#/LibraryPage"
Eliot Berriot's avatar
Eliot Berriot committed
464
465
466
467
        404:
          content:
            application/json:
              schema:
Agate's avatar
Agate committed
468
                $ref: "./api/definitions.yml#/ResourceNotFound"
Eliot Berriot's avatar
Eliot Berriot committed
469

470
  /api/v1/albums/:
Eliot Berriot's avatar
Eliot Berriot committed
471
472
473
    get:
      summary: List albums
      tags:
474
        - "Library and metadata"
475
476
477
478

      security:
        - oauth2:
          - "read:libraries"
Eliot Berriot's avatar
Eliot Berriot committed
479
      parameters:
Agate's avatar
Agate committed
480

Agate's avatar
Agate committed
481
        - $ref: "./api/parameters.yml#/Search"
Eliot Berriot's avatar
Eliot Berriot committed
482
483
484
485
486
487
488
489
490
        - name: "artist"
          in: "query"
          default: null
          description: "Only include albums by the requested artist"
          schema:
            required: false
            type: "integer"
            format: "int64"
        - allOf:
Agate's avatar
Agate committed
491
            - $ref: "./api/parameters.yml#/Ordering"
Eliot Berriot's avatar
Eliot Berriot committed
492
493
494
495
496
497
498
499
500
            - default: "-creation_date"
              schema:
                required: false
                type: "string"
                example: "creation_date"
                enum:
                  - creation_date
                  - release_date
                  - title
501
                  - random
Agate's avatar
Agate committed
502
        - $ref: "./api/parameters.yml#/Library"
Agate's avatar
Agate committed
503
504
505
        - $ref: "./api/parameters.yml#/Playable"
        - $ref: "./api/parameters.yml#/PageNumber"
        - $ref: "./api/parameters.yml#/PageSize"
Agate's avatar
Agate committed
506
        - $ref: "./api/parameters.yml#/Related"
Agate's avatar
Agate committed
507
        - $ref: "./api/parameters.yml#/Scope"
508
        - $ref: "./api/parameters.yml#/ContentType"
Eliot Berriot's avatar
Eliot Berriot committed
509
510
511
512
513
514
515

      responses:
        200:
          content:
            application/json:
              schema:
                allOf:
Agate's avatar
Agate committed
516
                  - $ref: "./api/definitions.yml#/ResultPage"
Eliot Berriot's avatar
Eliot Berriot committed
517
518
519
520
521
                  - type: "object"
                    properties:
                      results:
                        type: "array"
                        items:
Agate's avatar
Agate committed
522
                          $ref: "./api/definitions.yml#/Album"
523
  /api/v1/albums/{id}/:
Eliot Berriot's avatar
Eliot Berriot committed
524
525
526
    get:
      summary: Retrieve a single album
      parameters:
Agate's avatar
Agate committed
527
528
        - $ref: "./api/parameters.yml#/ObjectId"
        - $ref: "./api/parameters.yml#/Refresh"
Eliot Berriot's avatar
Eliot Berriot committed
529

530
531
532
      security:
        - oauth2:
          - "read:libraries"
Eliot Berriot's avatar
Eliot Berriot committed
533
      tags:
534
        - "Library and metadata"
Eliot Berriot's avatar
Eliot Berriot committed
535
536
537
538
539
      responses:
        200:
          content:
            application/json:
              schema:
Agate's avatar
Agate committed
540
                $ref: "./api/definitions.yml#/Album"
Eliot Berriot's avatar
Eliot Berriot committed
541
542
543
544
        404:
          content:
            application/json:
              schema:
Agate's avatar
Agate committed
545
                $ref: "./api/definitions.yml#/ResourceNotFound"
Eliot Berriot's avatar
Eliot Berriot committed
546

547
  /api/v1/albums/{id}/libraries/:
Eliot Berriot's avatar
Eliot Berriot committed
548
549
550
    get:
      summary: List available user libraries containing tracks from this album
      parameters:
Agate's avatar
Agate committed
551
552
553
        - $ref: "./api/parameters.yml#/ObjectId"
        - $ref: "./api/parameters.yml#/PageNumber"
        - $ref: "./api/parameters.yml#/PageSize"
Eliot Berriot's avatar
Eliot Berriot committed
554

555
556
557
      security:
        - oauth2:
          - "read:libraries"
Eliot Berriot's avatar
Eliot Berriot committed
558
      tags:
559
        - "Library and metadata"
Eliot Berriot's avatar
Eliot Berriot committed
560
561
562
563
564
      responses:
        200:
          content:
            application/json:
              schema:
Agate's avatar
Agate committed
565
                $ref: "./api/definitions.yml#/LibraryPage"
Eliot Berriot's avatar
Eliot Berriot committed
566
567
568
569
        404:
          content:
            application/json:
              schema:
Agate's avatar
Agate committed
570
                $ref: "./api/definitions.yml#/ResourceNotFound"
Eliot Berriot's avatar
Eliot Berriot committed
571

572
  /api/v1/tracks/:
Eliot Berriot's avatar
Eliot Berriot committed
573
574
575
    get:
      summary: List tracks
      tags:
576
        - "Library and metadata"
577
578
579
580

      security:
        - oauth2:
          - "read:libraries"
Eliot Berriot's avatar
Eliot Berriot committed
581
      parameters:
Agate's avatar
Agate committed
582

Agate's avatar
Agate committed
583
        - $ref: "./api/parameters.yml#/Search"
Eliot Berriot's avatar
Eliot Berriot committed
584
585
586
587
588
589
590
591
        - name: "artist"
          in: "query"
          default: null
          description: "Only include tracks by the requested artist"
          schema:
            required: false
            type: "integer"
            format: "int64"
Eliot Berriot's avatar
Eliot Berriot committed
592
593
594
595
596
597
598
        - name: "favorites"
          in: "query"
          default: null
          description: "filter/exclude tracks favorited by the current user"
          schema:
            required: false
            type: "boolean"
Eliot Berriot's avatar
Eliot Berriot committed
599
600
601
602
603
604
605
606
607
        - name: "album"
          in: "query"
          default: null
          description: "Only include tracks from the requested album"
          schema:
            required: false
            type: "integer"
            format: "int64"
        - name: "license"
608
          in: "query"
Eliot Berriot's avatar
Eliot Berriot committed
609
610
          description: "Only include tracks with the given license"
          default: null
611
          schema:
Eliot Berriot's avatar
Eliot Berriot committed
612
            example: "cc-by-sa-4.0"
613
            required: false
Eliot Berriot's avatar
Eliot Berriot committed
614
615
            type: "string"
        - allOf:
Agate's avatar
Agate committed
616
            - $ref: "./api/parameters.yml#/Ordering"
Eliot Berriot's avatar
Eliot Berriot committed
617
618
619
620
621
622
623
624
625
            - default: "-creation_date"
              schema:
                required: false
                type: "string"
                example: "creation_date"
                enum:
                  - creation_date
                  - release_date
                  - title
626
                  - random
Agate's avatar
Agate committed
627
        - $ref: "./api/parameters.yml#/Library"
Agate's avatar
Agate committed
628
629
630
        - $ref: "./api/parameters.yml#/Playable"
        - $ref: "./api/parameters.yml#/PageNumber"
        - $ref: "./api/parameters.yml#/PageSize"
Agate's avatar
Agate committed
631
        - $ref: "./api/parameters.yml#/Related"
Agate's avatar
Agate committed
632
        - $ref: "./api/parameters.yml#/Scope"
Eliot Berriot's avatar
Eliot Berriot committed
633

634
635
636
637
638
      responses:
        200:
          content:
            application/json:
              schema:
Eliot Berriot's avatar
Eliot Berriot committed
639
                allOf:
Agate's avatar
Agate committed
640
                  - $ref: "./api/definitions.yml#/ResultPage"
Eliot Berriot's avatar
Eliot Berriot committed
641
642
643
644
645
                  - type: "object"
                    properties:
                      results:
                        type: "array"
                        items:
Agate's avatar
Agate committed
646
                          $ref: "./api/definitions.yml#/Track"
647
  /api/v1/tracks/{id}/:
Eliot Berriot's avatar
Eliot Berriot committed
648
649
    get:
      parameters:
Agate's avatar
Agate committed
650
651
        - $ref: "./api/parameters.yml#/ObjectId"
        - $ref: "./api/parameters.yml#/Refresh"
652
      summary: Retrieve a single track
Eliot Berriot's avatar
Eliot Berriot committed
653

654
655
656
      security:
        - oauth2:
          - "read:libraries"
Eliot Berriot's avatar
Eliot Berriot committed
657
      tags:
658
        - "Library and metadata"
Eliot Berriot's avatar
Eliot Berriot committed
659
660
661
662
663
      responses:
        200:
          content:
            application/json:
              schema:
Agate's avatar
Agate committed
664
                $ref: "./api/definitions.yml#/Track"
Eliot Berriot's avatar
Eliot Berriot committed
665
666
667
668
        404:
          content:
            application/json:
              schema:
Agate's avatar
Agate committed
669
                $ref: "./api/definitions.yml#/ResourceNotFound"
Eliot Berriot's avatar
Eliot Berriot committed
670

671
  /api/v1/tracks/{id}/libraries/:
Eliot Berriot's avatar
Eliot Berriot committed
672
673
674
    get:
      summary: List available user libraries containing given track
      parameters:
Agate's avatar
Agate committed
675
676
677
        - $ref: "./api/parameters.yml#/ObjectId"
        - $ref: "./api/parameters.yml#/PageNumber"
        - $ref: "./api/parameters.yml#/PageSize"
678
679
680
      security:
        - oauth2:
          - "read:libraries"
Eliot Berriot's avatar
Eliot Berriot committed
681
      tags:
682
        - "Library and metadata"
Eliot Berriot's avatar
Eliot Berriot committed
683
684
685
686
687
      responses:
        200:
          content:
            application/json:
              schema:
Agate's avatar
Agate committed
688
                $ref: "./api/definitions.yml#/LibraryPage"
Eliot Berriot's avatar
Eliot Berriot committed
689
690
691
692
        404:
          content:
            application/json:
              schema:
Agate's avatar
Agate committed
693
                $ref: "./api/definitions.yml#/ResourceNotFound"
694
  /api/v1/listen/{uuid}/:
Eliot Berriot's avatar
Eliot Berriot committed
695
696
697
698
699
    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.
Eliot Berriot's avatar
Eliot Berriot committed
700

Eliot Berriot's avatar
Eliot Berriot committed
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
        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:
Agate's avatar
Agate committed
725
            $ref: "./api/properties.yml#/transcode_options"
Eliot Berriot's avatar
Eliot Berriot committed
726
727
728
729
730
731
732
733
734
735
736
737
        - 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
Agate's avatar
Agate committed
738
739
740
741
742
743
744
745
746
747
        - name: token
          in: query
          required: false
          description: |
            A listen token as returned by /users/me

            This offers an alternative authentication method for situations where HTTP headers
            can't be modified to include a Bearer token.
          schema:
            type: string
Eliot Berriot's avatar
Eliot Berriot committed
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762

      tags:
        - "Library and metadata"
      responses:
        200:
          content:
            '*/*':
              description: "Audio file, as binary data"
              schema:
                type: string
                format: binary
        404:
          content:
            application/json:
              schema:
Agate's avatar
Agate committed
763
                $ref: "./api/definitions.yml#/ResourceNotFound"
Eliot Berriot's avatar
Eliot Berriot committed
764

765
  /api/v1/licenses/:
Eliot Berriot's avatar
Eliot Berriot committed
766
767
    get:
      summary: List licenses
768
769
770
      security:
        - oauth2:
          - "read:libraries"
Eliot Berriot's avatar
Eliot Berriot committed
771
      tags:
772
        - "Library and metadata"
Eliot Berriot's avatar
Eliot Berriot committed
773
      parameters:
Agate's avatar
Agate committed
774
775
        - $ref: "./api/parameters.yml#/PageNumber"
        - $ref: "./api/parameters.yml#/PageSize"
Eliot Berriot's avatar
Eliot Berriot committed
776
777
778
779
780
781
      responses:
        200:
          content:
            application/json:
              schema:
                allOf:
Agate's avatar
Agate committed
782
                  - $ref: "./api/definitions.yml#/ResultPage"
Eliot Berriot's avatar
Eliot Berriot committed
783
784
785
786
787
                  - type: "object"
                    properties:
                      results:
                        type: "array"
                        items:
Agate's avatar
Agate committed
788
                          $ref: "./api/definitions.yml#/License"
Eliot Berriot's avatar
Eliot Berriot committed
789

790
  /api/v1/licenses/{code}/:
Eliot Berriot's avatar
Eliot Berriot committed
791
792
    get:
      summary: Retrieve a single license
793
794
795
      security:
        - oauth2:
          - "read:libraries"
Eliot Berriot's avatar
Eliot Berriot committed
796
797
798
799
800
801
802
803
804
805
      parameters:
        - name: code
          in: path
          description: License code
          required: true
          schema:
            type: string
            example: cc0-1.0

      tags:
806
        - "Library and metadata"
Eliot Berriot's avatar
Eliot Berriot committed
807
808
809
810
811
      responses:
        200:
          content:
            application/json:
              schema:
Agate's avatar
Agate committed
812
                $ref: "./api/definitions.yml#/License"
Eliot Berriot's avatar
Eliot Berriot committed
813
814
815
816
        404:
          content:
            application/json:
              schema:
Agate's avatar
Agate committed
817
                $ref: "./api/definitions.yml#/ResourceNotFound"
Eliot Berriot's avatar
Eliot Berriot committed
818

819
  /api/v1/libraries/:
820
821
822
823
824
    get:
      summary: List owned libraries
      tags:
        - "Uploads and audio content"
      parameters:
Agate's avatar
Agate committed
825
826
827
828
        - $ref: "./api/parameters.yml#/PageNumber"
        - $ref: "./api/parameters.yml#/PageSize"
        - $ref: "./api/parameters.yml#/Search"
        - $ref: "./api/parameters.yml#/Scope"
829
830
831
832
833
834
      responses:
        200:
          content:
            application/json:
              schema:
                allOf:
Agate's avatar
Agate committed
835
                  - $ref: "./api/definitions.yml#/ResultPage"
836
837
838
839
840
                  - type: "object"
                    properties:
                      results:
                        type: "array"
                        items:
Agate's avatar
Agate committed
841
                          $ref: "./api/definitions.yml#/OwnedLibrary"
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
    post:
      tags:
        - "Uploads and audio content"
      description:
        Create a new library
      responses:
        201:
          $ref: "#/responses/201"
        400:
          $ref: "#/responses/400"
      requestBody:
        required: true
        content:
          application/json:
            schema:
Agate's avatar
Agate committed
857
              $ref: "./api/definitions.yml#/OwnedLibraryCreate"
858

859
  /api/v1/libraries/{uuid}/:
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
    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:
Agate's avatar
Agate committed
876
                $ref: "./api/definitions.yml#/OwnedLibrary"
877
878
879
880
881
882
883
884
885
    post:
      summary: Update a library
      tags:
        - "Uploads and audio content"
      requestBody:
        required: true
        content:
          application/json:
            schema:
Agate's avatar
Agate committed
886
              $ref: "./api/definitions.yml#/OwnedLibraryCreate"
887
      responses:
Eliot Berriot's avatar
Eliot Berriot committed
888
        201:
889
890
891
          content:
            application/json:
              schema:
Agate's avatar
Agate committed
892
                $ref: "./api/definitions.yml#/OwnedLibrary"
893
894
895
896
897
898
899
900
901
902
    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"
Eliot Berriot's avatar
Eliot Berriot committed
903

904
905
906
907
  /api/v1/channels/:
    get:
      summary: List channels
      tags:
Agate's avatar
Agate committed
908
        - "Channels and subscriptions"
909
      parameters:
910
        - allOf:
Agate's avatar
Agate committed
911
            - $ref: "./api/parameters.yml#/Ordering"
912
913
914
915
916
917
918
919
920
            - default: "-creation_date"
              schema:
                required: false
                type: "string"
                example: "creation_date"
                enum:
                  - creation_date
                  - modification_date
                  - random
Agate's avatar
Agate committed
921
922
923
924
925
926
927
928
        - $ref: "./api/parameters.yml#/PageNumber"
        - $ref: "./api/parameters.yml#/PageSize"
        - $ref: "./api/parameters.yml#/Scope"
        - $ref: "./api/parameters.yml#/Search"
        - $ref: "./api/parameters.yml#/Tags"
        - $ref: "./api/parameters.yml#/Subscribed"
        - $ref: "./api/parameters.yml#/External"
        - $ref: "./api/parameters.yml#/ChannelOrdering"
Agate's avatar
Agate committed
929

930
931
932
933
934
935
      responses:
        200:
          content:
            application/json:
              schema:
                allOf:
Agate's avatar
Agate committed
936
                  - $ref: "./api/definitions.yml#/ResultPage"
937
938
939
940
941
                  - type: "object"
                    properties:
                      results:
                        type: "array"
                        items:
Agate's avatar
Agate committed
942
                          $ref: "./api/definitions.yml#/Channel"
943
944
945
    post:
      summary: Create a new channel
      tags:
Agate's avatar
Agate committed
946
        - "Channels and subscriptions"
947
948
949
950
951
952
953
954
955
956
      responses:
        201:
          $ref: "#/responses/201"
        400:
          $ref: "#/responses/400"
      requestBody:
        required: true
        content:
          application/json:
            schema:
Agate's avatar
Agate committed
957
              $ref: "./api/definitions.yml#/ChannelCreate"
958

Agate's avatar
Agate committed
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
  /api/v1/channels/metadata-choices:
    summary: List metadata (locales, itunes categories) for creating and editing channels.
    tags:
      - "Channels and subscriptions"
    get:
      summary: List channels metadata options
      tags:
        - "Channels and subscriptions"
      responses:
        200:
          content:
            application/json:
              schema:
                type: "object"
                properties:
                  language:
                    type: "array"
                    items:
                      type: object
                      properties:
                        value:
                          type: string
                          description: ID of the locale in ISO 639 format
                          example: "en"
                        language:
                          type: string
                          example: "English"
                  itunes_category:
                    type: "array"
                    items:
                      type: object
                      properties:
                        value:
                          type: string
                          description: ID of the category
                          example: "Business"
                        label:
                          type: string
                          description: Readable label of the category
                          example: "Business"
                        children:
                          type: array
For faster browsing, not all history is shown. View entire blame