Skip to content

4. Integrations

DannyVFilms edited this page Aug 21, 2026 · 11 revisions

Integrations (Overview)

Integrations connect Floppy to external services for imports, scrobbling (auto-logging), collection metadata, or automation. Each integration maps to specific media types and uses either pull-based imports (scheduled or manual) or push-based webhooks.

See Media Types for tracking behavior and provider mapping by type.

Account connections (imports / polling)

  • Plex: imports watch/listen history; optional webhook scrobbling; collection metadata extraction; watchlist sync.
  • Trakt: import movies + TV (public or OAuth for private).
  • Simkl: import movies + TV + anime (OAuth).
  • AniList: import anime + manga (public or OAuth for private).
  • Pocket Casts: import podcast history; scheduled every 2 hours.
  • Last.fm: poll recent music scrobbles on a schedule.
  • Koito: poll listening history from a self-hosted Koito server; receive-only.
  • Steam: import games using Steam ID 64.
  • Audiobookshelf: import audiobook progress from a self-hosted Audiobookshelf server.

Webhooks (push events)

  • Plex: playback and rating events for TV/Movie/Music.
  • Jellyfin: playback events for TV/Movie; one-time Playback Reporting history import.
  • Emby: playback events for TV/Movie.
  • Seerr: request automation for TV/Movie status updates.
  • Multi-Scrobbler (and any ListenBrainz client): push music listens in real time.

Import Overview

Imports are pull-based jobs that run in the background (Celery). Most support once or scheduled runs and a mode:

  • new: skip items already in your library.
  • overwrite: delete existing items for the matched media type/source and re-import.

Matching + dedupe

  • Imports match by provider IDs (TMDB, MAL, IGDB, etc.). Entries missing IDs are skipped.
  • Importers dedupe within a run and skip duplicates across runs. Some sources (Pocket Casts) perform extra merge steps for duplicate episodes.

Retries + SQLite locks

What imports affect

  • Imports create or update media items, statuses, and History entries.
  • They trigger calendar reloads and can schedule collection metadata updates (Plex).
  • Stats/history caches may refresh after imports (Last.fm polling explicitly refreshes Statistics).

See Celery and Background Tasks for worker/beat details.

Jump to providers

Plex

Media types

  • Movies (TMDB; see Movies), TV/Seasons/Episodes (TMDB; see TV Shows), Music (MusicBrainz; see Music).

Connect

  • Pin-based OAuth flow; stores a Plex token, account ID, and library sections.
  • Optional Plex username allowlist controls webhook processing.

Import

  • Pulls Plex watch/listen history and replays it into Floppy.
  • Supports once or scheduled runs and new/overwrite modes.
  • Can target a specific Plex library or all libraries.

Auto-logging (webhooks)

  • Supports media.play, media.scrobble, and media.rate events.
  • media.play marks items in progress; media.scrobble marks completed plays.
  • Ratings are updated when Plex sends media.rate (not always reliable).

Collection metadata

  • Collection metadata is fetched from Plex library items and stored on the item.
  • A separate “update_collection” mode can refresh collection metadata.
  • Rating key + Plex URI caching speeds up metadata refresh and avoids full library scans.

GUID parsing + rating key caching

  • Plex GUIDs can be incomplete or inconsistent. Floppy resolves TMDB IDs using TMDB/IMDB/TVDB IDs and title search fallbacks.
  • Cached rating keys allow future metadata updates without re-scanning Plex.

Watchlist sync

  • Floppy can poll your Plex Discover watchlist every 15 minutes and mirror it into your library.
  • Items on the watchlist are added as Planning status (Movies and TV via TMDB).
  • Items removed from the Plex watchlist are cleaned up in Floppy only if the item is still Planning and has not been modified (no score, progress, notes, or dates).
  • Enable watchlist sync in Settings → Integrations under Plex.

Troubleshooting

  • If items fail to match, check that Plex GUIDs include TMDB/IMDB/TVDB IDs.
  • If ratings don’t update, Plex may not emit media.rate; run an import to sync ratings.
  • Missing collection metadata usually means the item wasn’t matched or metadata fetch failed.

Pocket Casts

Media types

  • Podcasts (Show -> Episode; see Podcasts).

Connect

  • Email/password login; stores access + refresh tokens.

Import pipeline

  • Runs an initial import on connect, then scheduled imports every 2 hours.
  • Always uses new mode (no overwrite), and merges duplicate episodes.

RSS fallback

  • If a show lacks a feed URL, Floppy tries iTunes to discover the RSS feed.
  • RSS episodes are synced to fill in missing metadata and episode lists.

Common failure modes

  • OAuth logins (Apple/Google) require setting a password first.
  • If the connection is marked broken, reconnect to refresh tokens.
  • Missing episode metadata often resolves after RSS sync.

Last.fm

Media types

  • Music (scrobbles -> track plays; see Music).

Connect

  • Username-only connection; requires public scrobbles.

Polling vs scrobbling

  • Uses scheduled polling (default every 15 minutes) to fetch recent tracks.
  • All Last.fm scrobbles are treated as completed plays.

