Skip to main content
Version: 1.2

9.5 Notification Delivery Policies

Controller: NotificationDeliveryPoliciesController · Route: api/v1/NotificationDeliveryPolicies (renamed from the singular NotificationDeliveryPolicyController used in early phase reports — plural is current) · GroupName: notifications · 9 endpoints · Per-channel retry/backoff/dead-letter configuration — see Chapter 12 — Retry Engine for the engine that reads these.

Verb + routePermissionRequestResponse (data)
POST GetDataTableNotificationDeliveryPolicies.ViewAllDtParametersDtResult<NotificationDeliveryPolicyDto> (unwrapped)
GET GetDetails/{id}NotificationDeliveryPolicies.ViewNotificationDeliveryPolicyDetailsDto
GET GetEdit/{id}NotificationDeliveryPolicies.EditNotificationDeliveryPolicyEditDto
GET GetDropdownList/{findBy}?onlyActive=trueNotificationDeliveryPolicies.Viewroute + queryNotificationDeliveryPolicyViewListDto[]
POST CreateNotificationDeliveryPolicies.CreateNotificationDeliveryPolicyEditDtoGuid
PUT Update/{id}NotificationDeliveryPolicies.EditNotificationDeliveryPolicyEditDtoGuid
DELETE Delete?restore=NotificationDeliveryPolicies.DeleteDeleteDto[]Guid
PUT ActiveNotificationDeliveryPolicies.ActiveDeleteDto[]Guid
PUT DeactiveNotificationDeliveryPolicies.DeactiveDeleteDto[]Guid

Field-level detail — NotificationDeliveryPolicyEditDto

{
"id": "00000000-0000-0000-0000-000000000000",
"isActive": true,
"displayOrder": 0,
"channel": 1,
"enabled": true,
"maxRetries": 5,
"retryStrategy": 2,
"initialDelaySeconds": 60,
"maximumDelaySeconds": 3600,
"backoffMultiplier": 2.0,
"retryOnTimeout": true,
"retryOnRateLimit": true,
"retryOnNetworkFailure": true,
"retryOnTemporaryFailure": true,
"retryOnPermanentFailure": false,
"deadLetterEnabled": true,
"priority": 5,
"description": "Default Email retry policy",
"fDescription": "Default Email retry policy"
}

retryStrategy: None=0, Fixed=1, ExponentialBackoff=2, Linear=3, Immediate=4.

No FluentValidation validator currently exists for this DTO — invalid combinations (e.g. initialDelaySeconds > maximumDelaySeconds, negative maxRetries) are not rejected server-side today. Treat this as an operational gap when authoring new policies by hand.

Seed defaults (one policy per channel, created by the platform's ApplicationDbSeeder)

ChannelMaxRetriesStrategyInitialDelayMaxDelay
Email5ExponentialBackoff60s3600s
WhatsApp3ExponentialBackoff30s1800s
SMS3Fixed60s300s
Push5ExponentialBackoff15s900s
SignalR2Linear10s60s
InApp2Fixed5s30s

Business notes: a channel with no delivery policy row falls back to safe engine defaults rather than failing dispatch — but every channel above is seeded on first run, so an explicit policy normally always exists. Retry timing formulas: Fixed = initialDelay; Linear = initialDelay × attemptNumber; Exponential = initialDelay × multiplier^(attempt-1), capped at maximumDelaySeconds; Immediate = 0.

Angular: an admin "delivery tuning" screen — typically one row per channel, rarely created ad hoc since all 6 channels are pre-seeded. Backend: read via the ERP's DeliveryPolicyRepositoryAdapter, which bridges IRepositoryAsync to the framework's IDeliveryPolicyRepository port — see §5.6. Related APIs: Retry Queue, Dead Letters, Chapter 12.