Provider Plugins
ChannelWatch includes a Python file-based plugin loader for notification providers. If the built-in providers and Custom (Apprise) do not cover your destination, you can add a third-party provider as local Python code.
This page is about provider plugins only. Inbound webhook notifications are a separate feature and are documented on Webhooks.
How the plugin loader works
Section titled “How the plugin loader works”At startup, ChannelWatch scans /config/plugins/notifications/ for .py files. The current loader behavior is:
- files are scanned in sorted order
- filenames that start with
_are skipped - each file is imported under a unique module name
- concrete subclasses of
NotificationProviderare instantiated with no constructor arguments initialize()is called with no keyword arguments- the provider is registered only if
initialize()returnsTrue - import and initialization failures are logged and skipped instead of stopping the app
The loader also supports CHANNELWATCH_PLUGIN_DIR if you need to override the scan directory for testing.
Installing a plugin
Section titled “Installing a plugin”- Obtain the plugin
.pyfile from the plugin author. - Place it in the
/config/plugins/notifications/directory inside your mounted config volume. - Restart the ChannelWatch container.
- Check the startup logs to confirm the plugin loaded:
Plugin registered: MyCustomProvider (my_plugin.py)If the plugin failed to load, you’ll see a warning instead:
Plugin import failed, skipping: my_plugin.py: No module named 'requests'- Once loaded, the plugin becomes available in the notifications settings UI.
Directory layout
Section titled “Directory layout”Your config volume should look like this after adding a plugin:
/config/├── settings.json├── channelwatch.db└── plugins/ └── notifications/ └── my_plugin.pyCreate the plugins/notifications/ directories if they don’t exist yet.
Plugin dependencies
Section titled “Plugin dependencies”Plugins run inside the ChannelWatch container. If your plugin imports a third-party library that isn’t bundled with ChannelWatch, the import will fail and the plugin will be skipped.
To use a plugin with external dependencies, you have two options:
- Extend the image, create a custom
Dockerfilethat installs the required packages on top of the ChannelWatch base image. - Use only stdlib or bundled packages, write the plugin using only Python’s standard library and packages already present in the ChannelWatch image, such as
httpx,apprise, andpydantic.
What plugins can and cannot do
Section titled “What plugins can and cannot do”Plugins can:
- Register a new notification delivery provider
- Receive the notification payload,
title,message, optionalimage_url, and safe context kwargs likedvr_id,dvr_name, andevent_type - Send notifications to any destination using any Python-accessible transport
- Return a success or failure result that feeds into the delivery log
Plugins cannot:
- Replace the built-in routing engine
- Receive database handles, encryption keys, or raw ChannelWatch secrets from the loader
- Be hot-reloaded without a container restart
Scope: notification providers only
Section titled “Scope: notification providers only”In v1.0, the runtime plugin system covers notification providers only. Alert-source plugins are not dynamically loaded in v1.0, and UI plugins are not part of this system.
Related pages
Section titled “Related pages”- Delivery Log , track delivery status for all providers including plugins
- Custom (Apprise) , use any Apprise-supported service without writing a plugin
- Hot Reload , what changes take effect without a restart, plugins are not hot-reloaded