Jellyfin
Point the official Webhook plugin at the sidecar — watched minutes settle to the library owner.
What gets metered
watched playback time — the official first-party jellyfin-plugin-webhook POSTs PlaybackStop notifications to the sidecar, which bills floor(position_minutes) × RATE micro-USDC.
- Who pays: the watching user (
UserId, mapped inPAYER_WALLETS) - Who gets paid: the content owner for the item (
ItemId, mapped inCREATOR_WALLETS)
Attach surface — no fork
Jellyfin's own plugin catalog: install the official Webhook plugin (a separate first-party plugin, not a fork edit) and add a destination pointing at the sidecar, subscribed to PlaybackStop.
Quickstart
Run the sidecar, then configure the Webhook plugin in Jellyfin:
PLATFORM=jellyfin RATE=1000 \
PAYER_WALLETS='{"<UserId>":"0x…"}' \
CREATOR_WALLETS='{"<ItemId>":"0x…"}' \
FACILITATOR_URL=https://facilitator.example FACILITATOR_API_KEY=… \
npx up-integration # RATE = micro-USDC per minute
# In Jellyfin: Dashboard → Plugins → Catalog → install "Webhook".
# Add a destination: http://up-sidecar:8410/jellyfin
# subscribed to: PlaybackStop (optionally PlaybackProgress)
# template emits: NotificationType, UserId, ItemId, PlaybackPositionTicks
All values above are placeholders — supply your own facilitator, wallets, and rate.
The shared prerequisites (a deployed StakeVaultFactory, a running
facilitator, a wallet registry) are covered in the admin overview.
Verify
node scripts/e2e-jellyfin-live-docker.mjs Full loop against a live ghcr.io/jellyfin/jellyfin (10.11.11) + official Webhook plugin (21.0.0.0): playback start/stop → per-minute bill → settle on anvil.
Notes & caveats
Links
- Recipe:
packages/integrations/deploy/jellyfin/README.md— the authoritative attach instructions in the repo. - Testing plan — Jellyfin row
- Integration Playbook — how integrations like this one are built.
- Testing plan — this platform's row in the L1→L4 matrix.