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]
|
[workspace]
|
||||||
members = ["crates/*"]
|
members = ["crates/*", "xtask"]
|
||||||
exclude = ["crates/pinakes-core/tests/fixtures/test-plugin"]
|
exclude = ["crates/pinakes-core/tests/fixtures/test-plugin"]
|
||||||
resolver = "3"
|
resolver = "3"
|
||||||
|
|
||||||
|
|
@ -92,6 +92,9 @@ http = "1.4.0"
|
||||||
wasmtime = { version = "42.0.1", features = ["component-model"] }
|
wasmtime = { version = "42.0.1", features = ["component-model"] }
|
||||||
wit-bindgen = "0.53.1"
|
wit-bindgen = "0.53.1"
|
||||||
tempfile = "3.26.0"
|
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:
|
# See:
|
||||||
# <https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html>
|
# <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