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 + route | Permission | Request | Response (data) |
|---|---|---|---|
POST GetDataTable | NotificationDeliveryPolicies.ViewAll | DtParameters | DtResult<NotificationDeliveryPolicyDto> (unwrapped) |
GET GetDetails/{id} | NotificationDeliveryPolicies.View | — | NotificationDeliveryPolicyDetailsDto |
GET GetEdit/{id} | NotificationDeliveryPolicies.Edit | — | NotificationDeliveryPolicyEditDto |
GET GetDropdownList/{findBy}?onlyActive=true | NotificationDeliveryPolicies.View | route + query | NotificationDeliveryPolicyViewListDto[] |
POST Create | NotificationDeliveryPolicies.Create | NotificationDeliveryPolicyEditDto | Guid |
PUT Update/{id} | NotificationDeliveryPolicies.Edit | NotificationDeliveryPolicyEditDto | Guid |
DELETE Delete?restore= | NotificationDeliveryPolicies.Delete | DeleteDto[] | Guid |
PUT Active | NotificationDeliveryPolicies.Active | DeleteDto[] | Guid |
PUT Deactive | NotificationDeliveryPolicies.Deactive | DeleteDto[] | 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)
| Channel | MaxRetries | Strategy | InitialDelay | MaxDelay |
|---|---|---|---|---|
| 5 | ExponentialBackoff | 60s | 3600s | |
| 3 | ExponentialBackoff | 30s | 1800s | |
| SMS | 3 | Fixed | 60s | 300s |
| Push | 5 | ExponentialBackoff | 15s | 900s |
| SignalR | 2 | Linear | 10s | 60s |
| InApp | 2 | Fixed | 5s | 30s |
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.