mirror of
https://github.com/bybrooklyn/alchemist.git
synced 2026-04-18 09:53:33 -04:00
Architecture: - Split server.rs (4,727 LOC) into 11 focused modules - Add typed EventChannels (jobs/config/system) with appropriate capacities - Add database query timeouts (5s on critical queries) - Add graceful shutdown with signal handling API: - Add API versioning (/api/v1/) with backwards-compatible aliases - Add X-Request-Id header for request tracing - Create OpenAPI spec (docs/openapi.yaml) Security: - Add security headers middleware (CSP, X-Frame-Options, etc.) - Add HSTS header (config-gated via https_only setting) - Add config file permission check on Unix - Fix path traversal vulnerability in file browser - Add symlink detection in file browser Frontend: - Handle SSE lagged events with toast notification - Clean up banned CSS patterns in components - Add warning toast variant Testing & Docs: - Add FFmpeg integration tests with fixtures - Expand documentation site (9 new pages) - Pin MSRV to 1.85 in Cargo.toml Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2379 lines
61 KiB
YAML
2379 lines
61 KiB
YAML
openapi: 3.0.3
|
|
info:
|
|
title: Alchemist API
|
|
description: |
|
|
REST API for Alchemist - a self-hosted media transcoding pipeline.
|
|
|
|
## Authentication
|
|
|
|
Most endpoints require authentication. Obtain a session token via `/auth/login` and then include it as:
|
|
- **Cookie**: `alchemist_session=<token>`
|
|
- **Header**: `Authorization: Bearer <token>`
|
|
|
|
## Rate Limiting
|
|
|
|
- **Login attempts**: 10 per second
|
|
- **Global API**: 120 requests per minute
|
|
|
|
## Versioning
|
|
|
|
The API is available at both `/api/v1/*` (versioned) and `/api/*` (backwards-compatible alias).
|
|
version: 1.0.0
|
|
contact:
|
|
name: Alchemist
|
|
url: https://github.com/alchemist-dev/alchemist
|
|
license:
|
|
name: MIT
|
|
|
|
servers:
|
|
- url: /api/v1
|
|
description: Versioned API (recommended)
|
|
- url: /api
|
|
description: Backwards-compatible alias
|
|
|
|
tags:
|
|
- name: Auth
|
|
description: Authentication and session management
|
|
- name: Jobs
|
|
description: Transcoding job management
|
|
- name: Stats
|
|
description: Statistics and metrics
|
|
- name: Logs
|
|
description: System and job logging
|
|
- name: Events
|
|
description: Server-sent events for real-time updates
|
|
- name: Engine
|
|
description: Transcoding engine control
|
|
- name: Settings
|
|
description: Configuration management
|
|
- name: Scan
|
|
description: Library scanning operations
|
|
- name: Profiles
|
|
description: Encoding profile management
|
|
- name: Library
|
|
description: Library health and management
|
|
- name: System
|
|
description: System information and health checks
|
|
- name: Filesystem
|
|
description: Filesystem browsing
|
|
- name: Setup
|
|
description: Initial setup wizard
|
|
|
|
paths:
|
|
# ============================================================================
|
|
# AUTH ENDPOINTS
|
|
# ============================================================================
|
|
/auth/login:
|
|
post:
|
|
tags: [Auth]
|
|
summary: Authenticate user
|
|
description: Login with username and password to obtain a session token.
|
|
operationId: login
|
|
security: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/LoginRequest'
|
|
responses:
|
|
'200':
|
|
description: Login successful
|
|
headers:
|
|
Set-Cookie:
|
|
schema:
|
|
type: string
|
|
example: alchemist_session=abc123; HttpOnly; SameSite=Lax; Max-Age=2592000
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/StatusResponse'
|
|
'401':
|
|
description: Invalid credentials
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'429':
|
|
description: Too many login attempts
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/auth/logout:
|
|
post:
|
|
tags: [Auth]
|
|
summary: Logout and invalidate session
|
|
operationId: logout
|
|
responses:
|
|
'200':
|
|
description: Logout successful
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/StatusResponse'
|
|
|
|
# ============================================================================
|
|
# JOBS ENDPOINTS
|
|
# ============================================================================
|
|
/jobs:
|
|
get:
|
|
tags: [Jobs]
|
|
summary: List jobs with filtering and pagination
|
|
operationId: listJobs
|
|
parameters:
|
|
- name: limit
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
minimum: 1
|
|
maximum: 200
|
|
default: 50
|
|
- name: page
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
minimum: 1
|
|
default: 1
|
|
- name: status
|
|
in: query
|
|
description: Comma-separated list of statuses
|
|
schema:
|
|
type: string
|
|
example: Queued,Encoding,Completed
|
|
- name: search
|
|
in: query
|
|
description: Search in job paths/names
|
|
schema:
|
|
type: string
|
|
- name: sort_by
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: sort_desc
|
|
in: query
|
|
schema:
|
|
type: boolean
|
|
default: false
|
|
- name: archived
|
|
in: query
|
|
schema:
|
|
type: string
|
|
enum: ['true', 'false']
|
|
default: 'false'
|
|
responses:
|
|
'200':
|
|
description: List of jobs
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Job'
|
|
|
|
/jobs/table:
|
|
get:
|
|
tags: [Jobs]
|
|
summary: List jobs (alias for /jobs)
|
|
operationId: listJobsTable
|
|
parameters:
|
|
- $ref: '#/components/parameters/LimitParam'
|
|
- $ref: '#/components/parameters/PageParam'
|
|
- name: status
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: search
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: sort_by
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: sort_desc
|
|
in: query
|
|
schema:
|
|
type: boolean
|
|
- name: archived
|
|
in: query
|
|
schema:
|
|
type: string
|
|
enum: ['true', 'false']
|
|
responses:
|
|
'200':
|
|
description: List of jobs
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Job'
|
|
|
|
/jobs/batch:
|
|
post:
|
|
tags: [Jobs]
|
|
summary: Perform batch operation on jobs
|
|
operationId: batchJobs
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/BatchJobRequest'
|
|
responses:
|
|
'200':
|
|
description: Batch operation completed
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CountResponse'
|
|
'409':
|
|
description: Conflict - some jobs are active
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/jobs/{id}/cancel:
|
|
post:
|
|
tags: [Jobs]
|
|
summary: Cancel a job
|
|
operationId: cancelJob
|
|
parameters:
|
|
- $ref: '#/components/parameters/JobIdParam'
|
|
responses:
|
|
'200':
|
|
description: Job cancelled
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/StatusResponse'
|
|
'404':
|
|
description: Job not found
|
|
'409':
|
|
description: Job cannot be cancelled
|
|
|
|
/jobs/{id}/restart:
|
|
post:
|
|
tags: [Jobs]
|
|
summary: Restart a completed or failed job
|
|
operationId: restartJob
|
|
parameters:
|
|
- $ref: '#/components/parameters/JobIdParam'
|
|
responses:
|
|
'200':
|
|
description: Job restarted
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/StatusResponse'
|
|
'404':
|
|
description: Job not found
|
|
'409':
|
|
description: Job is currently active
|
|
|
|
/jobs/{id}/delete:
|
|
post:
|
|
tags: [Jobs]
|
|
summary: Delete a job
|
|
operationId: deleteJob
|
|
parameters:
|
|
- $ref: '#/components/parameters/JobIdParam'
|
|
responses:
|
|
'200':
|
|
description: Job deleted
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/StatusResponse'
|
|
'404':
|
|
description: Job not found
|
|
'409':
|
|
description: Job is currently active
|
|
|
|
/jobs/{id}/priority:
|
|
post:
|
|
tags: [Jobs]
|
|
summary: Update job priority
|
|
operationId: setJobPriority
|
|
parameters:
|
|
- $ref: '#/components/parameters/JobIdParam'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [priority]
|
|
properties:
|
|
priority:
|
|
type: integer
|
|
responses:
|
|
'200':
|
|
description: Priority updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
priority:
|
|
type: integer
|
|
|
|
/jobs/{id}/details:
|
|
get:
|
|
tags: [Jobs]
|
|
summary: Get detailed job information
|
|
operationId: getJobDetails
|
|
parameters:
|
|
- $ref: '#/components/parameters/JobIdParam'
|
|
responses:
|
|
'200':
|
|
description: Job details
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/JobDetails'
|
|
'404':
|
|
description: Job not found
|
|
|
|
/jobs/restart-failed:
|
|
post:
|
|
tags: [Jobs]
|
|
summary: Restart all failed/cancelled jobs
|
|
operationId: restartFailedJobs
|
|
responses:
|
|
'200':
|
|
description: Jobs queued for retry
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
count:
|
|
type: integer
|
|
message:
|
|
type: string
|
|
|
|
/jobs/clear-completed:
|
|
post:
|
|
tags: [Jobs]
|
|
summary: Clear completed jobs from queue
|
|
description: Preserves historical stats while removing completed jobs from the active queue.
|
|
operationId: clearCompletedJobs
|
|
responses:
|
|
'200':
|
|
description: Jobs cleared
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
count:
|
|
type: integer
|
|
message:
|
|
type: string
|
|
|
|
# ============================================================================
|
|
# STATS ENDPOINTS
|
|
# ============================================================================
|
|
/stats:
|
|
get:
|
|
tags: [Stats]
|
|
summary: Get current job statistics
|
|
operationId: getStats
|
|
responses:
|
|
'200':
|
|
description: Current statistics
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Stats'
|
|
|
|
/stats/aggregated:
|
|
get:
|
|
tags: [Stats]
|
|
summary: Get aggregated statistics
|
|
operationId: getAggregatedStats
|
|
responses:
|
|
'200':
|
|
description: Aggregated statistics
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/AggregatedStats'
|
|
|
|
/stats/daily:
|
|
get:
|
|
tags: [Stats]
|
|
summary: Get daily statistics for last 30 days
|
|
operationId: getDailyStats
|
|
responses:
|
|
'200':
|
|
description: Daily statistics
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/DailyStats'
|
|
|
|
/stats/detailed:
|
|
get:
|
|
tags: [Stats]
|
|
summary: Get detailed encode statistics
|
|
operationId: getDetailedStats
|
|
responses:
|
|
'200':
|
|
description: Detailed encode statistics (last 50 jobs)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/DetailedStats'
|
|
|
|
/stats/savings:
|
|
get:
|
|
tags: [Stats]
|
|
summary: Get storage savings summary
|
|
operationId: getSavingsStats
|
|
responses:
|
|
'200':
|
|
description: Storage savings breakdown
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SavingsStats'
|
|
|
|
# ============================================================================
|
|
# LOGS ENDPOINTS
|
|
# ============================================================================
|
|
/logs/history:
|
|
get:
|
|
tags: [Logs]
|
|
summary: Get system logs with pagination
|
|
operationId: getLogHistory
|
|
parameters:
|
|
- $ref: '#/components/parameters/PageParam'
|
|
- $ref: '#/components/parameters/LimitParam'
|
|
responses:
|
|
'200':
|
|
description: Log entries
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/LogEntry'
|
|
|
|
/logs:
|
|
delete:
|
|
tags: [Logs]
|
|
summary: Clear all system logs
|
|
operationId: clearLogs
|
|
responses:
|
|
'200':
|
|
description: Logs cleared
|
|
|
|
# ============================================================================
|
|
# EVENTS ENDPOINT (SSE)
|
|
# ============================================================================
|
|
/events:
|
|
get:
|
|
tags: [Events]
|
|
summary: Subscribe to real-time events
|
|
description: |
|
|
Server-Sent Events stream for real-time updates.
|
|
|
|
## Event Types
|
|
|
|
- **log**: System/job log entry
|
|
- **progress**: Job encoding progress
|
|
- **status**: Job status change
|
|
- **decision**: Transcoder decision
|
|
- **lagged**: Client fell behind event stream
|
|
operationId: subscribeEvents
|
|
responses:
|
|
'200':
|
|
description: SSE event stream
|
|
content:
|
|
text/event-stream:
|
|
schema:
|
|
type: string
|
|
description: |
|
|
Events are sent in SSE format:
|
|
```
|
|
event: log
|
|
data: {"level":"info","job_id":123,"message":"Starting encode"}
|
|
|
|
event: progress
|
|
data: {"job_id":123,"percentage":45,"time":"00:15:30"}
|
|
```
|
|
|
|
# ============================================================================
|
|
# ENGINE ENDPOINTS
|
|
# ============================================================================
|
|
/engine/status:
|
|
get:
|
|
tags: [Engine]
|
|
summary: Get engine status
|
|
operationId: getEngineStatus
|
|
responses:
|
|
'200':
|
|
description: Engine status
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/EngineStatus'
|
|
|
|
/engine/mode:
|
|
get:
|
|
tags: [Engine]
|
|
summary: Get engine mode configuration
|
|
operationId: getEngineMode
|
|
responses:
|
|
'200':
|
|
description: Engine mode details
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/EngineModeResponse'
|
|
post:
|
|
tags: [Engine]
|
|
summary: Set engine mode
|
|
operationId: setEngineMode
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/EngineModeRequest'
|
|
responses:
|
|
'200':
|
|
description: Mode updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
status:
|
|
type: string
|
|
mode:
|
|
$ref: '#/components/schemas/EngineMode'
|
|
concurrent_limit:
|
|
type: integer
|
|
is_manual_override:
|
|
type: boolean
|
|
|
|
/engine/pause:
|
|
post:
|
|
tags: [Engine]
|
|
summary: Pause the encoding engine
|
|
operationId: pauseEngine
|
|
responses:
|
|
'200':
|
|
description: Engine paused
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
status:
|
|
type: string
|
|
example: paused
|
|
|
|
/engine/resume:
|
|
post:
|
|
tags: [Engine]
|
|
summary: Resume the encoding engine
|
|
operationId: resumeEngine
|
|
responses:
|
|
'200':
|
|
description: Engine resumed
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
status:
|
|
type: string
|
|
example: running
|
|
|
|
/engine/drain:
|
|
post:
|
|
tags: [Engine]
|
|
summary: Drain the job queue
|
|
description: Stop accepting new jobs while finishing active ones.
|
|
operationId: drainEngine
|
|
responses:
|
|
'200':
|
|
description: Engine draining
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
status:
|
|
type: string
|
|
example: draining
|
|
|
|
/engine/stop-drain:
|
|
post:
|
|
tags: [Engine]
|
|
summary: Stop draining and resume normal operation
|
|
operationId: stopDrain
|
|
responses:
|
|
'200':
|
|
description: Drain stopped
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
status:
|
|
type: string
|
|
example: running
|
|
|
|
# ============================================================================
|
|
# SETTINGS ENDPOINTS
|
|
# ============================================================================
|
|
/settings/transcode:
|
|
get:
|
|
tags: [Settings]
|
|
summary: Get transcoding settings
|
|
operationId: getTranscodeSettings
|
|
responses:
|
|
'200':
|
|
description: Transcoding settings
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/TranscodeSettings'
|
|
post:
|
|
tags: [Settings]
|
|
summary: Update transcoding settings
|
|
operationId: updateTranscodeSettings
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/TranscodeSettings'
|
|
responses:
|
|
'200':
|
|
description: Settings updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/TranscodeSettings'
|
|
'400':
|
|
description: Invalid settings
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/settings/system:
|
|
get:
|
|
tags: [Settings]
|
|
summary: Get system settings
|
|
operationId: getSystemSettings
|
|
responses:
|
|
'200':
|
|
description: System settings
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SystemSettings'
|
|
post:
|
|
tags: [Settings]
|
|
summary: Update system settings
|
|
operationId: updateSystemSettings
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SystemSettings'
|
|
responses:
|
|
'200':
|
|
description: Settings updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SystemSettings'
|
|
|
|
/settings/hardware:
|
|
get:
|
|
tags: [Settings]
|
|
summary: Get hardware acceleration settings
|
|
operationId: getHardwareSettings
|
|
responses:
|
|
'200':
|
|
description: Hardware settings
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/HardwareSettings'
|
|
post:
|
|
tags: [Settings]
|
|
summary: Update hardware acceleration settings
|
|
operationId: updateHardwareSettings
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/HardwareSettings'
|
|
responses:
|
|
'200':
|
|
description: Settings updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/HardwareSettings'
|
|
|
|
/settings/bundle:
|
|
get:
|
|
tags: [Settings]
|
|
summary: Get entire configuration bundle
|
|
operationId: getConfigBundle
|
|
responses:
|
|
'200':
|
|
description: Full configuration
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ConfigBundle'
|
|
put:
|
|
tags: [Settings]
|
|
summary: Update entire configuration bundle
|
|
operationId: updateConfigBundle
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ConfigBundle'
|
|
responses:
|
|
'200':
|
|
description: Configuration updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ConfigBundle'
|
|
|
|
/settings/config:
|
|
get:
|
|
tags: [Settings]
|
|
summary: Get raw TOML configuration
|
|
operationId: getRawConfig
|
|
responses:
|
|
'200':
|
|
description: Raw configuration
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
raw_toml:
|
|
type: string
|
|
normalized:
|
|
type: object
|
|
put:
|
|
tags: [Settings]
|
|
summary: Update raw TOML configuration
|
|
operationId: updateRawConfig
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [raw_toml]
|
|
properties:
|
|
raw_toml:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Configuration updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
raw_toml:
|
|
type: string
|
|
normalized:
|
|
type: object
|
|
|
|
/settings/files:
|
|
get:
|
|
tags: [Settings]
|
|
summary: Get file settings
|
|
operationId: getFileSettings
|
|
responses:
|
|
'200':
|
|
description: File settings
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/FileSettings'
|
|
post:
|
|
tags: [Settings]
|
|
summary: Update file settings
|
|
operationId: updateFileSettings
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/FileSettings'
|
|
responses:
|
|
'200':
|
|
description: Settings updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/FileSettings'
|
|
|
|
/settings/preferences/{key}:
|
|
get:
|
|
tags: [Settings]
|
|
summary: Get user preference
|
|
operationId: getPreference
|
|
parameters:
|
|
- name: key
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Preference value
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
key:
|
|
type: string
|
|
value:
|
|
type: string
|
|
'404':
|
|
description: Preference not found
|
|
post:
|
|
tags: [Settings]
|
|
summary: Set user preference
|
|
operationId: setPreference
|
|
parameters:
|
|
- name: key
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [value]
|
|
properties:
|
|
value:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Preference saved
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
key:
|
|
type: string
|
|
value:
|
|
type: string
|
|
|
|
/settings/watch-dirs:
|
|
get:
|
|
tags: [Settings]
|
|
summary: List watch directories
|
|
operationId: listWatchDirs
|
|
responses:
|
|
'200':
|
|
description: Watch directories
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/WatchDir'
|
|
post:
|
|
tags: [Settings]
|
|
summary: Add watch directory
|
|
operationId: addWatchDir
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [path]
|
|
properties:
|
|
path:
|
|
type: string
|
|
is_recursive:
|
|
type: boolean
|
|
default: true
|
|
responses:
|
|
'201':
|
|
description: Watch directory added
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/WatchDir'
|
|
|
|
/settings/watch-dirs/{id}:
|
|
delete:
|
|
tags: [Settings]
|
|
summary: Remove watch directory
|
|
operationId: removeWatchDir
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
'200':
|
|
description: Watch directory removed
|
|
'404':
|
|
description: Watch directory not found
|
|
|
|
/settings/notifications:
|
|
get:
|
|
tags: [Settings]
|
|
summary: List notification targets
|
|
operationId: listNotificationTargets
|
|
responses:
|
|
'200':
|
|
description: Notification targets
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/NotificationTarget'
|
|
post:
|
|
tags: [Settings]
|
|
summary: Add notification target
|
|
operationId: addNotificationTarget
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/NotificationTargetInput'
|
|
responses:
|
|
'201':
|
|
description: Notification target added
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/NotificationTarget'
|
|
|
|
/settings/notifications/{id}:
|
|
delete:
|
|
tags: [Settings]
|
|
summary: Remove notification target
|
|
operationId: removeNotificationTarget
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
'200':
|
|
description: Notification target removed
|
|
'404':
|
|
description: Notification target not found
|
|
|
|
/settings/notifications/test:
|
|
post:
|
|
tags: [Settings]
|
|
summary: Send test notification
|
|
operationId: testNotification
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/NotificationTargetInput'
|
|
responses:
|
|
'200':
|
|
description: Test notification sent
|
|
'400':
|
|
description: Invalid notification configuration
|
|
|
|
/settings/schedule:
|
|
get:
|
|
tags: [Settings]
|
|
summary: List schedule windows
|
|
operationId: listScheduleWindows
|
|
responses:
|
|
'200':
|
|
description: Schedule windows
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/ScheduleWindow'
|
|
post:
|
|
tags: [Settings]
|
|
summary: Add schedule window
|
|
operationId: addScheduleWindow
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ScheduleWindowInput'
|
|
responses:
|
|
'201':
|
|
description: Schedule window added
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ScheduleWindow'
|
|
|
|
/settings/schedule/{id}:
|
|
delete:
|
|
tags: [Settings]
|
|
summary: Remove schedule window
|
|
operationId: removeScheduleWindow
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
'200':
|
|
description: Schedule window removed
|
|
'404':
|
|
description: Schedule window not found
|
|
|
|
# ============================================================================
|
|
# SCAN ENDPOINTS
|
|
# ============================================================================
|
|
/scan:
|
|
post:
|
|
tags: [Scan]
|
|
summary: Trigger library scan (legacy)
|
|
operationId: triggerScanLegacy
|
|
responses:
|
|
'200':
|
|
description: Scan completed
|
|
'202':
|
|
description: Scan started
|
|
|
|
/scan/start:
|
|
post:
|
|
tags: [Scan]
|
|
summary: Start library scan
|
|
operationId: startScan
|
|
responses:
|
|
'202':
|
|
description: Scan started
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
status:
|
|
type: string
|
|
example: accepted
|
|
|
|
/scan/status:
|
|
get:
|
|
tags: [Scan]
|
|
summary: Get scan status
|
|
operationId: getScanStatus
|
|
responses:
|
|
'200':
|
|
description: Scan status
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ScanStatus'
|
|
|
|
# ============================================================================
|
|
# PROFILES ENDPOINTS
|
|
# ============================================================================
|
|
/profiles/presets:
|
|
get:
|
|
tags: [Profiles]
|
|
summary: Get built-in profile presets
|
|
operationId: getProfilePresets
|
|
responses:
|
|
'200':
|
|
description: Built-in presets
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Profile'
|
|
|
|
/profiles:
|
|
get:
|
|
tags: [Profiles]
|
|
summary: List all profiles
|
|
operationId: listProfiles
|
|
responses:
|
|
'200':
|
|
description: All profiles
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Profile'
|
|
post:
|
|
tags: [Profiles]
|
|
summary: Create profile
|
|
operationId: createProfile
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ProfileInput'
|
|
responses:
|
|
'201':
|
|
description: Profile created
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Profile'
|
|
|
|
/profiles/{id}:
|
|
put:
|
|
tags: [Profiles]
|
|
summary: Update profile
|
|
operationId: updateProfile
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ProfileInput'
|
|
responses:
|
|
'200':
|
|
description: Profile updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Profile'
|
|
'404':
|
|
description: Profile not found
|
|
delete:
|
|
tags: [Profiles]
|
|
summary: Delete profile
|
|
operationId: deleteProfile
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
'200':
|
|
description: Profile deleted
|
|
'404':
|
|
description: Profile not found
|
|
'409':
|
|
description: Profile is in use
|
|
|
|
/watch-dirs/{id}/profile:
|
|
patch:
|
|
tags: [Profiles]
|
|
summary: Assign profile to watch directory
|
|
operationId: assignWatchDirProfile
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
profile_id:
|
|
type: integer
|
|
nullable: true
|
|
description: Profile ID to assign, or null to unassign
|
|
responses:
|
|
'200':
|
|
description: Profile assigned
|
|
'404':
|
|
description: Watch directory not found
|
|
|
|
# ============================================================================
|
|
# LIBRARY HEALTH ENDPOINTS
|
|
# ============================================================================
|
|
/library/health:
|
|
get:
|
|
tags: [Library]
|
|
summary: Get library health summary
|
|
operationId: getLibraryHealth
|
|
responses:
|
|
'200':
|
|
description: Health summary
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/LibraryHealth'
|
|
|
|
/library/health/issues:
|
|
get:
|
|
tags: [Library]
|
|
summary: Get jobs with health issues
|
|
operationId: getLibraryHealthIssues
|
|
responses:
|
|
'200':
|
|
description: Jobs with issues
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
job:
|
|
$ref: '#/components/schemas/Job'
|
|
report:
|
|
type: object
|
|
properties:
|
|
issues:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
type:
|
|
type: string
|
|
enum: [corruption, stream_issue]
|
|
severity:
|
|
type: string
|
|
enum: [critical, warning]
|
|
description:
|
|
type: string
|
|
|
|
/library/health/scan:
|
|
post:
|
|
tags: [Library]
|
|
summary: Start library health scan
|
|
operationId: startHealthScan
|
|
responses:
|
|
'202':
|
|
description: Health scan started
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
status:
|
|
type: string
|
|
example: accepted
|
|
|
|
/library/health/scan/{id}:
|
|
post:
|
|
tags: [Library]
|
|
summary: Rescan specific job for health issues
|
|
operationId: rescanJobHealth
|
|
parameters:
|
|
- $ref: '#/components/parameters/JobIdParam'
|
|
responses:
|
|
'200':
|
|
description: Health scan result
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
job_id:
|
|
type: integer
|
|
issue_found:
|
|
type: boolean
|
|
|
|
# ============================================================================
|
|
# SYSTEM ENDPOINTS
|
|
# ============================================================================
|
|
/health:
|
|
get:
|
|
tags: [System]
|
|
summary: Health check
|
|
operationId: healthCheck
|
|
security: []
|
|
responses:
|
|
'200':
|
|
description: Service is healthy
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/HealthResponse'
|
|
|
|
/ready:
|
|
get:
|
|
tags: [System]
|
|
summary: Readiness probe
|
|
description: Checks database connectivity
|
|
operationId: readinessProbe
|
|
security: []
|
|
responses:
|
|
'200':
|
|
description: Service is ready
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
ready:
|
|
type: boolean
|
|
example: true
|
|
'503':
|
|
description: Service not ready
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
ready:
|
|
type: boolean
|
|
example: false
|
|
reason:
|
|
type: string
|
|
|
|
/system/resources:
|
|
get:
|
|
tags: [System]
|
|
summary: Get system resource usage
|
|
description: Returns real-time CPU, memory, disk usage. Cached for 500ms.
|
|
operationId: getSystemResources
|
|
responses:
|
|
'200':
|
|
description: System resources
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SystemResources'
|
|
|
|
/system/hardware:
|
|
get:
|
|
tags: [System]
|
|
summary: Detect available hardware
|
|
description: Detects GPUs and hardware encoders. Public during setup.
|
|
operationId: detectHardware
|
|
security: []
|
|
responses:
|
|
'200':
|
|
description: Hardware detection results
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/HardwareInfo'
|
|
|
|
/system/version:
|
|
get:
|
|
tags: [System]
|
|
summary: Get version information
|
|
operationId: getVersion
|
|
responses:
|
|
'200':
|
|
description: Version info
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
version:
|
|
type: string
|
|
example: 1.2.3
|
|
commit:
|
|
type: string
|
|
build_date:
|
|
type: string
|
|
|
|
/system/ffmpeg:
|
|
get:
|
|
tags: [System]
|
|
summary: Get FFmpeg information
|
|
operationId: getFfmpegInfo
|
|
responses:
|
|
'200':
|
|
description: FFmpeg info
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
version:
|
|
type: string
|
|
path:
|
|
type: string
|
|
encoders:
|
|
type: array
|
|
items:
|
|
type: string
|
|
decoders:
|
|
type: array
|
|
items:
|
|
type: string
|
|
|
|
# ============================================================================
|
|
# FILESYSTEM ENDPOINTS
|
|
# ============================================================================
|
|
/fs/browse:
|
|
get:
|
|
tags: [Filesystem]
|
|
summary: Browse filesystem
|
|
operationId: browseFilesystem
|
|
parameters:
|
|
- name: path
|
|
in: query
|
|
schema:
|
|
type: string
|
|
default: /
|
|
responses:
|
|
'200':
|
|
description: Directory listing
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/DirectoryListing'
|
|
|
|
/fs/recommendations:
|
|
get:
|
|
tags: [Filesystem]
|
|
summary: Get recommended directories
|
|
operationId: getDirectoryRecommendations
|
|
security: []
|
|
responses:
|
|
'200':
|
|
description: Recommended directories
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
input_directories:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
path:
|
|
type: string
|
|
output_directory:
|
|
type: string
|
|
config_directory:
|
|
type: string
|
|
|
|
/fs/preview:
|
|
post:
|
|
tags: [Filesystem]
|
|
summary: Preview selected folders
|
|
operationId: previewFolders
|
|
security: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
input_paths:
|
|
type: array
|
|
items:
|
|
type: string
|
|
output_path:
|
|
type: string
|
|
config_path:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Folder preview
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
valid:
|
|
type: boolean
|
|
issues:
|
|
type: array
|
|
items:
|
|
type: string
|
|
space_available_gb:
|
|
type: number
|
|
estimated_library_size:
|
|
type: integer
|
|
|
|
# ============================================================================
|
|
# SETUP ENDPOINTS
|
|
# ============================================================================
|
|
/setup/status:
|
|
get:
|
|
tags: [Setup]
|
|
summary: Check if setup is required
|
|
operationId: getSetupStatus
|
|
security: []
|
|
responses:
|
|
'200':
|
|
description: Setup status
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
setup_required:
|
|
type: boolean
|
|
enable_telemetry:
|
|
type: boolean
|
|
config_mutable:
|
|
type: boolean
|
|
|
|
/setup/complete:
|
|
post:
|
|
tags: [Setup]
|
|
summary: Complete initial setup
|
|
operationId: completeSetup
|
|
security: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SetupRequest'
|
|
responses:
|
|
'200':
|
|
description: Setup completed
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
status:
|
|
type: string
|
|
message:
|
|
type: string
|
|
'400':
|
|
description: Validation errors
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
# ============================================================================
|
|
# UI PREFERENCES ENDPOINTS
|
|
# ============================================================================
|
|
/ui/preferences:
|
|
get:
|
|
tags: [Settings]
|
|
summary: Get UI preferences
|
|
operationId: getUiPreferences
|
|
responses:
|
|
'200':
|
|
description: UI preferences
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
additionalProperties: true
|
|
post:
|
|
tags: [Settings]
|
|
summary: Update UI preferences
|
|
operationId: updateUiPreferences
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
additionalProperties: true
|
|
responses:
|
|
'200':
|
|
description: Preferences updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
additionalProperties: true
|
|
|
|
# ==============================================================================
|
|
# COMPONENTS
|
|
# ==============================================================================
|
|
components:
|
|
securitySchemes:
|
|
bearerAuth:
|
|
type: http
|
|
scheme: bearer
|
|
cookieAuth:
|
|
type: apiKey
|
|
in: cookie
|
|
name: alchemist_session
|
|
|
|
parameters:
|
|
JobIdParam:
|
|
name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
LimitParam:
|
|
name: limit
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
minimum: 1
|
|
maximum: 200
|
|
default: 50
|
|
PageParam:
|
|
name: page
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
minimum: 1
|
|
default: 1
|
|
|
|
schemas:
|
|
# --------------------------------------------------------------------------
|
|
# Common Responses
|
|
# --------------------------------------------------------------------------
|
|
StatusResponse:
|
|
type: object
|
|
properties:
|
|
status:
|
|
type: string
|
|
example: ok
|
|
|
|
ErrorResponse:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
message:
|
|
type: string
|
|
details:
|
|
type: object
|
|
|
|
CountResponse:
|
|
type: object
|
|
properties:
|
|
count:
|
|
type: integer
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Auth
|
|
# --------------------------------------------------------------------------
|
|
LoginRequest:
|
|
type: object
|
|
required: [username, password]
|
|
properties:
|
|
username:
|
|
type: string
|
|
password:
|
|
type: string
|
|
format: password
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Jobs
|
|
# --------------------------------------------------------------------------
|
|
Job:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
input_path:
|
|
type: string
|
|
output_path:
|
|
type: string
|
|
nullable: true
|
|
status:
|
|
$ref: '#/components/schemas/JobStatus'
|
|
priority:
|
|
type: integer
|
|
default: 0
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
updated_at:
|
|
type: string
|
|
format: date-time
|
|
archived:
|
|
type: boolean
|
|
default: false
|
|
|
|
JobStatus:
|
|
type: string
|
|
enum:
|
|
- Queued
|
|
- Analyzing
|
|
- Encoding
|
|
- Remuxing
|
|
- Resuming
|
|
- Completed
|
|
- Failed
|
|
- Cancelled
|
|
- Archived
|
|
|
|
JobDetails:
|
|
type: object
|
|
properties:
|
|
job:
|
|
$ref: '#/components/schemas/Job'
|
|
metadata:
|
|
type: object
|
|
nullable: true
|
|
description: FFmpeg metadata if available
|
|
encode_stats:
|
|
type: object
|
|
nullable: true
|
|
description: Detailed encode statistics
|
|
job_logs:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/LogEntry'
|
|
job_failure_summary:
|
|
type: string
|
|
nullable: true
|
|
|
|
BatchJobRequest:
|
|
type: object
|
|
required: [action, ids]
|
|
properties:
|
|
action:
|
|
type: string
|
|
enum: [cancel, delete, restart]
|
|
ids:
|
|
type: array
|
|
items:
|
|
type: integer
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Stats
|
|
# --------------------------------------------------------------------------
|
|
Stats:
|
|
type: object
|
|
properties:
|
|
total:
|
|
type: integer
|
|
completed:
|
|
type: integer
|
|
active:
|
|
type: integer
|
|
failed:
|
|
type: integer
|
|
concurrent_limit:
|
|
type: integer
|
|
|
|
AggregatedStats:
|
|
type: object
|
|
properties:
|
|
total_input_bytes:
|
|
type: integer
|
|
format: int64
|
|
total_output_bytes:
|
|
type: integer
|
|
format: int64
|
|
total_savings_bytes:
|
|
type: integer
|
|
format: int64
|
|
total_time_seconds:
|
|
type: integer
|
|
total_jobs:
|
|
type: integer
|
|
avg_vmaf:
|
|
type: number
|
|
nullable: true
|
|
|
|
DailyStats:
|
|
type: object
|
|
properties:
|
|
date:
|
|
type: string
|
|
format: date
|
|
jobs_completed:
|
|
type: integer
|
|
total_input_bytes:
|
|
type: integer
|
|
format: int64
|
|
total_output_bytes:
|
|
type: integer
|
|
format: int64
|
|
total_time_seconds:
|
|
type: integer
|
|
|
|
DetailedStats:
|
|
type: object
|
|
properties:
|
|
job_id:
|
|
type: integer
|
|
input_size:
|
|
type: integer
|
|
format: int64
|
|
output_size:
|
|
type: integer
|
|
format: int64
|
|
encode_time_seconds:
|
|
type: integer
|
|
vmaf_score:
|
|
type: number
|
|
nullable: true
|
|
codec:
|
|
type: string
|
|
quality:
|
|
type: string
|
|
|
|
SavingsStats:
|
|
type: object
|
|
properties:
|
|
total_saved_bytes:
|
|
type: integer
|
|
format: int64
|
|
by_codec:
|
|
type: object
|
|
additionalProperties:
|
|
type: object
|
|
properties:
|
|
count:
|
|
type: integer
|
|
saved_bytes:
|
|
type: integer
|
|
format: int64
|
|
by_quality:
|
|
type: object
|
|
additionalProperties:
|
|
type: object
|
|
properties:
|
|
count:
|
|
type: integer
|
|
saved_bytes:
|
|
type: integer
|
|
format: int64
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Logs
|
|
# --------------------------------------------------------------------------
|
|
LogEntry:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
level:
|
|
type: string
|
|
enum: [info, warn, error]
|
|
job_id:
|
|
type: integer
|
|
nullable: true
|
|
message:
|
|
type: string
|
|
timestamp:
|
|
type: string
|
|
format: date-time
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Engine
|
|
# --------------------------------------------------------------------------
|
|
EngineStatus:
|
|
type: object
|
|
properties:
|
|
status:
|
|
type: string
|
|
enum: [running, paused, draining]
|
|
manual_paused:
|
|
type: boolean
|
|
scheduler_paused:
|
|
type: boolean
|
|
draining:
|
|
type: boolean
|
|
mode:
|
|
$ref: '#/components/schemas/EngineMode'
|
|
concurrent_limit:
|
|
type: integer
|
|
is_manual_override:
|
|
type: boolean
|
|
|
|
EngineMode:
|
|
type: string
|
|
enum: [Background, Balanced, Throughput]
|
|
|
|
EngineModeResponse:
|
|
type: object
|
|
properties:
|
|
mode:
|
|
$ref: '#/components/schemas/EngineMode'
|
|
is_manual_override:
|
|
type: boolean
|
|
concurrent_limit:
|
|
type: integer
|
|
cpu_count:
|
|
type: integer
|
|
computed_limits:
|
|
type: object
|
|
properties:
|
|
background:
|
|
type: integer
|
|
balanced:
|
|
type: integer
|
|
throughput:
|
|
type: integer
|
|
|
|
EngineModeRequest:
|
|
type: object
|
|
required: [mode]
|
|
properties:
|
|
mode:
|
|
$ref: '#/components/schemas/EngineMode'
|
|
concurrent_jobs_override:
|
|
type: integer
|
|
nullable: true
|
|
threads_override:
|
|
type: integer
|
|
nullable: true
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Settings
|
|
# --------------------------------------------------------------------------
|
|
TranscodeSettings:
|
|
type: object
|
|
properties:
|
|
concurrent_jobs:
|
|
type: integer
|
|
minimum: 1
|
|
size_reduction_threshold:
|
|
type: number
|
|
minimum: 0
|
|
maximum: 1
|
|
min_bpp_threshold:
|
|
type: number
|
|
min_file_size_mb:
|
|
type: integer
|
|
output_codec:
|
|
type: string
|
|
enum: [h265, vp9, av1]
|
|
quality_profile:
|
|
type: string
|
|
enum: [high, medium, low]
|
|
threads:
|
|
type: integer
|
|
minimum: 0
|
|
maximum: 512
|
|
description: 0 = auto
|
|
allow_fallback:
|
|
type: boolean
|
|
hdr_mode:
|
|
type: string
|
|
enum: [tone-map, passthrough, strip]
|
|
tonemap_algorithm:
|
|
type: string
|
|
enum: [linear, gamma, bt2390]
|
|
tonemap_peak:
|
|
type: number
|
|
minimum: 50
|
|
maximum: 1000
|
|
tonemap_desat:
|
|
type: number
|
|
subtitle_mode:
|
|
type: string
|
|
enum: [none, passthrough, burn]
|
|
stream_rules:
|
|
type: object
|
|
description: Stream filtering rules
|
|
|
|
SystemSettings:
|
|
type: object
|
|
properties:
|
|
monitoring_poll_interval:
|
|
type: number
|
|
minimum: 0.5
|
|
maximum: 10
|
|
enable_telemetry:
|
|
type: boolean
|
|
watch_enabled:
|
|
type: boolean
|
|
|
|
HardwareSettings:
|
|
type: object
|
|
properties:
|
|
allow_cpu_fallback:
|
|
type: boolean
|
|
allow_cpu_encoding:
|
|
type: boolean
|
|
cpu_preset:
|
|
type: string
|
|
enum: [slow, medium, fast, faster]
|
|
preferred_vendor:
|
|
type: string
|
|
enum: [nvidia, intel, amd]
|
|
nullable: true
|
|
device_path:
|
|
type: string
|
|
nullable: true
|
|
|
|
FileSettings:
|
|
type: object
|
|
additionalProperties: true
|
|
|
|
ConfigBundle:
|
|
type: object
|
|
description: Complete configuration including all settings sections
|
|
additionalProperties: true
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Watch Directories
|
|
# --------------------------------------------------------------------------
|
|
WatchDir:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
path:
|
|
type: string
|
|
is_recursive:
|
|
type: boolean
|
|
profile_id:
|
|
type: integer
|
|
nullable: true
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
updated_at:
|
|
type: string
|
|
format: date-time
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Notifications
|
|
# --------------------------------------------------------------------------
|
|
NotificationTarget:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
name:
|
|
type: string
|
|
target_type:
|
|
type: string
|
|
enum: [webhook, discord, gotify]
|
|
endpoint_url:
|
|
type: string
|
|
auth_token:
|
|
type: string
|
|
nullable: true
|
|
events:
|
|
type: string
|
|
description: JSON array of event types
|
|
enabled:
|
|
type: boolean
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
|
|
NotificationTargetInput:
|
|
type: object
|
|
required: [name, target_type, endpoint_url]
|
|
properties:
|
|
name:
|
|
type: string
|
|
target_type:
|
|
type: string
|
|
enum: [webhook, discord, gotify]
|
|
endpoint_url:
|
|
type: string
|
|
format: uri
|
|
auth_token:
|
|
type: string
|
|
events:
|
|
type: array
|
|
items:
|
|
type: string
|
|
enabled:
|
|
type: boolean
|
|
default: true
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Schedule
|
|
# --------------------------------------------------------------------------
|
|
ScheduleWindow:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
start_time:
|
|
type: string
|
|
example: '09:00'
|
|
end_time:
|
|
type: string
|
|
example: '17:00'
|
|
days_of_week:
|
|
type: string
|
|
description: JSON array of day numbers (0=Sunday, 6=Saturday)
|
|
enabled:
|
|
type: boolean
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
updated_at:
|
|
type: string
|
|
format: date-time
|
|
|
|
ScheduleWindowInput:
|
|
type: object
|
|
required: [start_time, end_time, days_of_week]
|
|
properties:
|
|
start_time:
|
|
type: string
|
|
example: '09:00'
|
|
end_time:
|
|
type: string
|
|
example: '17:00'
|
|
days_of_week:
|
|
type: array
|
|
items:
|
|
type: integer
|
|
minimum: 0
|
|
maximum: 6
|
|
enabled:
|
|
type: boolean
|
|
default: true
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Profiles
|
|
# --------------------------------------------------------------------------
|
|
Profile:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
name:
|
|
type: string
|
|
preset:
|
|
type: string
|
|
codec:
|
|
type: string
|
|
quality_profile:
|
|
type: string
|
|
hdr_mode:
|
|
type: string
|
|
audio_mode:
|
|
type: string
|
|
crf_override:
|
|
type: integer
|
|
nullable: true
|
|
notes:
|
|
type: string
|
|
nullable: true
|
|
builtin:
|
|
type: boolean
|
|
|
|
ProfileInput:
|
|
type: object
|
|
required: [name]
|
|
properties:
|
|
name:
|
|
type: string
|
|
preset:
|
|
type: string
|
|
codec:
|
|
type: string
|
|
quality_profile:
|
|
type: string
|
|
hdr_mode:
|
|
type: string
|
|
audio_mode:
|
|
type: string
|
|
crf_override:
|
|
type: integer
|
|
notes:
|
|
type: string
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Library Health
|
|
# --------------------------------------------------------------------------
|
|
LibraryHealth:
|
|
type: object
|
|
properties:
|
|
files_checked:
|
|
type: integer
|
|
issues_found:
|
|
type: integer
|
|
last_scan_time:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
status:
|
|
type: string
|
|
enum: [healthy, issues_detected]
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Scan
|
|
# --------------------------------------------------------------------------
|
|
ScanStatus:
|
|
type: object
|
|
properties:
|
|
scanning:
|
|
type: boolean
|
|
files_scanned:
|
|
type: integer
|
|
files_queued:
|
|
type: integer
|
|
start_time:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
elapsed_seconds:
|
|
type: integer
|
|
|
|
# --------------------------------------------------------------------------
|
|
# System
|
|
# --------------------------------------------------------------------------
|
|
HealthResponse:
|
|
type: object
|
|
properties:
|
|
status:
|
|
type: string
|
|
example: ok
|
|
version:
|
|
type: string
|
|
uptime:
|
|
type: string
|
|
example: 48h 30m 15s
|
|
uptime_seconds:
|
|
type: integer
|
|
|
|
SystemResources:
|
|
type: object
|
|
properties:
|
|
cpu_usage_percent:
|
|
type: number
|
|
memory_used_bytes:
|
|
type: integer
|
|
format: int64
|
|
memory_total_bytes:
|
|
type: integer
|
|
format: int64
|
|
disk_used_bytes:
|
|
type: integer
|
|
format: int64
|
|
disk_total_bytes:
|
|
type: integer
|
|
format: int64
|
|
gpu_usage_percent:
|
|
type: number
|
|
nullable: true
|
|
gpu_memory_used_bytes:
|
|
type: integer
|
|
format: int64
|
|
nullable: true
|
|
|
|
HardwareInfo:
|
|
type: object
|
|
properties:
|
|
gpus:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
vendor:
|
|
type: string
|
|
device_path:
|
|
type: string
|
|
encoders:
|
|
type: array
|
|
items:
|
|
type: string
|
|
cpu_cores:
|
|
type: integer
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Filesystem
|
|
# --------------------------------------------------------------------------
|
|
DirectoryListing:
|
|
type: object
|
|
properties:
|
|
path:
|
|
type: string
|
|
parent:
|
|
type: string
|
|
nullable: true
|
|
directories:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
path:
|
|
type: string
|
|
files:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
path:
|
|
type: string
|
|
size:
|
|
type: integer
|
|
format: int64
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Setup
|
|
# --------------------------------------------------------------------------
|
|
SetupRequest:
|
|
type: object
|
|
required: [username, password, input_directories, output_directory]
|
|
properties:
|
|
username:
|
|
type: string
|
|
minLength: 1
|
|
password:
|
|
type: string
|
|
format: password
|
|
minLength: 8
|
|
input_directories:
|
|
type: array
|
|
items:
|
|
type: string
|
|
minItems: 1
|
|
output_directory:
|
|
type: string
|
|
enable_telemetry:
|
|
type: boolean
|
|
default: false
|
|
|
|
security:
|
|
- bearerAuth: []
|
|
- cookieAuth: []
|