9.10 Notification Campaign Execution
Controller: NotificationCampaignExecutionController · Route: api/v1/NotificationCampaignExecution
· GroupName: notifications.campaigns · 4 endpoints · Read-only run history and analytics for a
campaign, plus the ability to cancel an in-flight execution. Every action requires
NotificationCampaigns.Analytics except Cancel, which requires NotificationCampaigns.Cancel.
| Verb + route | Permission | Request | Response (data) |
|---|---|---|---|
POST GetDataTable/{campaignId} | NotificationCampaigns.Analytics | DtParameters + route campaignId | DtResult<NotificationCampaignExecutionDto> (unwrapped) |
GET GetDetails/{id} | NotificationCampaigns.Analytics | — | NotificationCampaignExecutionDto |
GET GetAnalytics/{campaignId} | NotificationCampaigns.Analytics | — | NotificationCampaignAnalyticsSummaryDto[] |
PUT Cancel/{id} | NotificationCampaigns.Cancel | — | Guid |
GET GetDetails/{id} — response shape
{
"succeeded": true,
"message": null,
"data": {
"id": "4a5b6c70-0000-0000-0000-000000000001",
"campaignId": "3c4d5e60-0000-0000-0000-000000000001",
"status": 1,
"scheduledFor": "2026-07-10T06:00:00Z",
"startedAt": "2026-07-10T06:00:03Z",
"completedAt": null,
"totalRecipients": 842,
"totalDispatched": 610,
"totalSucceeded": 598,
"totalFailed": 12,
"correlationId": "campaign-exec-7f8e9d",
"errorMessage": null
}
}
status (CampaignExecutionStatus): Pending=0, Running=1, Succeeded=2, Failed=3, Skipped=4, Cancelled=5.
Business notes: NotificationCampaignExecution rows are claimed by the campaign worker via a
WorkerToken (Guid?, added by migration 20260703205850_Add_NotificationCampaignExecution_WorkerToken as
part of the platform's Background Jobs Framework per-row-claiming pattern) — the same atomic-claim technique
used by the notification retry queue, preventing two concurrent worker instances from double-processing the
same execution.
GET GetAnalytics/{campaignId}
Aggregates every execution and step-execution for a campaign into a per-step summary:
{
"succeeded": true,
"message": null,
"data": [
{ "stepNumber": 1, "channel": 1, "totalDispatched": 842, "totalSucceeded": 830, "totalFailed": 12, "deliveryRate": 98.57 },
{ "stepNumber": 2, "channel": 6, "totalDispatched": 610, "totalSucceeded": 598, "totalFailed": 12, "deliveryRate": 98.03 }
]
}
Angular: the campaign detail page's "Runs" tab — GetDataTable/{campaignId} for a history grid,
GetAnalytics/{campaignId} for a per-step funnel chart.
Backend: campaign-workflow-executor-pipeline Hangfire job advances NotificationCampaignStepExecution
rows; NotificationCampaignExecution.TotalDispatched/Succeeded/Failed are updated incrementally as each
recipient's dispatch resolves.
Related APIs: Campaigns, Analytics.