Novu
Open-source notification infrastructure. The official Python SDK is novu-py (pip install novu-py, import novu_py), NOT the older community packages novu or novu-python. Current version is 3.13.0 (Jan 2026). Three separate PyPI packages exist with different APIs — using the wrong one is the #1 footgun.
Warnings
- breaking Three separate PyPI packages exist: novu (community, dead), novu-python (community, dead), novu-py (official, active). pip install novu installs the wrong unmaintained package. LLMs almost always generate the wrong package name.
- breaking The old community novu package uses EventApi with name= (template name) and recipients= parameters. The official novu-py uses Novu.trigger() with workflow_id= and to= parameters. Code from tutorials using the old package will fail with ImportError or TypeError on the official SDK.
- breaking novu-py went through extremely rapid versioning: 0.x → 1.x → 3.x in under a year (Jan–Nov 2025). Each major version has breaking changes. Code from tutorials written for 0.x will not work on 3.x.
- gotcha The Novu class should be used as a context manager in long-lived applications to properly close HTTPX connections. Forgetting to close the client leaks HTTP connections.
- gotcha Novu requires subscribers to exist before triggering notifications. Triggering to a non-existent subscriber_id auto-creates it, but without email/phone data the notification may silently fail to deliver.
Install
-
pip install novu-py -
pip install novu -
pip install novu-python
Imports
- Novu
from novu_py import Novu with Novu(secret_key='YOUR_SECRET_KEY') as novu: response = novu.trigger( workflow_id='welcome-onboarding', to={'subscriber_id': 'user-123'}, payload={'firstName': 'Alice'} )
Quickstart
from novu_py import Novu
# Initialize with your Novu API key
novu = Novu(secret_key='YOUR_NOVU_API_KEY')
# Trigger a notification workflow
response = novu.trigger(
workflow_id='welcome-email', # workflow ID from Novu dashboard
to={
'subscriber_id': 'user-123',
'email': 'alice@example.com',
'first_name': 'Alice'
},
payload={
'company': 'Acme Corp',
'action_url': 'https://app.example.com'
}
)
print(response)
# Use as context manager for proper cleanup
with Novu(secret_key='YOUR_NOVU_API_KEY') as novu:
novu.trigger(
workflow_id='password-reset',
to={'subscriber_id': 'user-456'},
payload={'reset_url': 'https://app.example.com/reset/token'}
)