9.8 Notification Analytics
Controller: NotificationAnalyticsController · Route: api/v1/NotificationAnalytics ·
GroupName: notifications · 10 endpoints, all GET, all read-only. Every action returns
Task<IActionResult> (not ActionResult<T>) but still wraps its payload in the standard Result<T> shape.
All list-style endpoints accept NotificationAnalyticsFilterDto as [FromQuery]:
GET /api/v1/NotificationAnalytics/Summary?dateFrom=2026-06-27&dateTo=2026-07-04&channel=1&eventKey=PurchaseInvoicePosted
| Field | Type | Notes |
|---|---|---|
dateFrom / dateTo | DateTime? | Default range when omitted: last 7 days. Maximum range: 90 days (per source XML doc comments) |
channel | NotificationChannel? | Optional filter |
eventKey | string? | Optional filter |
| Verb + route | Permission | Returns |
|---|---|---|
GET Summary | NotificationAnalytics.View | NotificationAnalyticsSummaryDto |
GET Channels | NotificationAnalytics.View | NotificationChannelPerformanceDto[] |
GET Events | NotificationAnalytics.View | NotificationEventPerformanceDto[] |
GET Failures/TopReasons | NotificationAnalytics.ViewAll | NotificationFailureReasonDto[] |
GET RetryQueue | NotificationAnalytics.View | NotificationRetryQueueMetricsDto |
GET DeadLetters | NotificationAnalytics.ViewAll | NotificationDeadLetterMetricsDto |
GET Trends | NotificationAnalytics.View | NotificationDeliveryTrendDto[] |
GET RecentFailures | NotificationAnalytics.ViewAll | NotificationRecentFailureDto[] |
GET Sla | NotificationAnalytics.View | NotificationSlaIndicatorDto[] |
GET Providers | NotificationAnalytics.View | NotificationProviderStatisticsDto[] |
Note the split permission model: broad operational views (Summary, Channels, Events, RetryQueue,
Trends, Sla, Providers) require only .View; failure-detail views that could expose sensitive error
context (Failures/TopReasons, DeadLetters, RecentFailures) require the stricter .ViewAll.
GET Summary
{
"succeeded": true,
"message": null,
"data": {
"totalDispatched": 18420,
"totalSucceeded": 18103,
"totalFailed": 210,
"totalPending": 107,
"deliveryRate": 98.28,
"dateFrom": "2026-06-27T00:00:00Z",
"dateTo": "2026-07-04T23:59:59Z"
}
}
(Field names shown reflect the DTO's confirmed purpose from source XML doc comments; exact property names
should be cross-checked against NotificationAnalyticsSummaryDto at integration time if binding strictly —
see Appendix § Verification Notes.)
GET RetryQueue
{
"succeeded": true,
"message": null,
"data": {
"totalPending": 12,
"totalRetrying": 3,
"totalExpired": 0,
"totalCancelled": 5,
"oldestPendingAgeMinutes": 47.5,
"oldestScheduledAt": "2026-07-04T09:30:00Z"
}
}
GET Providers
{
"succeeded": true,
"message": null,
"data": [
{
"providerName": "ZohoEmailProvider",
"channel": 1,
"healthState": 1,
"healthStateName": "Healthy",
"totalRequests": 9200,
"totalSucceeded": 9188,
"totalFailed": 12,
"totalFailovers": 2,
"consecutiveFailures": 0,
"averageLatencyMs": 340.2,
"availabilityPercentage": 99.87,
"lastSuccessOn": "2026-07-04T11:02:10Z",
"lastFailureOn": "2026-07-03T22:14:00Z",
"unavailableSince": null
}
]
}
healthState (ProviderHealthState): Unknown=0, Healthy=1, Degraded=2, Unavailable=3.
Angular: an operations dashboard — Summary/Channels/Trends/Sla for a health overview page;
Failures/TopReasons/RecentFailures/DeadLetters for a drill-down incident view. Cache Summary/Trends
briefly (e.g. 60s) since they aggregate over potentially large tables; do not cache RetryQueue/DeadLetters
counts, which need to feel live to an operator actively triaging.
Backend: INotificationAnalyticsService — aggregation queries against NotificationDeliveryAttempt,
NotificationRetryQueue, NotificationDeadLetter, and provider health-monitor state.
Related APIs: Retry Queue, Dead Letters,
Delivery Receipts.