You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[FEATURE] Add Grimmory Connect integration for library synchronization #99
Chaptarr can manage, download, rename, upgrade, and delete eBooks and audiobooks, while Grimmory can act as the reader and collection/library frontend. There is currently no native Settings → Connect provider that keeps a Grimmory collection in sync after Chaptarr changes files.
Users must rely on filesystem watchers, scheduled scans, or custom webhooks/scripts. This is unreliable when watchers are disabled, Docker mounts differ, or a rename/upgrade produces several filesystem events.
This request applies to:
eBooks
Audiobooks
Requested solution
Add a native Grimmory Connect provider that notifies the correct Grimmory library after Chaptarr imports, upgrades, renames, or deletes book files.
The recommended MVP is shared-filesystem library refresh. Grimmory already exposes the required REST operations:
GET /api/v1/version — connection/version check
POST /api/v1/auth/login — obtain access and refresh JWTs
POST /api/v1/auth/refresh — renew the JWT
GET /api/v1/libraries — populate library mappings
PUT /api/v1/libraries/{libraryId}/refresh — rescan the affected library
GET /api/v1/libraries/health — optional path-access validation
Server URL (prefer a complete base URL so HTTPS, reverse proxies, custom ports, and URL bases work)
Username
Password (secret/redacted)
Sync mode:
Shared library / refresh (recommended and MVP)
BookDrop upload (optional later phase)
Root-folder/library mappings:
Chaptarr root folder
Media type (ebook or audiobook)
Grimmory library ID/name
Optional path translation for Docker/remote mounts
Event toggles using the standard Connect event model
Optional debounce interval (a small default such as 5–15 seconds)
If Grimmory adds long-lived API tokens or service accounts, an API token should be preferred over storing a user password. Until then, Chaptarr can store the credentials with the existing secret/privacy mechanisms, cache the short-lived access token in memory, refresh it before expiry, and retry once after a 401.
Proposed implementation
1. Follow the existing Connect provider pattern
Add a provider under src/NzbDrone.Core/Notifications/Grimmory/, broadly following the separation used by the current AudioBookShelf/Kavita providers:
Grimmory.cs — event handling and mapping selection
GrimmoryProxy.cs — HTTP, authentication, DTOs, and error translation
Small DTOs for token, version, library, and health responses
The provider should implement:
OnReleaseImport
OnRename
OnBookFileDelete
OnBookDelete where files are removed
2. Shared-filesystem refresh flow (MVP)
Determine the Chaptarr root folder and media type affected by the event.
Resolve it to one or more configured Grimmory library IDs.
Deduplicate and debounce refresh requests per Grimmory connection + library ID.
Call PUT /api/v1/libraries/{libraryId}/refresh once for each affected library.
Log a concise success/failure result without credentials or JWTs.
This mode must not upload or copy book files. Both applications see the same files through their own mount paths, so path translation is used for validation/mapping only; the library ID is the stable integration key.
A full-library refresh is a sensible first implementation because the current public API exposes it directly. If Grimmory later provides a targeted watcher/file-change endpoint, the proxy can use it and retain full refresh as a fallback.
3. Test Connection behavior
The Test button should:
Validate and normalize the base URL.
Call GET /api/v1/version.
Authenticate.
Fetch the available Grimmory libraries.
Optionally call GET /api/v1/libraries/health and show inaccessible mapped paths as an actionable validation error.
Reject mappings to libraries that no longer exist.
Version detection is important because Grimmory currently labels its public API as unstable. Keep all endpoint paths and JSON contracts inside GrimmoryProxy, report incompatible versions clearly, and cover the supported contract with fixture-based tests.
4. Optional BookDrop push mode (phase 2)
Grimmory also supports POST /api/v1/files/upload/bookdrop using multipart/form-data: Upload via BookDrop.
This can support installations where Chaptarr and Grimmory cannot share storage, but should be a separate explicit mode rather than the default:
Upload only after a successful Chaptarr import.
Stream from disk; do not buffer large ebooks/audiobooks entirely in memory.
Preserve the real filename and content type.
Treat each file of a multi-file audiobook as one coordinated job.
Apply retry/backoff for transient failures, but do not blindly retry an ambiguous completed upload.
Surface the Grimmory book/import ID returned by the API for diagnostics.
Before enabling automatic BookDrop sync, the integration needs a defined idempotency and lifecycle strategy for upgrades, renames, and deletions. Otherwise a replacement can create duplicates and a Chaptarr deletion may leave an orphan in Grimmory. Shared-library refresh avoids that problem and should therefore be the MVP.
Error handling and security
Use Authorization: Bearer <accessToken> for protected API calls.
Refresh proactively from the returned expiry and retry only once on 401.
Treat 401/403 as configuration/authentication errors.
Respect 429 and transient 5xx responses with bounded backoff.
Use normal Chaptarr SSRF/base-URL validation and TLS behavior.
Never log passwords, access tokens, refresh tokens, or upload bodies.
Ensure provider secrets remain redacted through the API, logs, and settings backup/restore.
Coalesce repeated events so an import/upgrade does not start overlapping scans.
Acceptance criteria
Grimmory appears as a provider under Settings → Connect.
Test Connection verifies version, authentication, and library discovery.
Users can map ebook and audiobook root folders to Grimmory libraries.
Import/upgrade, rename, file deletion, and book deletion refresh only the affected mapped libraries.
Multiple events for the same library are deduplicated/debounced.
Unmapped roots are skipped with useful debug logging, not a global scan.
Expired JWTs refresh automatically; a failed refresh produces a clear health/configuration error.
Secrets and tokens are always redacted.
Tests cover mapping, multi-library and multi-file books, Linux/Windows paths, token refresh/401 retry, unreachable hosts, removed library IDs, and scan deduplication.
Documentation explains shared-volume requirements and the API-version compatibility policy.
Alternatives considered
Grimmory filesystem watcher only: simple, but it can be disabled or miss Docker/NFS/SMB events and gives Chaptarr no success/failure signal.
Generic webhook/custom script: possible, but every user must maintain authentication, token refresh, mappings, retries, and API changes.
BookDrop as the only integration: useful without shared storage, but currently needs stronger replacement/delete/idempotency semantics to safely mirror Chaptarr upgrades and removals.
OPDS: useful for reading/downloading from Grimmory, but it is not a Chaptarr-to-Grimmory collection update mechanism.
Notes
Grimmory's documentation currently identifies the API as version 3.3.3 / OpenAPI 3.1 and explicitly warns that it is unstable. Keeping the implementation behind one small proxy/adapter and adding contract fixtures will limit maintenance when the upstream API changes.
Problem
Chaptarr can manage, download, rename, upgrade, and delete eBooks and audiobooks, while Grimmory can act as the reader and collection/library frontend. There is currently no native Settings → Connect provider that keeps a Grimmory collection in sync after Chaptarr changes files.
Users must rely on filesystem watchers, scheduled scans, or custom webhooks/scripts. This is unreliable when watchers are disabled, Docker mounts differ, or a rename/upgrade produces several filesystem events.
This request applies to:
Requested solution
Add a native Grimmory Connect provider that notifies the correct Grimmory library after Chaptarr imports, upgrades, renames, or deletes book files.
The recommended MVP is shared-filesystem library refresh. Grimmory already exposes the required REST operations:
GET /api/v1/version— connection/version checkPOST /api/v1/auth/login— obtain access and refresh JWTsPOST /api/v1/auth/refresh— renew the JWTGET /api/v1/libraries— populate library mappingsPUT /api/v1/libraries/{libraryId}/refresh— rescan the affected libraryGET /api/v1/libraries/health— optional path-access validationAPI documentation: Grimmory API, rescan a library, login, and refresh token.
Proposed configuration
The Connect form could contain:
ebookoraudiobook)If Grimmory adds long-lived API tokens or service accounts, an API token should be preferred over storing a user password. Until then, Chaptarr can store the credentials with the existing secret/privacy mechanisms, cache the short-lived access token in memory, refresh it before expiry, and retry once after a
401.Proposed implementation
1. Follow the existing Connect provider pattern
Add a provider under
src/NzbDrone.Core/Notifications/Grimmory/, broadly following the separation used by the current AudioBookShelf/Kavita providers:Grimmory.cs— event handling and mapping selectionGrimmorySettings.cs— validated provider configurationGrimmoryProxy.cs— HTTP, authentication, DTOs, and error translationThe provider should implement:
OnReleaseImportOnRenameOnBookFileDeleteOnBookDeletewhere files are removed2. Shared-filesystem refresh flow (MVP)
PUT /api/v1/libraries/{libraryId}/refreshonce for each affected library.This mode must not upload or copy book files. Both applications see the same files through their own mount paths, so path translation is used for validation/mapping only; the library ID is the stable integration key.
A full-library refresh is a sensible first implementation because the current public API exposes it directly. If Grimmory later provides a targeted watcher/file-change endpoint, the proxy can use it and retain full refresh as a fallback.
3. Test Connection behavior
The Test button should:
GET /api/v1/version.GET /api/v1/libraries/healthand show inaccessible mapped paths as an actionable validation error.Version detection is important because Grimmory currently labels its public API as unstable. Keep all endpoint paths and JSON contracts inside
GrimmoryProxy, report incompatible versions clearly, and cover the supported contract with fixture-based tests.4. Optional BookDrop push mode (phase 2)
Grimmory also supports
POST /api/v1/files/upload/bookdropusingmultipart/form-data: Upload via BookDrop.This can support installations where Chaptarr and Grimmory cannot share storage, but should be a separate explicit mode rather than the default:
Before enabling automatic BookDrop sync, the integration needs a defined idempotency and lifecycle strategy for upgrades, renames, and deletions. Otherwise a replacement can create duplicates and a Chaptarr deletion may leave an orphan in Grimmory. Shared-library refresh avoids that problem and should therefore be the MVP.
Error handling and security
Authorization: Bearer <accessToken>for protected API calls.401.401/403as configuration/authentication errors.429and transient5xxresponses with bounded backoff.Acceptance criteria
Alternatives considered
Notes
Grimmory's documentation currently identifies the API as version 3.3.3 / OpenAPI 3.1 and explicitly warns that it is unstable. Keeping the implementation behind one small proxy/adapter and adding contract fixtures will limit maintenance when the upstream API changes.