Base URL: http://localhost:3000
All authenticated endpoints require the header:
Authorization: Bearer <jwt_token>
Create a new account.
Body:
{ "username": "string", "password": "string" }Response 201:
{ "token": "jwt_string", "userId": 1, "username": "string" }Authenticate and receive a JWT (30-day expiry).
Body:
{ "username": "string", "password": "string" }Response 200:
{ "token": "jwt_string", "userId": 1, "username": "string" }List all media items. Requires auth.
Query params: search (optional string)
Response 200:
[
{
"id": 1,
"filename": "Blade Runner 2049.mkv",
"title": "Blade Runner 2049",
"year": 2017,
"duration": 9720,
"size": 15728640000,
"thumbnail": "/thumbnails/1.jpg",
"tmdb_id": 335984,
"overview": "..."
}
]Trigger a library scan. Requires auth.
Response 200:
{ "message": "Scan started" }Get watch progress for the authenticated user.
Response 200:
{ "position": 3600, "duration": 9720 }Save watch progress.
Body:
{ "position": 3600, "duration": 9720 }Stream a video file. Supports Range header for seek.
Headers: Range: bytes=0- (optional)
Response: 200 (full) or 206 (partial) with video stream.
List all TV shows (grouped from scanned media). Requires auth.
Get show details with episodes.
Generate a QR code + 6-digit code for device pairing. Requires auth.
Response 200:
{
"code": "ABC123",
"qr": "data:image/png;base64,...",
"expiresAt": "2026-06-04T10:10:00.000Z"
}Exchange a 6-digit code for a JWT (no prior auth needed).
Body:
{ "code": "ABC123" }Response 200:
{ "token": "jwt_string", "userId": 1, "username": "string" }List all configured libraries. Requires auth.
Create a new library. Requires auth.
Body:
{ "name": "Movies", "path": "/media/movies" }List available subtitle tracks for a media item.
Download a subtitle file (SRT or VTT).
No auth required.
Response 200:
{ "status": "ok", "service": "PixelVault", "version": "0.1.0" }