docs: auto-generate API route documentation
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Id0d1f9769b7ccdbf83d5fa78adef62e46a6a6964
This commit is contained in:
parent
9d58927cb4
commit
934691c0f9
40 changed files with 17444 additions and 1 deletions
BIN
Cargo.lock
generated
BIN
Cargo.lock
generated
Binary file not shown.
|
|
@ -1,5 +1,5 @@
|
|||
[workspace]
|
||||
members = ["crates/*"]
|
||||
members = ["crates/*", "xtask"]
|
||||
exclude = ["crates/pinakes-core/tests/fixtures/test-plugin"]
|
||||
resolver = "3"
|
||||
|
||||
|
|
@ -92,6 +92,9 @@ http = "1.4.0"
|
|||
wasmtime = { version = "42.0.1", features = ["component-model"] }
|
||||
wit-bindgen = "0.53.1"
|
||||
tempfile = "3.26.0"
|
||||
utoipa = { version = "5.4.0", features = ["axum_extras", "uuid", "chrono"] }
|
||||
utoipa-axum = { version = "0.2.0" }
|
||||
utoipa-swagger-ui = { version = "9.0.2", features = ["axum"] }
|
||||
|
||||
# See:
|
||||
# <https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html>
|
||||
|
|
|
|||
117
docs/api/analytics.md
Normal file
117
docs/api/analytics.md
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
# Analytics
|
||||
|
||||
Usage analytics and viewing history
|
||||
|
||||
## Endpoints
|
||||
|
||||
### POST /api/v1/analytics/events
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Event recorded |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/analytics/most-viewed
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `limit` | query | No | Maximum number of results |
|
||||
| `offset` | query | No | Pagination offset |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Most viewed media |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/analytics/recently-viewed
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `limit` | query | No | Maximum number of results |
|
||||
| `offset` | query | No | Pagination offset |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Recently viewed media |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/media/{id}/progress
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Watch progress |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### PUT /api/v1/media/{id}/progress
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Progress updated |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
27
docs/api/audit.md
Normal file
27
docs/api/audit.md
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# Audit
|
||||
|
||||
Audit log entries
|
||||
|
||||
## Endpoints
|
||||
|
||||
### GET /api/v1/audit
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `offset` | query | No | Pagination offset |
|
||||
| `limit` | query | No | Page size |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Audit log entries |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
103
docs/api/auth.md
Normal file
103
docs/api/auth.md
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
# Auth
|
||||
|
||||
Authentication and session management
|
||||
|
||||
## Endpoints
|
||||
|
||||
### POST /api/v1/auth/login
|
||||
|
||||
**Authentication:** Not required
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Login successful |
|
||||
| 400 | Bad request |
|
||||
| 401 | Invalid credentials |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/auth/logout
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Logged out |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/auth/me
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Current user info |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/auth/refresh
|
||||
|
||||
Refresh the current session, extending its expiry by the configured
|
||||
duration.
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Session refreshed |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/auth/revoke-all
|
||||
|
||||
Revoke all sessions for the current user
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | All sessions revoked |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/auth/sessions
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Active sessions |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
27
docs/api/backup.md
Normal file
27
docs/api/backup.md
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# Backup
|
||||
|
||||
Database backup
|
||||
|
||||
## Endpoints
|
||||
|
||||
### POST /api/v1/admin/backup
|
||||
|
||||
Create a database backup and return it as a downloadable file.
|
||||
POST /api/v1/admin/backup
|
||||
|
||||
For `SQLite`: creates a backup via VACUUM INTO and returns the file.
|
||||
For `PostgreSQL`: returns unsupported error (use `pg_dump` instead).
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Backup file download |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
208
docs/api/books.md
Normal file
208
docs/api/books.md
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
# Books
|
||||
|
||||
Book metadata, series, authors, and reading progress
|
||||
|
||||
## Endpoints
|
||||
|
||||
### GET /api/v1/books
|
||||
|
||||
List all books with optional search filters
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `isbn` | query | No | Filter by ISBN |
|
||||
| `author` | query | No | Filter by author |
|
||||
| `series` | query | No | Filter by series |
|
||||
| `publisher` | query | No | Filter by publisher |
|
||||
| `language` | query | No | Filter by language |
|
||||
| `offset` | query | No | Pagination offset |
|
||||
| `limit` | query | No | Pagination limit |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | List of books |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/books/authors
|
||||
|
||||
List all authors with book counts
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `offset` | query | No | Pagination offset |
|
||||
| `limit` | query | No | Pagination limit |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Authors with book counts |
|
||||
| 401 | Unauthorized |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/books/authors/{name}/books
|
||||
|
||||
Get books by a specific author
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `name` | path | Yes | Author name |
|
||||
| `offset` | query | No | Pagination offset |
|
||||
| `limit` | query | No | Pagination limit |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Books by author |
|
||||
| 401 | Unauthorized |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/books/reading-list
|
||||
|
||||
Get user's reading list
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `status` | query | No | Filter by reading status |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Reading list |
|
||||
| 401 | Unauthorized |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/books/series
|
||||
|
||||
List all series with book counts
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | List of series with counts |
|
||||
| 401 | Unauthorized |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/books/series/{name}
|
||||
|
||||
Get books in a specific series
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `name` | path | Yes | Series name |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Books in series |
|
||||
| 401 | Unauthorized |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/books/{id}/metadata
|
||||
|
||||
Get book metadata by media ID
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Book metadata |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/books/{id}/progress
|
||||
|
||||
Get reading progress for a book
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Reading progress |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### PUT /api/v1/books/{id}/progress
|
||||
|
||||
Update reading progress for a book
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 204 | Progress updated |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
|
||||
---
|
||||
|
||||
157
docs/api/collections.md
Normal file
157
docs/api/collections.md
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
# Collections
|
||||
|
||||
Media collections
|
||||
|
||||
## Endpoints
|
||||
|
||||
### GET /api/v1/collections
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | List of collections |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/collections
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Collection created |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/collections/{id}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Collection ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Collection |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### DELETE /api/v1/collections/{id}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Collection ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Collection deleted |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/collections/{id}/members
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Collection ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Collection members |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/collections/{id}/members
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Collection ID |
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Member added |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### DELETE /api/v1/collections/{id}/members/{media_id}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Collection ID |
|
||||
| `media_id` | path | Yes | Media item ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Member removed |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
120
docs/api/config.md
Normal file
120
docs/api/config.md
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
# Config
|
||||
|
||||
Server configuration
|
||||
|
||||
## Endpoints
|
||||
|
||||
### GET /api/v1/config
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Current server configuration |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/config/roots
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Updated configuration |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### DELETE /api/v1/config/roots
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Updated configuration |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### PATCH /api/v1/config/scanning
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Updated configuration |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/config/ui
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | UI configuration |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### PATCH /api/v1/config/ui
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Updated UI configuration |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
51
docs/api/database.md
Normal file
51
docs/api/database.md
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
# Database
|
||||
|
||||
Database administration
|
||||
|
||||
## Endpoints
|
||||
|
||||
### POST /api/v1/admin/database/clear
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Database cleared |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/admin/database/stats
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Database statistics |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/admin/database/vacuum
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Database vacuumed |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
20
docs/api/duplicates.md
Normal file
20
docs/api/duplicates.md
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# Duplicates
|
||||
|
||||
Duplicate media detection
|
||||
|
||||
## Endpoints
|
||||
|
||||
### GET /api/v1/media/duplicates
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Duplicate groups |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
71
docs/api/enrichment.md
Normal file
71
docs/api/enrichment.md
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
# Enrichment
|
||||
|
||||
External metadata enrichment
|
||||
|
||||
## Endpoints
|
||||
|
||||
### POST /api/v1/media/enrich/batch
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Enrichment job submitted |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/media/{id}/enrich
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Enrichment job submitted |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/media/{id}/metadata/external
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | External metadata |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
42
docs/api/export.md
Normal file
42
docs/api/export.md
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
# Export
|
||||
|
||||
Media library export
|
||||
|
||||
## Endpoints
|
||||
|
||||
### POST /api/v1/export
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Export job submitted |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/export/options
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Export job submitted |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
63
docs/api/health.md
Normal file
63
docs/api/health.md
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
# Health
|
||||
|
||||
Server health checks
|
||||
|
||||
## Endpoints
|
||||
|
||||
### GET /api/v1/health
|
||||
|
||||
Comprehensive health check - includes database, filesystem, and cache status
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Health status |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/health/detailed
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Detailed health status |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/health/live
|
||||
|
||||
Liveness probe - just checks if the server is running
|
||||
Returns 200 OK if the server process is alive
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Server is alive |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/health/ready
|
||||
|
||||
Readiness probe - checks if the server can serve requests
|
||||
Returns 200 OK if database is accessible
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Server is ready |
|
||||
| 503 | Server not ready |
|
||||
|
||||
---
|
||||
|
||||
99
docs/api/integrity.md
Normal file
99
docs/api/integrity.md
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
# Integrity
|
||||
|
||||
Library integrity checks and repairs
|
||||
|
||||
## Endpoints
|
||||
|
||||
### POST /api/v1/admin/integrity/orphans/detect
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Orphan detection job submitted |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/admin/integrity/orphans/resolve
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Orphans resolved |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/admin/integrity/thumbnails/cleanup
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Thumbnail cleanup job submitted |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/admin/integrity/thumbnails/generate
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Thumbnail generation job submitted |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/admin/integrity/verify
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Integrity verification job submitted |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
62
docs/api/jobs.md
Normal file
62
docs/api/jobs.md
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
# Jobs
|
||||
|
||||
Background job management
|
||||
|
||||
## Endpoints
|
||||
|
||||
### GET /api/v1/jobs
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | List of jobs |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/jobs/{id}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Job ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Job details |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/jobs/{id}/cancel
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Job ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Job cancelled |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
640
docs/api/media.md
Normal file
640
docs/api/media.md
Normal file
|
|
@ -0,0 +1,640 @@
|
|||
# Media
|
||||
|
||||
Media item management
|
||||
|
||||
## Endpoints
|
||||
|
||||
### GET /api/v1/media
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `offset` | query | No | Pagination offset |
|
||||
| `limit` | query | No | Page size |
|
||||
| `sort` | query | No | Sort field |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | List of media items |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### DELETE /api/v1/media
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | All media deleted |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/media/batch/collection
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Batch collection result |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/media/batch/delete
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Batch delete result |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/media/batch/move
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Batch move result |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/media/batch/tag
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Batch tag result |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/media/batch/update
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Batch update result |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/media/count
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Media count |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/media/import
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Media imported |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/media/import/batch
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Batch import results |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/media/import/directory
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Directory import results |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/media/import/options
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Media imported |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/media/import/preview
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Directory preview |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/media/trash
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `offset` | query | No | Pagination offset |
|
||||
| `limit` | query | No | Page size |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Trashed media items |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### DELETE /api/v1/media/trash
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Trash emptied |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/media/trash/info
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Trash info |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/media/{id}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Media item |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### PATCH /api/v1/media/{id}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Updated media item |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### DELETE /api/v1/media/{id}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Media deleted |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### PUT /api/v1/media/{id}/custom-fields
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Custom field set |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### DELETE /api/v1/media/{id}/custom-fields/{name}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
| `name` | path | Yes | Custom field name |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Custom field deleted |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/media/{id}/move
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Moved media item |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/media/{id}/open
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Media opened |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### DELETE /api/v1/media/{id}/permanent
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
| `permanent` | query | No | Set to 'true' for permanent deletion |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Media deleted |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/media/{id}/rename
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Renamed media item |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/media/{id}/restore
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Media restored |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/media/{id}/stream
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Media stream |
|
||||
| 206 | Partial content |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/media/{id}/thumbnail
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Thumbnail image |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### DELETE /api/v1/media/{id}/trash
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Media moved to trash |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
142
docs/api/notes.md
Normal file
142
docs/api/notes.md
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
# Notes
|
||||
|
||||
Markdown notes link graph
|
||||
|
||||
## Endpoints
|
||||
|
||||
### GET /api/v1/media/{id}/backlinks
|
||||
|
||||
Get backlinks (incoming links) to a media item.
|
||||
|
||||
GET /api/v1/media/{id}/backlinks
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Backlinks |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/media/{id}/outgoing-links
|
||||
|
||||
Get outgoing links from a media item.
|
||||
|
||||
GET /api/v1/media/{id}/outgoing-links
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Outgoing links |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/media/{id}/reindex-links
|
||||
|
||||
Re-extract links from a media item.
|
||||
|
||||
POST /api/v1/media/{id}/reindex-links
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Links reindexed |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/notes/graph
|
||||
|
||||
Get graph data for visualization.
|
||||
|
||||
GET /api/v1/notes/graph?center={uuid}&depth={n}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `center` | query | No | Center node ID |
|
||||
| `depth` | query | No | Traversal depth (max 5, default 2) |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Graph data |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/notes/resolve-links
|
||||
|
||||
Resolve all unresolved links in the database.
|
||||
|
||||
POST /api/v1/notes/resolve-links
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Links resolved |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/notes/unresolved-count
|
||||
|
||||
Get count of unresolved links.
|
||||
|
||||
GET /api/v1/notes/unresolved-count
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Unresolved link count |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
12810
docs/api/openapi.json
Normal file
12810
docs/api/openapi.json
Normal file
File diff suppressed because it is too large
Load diff
57
docs/api/photos.md
Normal file
57
docs/api/photos.md
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
# Photos
|
||||
|
||||
Photo timeline and map view
|
||||
|
||||
## Endpoints
|
||||
|
||||
### GET /api/v1/photos/map
|
||||
|
||||
Get photos in a bounding box for map view
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `lat1` | query | Yes | Bounding box latitude 1 |
|
||||
| `lon1` | query | Yes | Bounding box longitude 1 |
|
||||
| `lat2` | query | Yes | Bounding box latitude 2 |
|
||||
| `lon2` | query | Yes | Bounding box longitude 2 |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Map markers |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/photos/timeline
|
||||
|
||||
Get timeline of photos grouped by date
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `group_by` | query | No | Grouping: day, month, year |
|
||||
| `year` | query | No | Filter by year |
|
||||
| `month` | query | No | Filter by month |
|
||||
| `limit` | query | No | Max items (default 10000) |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Photo timeline groups |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
229
docs/api/playlists.md
Normal file
229
docs/api/playlists.md
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
# Playlists
|
||||
|
||||
Media playlists
|
||||
|
||||
## Endpoints
|
||||
|
||||
### GET /api/v1/playlists
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | List of playlists |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/playlists
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Playlist created |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/playlists/{id}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Playlist ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Playlist details |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### PATCH /api/v1/playlists/{id}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Playlist ID |
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Playlist updated |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### DELETE /api/v1/playlists/{id}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Playlist ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Playlist deleted |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/playlists/{id}/items
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Playlist ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Playlist items |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/playlists/{id}/items
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Playlist ID |
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Item added |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### PATCH /api/v1/playlists/{id}/items/reorder
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Playlist ID |
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Item reordered |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### DELETE /api/v1/playlists/{id}/items/{media_id}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Playlist ID |
|
||||
| `media_id` | path | Yes | Media item ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Item removed |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/playlists/{id}/shuffle
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Playlist ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Shuffled playlist items |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
209
docs/api/plugins.md
Normal file
209
docs/api/plugins.md
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
# Plugins
|
||||
|
||||
Plugin management
|
||||
|
||||
## Endpoints
|
||||
|
||||
### GET /api/v1/plugins
|
||||
|
||||
List all installed plugins
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | List of plugins |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/plugins
|
||||
|
||||
Install a plugin from URL or file path
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Plugin installed |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/plugins/events
|
||||
|
||||
Receive a plugin event emitted from the UI and dispatch it to interested
|
||||
server-side event-handler plugins via the pipeline.
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Event received |
|
||||
| 401 | Unauthorized |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/plugins/ui/pages
|
||||
|
||||
List all UI pages provided by loaded plugins
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Plugin UI pages |
|
||||
| 401 | Unauthorized |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/plugins/ui/theme
|
||||
|
||||
List merged CSS custom property overrides from all enabled plugins
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Plugin UI theme extensions |
|
||||
| 401 | Unauthorized |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/plugins/ui/widgets
|
||||
|
||||
List all UI widgets provided by loaded plugins
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Plugin UI widgets |
|
||||
| 401 | Unauthorized |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/plugins/{id}
|
||||
|
||||
Get a specific plugin by ID
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Plugin ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Plugin details |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### DELETE /api/v1/plugins/{id}
|
||||
|
||||
Uninstall a plugin
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Plugin ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Plugin uninstalled |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/plugins/{id}/reload
|
||||
|
||||
Reload a plugin (for development)
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Plugin ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Plugin reloaded |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### PATCH /api/v1/plugins/{id}/toggle
|
||||
|
||||
Enable or disable a plugin
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Plugin ID |
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Plugin toggled |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
62
docs/api/saved_searches.md
Normal file
62
docs/api/saved_searches.md
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
# Saved_searches
|
||||
|
||||
Saved search queries
|
||||
|
||||
## Endpoints
|
||||
|
||||
### GET /api/v1/searches
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | List of saved searches |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/searches
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Search saved |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### DELETE /api/v1/searches/{id}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Saved search ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Saved search deleted |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
42
docs/api/scan.md
Normal file
42
docs/api/scan.md
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
# Scan
|
||||
|
||||
Directory scanning
|
||||
|
||||
## Endpoints
|
||||
|
||||
### POST /api/v1/scan
|
||||
|
||||
Trigger a scan as a background job. Returns the job ID immediately.
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Scan job submitted |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/scan/status
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Scan status |
|
||||
| 401 | Unauthorized |
|
||||
|
||||
---
|
||||
|
||||
62
docs/api/scheduled_tasks.md
Normal file
62
docs/api/scheduled_tasks.md
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
# Scheduled_tasks
|
||||
|
||||
Scheduled background tasks
|
||||
|
||||
## Endpoints
|
||||
|
||||
### GET /api/v1/scheduled-tasks
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | List of scheduled tasks |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/scheduled-tasks/{id}/run
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Task ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Task triggered |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/scheduled-tasks/{id}/toggle
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Task ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Task toggled |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
51
docs/api/search.md
Normal file
51
docs/api/search.md
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
# Search
|
||||
|
||||
Full-text media search
|
||||
|
||||
## Endpoints
|
||||
|
||||
### GET /api/v1/search
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `q` | query | Yes | Search query |
|
||||
| `sort` | query | No | Sort order |
|
||||
| `offset` | query | No | Pagination offset |
|
||||
| `limit` | query | No | Pagination limit |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Search results |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/search
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Search results |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
282
docs/api/shares.md
Normal file
282
docs/api/shares.md
Normal file
|
|
@ -0,0 +1,282 @@
|
|||
# Shares
|
||||
|
||||
Media sharing and notifications
|
||||
|
||||
## Endpoints
|
||||
|
||||
### GET /api/v1/notifications/shares
|
||||
|
||||
Get unread share notifications
|
||||
GET /api/notifications/shares
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Unread notifications |
|
||||
| 401 | Unauthorized |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/notifications/shares/read-all
|
||||
|
||||
Mark all notifications as read
|
||||
POST /api/notifications/shares/read-all
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | All notifications marked as read |
|
||||
| 401 | Unauthorized |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/notifications/shares/{id}/read
|
||||
|
||||
Mark a notification as read
|
||||
POST /api/notifications/shares/{id}/read
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Notification ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Notification marked as read |
|
||||
| 401 | Unauthorized |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/shared/{token}
|
||||
|
||||
Access a public shared resource
|
||||
GET /api/shared/{token}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `token` | path | Yes | Share token |
|
||||
| `password` | query | No | Share password if required |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Shared content |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/shares
|
||||
|
||||
Create a new share
|
||||
POST /api/shares
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Share created |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/shares/batch/delete
|
||||
|
||||
Batch delete shares
|
||||
POST /api/shares/batch/delete
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Shares deleted |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/shares/incoming
|
||||
|
||||
List incoming shares (shares shared with me)
|
||||
GET /api/shares/incoming
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `offset` | query | No | Pagination offset |
|
||||
| `limit` | query | No | Pagination limit |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Incoming shares |
|
||||
| 401 | Unauthorized |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/shares/outgoing
|
||||
|
||||
List outgoing shares (shares I created)
|
||||
GET /api/shares/outgoing
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `offset` | query | No | Pagination offset |
|
||||
| `limit` | query | No | Pagination limit |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Outgoing shares |
|
||||
| 401 | Unauthorized |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/shares/{id}
|
||||
|
||||
Get share details
|
||||
GET /api/shares/{id}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Share ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Share details |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### PATCH /api/v1/shares/{id}
|
||||
|
||||
Update a share
|
||||
PATCH /api/shares/{id}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Share ID |
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Share updated |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### DELETE /api/v1/shares/{id}
|
||||
|
||||
Delete (revoke) a share
|
||||
DELETE /api/shares/{id}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Share ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 204 | Share deleted |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/shares/{id}/activity
|
||||
|
||||
Get share activity log
|
||||
GET /api/shares/{id}/activity
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Share ID |
|
||||
| `offset` | query | No | Pagination offset |
|
||||
| `limit` | query | No | Pagination limit |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Share activity |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
196
docs/api/social.md
Normal file
196
docs/api/social.md
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
# Social
|
||||
|
||||
Ratings, comments, favorites, and share links
|
||||
|
||||
## Endpoints
|
||||
|
||||
### GET /api/v1/favorites
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | User favorites |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/favorites
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Added to favorites |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### DELETE /api/v1/favorites/{media_id}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `media_id` | path | Yes | Media item ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Removed from favorites |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/media/share
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Share link created |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/media/{id}/comments
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Media comments |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/media/{id}/comments
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Comment added |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/media/{id}/rate
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Rating saved |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/media/{id}/ratings
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Media ratings |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/shared/media/{token}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `token` | path | Yes | Share token |
|
||||
| `password` | query | No | Share password |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Shared media |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
20
docs/api/statistics.md
Normal file
20
docs/api/statistics.md
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# Statistics
|
||||
|
||||
Library statistics
|
||||
|
||||
## Endpoints
|
||||
|
||||
### GET /api/v1/statistics
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Library statistics |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
115
docs/api/streaming.md
Normal file
115
docs/api/streaming.md
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
# Streaming
|
||||
|
||||
HLS and DASH adaptive streaming
|
||||
|
||||
## Endpoints
|
||||
|
||||
### GET /api/v1/media/{id}/stream/dash/manifest.mpd
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | DASH manifest |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/media/{id}/stream/dash/{profile}/{segment}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
| `profile` | path | Yes | Transcode profile name |
|
||||
| `segment` | path | Yes | Segment filename |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | DASH segment data |
|
||||
| 202 | Segment not yet available |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/media/{id}/stream/hls/master.m3u8
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | HLS master playlist |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/media/{id}/stream/hls/{profile}/playlist.m3u8
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
| `profile` | path | Yes | Transcode profile name |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | HLS variant playlist |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/media/{id}/stream/hls/{profile}/{segment}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
| `profile` | path | Yes | Transcode profile name |
|
||||
| `segment` | path | Yes | Segment filename |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | HLS segment data |
|
||||
| 202 | Segment not yet available |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
|
||||
---
|
||||
|
||||
120
docs/api/subtitles.md
Normal file
120
docs/api/subtitles.md
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
# Subtitles
|
||||
|
||||
Media subtitle management
|
||||
|
||||
## Endpoints
|
||||
|
||||
### GET /api/v1/media/{id}/subtitles
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Subtitles |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/media/{id}/subtitles
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Subtitle added |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/media/{media_id}/subtitles/{subtitle_id}/content
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `media_id` | path | Yes | Media item ID |
|
||||
| `subtitle_id` | path | Yes | Subtitle ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Subtitle content |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### DELETE /api/v1/subtitles/{id}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Subtitle ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Subtitle deleted |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### PATCH /api/v1/subtitles/{id}/offset
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Subtitle ID |
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Offset updated |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
412
docs/api/sync.md
Normal file
412
docs/api/sync.md
Normal file
|
|
@ -0,0 +1,412 @@
|
|||
# Sync
|
||||
|
||||
Multi-device library synchronization
|
||||
|
||||
## Endpoints
|
||||
|
||||
### POST /api/v1/sync/ack
|
||||
|
||||
Acknowledge processed changes
|
||||
POST /api/sync/ack
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Changes acknowledged |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/sync/changes
|
||||
|
||||
Get changes since cursor
|
||||
GET /api/sync/changes
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `cursor` | query | No | Sync cursor |
|
||||
| `limit` | query | No | Max changes (max 1000) |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Changes since cursor |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/sync/conflicts
|
||||
|
||||
List unresolved conflicts
|
||||
GET /api/sync/conflicts
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Unresolved conflicts |
|
||||
| 401 | Unauthorized |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/sync/conflicts/{id}/resolve
|
||||
|
||||
Resolve a sync conflict
|
||||
POST /api/sync/conflicts/{id}/resolve
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Conflict ID |
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Conflict resolved |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/sync/devices
|
||||
|
||||
List user's sync devices
|
||||
GET /api/sync/devices
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | List of devices |
|
||||
| 401 | Unauthorized |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/sync/devices
|
||||
|
||||
Register a new sync device
|
||||
POST /api/sync/devices
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Device registered |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/sync/devices/{id}
|
||||
|
||||
Get device details
|
||||
GET /api/sync/devices/{id}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Device ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Device details |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### PUT /api/v1/sync/devices/{id}
|
||||
|
||||
Update a device
|
||||
PUT /api/sync/devices/{id}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Device ID |
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Device updated |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### DELETE /api/v1/sync/devices/{id}
|
||||
|
||||
Delete a device
|
||||
DELETE /api/sync/devices/{id}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Device ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 204 | Device deleted |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/sync/devices/{id}/token
|
||||
|
||||
Regenerate device token
|
||||
POST /api/sync/devices/{id}/token
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Device ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Token regenerated |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/sync/download/{path}
|
||||
|
||||
Download a file for sync (supports Range header)
|
||||
GET /api/sync/download/{*path}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `path` | path | Yes | File path |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | File content |
|
||||
| 206 | Partial content |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/sync/report
|
||||
|
||||
Report local changes from client
|
||||
POST /api/sync/report
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Changes processed |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/sync/upload
|
||||
|
||||
Create an upload session for chunked upload
|
||||
POST /api/sync/upload
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Upload session created |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/sync/upload/{id}
|
||||
|
||||
Get upload session status
|
||||
GET /api/sync/upload/{id}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Upload session ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Upload session status |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### DELETE /api/v1/sync/upload/{id}
|
||||
|
||||
Cancel an upload session
|
||||
DELETE /api/sync/upload/{id}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Upload session ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 204 | Upload cancelled |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### PUT /api/v1/sync/upload/{id}/chunks/{index}
|
||||
|
||||
Upload a chunk
|
||||
PUT /api/sync/upload/{id}/chunks/{index}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Upload session ID |
|
||||
| `index` | path | Yes | Chunk index |
|
||||
|
||||
#### Request Body
|
||||
|
||||
Chunk binary data
|
||||
`Content-Type: application/octet-stream`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Chunk received |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/sync/upload/{id}/complete
|
||||
|
||||
Complete an upload session
|
||||
POST /api/sync/upload/{id}/complete
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Upload session ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Upload completed |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
157
docs/api/tags.md
Normal file
157
docs/api/tags.md
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
# Tags
|
||||
|
||||
Media tag management
|
||||
|
||||
## Endpoints
|
||||
|
||||
### GET /api/v1/media/{media_id}/tags
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `media_id` | path | Yes | Media item ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Media tags |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/media/{media_id}/tags
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `media_id` | path | Yes | Media item ID |
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Tag applied |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### DELETE /api/v1/media/{media_id}/tags/{tag_id}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `media_id` | path | Yes | Media item ID |
|
||||
| `tag_id` | path | Yes | Tag ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Tag removed |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/tags
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | List of tags |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/tags
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Tag created |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/tags/{id}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Tag ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Tag |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### DELETE /api/v1/tags/{id}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Tag ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Tag deleted |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
86
docs/api/transcode.md
Normal file
86
docs/api/transcode.md
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
# Transcode
|
||||
|
||||
Video transcoding sessions
|
||||
|
||||
## Endpoints
|
||||
|
||||
### POST /api/v1/media/{id}/transcode
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Transcode job submitted |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/transcode
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | List of transcode sessions |
|
||||
| 401 | Unauthorized |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/transcode/{id}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Transcode session ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Transcode session details |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### DELETE /api/v1/transcode/{id}
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Transcode session ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Transcode session cancelled |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
89
docs/api/upload.md
Normal file
89
docs/api/upload.md
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
# Upload
|
||||
|
||||
File upload and managed storage
|
||||
|
||||
## Endpoints
|
||||
|
||||
### GET /api/v1/managed/stats
|
||||
|
||||
Get managed storage statistics
|
||||
GET /api/managed/stats
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Managed storage statistics |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/media/{id}/download
|
||||
|
||||
Download a managed file
|
||||
GET /api/media/{id}/download
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | File content |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/media/{id}/move-to-managed
|
||||
|
||||
Migrate an external file to managed storage
|
||||
POST /api/media/{id}/move-to-managed
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | Media item ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 204 | File migrated |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/upload
|
||||
|
||||
Upload a file to managed storage
|
||||
POST /api/upload
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | File uploaded |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
207
docs/api/users.md
Normal file
207
docs/api/users.md
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
# Users
|
||||
|
||||
User and library access management
|
||||
|
||||
## Endpoints
|
||||
|
||||
### GET /api/v1/admin/users
|
||||
|
||||
List all users (admin only)
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | List of users |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/admin/users
|
||||
|
||||
Create a new user (admin only)
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Request Body
|
||||
|
||||
username, password, role, and optional profile fields
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | User created |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/admin/users/{id}
|
||||
|
||||
Get a specific user by ID
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | User ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | User details |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### PATCH /api/v1/admin/users/{id}
|
||||
|
||||
Update a user
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | User ID |
|
||||
|
||||
#### Request Body
|
||||
|
||||
Optional password, role, or profile fields to update
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | User updated |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### DELETE /api/v1/admin/users/{id}
|
||||
|
||||
Delete a user (admin only)
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | User ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | User deleted |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
| 404 | Not found |
|
||||
|
||||
---
|
||||
|
||||
### GET /api/v1/admin/users/{id}/libraries
|
||||
|
||||
Get user's accessible libraries
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | User ID |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | User libraries |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/admin/users/{id}/libraries
|
||||
|
||||
Grant library access to a user (admin only)
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | User ID |
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Access granted |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
|
||||
---
|
||||
|
||||
### DELETE /api/v1/admin/users/{id}/libraries
|
||||
|
||||
Revoke library access from a user (admin only)
|
||||
|
||||
Uses a JSON body instead of a path parameter because `root_path` may contain
|
||||
slashes that conflict with URL routing.
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | In | Required | Description |
|
||||
|------|----|----------|-------------|
|
||||
| `id` | path | Yes | User ID |
|
||||
|
||||
#### Request Body
|
||||
|
||||
`Content-Type: application/json`
|
||||
|
||||
See `docs/api/openapi.json` for the full schema.
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Access revoked |
|
||||
| 400 | Bad request |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
|
||||
---
|
||||
|
||||
34
docs/api/webhooks.md
Normal file
34
docs/api/webhooks.md
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# Webhooks
|
||||
|
||||
Webhook configuration
|
||||
|
||||
## Endpoints
|
||||
|
||||
### GET /api/v1/webhooks
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | List of configured webhooks |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
|
||||
---
|
||||
|
||||
### POST /api/v1/webhooks/test
|
||||
|
||||
**Authentication:** Required (Bearer JWT)
|
||||
|
||||
#### Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 200 | Test webhook sent |
|
||||
| 401 | Unauthorized |
|
||||
| 403 | Forbidden |
|
||||
|
||||
---
|
||||
|
||||
17
xtask/Cargo.toml
Normal file
17
xtask/Cargo.toml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
[package]
|
||||
name = "xtask"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
publish = false
|
||||
|
||||
[[bin]]
|
||||
name = "xtask"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
pinakes-server = { workspace = true }
|
||||
utoipa = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
215
xtask/src/docs.rs
Normal file
215
xtask/src/docs.rs
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
use std::{collections::BTreeMap, fmt::Write as _};
|
||||
|
||||
use pinakes_server::api_doc::ApiDoc;
|
||||
use utoipa::{
|
||||
OpenApi,
|
||||
openapi::{RefOr, Required, path::ParameterIn},
|
||||
};
|
||||
|
||||
#[expect(
|
||||
clippy::expect_used,
|
||||
clippy::print_stdout,
|
||||
reason = "Panics are acceptable here."
|
||||
)]
|
||||
pub fn run() {
|
||||
let api = ApiDoc::openapi();
|
||||
|
||||
let out_dir = std::path::Path::new("docs/api");
|
||||
std::fs::create_dir_all(out_dir).expect("create docs/api dir");
|
||||
|
||||
let json = serde_json::to_string_pretty(&api).expect("serialize openapi");
|
||||
std::fs::write(out_dir.join("openapi.json"), &json)
|
||||
.expect("write openapi.json");
|
||||
println!("Written docs/api/openapi.json");
|
||||
|
||||
// Collect all operations grouped by tag.
|
||||
let mut tag_ops: BTreeMap<
|
||||
String,
|
||||
Vec<(String, String, &utoipa::openapi::path::Operation)>,
|
||||
> = BTreeMap::new();
|
||||
|
||||
for (path, item) in &api.paths.paths {
|
||||
let method_ops: &[(&str, Option<&utoipa::openapi::path::Operation>)] = &[
|
||||
("GET", item.get.as_ref()),
|
||||
("POST", item.post.as_ref()),
|
||||
("PUT", item.put.as_ref()),
|
||||
("PATCH", item.patch.as_ref()),
|
||||
("DELETE", item.delete.as_ref()),
|
||||
];
|
||||
|
||||
for (method, maybe_op) in method_ops {
|
||||
let Some(op) = maybe_op else { continue };
|
||||
|
||||
let tags = op.tags.as_deref().unwrap_or(&[]);
|
||||
if tags.is_empty() {
|
||||
tag_ops.entry("_untagged".to_owned()).or_default().push((
|
||||
(*method).to_owned(),
|
||||
path.clone(),
|
||||
op,
|
||||
));
|
||||
} else {
|
||||
for tag in tags {
|
||||
tag_ops.entry(tag.clone()).or_default().push((
|
||||
(*method).to_owned(),
|
||||
path.clone(),
|
||||
op,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build a lookup from tag name to description.
|
||||
let tag_descriptions: BTreeMap<String, String> = api
|
||||
.tags
|
||||
.as_deref()
|
||||
.unwrap_or(&[])
|
||||
.iter()
|
||||
.map(|t| {
|
||||
let desc = t.description.as_deref().unwrap_or("").to_owned();
|
||||
(t.name.clone(), desc)
|
||||
})
|
||||
.collect();
|
||||
|
||||
let mut files_written = 0usize;
|
||||
|
||||
for (tag_name, ops) in &tag_ops {
|
||||
let description = tag_descriptions.get(tag_name).map_or("", String::as_str);
|
||||
|
||||
let mut md = String::new();
|
||||
|
||||
write!(md, "# {}\n\n", title_case(tag_name)).expect("write to String");
|
||||
if !description.is_empty() {
|
||||
write!(md, "{description}\n\n").expect("write to String");
|
||||
}
|
||||
md.push_str("## Endpoints\n\n");
|
||||
|
||||
for (method, path, op) in ops {
|
||||
write_operation(&mut md, method, path, op);
|
||||
}
|
||||
|
||||
let file_name = format!("{}.md", tag_name.replace('/', "_"));
|
||||
let dest = out_dir.join(&file_name);
|
||||
std::fs::write(&dest, &md).expect("write markdown file");
|
||||
println!("Written docs/api/{file_name}");
|
||||
files_written += 1;
|
||||
}
|
||||
|
||||
println!(
|
||||
"Done: wrote docs/api/openapi.json and {files_written} markdown files."
|
||||
);
|
||||
}
|
||||
|
||||
fn title_case(s: &str) -> String {
|
||||
let mut chars = s.chars();
|
||||
chars.next().map_or_else(String::new, |c| {
|
||||
c.to_uppercase().collect::<String>() + chars.as_str()
|
||||
})
|
||||
}
|
||||
|
||||
#[expect(
|
||||
clippy::expect_used,
|
||||
reason = "write! on String is infallible, but clippy still warns on expect()"
|
||||
)]
|
||||
fn write_operation(
|
||||
md: &mut String,
|
||||
method: &str,
|
||||
path: &str,
|
||||
op: &utoipa::openapi::path::Operation,
|
||||
) {
|
||||
let summary = op.summary.as_deref().unwrap_or("");
|
||||
let description = op.description.as_deref().unwrap_or("");
|
||||
|
||||
write!(md, "### {method} {path}\n\n").expect("write to String");
|
||||
|
||||
if !summary.is_empty() {
|
||||
md.push_str(summary);
|
||||
md.push('\n');
|
||||
if !description.is_empty() {
|
||||
md.push('\n');
|
||||
md.push_str(description);
|
||||
md.push('\n');
|
||||
}
|
||||
md.push('\n');
|
||||
} else if !description.is_empty() {
|
||||
write!(md, "{description}\n\n").expect("write to String");
|
||||
}
|
||||
|
||||
// Authentication
|
||||
let needs_auth = op.security.as_ref().is_none_or(|s| !s.is_empty());
|
||||
if needs_auth {
|
||||
md.push_str("**Authentication:** Required (Bearer JWT)\n\n");
|
||||
} else {
|
||||
md.push_str("**Authentication:** Not required\n\n");
|
||||
}
|
||||
|
||||
// Parameters
|
||||
if let Some(params) = &op.parameters {
|
||||
if !params.is_empty() {
|
||||
md.push_str("#### Parameters\n\n");
|
||||
md.push_str("| Name | In | Required | Description |\n");
|
||||
md.push_str("|------|----|----------|-------------|\n");
|
||||
for p in params {
|
||||
let location = param_in_str(&p.parameter_in);
|
||||
let required = match p.required {
|
||||
Required::True => "Yes",
|
||||
Required::False => "No",
|
||||
};
|
||||
let desc = p
|
||||
.description
|
||||
.as_deref()
|
||||
.unwrap_or("")
|
||||
.replace('|', "\\|")
|
||||
.replace('\n', " ");
|
||||
writeln!(
|
||||
md,
|
||||
"| `{}` | {} | {} | {} |",
|
||||
p.name, location, required, desc
|
||||
)
|
||||
.expect("write to String");
|
||||
}
|
||||
md.push('\n');
|
||||
}
|
||||
}
|
||||
|
||||
// Request body
|
||||
if let Some(rb) = &op.request_body {
|
||||
md.push_str("#### Request Body\n\n");
|
||||
if let Some(desc) = &rb.description {
|
||||
writeln!(md, "{desc}").expect("write to String");
|
||||
}
|
||||
for content_type in rb.content.keys() {
|
||||
write!(md, "`Content-Type: {content_type}`\n\n")
|
||||
.expect("write to String");
|
||||
md.push_str("See `docs/api/openapi.json` for the full schema.\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Responses
|
||||
let responses = &op.responses;
|
||||
if !responses.responses.is_empty() {
|
||||
md.push_str("#### Responses\n\n");
|
||||
md.push_str("| Status | Description |\n");
|
||||
md.push_str("|--------|-------------|\n");
|
||||
for (status, resp) in &responses.responses {
|
||||
let raw = match resp {
|
||||
RefOr::T(r) => r.description.as_str(),
|
||||
RefOr::Ref(_) => "See schema",
|
||||
};
|
||||
let desc = raw.replace('|', "\\|").replace('\n', " ");
|
||||
writeln!(md, "| {status} | {desc} |").expect("write to String");
|
||||
}
|
||||
md.push('\n');
|
||||
}
|
||||
|
||||
md.push_str("---\n\n");
|
||||
}
|
||||
|
||||
const fn param_in_str(pin: &ParameterIn) -> &'static str {
|
||||
match pin {
|
||||
ParameterIn::Path => "path",
|
||||
ParameterIn::Query => "query",
|
||||
ParameterIn::Header => "header",
|
||||
ParameterIn::Cookie => "cookie",
|
||||
}
|
||||
}
|
||||
19
xtask/src/main.rs
Normal file
19
xtask/src/main.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
mod docs;
|
||||
|
||||
#[expect(clippy::print_stderr)]
|
||||
fn main() {
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
match args.get(1).map(String::as_str) {
|
||||
Some("docs") => docs::run(),
|
||||
Some(cmd) => {
|
||||
eprintln!("Unknown command: {cmd}");
|
||||
std::process::exit(1);
|
||||
},
|
||||
None => {
|
||||
eprintln!("Usage: cargo xtask <command>");
|
||||
eprintln!("Commands:");
|
||||
eprintln!(" docs Generate API documentation");
|
||||
std::process::exit(1);
|
||||
},
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue