Notification plugin for FastAPI projects using FastAPI SDK and Postmark provider.
Project description
FastAPI Plugin Notification
A notification plugin for FastAPI that integrates with FastAPI SDK and Postmark provider to send notifications via email and store them in a database.
Features
- 📧 Email Notifications: Send notifications via Postmark email provider
- 💾 Database Storage: Store notifications in MongoDB using ODMantic
- 🔐 User Ownership: Automatic ownership filtering based on user claims
- 📊 Notification Management:
- Get all notifications for a user
- Mark notifications as seen/acknowledged
- Get unseen notification count
- 🚀 FastAPI Integration: Full CRUD API endpoints with authentication
- 📦 PyPI Package: Easy to install and use in any FastAPI project
Installation
Using UV:
uv add fastapi-plugin-notification
Or using pip:
pip install fastapi-plugin-notification
Quick Start
1. Initialize the Notification Client
from fastapi import FastAPI, Depends
from odmantic import AIOEngine
from fastapi_provider_postmark import PostmarkProvider
from fastapi_plugin_notification import NotificationClient
app = FastAPI()
# Initialize Postmark provider
postmark = PostmarkProvider(
api_key="your-postmark-api-key",
from_email="noreply@example.com",
from_name="My App",
)
# Initialize notification client (no DB engine needed)
notification_client = NotificationClient(
postmark_provider=postmark,
default_template_id=123456, # Your Postmark template ID
)
# Dependency for notification client
def get_notification_client() -> NotificationClient:
return notification_client
# Dependency for database engine
def get_db() -> AIOEngine:
return AIOEngine(database="your_database")
2. Add Notification Routes to Your App
from fastapi_plugin_notification.app import create_notification_router
# Add notification routes
notification_router = create_notification_router(
prefix="/notifications",
get_db=lambda: engine,
)
app.include_router(notification_router)
3. Send Notifications
@app.post("/send-welcome")
async def send_welcome_notification(
user_id: str,
user_email: str,
notification_client: NotificationClient = Depends(get_notification_client),
db: AIOEngine = Depends(get_db),
):
"""Send a welcome notification to a user."""
notification = await notification_client.send_notification(
db_engine=db,
name="welcome",
user_id=user_id,
user_email=user_email,
claims=request.state.claims, # Required: user claims for ownership verification
metadata={
"welcome_message": "Welcome to our platform!",
},
link="https://example.com/dashboard",
link_name="Go to Dashboard",
template_variables={
"user_name": "John Doe",
"action_url": "https://example.com/dashboard",
},
)
return {"notification_id": notification.uuid, "message": "Notification sent"}
4. Get User Notifications
The plugin automatically provides these user-specific endpoints:
GET /notifications/me- Get all notifications for the current userGET /notifications/me?seen=false- Get only unseen notificationsGET /notifications/me/{notification_id}- Get a specific notification (automatically marks as seen)DELETE /notifications/me/{notification_id}- Delete a notificationGET /notifications/count/unseen- Get count of unseen notifications
Usage Examples
Sending a Notification with Email
# In a FastAPI route handler
@app.post("/send-password-reset")
async def send_password_reset(
user_id: str,
user_email: str,
notification_client: NotificationClient = Depends(get_notification_client),
db: AIOEngine = Depends(get_db),
):
notification = await notification_client.send_notification(
db_engine=db,
name="password_reset",
user_id=user_id,
user_email=user_email,
claims=request.state.claims, # Required: user claims for ownership verification
metadata={
"reset_token": "abc123",
"expires_in": 3600,
},
link="https://example.com/reset-password?token=abc123",
link_name="Reset Password",
template_variables={
"reset_link": "https://example.com/reset-password?token=abc123",
"expires_in_minutes": 60,
},
)
return {"notification_id": notification.uuid}
Getting User Notifications
# Get all notifications for a user
notifications = await notification_client.get_user_notifications(
db_engine=db,
user_id="user_123",
page=1,
)
# Get only unseen notifications
unseen_notifications = await notification_client.get_user_notifications(
db_engine=db,
user_id="user_123",
page=1,
seen=False,
)
# Get unseen count
unseen_count = await notification_client.get_unseen_count(
db_engine=db,
user_id="user_123",
)
Marking Notifications as Seen
# Mark a specific notification as seen
notification = await notification_client.mark_as_seen(
db_engine=db,
notification_uuid="not_abc123",
)
Creating Notifications Without Email
# Create notification without sending email
notification = await notification_client.send_notification(
db_engine=db,
name="system_alert",
user_id="user_123",
user_email="user@example.com",
claims=request.state.claims, # Required: user claims for ownership verification
metadata={"alert_type": "info"},
send_email=False, # Don't send email
)
API Endpoints
Get My Notifications
GET /notifications/me?page=1&seen=false
Query Parameters:
page(int): Page number (default: 1)seen(bool, optional): Filter by seen status
Response:
{
"items": [
{
"uuid": "not_abc123",
"name": "welcome",
"user_id": "user_123",
"user_email": "user@example.com",
"metadata": {},
"link": "https://example.com/dashboard",
"seen": false,
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z",
"deleted": false
}
],
"total": 1,
"page": 1,
"pages": 1,
"size": 1
}
Get Unseen Count
GET /notifications/count/unseen
Response:
{
"count": 5
}
Get My Notification (Auto-marks as Seen)
GET /notifications/me/{notification_id}
Note: This endpoint automatically marks the notification as seen: true when accessed. Only returns notifications belonging to the current user.
Response:
{
"uuid": "not_abc123",
"name": "welcome",
"user_id": "user_123",
"user_email": "user@example.com",
"metadata": {},
"link": "https://example.com/dashboard",
"link_name": "Go to Dashboard",
"seen": true,
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z",
"deleted": false
}
Model Structure
The NotificationModel includes:
uuid: Unique identifier (short UUID with "not" prefix)name: Name/type of the notificationmetadata: Additional metadata (dict)user_id: ID of the user who should receive the notificationuser_email: Email address of the userlink: Call to action link (optional)link_name: Text to display on the call to action button/link in the email (optional)seen: Whether the notification has been seen (default: False)created_at: Creation timestampupdated_at: Last update timestampdeleted: Soft delete flag
Ownership and Permissions
The plugin uses FastAPI SDK's ownership rules to ensure users can only access their own notifications. The ownership is based on the user_id claim in the JWT token.
Required permissions:
notification:create- Create notificationsnotification:read- Read notificationsnotification:update- Update notificationsnotification:delete- Delete notifications
Configuration
Custom Router Configuration
from fastapi_plugin_notification.app import create_notification_router
# Create router with custom prefix and tags
notification_router = create_notification_router(
prefix="/notifications",
tags=["notifications", "alerts"],
get_db=lambda: engine,
)
Note: All routes are user-specific and automatically filter by the current user's ID from JWT claims.
Custom Template Variables
The notification client automatically includes:
notification_name: The name of the notificationuser_email: The user's emaillink: The notification linklink_name: The text for the call to action button/link- All
metadatafields - All
template_variablesfields
These are merged and passed to the Postmark template. You can use link_name in your email template to display custom button text for the call to action link.
Error Handling
The plugin handles errors gracefully:
- If email sending fails, the notification is still stored in the database
- Errors are logged but don't interrupt the notification creation process
- Database errors are propagated as HTTP exceptions
Development
Setup
- Clone the repository
- Install dependencies:
uv sync
Running Tests
pytest
License
MIT License - see LICENSE file for details
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fastapi_plugin_notification-0.1.0.tar.gz.
File metadata
- Download URL: fastapi_plugin_notification-0.1.0.tar.gz
- Upload date:
- Size: 15.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
33c82c3b15c2234076de5e946e058b33feaa09b04282068c0a7793b6a377cbc7
|
|
| MD5 |
50c516ae501e2f7a1588937a7c3f67ce
|
|
| BLAKE2b-256 |
4568de3c651891b537c04d81e9cbe9207e2fbced92e3bc1a997227d080d166b9
|
Provenance
The following attestation bundles were made for fastapi_plugin_notification-0.1.0.tar.gz:
Publisher:
python-publish.yml on Studio-Piot/fastapi-plugin-notification
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fastapi_plugin_notification-0.1.0.tar.gz -
Subject digest:
33c82c3b15c2234076de5e946e058b33feaa09b04282068c0a7793b6a377cbc7 - Sigstore transparency entry: 709089341
- Sigstore integration time:
-
Permalink:
Studio-Piot/fastapi-plugin-notification@13ed8ae1cba6fcab75bf1c80fa71da75c5be4e2f -
Branch / Tag:
refs/tags/0.1.0 - Owner: https://github.com/Studio-Piot
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@13ed8ae1cba6fcab75bf1c80fa71da75c5be4e2f -
Trigger Event:
release
-
Statement type:
File details
Details for the file fastapi_plugin_notification-0.1.0-py3-none-any.whl.
File metadata
- Download URL: fastapi_plugin_notification-0.1.0-py3-none-any.whl
- Upload date:
- Size: 11.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5fe3cf85c673b3e2ce5ed472f54735800ecb628916803c7e85b4b2fc36379bc4
|
|
| MD5 |
6b08b14438f9d583ff57ea92ca5c858d
|
|
| BLAKE2b-256 |
b39b9286b0e5daf0285736d2d87302f887995d3f7b01519656e14d1a3b8eface
|
Provenance
The following attestation bundles were made for fastapi_plugin_notification-0.1.0-py3-none-any.whl:
Publisher:
python-publish.yml on Studio-Piot/fastapi-plugin-notification
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fastapi_plugin_notification-0.1.0-py3-none-any.whl -
Subject digest:
5fe3cf85c673b3e2ce5ed472f54735800ecb628916803c7e85b4b2fc36379bc4 - Sigstore transparency entry: 709089348
- Sigstore integration time:
-
Permalink:
Studio-Piot/fastapi-plugin-notification@13ed8ae1cba6fcab75bf1c80fa71da75c5be4e2f -
Branch / Tag:
refs/tags/0.1.0 - Owner: https://github.com/Studio-Piot
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@13ed8ae1cba6fcab75bf1c80fa71da75c5be4e2f -
Trigger Event:
release
-
Statement type: