A Navidrome plugin that watches your music library for newly added albums and pushes a notification to an ntfy topic and/or a generic webhook endpoint (e.g. Apprise API) for each one discovered.
- On startup (
nd_on_init) the plugin schedules a recurring cron job (default: every minute). - On each tick it calls the internal Subsonic API (
getAlbumList2?type=newest) to fetch the 20 most recently added albums. - It compares the results against the last known album ID stored in KVStore. Any albums that appear before (i.e. newer than) that watermark are considered new.
- For each new album it sends an HTTP POST to the configured ntfy topic URL.
- After all notifications are sent successfully it updates the KVStore watermark. If a POST fails the watermark is not updated, so the album will be retried on the next tick.
First run: On the very first poll the plugin establishes the watermark without sending any notifications, preventing a flood of alerts for your entire existing library.
- Navidrome with the plugin system enabled (see plugin docs)
- TinyGo to build the
.wasmbinary - An ntfy server (self-hosted or ntfy.sh) and/or a generic webhook endpoint
# 1. Build the WebAssembly module
make build
# 2. Package as .ndp
make package # produces navidrome-ntfy.ndp
# 3. Copy to your Navidrome plugins folder
cp navidrome-ntfy.ndp /path/to/navidrome/plugins/
# 4. Enable plugins in navidrome.toml (if not already)
# [Plugins]
# Enabled = true
# Folder = "/path/to/plugins"Set these values in the Navidrome web UI under Settings → Plugins → ntfy New Album Notifications.
At least one of ntfy_url or webhook_url must be configured. Both can be set simultaneously to send notifications to multiple destinations.
| Key | Required | Description |
|---|---|---|
subsonic_user |
Yes | Navidrome username the plugin uses for internal Subsonic API calls. The user must be granted access to this plugin in the Users section of the plugin settings. |
ntfy_url |
One of | Full ntfy topic URL, e.g. https://ntfy.example.com/music |
webhook_url |
One of | Generic webhook endpoint URL. Receives a JSON POST with title and body fields. Compatible with Apprise API. |
ntfy_token |
No | Bearer token for authenticated ntfy instances. Leave blank for public topics. |
webhook_token |
No | Bearer token for authenticated webhook endpoints. Leave blank if not required. |
webhook_notification_urls |
No | Apprise-compatible notification URL(s) included as urls in the webhook body. Required when using the Apprise stateless /notify endpoint (e.g. ntfy://ntfy.example.com/topic?token=...). |
poll_interval |
No | Cron expression override. Default: */1 * * * * (every minute). |
Because this plugin uses the subsonicapi permission it requires at least one Navidrome user to be assigned to it. In the plugin settings page either:
- Enable Allow all users, or
- Select a specific user from the list (a dedicated read-only account is recommended).
ntfy
| Field | Value |
|---|---|
| Body | New album added: {Album Title} — {Artist Name} |
| Title | New Album in Navidrome |
| Priority | default |
| Tags | musical_note |
Generic webhook / Apprise API
A JSON POST is sent to webhook_url:
{
"title": "New Album in Navidrome",
"body": "New album added: {Album Title} — {Artist Name}"
}When webhook_notification_urls is set, a urls field is added to the body, enabling the Apprise stateless endpoint:
{
"urls": "ntfy://ntfy.example.com/navidrome?token=...",
"title": "New Album in Navidrome",
"body": "New album added: {Album Title} — {Artist Name}"
}Apprise API (stateless /notify): set webhook_url to http://your-apprise:8000/notify and webhook_notification_urls to your Apprise notification URL (e.g. ntfy://ntfy.example.com/navidrome?token=...).
Apprise API (keyed /notify/{key}): set webhook_url to http://your-apprise:8000/notify/navidrome with the key pre-configured in Apprise. Leave webhook_notification_urls blank.
| Key | Description |
|---|---|
last_seen_album_id |
Album ID of the most recently notified album. Delete this key (via the Navidrome debug tools) to reset the watermark. |
# Clean build artefacts
make clean
# Rebuild and repackage in one step
makeThe replace directive in go.mod points to the PDK sources inside the Navidrome repository. Adjust the path if your working tree is structured differently:
replace github.com/navidrome/navidrome/plugins/pdk/go => ../navidrome/plugins/pdk/go