http://localhost:8080/api
Most endpoints require authentication via JWT token. Include the token in the Authorization header:
Authorization: Bearer <your-token>
POST /auth/register
Body: {
"username": "string",
"email": "string",
"password": "string" (min 8 characters)
}
Response: {
"token": "string",
"user": { ... },
"expires_at": "timestamp"
}
> **Note:** After the initial admin account is created, this endpoint is disabled. Future user creation will be handled through an invite/admin interface.
#### Auth Status
GET /auth/status Response: { "needs_setup": boolean }
POST /auth/login
Body: {
"username": "string",
"password": "string"
}
Response: {
"token": "string",
"user": { ... },
"expires_at": "timestamp"
}
GET /media
Query Parameters:
- page: integer (default: 1)
- limit: integer (default: 20)
- type: string (movie, tv_series, documentary)
- genre: string
- search: string
- sort: string (title, release_date, rating_average, created_at)
- order: string (asc, desc)
GET /media/:id
Response: {
"id": "uuid",
"title": "string",
"overview": "string",
"release_date": "date",
"poster_url": "string",
"backdrop_url": "string",
"media_type": "string",
"rating_average": "float",
"genres": [...],
"tags": [...],
"files": [...]
}
GET /media/:id/stream
Returns: Video file stream
GET /movies
Same query parameters as /media
GET /movies/:id
GET /tv
GET /tv/:id
GET /tv/:id/seasons
GET /tv/:id/seasons/:seasonNumber/episodes
GET /search?q=<query>
GET /profiles
POST /profiles
Body: {
"name": "string",
"avatar_url": "string",
"is_child": "boolean",
"parental_rating_limit": "string"
}
GET /history?profile_id=<uuid>
POST /history
Body: {
"profile_id": "uuid",
"media_id": "uuid",
"episode_id": "uuid" (optional),
"watched_seconds": "integer",
"total_seconds": "integer",
"completed": "boolean"
}
GET /history/continue?profile_id=<uuid>
GET /watchlist?profile_id=<uuid>
POST /watchlist
Body: {
"profile_id": "uuid",
"media_id": "uuid"
}
GET /tags
GET /genres
POST /ratings
Body: {
"media_id": "uuid",
"profile_id": "uuid",
"rating": "integer" (1-10)
}
GET /libraries
GET /libraries/:id
POST /libraries
Body: {
"name": "Movies",
"library_type": "movie" | "tv" | "music" | "photos" | "other",
"language": "en-US",
"paths": ["/media/movies"]
}
PATCH /libraries/:id
PUT /libraries/:id/paths
Body: {
"paths": [
{ "path": "/media/movies", "priority": 10 }
]
}
POST /libraries/:id/scan
GET /libraries/:id/recent