History + stats

  • Scrobbles create track-level history entries that roll up to albums/artists.
  • Statistics cache is refreshed after polling.

Troubleshooting

  • Rate limits can delay imports; try again later.
  • Private profiles or invalid usernames will not connect.

Koito

Koito is a self-hosted, ListenBrainz-compatible scrobble server. Floppy imports your Koito listening history and keeps it in sync.

Media types

  • Music (listens -> track plays; see Music).

Receive-only

  • Floppy only ever reads from Koito. It never submits, relays, or scrobbles anything back, so Koito stays the authoritative listening database.

Connect

  • In Koito, go to Settings → API Keys and generate a key.
  • In Floppy, go to Settings → Import Data → Koito and enter your Koito server URL (for example https://koito.example.com) and the API key.
  • The key is encrypted before it is stored and is never displayed again.

Polling vs import

  • Connecting queues a full history import using Koito's export endpoint, which carries MusicBrainz IDs, track durations, and release data.
  • After that, Floppy polls for new listens every 15 minutes.
  • Sync now runs a poll immediately; Import full history re-runs the complete backfill.
  • The poll only advances its cursor after a fully successful fetch, so listens are not skipped when Floppy or Koito is briefly unavailable.

History + stats

  • Listens create track-level history entries that roll up to albums and artists.
  • Statistics caches refresh after each sync.

Troubleshooting

  • Connection fails on Koito 0.1.7 or older: set KOITO_ALLOWED_HOSTS in your Koito environment to the hostname you use to reach Koito (for example koito.mydomain.com). This is the most common cause of a failed connect.
  • "Koito rejected the API key": the key was revoked or mistyped. Generate a new one in Koito and reconnect.
  • Server unreachable: confirm Floppy's container can reach the Koito URL. A localhost address will not resolve from inside a container.
  • Duplicate listens are filtered by timestamp, artist, track, and album, so re-running the full import is safe.

Multi-Scrobbler

Multi-Scrobbler forwards plays from many music sources to multiple destinations. It can push listens to Floppy in real time.

There is no "Floppy" client in Multi-Scrobbler. Floppy implements the ListenBrainz submit API, so you configure Multi-Scrobbler's ListenBrainz client and point it at Floppy.

Media types

  • Music (listens -> track plays; see Music).

Setup

  • URL: your Floppy base URL, for example https://floppy.example.com
  • Token: your API token from Settings → Integrations → API Token (the same token used for webhooks and the REST API)

Example Multi-Scrobbler client config:

{
  "clients": [
    {
      "name": "floppy",
      "type": "listenbrainz",
      "data": {
        "url": "https://floppy.example.com",
        "token": "YOUR_FLOPPY_API_TOKEN"
      }
    }
  ]
}

Multi-Scrobbler can send to Koito and Floppy at the same time, so you can keep Koito as your canonical database while Floppy receives the same listens live.

Any ListenBrainz-compatible client works The same two values work anywhere a "custom ListenBrainz URL" can be set, including Navidrome, Pano Scrobbler, Feishin, and Symfonium.

Verify the connection

curl -H "Authorization: Token YOUR_FLOPPY_API_TOKEN" \
  https://floppy.example.com/apis/listenbrainz/1/validate-token

Submit a test listen:

curl -X POST https://floppy.example.com/apis/listenbrainz/1/submit-listens \
  -H "Authorization: Token YOUR_FLOPPY_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"listen_type":"single","payload":[{"listened_at":1750000000,"track_metadata":{"artist_name":"Boards of Canada","track_name":"Roygbiv","release_name":"Music Has the Right to Children"}}]}'

See ListenBrainz-Compatible Ingest for the full endpoint reference.

Troubleshooting

  • 401 Unauthorized: the token is wrong. Copy it again from Settings → Integrations. Regenerating the token breaks every client using it.
  • 403 Forbidden: music tracking is disabled for the account. Enable it in Settings.
  • Now-playing does not appear: playing_now submissions are accepted but not recorded. Only completed listens become history.

Seerr

Media types

Webhook setup

  • Configure Seerr to POST a JSON payload to Floppy’s webhook URL.
  • Payload keys: media_type, media_tmdbid, media_status, requestedBy_username.

Automation behavior

  • Creates the item if missing and sets status (Planning or In Progress).
  • Triggered statuses and allowed requesters are configurable per user.
  • Does not log history plays; it only adds or updates items.

Global webhook (multi-user households)

  • Seerr supports only one webhook per instance, so a shared Seerr/Overseerr install can't send per-user URLs to every Floppy user.
  • The admin sets a SEERR_GLOBAL_WEBHOOK_SECRET env var (see Environment Variables), then points Seerr at Floppy's single global webhook URL instead (/webhook/seerr/global/; shown with a copy button in Settings → Integrations → Seerr when the env var is set).
  • The JSON payload must include an extra secret key matching that env var value, alongside the usual keys:
    {
      "media_type": "{{media_type}}",
      "media_tmdbid": "{{media_tmdbid}}",
      "media_status": "{{media_status}}",
      "requestedBy_username": "{{requestedBy_username}}",
      "secret": "<value of SEERR_GLOBAL_WEBHOOK_SECRET>"
    }
  • Requests with a missing or incorrect secret are rejected with 401.
  • Floppy matches the payload's requestedBy_username against each user's own "Allowed Seerr usernames" list to route the request, so each user still needs "Auto-add requested media" enabled and their Seerr username listed there.
  • The global webhook is hidden/disabled (404) until SEERR_GLOBAL_WEBHOOK_SECRET is set.

Jellyfin

Media types

  • Movies and TV (via TMDB/IMDB/TVDB IDs in webhook payloads or the connected Jellyfin server's library; see Movies and TV Shows).

Webhook setup

  • Configure Jellyfin webhook to send Play/Stop events to Floppy.

Auto-logging

  • Marks items watched when Jellyfin reports UserData.Played.
  • No bulk import from the webhook itself; live events only.

Playback Reporting history import (one-time, not a scheduled/bulk import)

  • This is a separate, manual TSV upload — not a Trakt/Plex-style scheduled or bulk import. It requires the connection below, and each file has to be uploaded by hand.
  • Requires the Floppy → Jellyfin connection first: go to Settings → Integrations → Jellyfin and connect your Jellyfin server URL and API key under "Floppy → Jellyfin" (this is a different section from the Play/Stop webhook setup above).
  • In Jellyfin, install/enable the Playback Reporting plugin, then export its history as TSV.
  • Back in Floppy, under the same "Floppy → Jellyfin" section, a "Playback Reporting history" upload field appears once connected. Upload the TSV there and submit.
  • Floppy replays the export's 9-column rows (movies and episodes only), matching each row's Jellyfin ItemId against your connected server's current library to resolve TMDB/IMDB/TVDB IDs — items removed from the server can no longer be matched.
  • Only rows belonging to the connected Jellyfin user are imported; rows for other users on the same export are skipped.
  • Re-uploading the same export is safe: previously imported rows are recognized and skipped rather than duplicated.
  • Progress and results (created/skipped counts, warnings) show on the same page after the upload completes.

Troubleshooting

  • If IDs are missing in the webhook payload, Floppy can’t match items.
  • Playback Reporting rows are skipped (not failed) when the Jellyfin item was deleted/moved, lacks a supported provider ID, or belongs to another Jellyfin user.

Emby

Media types

  • Movies and TV (via TMDB/IMDB/TVDB IDs in webhook payloads; see Movies and TV Shows).

Webhook setup

  • Configure Emby webhook to send playback.start/playback.stop events.

Auto-logging

  • Marks items watched when PlaybackInfo.PlayedToCompletion is true.
  • No bulk import; webhook events only.

Troubleshooting

  • Ensure Emby sends provider IDs (TMDB/IMDB/TVDB) for matching.

Trakt

Media types

  • Movies and TV (including seasons/episodes; see Movies and TV Shows).

Public profile import

  • Enter a public Trakt username to import watch history and statuses.

Private profile import (OAuth)

  • OAuth is required to access private history.

Notes

  • Imports can be run once or scheduled.
  • Uses TMDB IDs to match movies and shows.
  • Watchlist entries are imported as Planning status in the standard Trakt import.
  • Trakt lists and watchlist can also be imported into Custom Lists from the Lists page (separate Trakt OAuth + client ID/secret).

Simkl

Media types

Configuration

  • OAuth connection required (SIMKL ID + secret).

Notes

  • Imports can be run once or scheduled.
  • Movies/TV map to TMDB; anime maps to MAL IDs.

AniList

Media types

Public import

  • Enter a public AniList username to import lists and history.

Private import (OAuth)

  • OAuth is required to access private lists.

Notes

  • Imports can be run once or scheduled.

Steam

Media types

Configuration

  • Requires a Steam API key and Steam ID 64.

Import requirements

  • Your Steam profile must be public.

Notes

  • Imports can be run once or scheduled.

Audiobookshelf

Media types

  • Books (source audiobookshelf; see Books).

Connect

  • Enter your Audiobookshelf server URL and API token in Settings → Integrations.
  • Credentials are stored per user in the database; no global environment variable is required.

Import

  • Syncs audiobook progress, completion status, and metadata from your Audiobookshelf library.
  • Only entries changed since the last sync are processed (change detection via timestamp).
  • Imported items are tagged format=audiobook to distinguish them from other book sources.
  • When Audiobookshelf metadata is incomplete, the importer enriches it using Hardcover or OpenLibrary ISBN lookups.

Notes

  • Imports can be run once or scheduled.
  • If metadata is missing after import, the importer falls back to Hardcover/OpenLibrary; re-running the import after Audiobookshelf syncs new metadata will fill in gaps.

CSV Import (Floppy / Yamtrack format)

Use the Floppy CSV format (identical to Yamtrack's, so exports from either import cleanly) for bulk migrations or offline exports. CSV imports are pull-based jobs and use the same new/overwrite modes as other importers.

For the full format specification and field list, see:

Clone this wiki locally