A modular, DI-native NuGet notification library for ASP.NET Core. Drop it in. Bring your own API keys. Own your data.
✅ v0.3.0 STABLE — 39 packages · 442 tests · Dashboard + MSG91 + full adapter auto-registration
RecurPixel.Notify is a pure .NET library — not a platform, not SaaS, no external dependency. It handles multi-channel notification delivery (Email, SMS, Push, WhatsApp, Slack, Discord, Teams, Mattermost, Rocket.Chat, Telegram, Facebook, LINE, Viber, In-App) through a single consistent interface.
You bring: your API keys, your message content.
We handle: provider API calls, retry with exponential backoff, cross-channel fallback chains, parallel dispatch, delivery hooks, and optional delivery log dashboard.
All adapters are unit-tested. The table below shows which have integration testing (real API verification) and community usage. This matrix validates the "stable" label — you're not betting on guesses.
| Package | Provider | Channel | Unit Tested | Integration Tested | Community Approved |
|---|---|---|---|---|---|
Email.SendGrid |
Twilio SendGrid | ✅ | ✅ | 🔲 | |
Email.Smtp |
Any SMTP server | ✅ | ✅ | 🔲 | |
Email.Mailgun |
Mailgun | ✅ | 🔲 | 🔲 | |
Email.Resend |
Resend | ✅ | 🔲 | 🔲 | |
Email.Postmark |
Postmark | ✅ | 🔲 | 🔲 | |
Email.AwsSes |
AWS SES | ✅ | 🔲 | 🔲 | |
Email.AzureCommEmail |
Azure Communication Services | ✅ | 🔲 | 🔲 | |
Sms.Twilio |
Twilio | SMS | ✅ | ✅ | 🔲 |
Sms.Vonage |
Vonage (Nexmo) | SMS | ✅ | 🔲 | 🔲 |
Sms.Plivo |
Plivo | SMS | ✅ | 🔲 | 🔲 |
Sms.Sinch |
Sinch | SMS | ✅ | 🔲 | 🔲 |
Sms.MessageBird |
MessageBird | SMS | ✅ | 🔲 | 🔲 |
Sms.AwsSns |
AWS SNS | SMS | ✅ | 🔲 | 🔲 |
Sms.AzureCommSms |
Azure Communication Services | SMS | ✅ | 🔲 | 🔲 |
Sms.Msg91 |
MSG91 | SMS | ✅ | ✅ | 🔲 |
Push.Fcm |
Firebase Cloud Messaging | Push | ✅ | 🔲 | 🔲 |
Push.Apns |
Apple Push Notification Service | Push | ✅ | 🔲 | 🔲 |
Push.OneSignal |
OneSignal | Push | ✅ | 🔲 | 🔲 |
Push.Expo |
Expo Push | Push | ✅ | 🔲 | 🔲 |
WhatsApp.Twilio |
Twilio WhatsApp | ✅ | ✅ | 🔲 | |
WhatsApp.MetaCloud |
Meta Cloud API | ✅ | 🔲 | 🔲 | |
WhatsApp.Vonage |
Vonage WhatsApp | ✅ | 🔲 | 🔲 | |
WhatsApp.Msg91 |
MSG91 WhatsApp Business | ✅ | ✅ | 🔲 | |
Slack |
Slack Webhooks / Bot API | Team Chat | ✅ | ✅ | 🔲 |
Discord |
Discord Webhooks | Team Chat | ✅ | ✅ | 🔲 |
Teams |
Microsoft Teams Webhooks | Team Chat | ✅ | 🔲 | 🔲 |
Mattermost |
Mattermost Webhooks | Team Chat | ✅ | 🔲 | 🔲 |
RocketChat |
Rocket.Chat Webhooks | Team Chat | ✅ | 🔲 | 🔲 |
Facebook |
Meta Messenger API | Social | ✅ | 🔲 | 🔲 |
Telegram |
Telegram Bot API | Social | ✅ | ✅ | 🔲 |
Line |
LINE Messaging API | Social | ✅ | 🔲 | 🔲 |
Viber |
Viber Business Messages | Social | ✅ | 🔲 | 🔲 |
InApp |
Hook-based (user-defined storage) | In-App | ✅ | ✅ | 🔲 |
Legend: ✅ Complete · 🔲 Not yet ·
# Full SDK — everything included
dotnet add package RecurPixel.Notify.Sdk
# Or install only what you need
dotnet add package RecurPixel.Notify
dotnet add package RecurPixel.Notify.Email.SendGrid
dotnet add package RecurPixel.Notify.Sms.Twilio→ Getting Started · Quick Start · Usage Tiers · Adapter Reference
⚠️ Upgrading from v0.1.0-beta.1 or v0.2.0-beta? v0.2.0 includes breaking changes: namespace reorganization, new meta-package structure, typedTriggerResultreturns, and explicitUseHandlerfor InApp channels. → See the Migration Guide for step-by-step upgrade instructions.
- Zero infrastructure — pure library, no platform to host or sign up for
- Provider agnostic — swap Twilio for Vonage with a config change, nothing else breaks
- DI-native — registers via
AddRecurPixelNotify(), injected asINotifyService - Config agnostic — accepts
IConfiguration, options builder, or a raw POCO - Content agnostic — we deliver the payload, you build the subject and body
- Config-filtered registration — only adapters whose credentials are present get registered in DI; unconfigured providers have zero DI footprint
- Pluggable observability —
OnDelivery()hook for user-owned logging, or drop inRecurPixel.Notify.Dashboardfor a zero-config delivery log with embedded UI
Drop-in delivery log dashboard. Pattern is identical to Hangfire — one middleware call, embedded HTML, zero Razor/Blazor dependencies.
// Program.cs
builder.Services.AddNotifyDashboard(options =>
{
options.RoutePrefix = "notify-dashboard";
options.PageTitle = "My App — Notifications";
options.RequireRole = "Admin"; // null = open (warns in non-Development)
});
// Option A — standalone context (own connection string, own migration)
builder.Services.AddNotifyDashboardEfCore(db =>
db.UseSqlite(connectionString));
// Option B — plug into your existing DbContext (one DB, one migration)
builder.Services.AddDbContext<AppDbContext>(db => db.UseSqlite(connectionString));
builder.Services.AddNotifyDashboardEfCore<AppDbContext>();
app.UseNotifyDashboard();Option B requires your DbContext to call builder.AddNotifyDashboard() in OnModelCreating:
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.AddNotifyDashboard(); // adds NotificationLogs table + indexes
}What it shows: summary row (total today, success rate, failure count, active channels), filterable log table with channel/provider/status badges, bulk row expansion (all recipients grouped inline), failed row expansion (full error text).
Bring your own store: implement INotificationLogStore and skip the EfCore package entirely.
dotnet add package RecurPixel.Notify.Sms.Msg91
dotnet add package RecurPixel.Notify.WhatsApp.Msg91"Sms": {
"Provider": "msg91",
"Msg91": { "AuthKey": "your-auth-key", "SenderId": "NOTIFY", "Route": "4" }
},
"WhatsApp": {
"Provider": "msg91",
"Msg91": { "AuthKey": "your-auth-key", "IntegratedNumber": "+91XXXXXXXXXX", "Namespace": "your-ns" }
}Every NotifyResult now carries full delivery context:
result.EventName // which event triggered this send
result.BulkBatchId // groups all results from one BulkTriggerAsync call
result.Metadata // passthrough from NotifyContext
result.Subject // payload subject — useful for dashboard displayNo breaking changes. Existing OnDelivery handlers work without modification.
Auto-registration is now driven by one IAdapterRegistrar per adapter package. Fixes: FCM crash, AwsSns/AwsSes/AzureComm registration crashes, Twilio credential corruption when SMS + WhatsApp are both configured, 19 HTTP adapters missing timeouts, MetaCloud key mismatch. See CHANGELOG for full details.
- Polly hooks — expose
IHttpClientBuilderper adapter for user-owned resilience policies - OpenTelemetry — optional
AddRecurPixelNotifyInstrumentation()for distributed tracing - Additional adapters —
Sms.Kaleyra,WhatsApp.Gupshup,WhatsApp.AiSensy, community-submitted - Dashboard v2 — batch detail page, provider health indicators, CSV export
MIT — see LICENSE.