Appearance
Contracts And Payloads
Microtec.Notifications.Contracts is the shared contract package. Use it for payloads, enums, DTOs, metadata keys, and integration events.
Contracts must stay serialization-friendly and backward compatible because they are:
- sent over HTTP
- published through MassTransit
- persisted as JSON in
NotificationRequest.PayloadJson - used by retry deserializers
Base Payload
All channel payloads inherit from NotificationPayload.
csharp
public abstract record NotificationPayload
{
public string? Subdomain { get; set; }
public List<Guid>? UserIds { get; set; }
public NotificationSourceSystem? SourceSystem { get; set; }
public string? ModuleName { get; set; }
public string? ModuleNameAr { get; set; }
public string? ServiceName { get; set; }
public string? ServiceNameAr { get; set; }
public string? NotificationSettingType { get; set; }
public Dictionary<string, string>? Data { get; set; }
}The base type uses JsonDerivedType for:
EmailPayloadSmsPayloadPushPayloadWhatsAppPayload
Do not instantiate NotificationPayload directly. Use a concrete payload.
Common Fields
| Field | Purpose |
|---|---|
Subdomain | Tenant identifier. Required unless SourceSystem is used. |
UserIds | Target users. Required for push, optional for other channels. |
SourceSystem | System sender identity. Allows source-system configs with no tenant subdomain. |
ModuleName, ModuleNameAr | Metadata used by Notification Center filtering and display. |
ServiceName, ServiceNameAr | Metadata used by Notification Center filtering and display. |
NotificationSettingType | Business setting/category key. |
Data | Additional metadata. WhatsApp template data also uses this dictionary. |
Email Payload
csharp
public sealed record EmailPayload(
string Subject,
string Body,
List<string> To,
List<string>? Cc = null,
List<string>? Bcc = null,
NotificationLanguage Language = NotificationLanguage.English,
EmailTemplateData? TemplateData = null,
bool UseSharedLayout = true) : NotificationPayload;Use plain HTML in Body, or supply TemplateData to render a stored template. When UseSharedLayout is true, the rendered body is wrapped in EmailLayoutTemplate for the selected language.
Supported template data types include:
| Type | Template |
|---|---|
VerificationTemplateData | VerificationTemplate |
InvitationTemplateData | InvitationTemplate |
ExistingUserInvitationTemplateData | ExistingUserInvitationTemplate |
InvoiceTemplateData | SendInvoiceTemplate |
OfflineInvoiceTemplateData | AddOfflineInvoiceTemplate |
WorkflowNotificationTemplateData | WorkFlowTemplate |
DeviceRegistrationTemplateData | DeviceRegistration |
MinimumQuantityTemplateData | MinimumQuantityTemplate |
InvoicesPastDueDateTemplateData | InvoicesPastDueDateTemplate |
CustomTemplateData | Selected at runtime |
SMS Payload
csharp
public sealed record SmsPayload(
string Body,
string PhoneNumber,
string RegionCode,
string? Sender = null) : NotificationPayload;The service normalizes PhoneNumber using RegionCode before calling the SMS provider.
Push Payload
csharp
public sealed record PushPayload : NotificationPayload
{
public NotificationContent Content { get; init; }
public PlatformType Platform { get; init; }
public ApplicationTarget ApplicationTarget { get; init; }
public DeliveryOptions? DeliveryOptions { get; init; }
public PushProviders PreferredProvider { get; set; } = PushProviders.FCM;
}NotificationContent contains:
TitleBodyImageUrlCategoryPriorityTitleArBodyArRouteUrl
DeliveryOptions contains:
ScheduledTimeExpireIfOfflineCollapseKeyTagRequireInteraction
Current push sending resolves active and valid DeviceRegistration records by:
- user id
- platform
- application target
WhatsApp Payload
csharp
public sealed record WhatsAppPayload(string PhoneNumber) : NotificationPayload;WhatsApp template sends use reserved metadata keys inside Data:
| Key | Constant | Purpose |
|---|---|---|
__wa_template_name | TemplateNameKey | Local template name to find in WhatsAppTemplate. |
__wa_template_params | TemplateParamsKey | JSON array of ordered template parameter values. |
__wa_tmpl_media_type | TmplMediaTypeKey | Template media header type, for example document. |
__wa_tmpl_media_url | TmplMediaUrlKey | Media URL. |
__wa_tmpl_media_name | TmplMediaNameKey | Media display name. |
EntityId | EntityId | Optional business entity id. |
NotificationEntityType | EntityType | Optional business entity type. |
Prefer NotificationBuilder.WhatsApp() to populate these keys safely.
Integration Events
SendNotificationEvent
csharp
public sealed record SendNotificationEvent(NotificationPayload Payload);This is the queue delivery contract. The Notification service consumes it through NotificationEventConsumer.
WhatsAppDeliveryStatusChangedIntegrationEvent
This event is broadcast when WhatsApp delivery status changes. It contains:
NotificationRequestIdPhoneNumberStatusFailureReasonNotificationEntityTypeEntityId
Important Enums
| Enum | Current values |
|---|---|
NotificationChannelType | PushNotification, Email, SMS, WhatsApp |
DeliveryMode | Http, Queue |
NotificationStatus | Pending, Scheduled, Processing, Sent, Delivered, Failed, Cancelled |
DeliveryStatus | Pending, Sent, Delivered, Failed, Expired, Rejected, Bounced, Opened, Clicked |
EmailProviders | SMTP, AzureGraph |
SmsProviders | GenericHttpSms |
PushProviders | FCM |
WhatsAppProviders | MsegatWhatsApp |
PlatformType | Mobile, Web, All |
ApplicationTarget | ERP, POS, AdminPortal, All |
WhatsAppProvisioningStatus | NotStarted, Queued, Running, WaitingForApproval, Completed, Failed |
Compatibility Rules
When changing contracts:
- Add optional fields instead of renaming or removing existing fields.
- Avoid changing enum numeric values.
- Do not remove
JsonDerivedTypemappings for payloads that may exist in persisted rows or queued messages. - Keep payloads as simple DTOs and records; do not add service behavior or infrastructure dependencies.
- Consider old persisted
PayloadJsonrows when changing constructors or required fields. - Add deserializer tests for retry whenever payload shapes change.