Download activity
HTTP routes and behavior for download activity.
GET /api/downloads/activity?scope=all|mineGET /api/downloads/summary?scope=all|mineGET /api/admin/downloads/settingsPUT /api/admin/downloads/settingsActivity and summary require downloads:activity, available to authenticated users and admins. Activity returns groups, unique jobs, effective scope, user_scope, count, complete, stale, fetched_at, and source availability. Summary returns the same count and freshness fields without groups/jobs. A null count means the exact total is unavailable. Each group has a stable ID, media type, library instance, title/year, creator/format/artwork when known, job_ids, confirmed children, details_known, and progress weighted by bytes across unique jobs. Child rows reference the shared job; they do not claim separate pack percentages.
Jobs come from live Radarr, Sonarr, Chaptarr, and Lidarr queues plus the six normalized download clients. Provider snapshots coalesce concurrent reads and expire within 15 seconds; queue/configuration events and successful client actions invalidate them. The download ID the client assigned (SABnzbd nzo_id, torrent hash, NZBGet tracking alias, never its numeric control ID) joins an arr queue row to a connected client’s job, scoped by the client type the arr’s own download-client definition names; the arr and Cantinarr may reach that client through different hostnames or URL bases. The address only breaks a tie when several connected clients of one type report the same ID, and a tie it cannot break leaves the admin count unavailable. No filename/category matching occurs. A job no connected client reports keeps the arr’s progress with no controls. Admins receive each job’s client or arr name and also see unmatched client jobs; requesters receive neither. Queued, paused, stalled, and failed unfinished jobs count once; completed/seeding jobs, import processing, and requests without a job do not count.
Per-request instance grants, kids policies, and saved request identities are applied after shared reads and rechecked before the response. My requests uses exact movie/book/album identities, instance targets, saved TV season/pilot mappings, and book-format subscriptions. Unidentifiable scope is incomplete, never confirmed empty. Requesters receive no raw filenames, paths, client configuration, other user identities, or control IDs. Missing artwork uses an app placeholder; unreadable identity/authorization fails closed.
The settings routes require admin:* and read/write { "user_scope": "all" } or { "user_scope": "mine" }. This is downloads_user_scope in the existing server-settings JSON, defaulting to all, with no schema migration. Config advertises downloads_activity: true and downloads_user_scope. Restricting users to mine overrides their requested scope immediately. Admin totals remain server-wide. Raw client REST endpoints and downloads_queue WebSocket snapshots remain admin-only.
The opt-in live check is go test ./internal/downloads -run TestLiveDownloadsActivity -downloads-canary=/path/to/private-manifest.json -v. The private manifest contains disposable: true and an instances array using the server instance fields (service_type, url, and credentials). Only loopback Radarr/NZBGet services are accepted. NZBGet must contain exactly one synthetic job named Codex Downloads Fixture 632 with the drone parameter codex-downloads-632; the check resumes, pauses, then removes that job. Keep its NNTP providers disabled. It verifies real alias/control handling, unmatched visibility, and count transitions, while ordinary fixtures cover media matching. Never use a production service for this check.