9.11 Notification Delivery Receipts
Controller: NotificationDeliveryReceiptController · Route: api/v1/NotificationDeliveryReceipt ·
GroupName: notifications.receipts · 5 endpoints, all read-only. Delivery receipts capture
provider-reported, asynchronous delivery status — distinct from the synchronous ChannelDeliveryResult
recorded at dispatch time. Today this is populated exclusively by the WhatsApp inbound webhook (Meta
delivery-status callbacks); it is not a general outbound webhook-subscription feature — see
§9.11.3.
| Verb + route | Permission | Request | Response (data) |
|---|---|---|---|
POST GetDataTable | NotificationReceipts.ViewAll | DtParameters | DtResult<NotificationDeliveryReceiptDto> (unwrapped) |
GET GetDetails/{id} | NotificationReceipts.View | — | NotificationDeliveryReceiptDetailsDto |
GET GetByProviderMessageId/{providerMessageId} | NotificationReceipts.View | route | NotificationDeliveryReceiptDto[] |
GET GetSummary?from=&to= | NotificationReceipts.View | query DateTime? | NotificationReceiptSummaryDto |
GET GetTimeline?from=&to= | NotificationReceipts.View | query DateTime? | NotificationReceiptTimelineDto[] |
PermissionConstants.NotificationReceipts.Export is defined but not referenced by any action here —
likely reserved for a future export/download endpoint.
9.11.1 How a receipt gets created — inbound webhook, not this controller
There is no POST/PUT action on this controller — receipts are never created through this API surface.
They are written by the existing WhatsAppWebhookController (outside this controller, part of the WhatsApp
integration surface), which:
- Validates the Meta webhook signature (HMAC-SHA256 against
WhatsAppCloudApi.AppSecret). - Runs its pre-existing
ProcessWebhookStatusAsynclogic (unchanged). - Additionally (added later, try/catch-isolated so a receipt-mapping bug can never break webhook
processing) calls
INotificationDeliveryReceiptService.UpsertAsyncto record/update aNotificationDeliveryReceiptrow viaWhatsAppMetaReceiptMapper(INotificationReceiptMapper).
GET GetDetails/{id} — response shape
{
"succeeded": true,
"message": null,
"data": {
"id": "5b6c7d80-0000-0000-0000-000000000001",
"notificationId": "8b1e2f40-0000-0000-0000-000000000002",
"deliveryAttemptId": "6c7d8e90-0000-0000-0000-000000000001",
"campaignId": null,
"campaignStepId": null,
"providerName": "MetaWhatsApp",
"providerMessageId": "wamid.HBgLOTY2NTQ5MDAwMTkxFQIAERgSNzc4RUY2QjM3RjM4RjM4RjM4AA==",
"channel": 6,
"recipient": "966549000191",
"eventKey": "PurchaseInvoicePosted",
"receiptStatus": 2,
"providerStatus": "delivered",
"providerErrorCode": null,
"providerErrorMessage": null,
"receivedOn": "2026-07-04T09:13:40Z",
"providerTimestamp": "2026-07-04T09:13:38Z",
"correlationId": "corr-9f1a2b3c",
"createdBy": "System",
"createdOn": "2026-07-04T09:13:40Z"
}
}
receiptStatus (NotificationReceiptStatus): Unknown=0, Sent=1, Delivered=2, Read=3, Opened=4, Clicked=5, Failed=6, Rejected=7, Expired=8, Bounced=9, Unsubscribed=10.
GET GetSummary
{
"succeeded": true,
"message": null,
"data": {
"totalReceipts": 4200,
"totalSent": 4200,
"totalDelivered": 4110,
"totalRead": 3502,
"totalOpened": 0,
"totalClicked": 0,
"totalFailed": 90,
"totalBounced": 0,
"totalRejected": 0,
"deliveryRate": 97.86,
"readRate": 83.38,
"clickRate": 0,
"failureRate": 2.14,
"dateFrom": "2026-06-27T00:00:00Z",
"dateTo": "2026-07-04T23:59:59Z",
"byChannel": [
{ "channel": 6, "totalReceipts": 4200, "totalSent": 4200, "totalDelivered": 4110, "totalRead": 3502, "totalFailed": 90, "deliveryRate": 97.86, "readRate": 83.38 }
]
}
}
9.11.3 Inbound vs outbound — what this is not
This is not an outbound webhook-subscription feature (i.e. Shumoul does not let customers register a URL to be called when a delivery status changes). "Webhook" here means exclusively the inbound Meta → Shumoul provider callback. Email/SMS/Push provider delivery-status webhooks are documented as future extension points in earlier phase reports, but no controller exists for them today — do not represent them as implemented.
Angular: a delivery-receipts drill-down view, typically linked from a specific NotificationDeliveryAttempt
or campaign step via GetByProviderMessageId.
Related APIs: Analytics, Campaigns,
Chapter 7 § WhatsApp.