Skip to content

7. API and MCP Server

DannyVFilms edited this page Jul 31, 2026 · 2 revisions

API & MCP Server Overview

Floppy 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

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://floppy.example.com/api/v1/media

# X-API-Key
curl -H "X-API-Key: YOUR_TOKEN" https://floppy.example.com/api/v1/media

Regenerating 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://floppy.example.com/api/v1/user/token/regenerate/

Interactive Docs and Schema

The full, always-up-to-date reference lives in the running app, not this page:

  • Swagger UI: https://floppy.example.com/api/docs/ — browsable, try-it-out requests (click Authorize and paste your token).
  • OpenAPI schema: https://floppy.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.

Endpoint Reference

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 by media_type, status, search, sort, plus limit/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; /episodes for 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/reorder or /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= (or month/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.

Request Conventions

  • Media identity: most routes key on {media_type}/{source}/{media_id} — e.g. tv/tmdb/1399, game/igdb/1020, book/openlibrary/OL123M. media_type matches the values used throughout the UI (movie, tv, season, episode, anime, manga, game, boardgame, book, comic).
  • Pagination: list endpoints accept limit and offset query 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 by ApiJsonErrorMiddleware, so clients always get a JSON body on failure.
  • Responses: JSON only (DEFAULT_RENDERER_CLASSES is JSON-only — no browsable API renderer in production).

Public Endpoints

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.

MCP Server

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:

  • FLOPPY_URL — your instance's base URL (no trailing slash), e.g. https://floppy.example.com.
  • FLOPPY_TOKEN — your API token from Settings → Integrations (sent as X-API-Key).

Run it (stdio, for Claude Code / Claude Desktop)

FLOPPY_URL=https://floppy.example.com \
FLOPPY_TOKEN=your-token \
python -m floppy_mcp.server

Register with Claude Code

claude mcp add floppy \
  --env FLOPPY_URL=https://floppy.example.com \
  --env FLOPPY_TOKEN=your-token \
  -- python -m floppy_mcp.server

Once 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).

Limitations

  • No API-level rate limiting or throttling is configured — be considerate with polling frequency, especially against /discover and /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.

Clone this wiki locally