Dubby provides a REST API at /v1/ for programmatic access to all server functionality. The API follows OpenAPI 3.1 conventions with auto-generated documentation.
OpenAPI spec: GET /v1/openapi.json
Swagger UI: GET /docs
The Swagger UI lets you explore endpoints, view request/response schemas, and make test requests directly from your browser.
The web client uses better-auth session cookies. Same-origin requests include the cookie automatically.
Sign in to get a token:
curl -X POST http://localhost:3000/api/auth/sign-in/email \
-H " Content-Type: application/json " \
Use the token in subsequent requests:
curl http://localhost:3000/v1/movies \
-H " Authorization: Bearer <token> "
Sessions last 7 days and auto-extend every 24 hours on activity.
Convention Details Content type application/json for request and response bodiesIDs Nanoid strings (21 characters) Pagination Cursor-based via cursor query parameter Page size limit parameter (1-100, default 20)Errors { "error": "description" } with appropriate HTTP statusValidation 422 with { "error": "Validation error", "details": [{ "path": "...", "message": "..." }] }Max body 1 MB (returns 413 if exceeded)
The REST API has 34 route groups. Below are the most commonly used endpoints. For the complete list, use the interactive Swagger UI at /docs or fetch the OpenAPI spec at /v1/openapi.json.
Method Endpoint Description POST/api/auth/sign-in/emailSign in with email and password POST/api/auth/sign-outSign out
Method Endpoint Description GET/v1/librariesList libraries (filtered by user permissions) POST/v1/librariesCreate a library GET/v1/libraries/:idGet library details PATCH/v1/libraries/:idUpdate a library DELETE/v1/libraries/:idDelete a library (files on disk are not deleted) POST/v1/libraries/:id/scanStart a library scan GET/v1/libraries/:id/statsLibrary statistics
Method Endpoint Description GET/v1/moviesList movies with filters and sorting GET/v1/movies/recently-addedRecently added movies GET/v1/movies/:idMovie details GET/v1/movies/:id/creditsCast and crew PUT/v1/movies/:id/watchedMark as watched DELETE/v1/movies/:id/watchedMark as unwatched GET/v1/movies/:id/file-statsFile codec/resolution details
Method Endpoint Description GET/v1/showsList TV shows with filters and sorting GET/v1/shows/recently-addedRecently added shows GET/v1/shows/:idShow details GET/v1/shows/:id/seasonsList seasons GET/v1/shows/:id/seasons/:numSeason details GET/v1/shows/:id/seasons/:num/episodesList episodes in a season GET/v1/shows/:id/seasons/:num/episodes/:numEpisode details
Method Endpoint Description POST/v1/playback/sessionsCreate a playback session POST/v1/playback/sessions/:id/heartbeatKeep session alive, update position POST/v1/playback/sessions/:id/seekSeek to a position DELETE/v1/playback/sessions/:idEnd a session GET/v1/playback/continue-watchingContinue watching list GET/v1/playback/sessions/activeActive sessions
Method Endpoint Description GET/v1/searchFull-text search across all media types GET/v1/search/suggestionsAutocomplete search suggestions
Method Endpoint Description GET/v1/collectionsList collections POST/v1/collectionsCreate a collection GET/v1/collections/:idGet collection details PATCH/v1/collections/:idUpdate a collection DELETE/v1/collections/:idDelete a collection GET/v1/collections/:id/itemsList items in a collection POST/v1/collections/:id/itemsAdd an item POST/v1/collections/:id/items/batchAdd multiple items DELETE/v1/collections/:id/items/:mediaType/:mediaIdRemove an item PUT/v1/collections/:id/items/orderReorder items POST/v1/collections/:id/refreshRefresh an auto-collection POST/v1/collections/preview-rulesPreview rule match count
Method Endpoint Description GET/v1/ai/availableCheck if AI inference is available POST/v1/ai/searchInterpret natural language search query POST/v1/ai/suggest-collectionsAI-powered collection suggestion POST/v1/ai/enrich-metadataSubmit AI metadata enrichment job GET/v1/ai/usageGet inference usage and credit balance GET/v1/ai/requestsPaginated inference request log (admin) GET/v1/enrichment/:mediaType/:mediaIdGet AI enrichment for a media item POST/v1/enrichment/enrichEnrich a single item POST/v1/enrichment/enrich-libraryBulk enrich a library GET/v1/enrichment/statsEnrichment statistics
Method Endpoint Description GET/v1/watchlistList watchlist items POST/v1/watchlistAdd item to watchlist DELETE/v1/watchlist/:idRemove from watchlist
Method Endpoint Description GET/v1/discoverBrowse trending/popular from TMDB
Method Endpoint Description GET/v1/people/:idPerson details and roles
Method Endpoint Description GET/v1/podcastsList subscribed podcasts POST/v1/podcastsSubscribe to a podcast DELETE/v1/podcasts/:idUnsubscribe GET/v1/podcasts/:id/episodesList episodes
Method Endpoint Description GET/v1/migration/discoverAuto-discover media servers on network POST/v1/migration/test-connectionTest connectivity to a source server POST/v1/migration/previewPreview libraries and users on source POST/v1/migration/sourcesCreate a migration source connection GET/v1/migration/sourcesList migration sources POST/v1/migration/importStart a migration import workflow GET/v1/migration/gap-reportCount shell records awaiting files
Method Endpoint Description POST/v1/parental-controls/pinSet or update profile PIN POST/v1/parental-controls/pin/verifyVerify a PIN GET/v1/parental-controls/profilesList managed profiles POST/v1/parental-controls/profilesCreate a managed profile PATCH/v1/parental-controls/profiles/:profileIdUpdate a profile DELETE/v1/parental-controls/profiles/:profileIdDelete a profile POST/v1/parental-controls/switch-profileSwitch active profile
Method Endpoint Description GET/v1/backupsList backups POST/v1/backupsCreate a backup GET/v1/backups/:idGet backup details DELETE/v1/backups/:idDelete a backup POST/v1/backups/restoreRestore from a backup
Method Endpoint Description GET/v1/admin/dashboardDashboard analytics GET/v1/admin/usersList all users GET/v1/audit-logsQuery audit logs (admin) GET/v1/feature-flagsList feature flags PATCH/v1/feature-flags/:keyToggle flag default GET/v1/jobsList background jobs GET/v1/workflowsList workflow runs
These route groups are fully documented in the Swagger UI:
Route group Description /v1/settingsServer settings CRUD /v1/setupFirst-run setup wizard /v1/configUnified server configuration /v1/metadataMetadata search, identification, refresh /v1/integrationsTMDB, Trakt, Radarr/Sonarr configuration /v1/subtitlesSubtitle track management /v1/audioAudio track information /v1/playback-preferencesPer-user audio/subtitle language rules /v1/optimizationAhead-of-time transcoding profiles /v1/seerrSeerr integration management /v1/healthLiveness and readiness probes /v1/usersUser profile management
Status Meaning 400Bad request 401Missing or invalid authentication 403Insufficient permissions 404Resource not found 409Conflict (e.g., scan already running) 413Request body too large 422Validation error 429Rate limit exceeded (check Retry-After header) 503Service unavailable
Scope Limit General API 100 requests/minute Speedtest 3 requests/minute
Rate-limited responses include a Retry-After header indicating when you can retry.
Streaming uses separate routes outside the /v1/ prefix. See Stream Tokens for authentication details.
Route Description GET /api/stream/:sessionId/master.m3u8HLS master playlist GET /api/stream/:sessionId/:quality/playlist.m3u8Quality-specific playlist GET /api/stream/:sessionId/:quality/:filenameHLS segment GET /api/stream/:sessionId/fileDirect file (HTTP Range) GET /api/stream/:sessionId/subtitles/:filenameWebVTT subtitle