-
-
Notifications
You must be signed in to change notification settings - Fork 55
4. Integrations
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.
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
- Import write operations retry on SQLite lock or disk I/O errors with exponential backoff (see Database: SQLite vs Postgres).
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
- Pocket Casts
- Last.fm
- Koito
- Multi-Scrobbler
- Seerr
- Jellyfin
- Emby
- Trakt
- Simkl
- AniList
- Steam
- Audiobookshelf
- CSV Import
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, andmedia.rateevents. -
media.playmarks items in progress;media.scrobblemarks 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.
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
newmode (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.
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 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_HOSTSin your Koito environment to the hostname you use to reach Koito (for examplekoito.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
localhostaddress 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 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-tokenSubmit 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_nowsubmissions are accepted but not recorded. Only completed listens become history.
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_SECRETenv 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
secretkey 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
secretare rejected with 401. - Floppy matches the payload's
requestedBy_usernameagainst 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_SECRETis set.
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/Stopevents 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/Stopwebhook 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
ItemIdagainst 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.
Media types
Webhook setup
- Configure Emby webhook to send
playback.start/playback.stopevents.
Auto-logging
- Marks items watched when
PlaybackInfo.PlayedToCompletionis true. - No bulk import; webhook events only.
Troubleshooting
- Ensure Emby sends provider IDs (TMDB/IMDB/TVDB) for matching.
Media types
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).
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.
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.
Media types
- Games (see Games).
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.
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=audiobookto 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.
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: