-
-
Notifications
You must be signed in to change notification settings - Fork 30
7. API and MCP Server
Yamtrack ships a REST API (/api/v1/) covering nearly everything the web UI can do — media tracking, lists, history, statistics, discover, music/podcast plays, imports/exports, and account settings. On top of that, a separate MCP (Model Context Protocol) server wraps the API so AI agents (Claude Code, Claude Desktop, etc.) can search, track, and manage your library conversationally.
Jump to sections:
- Authentication
- Interactive Docs and Schema
- Endpoint Reference
- Request Conventions
- Public Endpoints
- MCP Server
- Limitations
Every authenticated request needs your API token, found at Settings → Integrations → API Token. This is the same token already used for Plex/Jellyfin/Emby/Kodi/Stremio webhook URLs and the iCal feed — there's no separate API key to generate.
Send it as either header:
# Bearer token
curl -H "Authorization: Bearer YOUR_TOKEN" https://yamtrack.example.com/api/v1/media
# X-API-Key
curl -H "X-API-Key: YOUR_TOKEN" https://yamtrack.example.com/api/v1/mediaRegenerating the token invalidates the old one immediately — anything using it (webhooks, the MCP server, scripts) breaks until you update it there too. Regenerate from the Integrations page, or via the API itself:
curl -X POST -H "Authorization: Bearer YOUR_TOKEN" \
https://yamtrack.example.com/api/v1/user/token/regenerate/The full, always-up-to-date reference lives in the running app, not this page:
-
Swagger UI:
https://yamtrack.example.com/api/docs/— browsable, try-it-out requests (click Authorize and paste your token). -
OpenAPI schema:
https://yamtrack.example.com/api/schema/— raw schema JSON, useful for generating a typed client.
Treat the sections below as an orientation to the shape of the API; treat /api/docs/ as the source of truth for exact request/response fields.
All routes are under /api/v1/. Grouped by resource:
Media (movies, TV, anime, manga, books, comics, games, board games)
-
GET /media— your tracked library, filterable bymedia_type,status,search,sort, pluslimit/offset. -
GET /media/{media_type}— same, scoped to one type. -
GET|POST|PUT|DELETE /media/{media_type}/{source}/{media_id}— detail / track / update / untrack a title. -
GET /media/{media_type}/{source}/{media_id}/sync(and/{season_number}/sync) — refresh metadata from the source provider. -
GET /media/{media_type}/{source}/{media_id}/{season_number}— season detail;/episodesfor the episode list. -
POST /media/{media_type}/{source}/{media_id}/{season_number}/episodes/{episode_number}/watch|drop— log or remove an episode watch. -
POST /media/{media_type}/{source}/{media_id}/episodes/bulk— bulk-log multiple episode plays in one call. -
GET|POST /media/{media_type}/{source}/{media_id}/{season_number}/episodes/{episode_number}/score— episode-level scoring. -
GET|POST /media/{media_type}/{source}/{media_id}/progress(and season variant) — increment/decrement progress. -
GET /media/{media_type}/{source}/{media_id}/history— consumption history for that title; entry-level delete via/history/{consumption_id}. -
GET /media/{media_type}/{source}/{media_id}/changes_history— audit trail of field edits. -
GET /media/{media_type}/{source}/{media_id}/lists— lists containing this item; add/remove via/lists/{list_id}. GET /media/{media_type}/{source}/{media_id}/recommendations-
GET|POST /media/{media_type}/{source}/{media_id}/tags— tag management on a tracked item. -
GET|POST /media/{media_type}/{source}/{media_id}/provider-preference— preferred metadata provider override.
Music and podcasts (first-class, not modeled as generic "media")
-
GET /music/artists,/music/artists/{id},/music/artists/{id}/sync-discography,/music/artists/{id}/plays -
GET /music/albums,/music/albums/{id},/music/albums/{id}/tracks,/music/albums/{id}/plays -
POST /music/songs/plays,POST /music/bulk-plays,POST /music/tracks/{id}/score -
GET /podcasts/shows,/podcasts/shows/{id},/podcasts/shows/{id}/episodes -
POST /podcasts/shows/{id}/mark-all-played,POST /podcasts/episodes/plays
Lists
-
GET|POST /lists,GET|PUT|DELETE /lists/{id} -
POST|DELETE /lists/{id}/items— add/remove tracked items. -
PUT /lists/{id}/items/reorderor/order— manual ordering. -
GET|POST /lists/{id}/smart-rules,POST /lists/{id}/smart-sync— smart list rule management and re-sync. -
GET|POST /lists/{id}/collaborators— shared list collaborators. -
GET /lists/{id}/recommendations,POST .../{recommendation_id}/approve|deny -
GET /lists/{id}/activity— list activity feed.
Collection (owned physical/digital copies)
-
GET|POST /collection,GET|PUT|DELETE /collection/{entry_id} -
GET /collection/status/{item_id},GET /collection/seasons/{season_item_id}
Discover and Home
-
GET /discover,POST /discover/refresh,GET /discover/hidden -
GET /home— the same rows the home page renders.
History, tags, statistics
-
GET /history— day-grouped consumption timeline across all media;GET|DELETE /history/{media_type}/{history_id}for a single record. -
GET|POST /tags,GET|PUT|DELETE /tags/{id} -
GET /statistics/overview,POST /statistics/refresh
Imports and exports
-
GET /imports/activity— recent/queued import jobs. -
POST /imports/{service}— kick off an import (mal,anilist,kitsu,steam, etc.). -
GET /export/csv,GET /export/template
User settings
-
GET|PUT /user/preferences,/user/sidebar,/user/notifications -
PUT /user/notifications/exclusions,POST /user/notifications/test POST /user/token/regenerate
Calendar
-
GET /calendar?start_date=&end_date=(ormonth/year) — upcoming releases for your tracked media. -
POST /calendar/update— force-refresh calendar entries.
Background tasks
-
GET /tasks/{task_id}— poll the status of an async job (import, bulk play, sync, statistics refresh, ...).
This list favors coverage over exhaustive parameter docs — check /api/docs/ for exact request/response shapes and required fields per endpoint.
-
Media identity: most routes key on
{media_type}/{source}/{media_id}— e.g.tv/tmdb/1399,game/igdb/1020,book/openlibrary/OL123M.media_typematches the values used throughout the UI (movie,tv,season,episode,anime,manga,game,boardgame,book,comic). -
Pagination: list endpoints accept
limitandoffsetquery params (no default page size enforced beyond each endpoint's own cap) rather than a global DRF paginator. -
Errors: any error response under
/api/— including ones that would otherwise render as Django's HTML error pages — is converted to JSON byApiJsonErrorMiddleware, so clients always get a JSON body on failure. -
Responses: JSON only (
DEFAULT_RENDERER_CLASSESis JSON-only — no browsable API renderer in production).
Two endpoints don't require a token:
-
GET /api/v1/health— health check (used by container orchestration). -
GET /api/v1/info— basic app/version info.
Everything else requires the token described above.
The mcp_server/ directory in the repo is a standalone MCP server that wraps this API into 20 agent-shaped tools (search_media, track_media, manage_list, get_statistics, run_import, ...) rather than exposing every route 1:1, so an AI agent's tool list stays small and each call maps to a coherent user intent. Full tool list and contract notes are in mcp_server/README.md.
Install and configure
cd mcp_server
pip install -e .Two environment variables:
-
YAMTRACK_URL— your instance's base URL (no trailing slash), e.g.https://yamtrack.example.com. -
YAMTRACK_TOKEN— your API token from Settings → Integrations (sent asX-API-Key).
Run it (stdio, for Claude Code / Claude Desktop)
YAMTRACK_URL=https://yamtrack.example.com \
YAMTRACK_TOKEN=your-token \
python -m yamtrack_mcp.serverRegister with Claude Code
claude mcp add yamtrack \
--env YAMTRACK_URL=https://yamtrack.example.com \
--env YAMTRACK_TOKEN=your-token \
-- python -m yamtrack_mcp.serverOnce connected, you can ask the agent things like "mark episode 5 of Severance season 2 as watched" or "what's on my watchlist that released this month" and it will call the wrapped API on your behalf, using your token's permissions (i.e. your account, your library).
- No API-level rate limiting or throttling is configured — be considerate with polling frequency, especially against
/discoverand/statistics, which can trigger real backend refresh work. - No official client SDKs; generate one from
/api/schema/if you want typed bindings (e.g.openapi-generator,openapi-python-client). - The token is account-wide with full read/write access to everything that account can touch — there's no scoped/read-only token option.