Skip to content

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:

  • EmailPayload
  • SmsPayload
  • PushPayload
  • WhatsAppPayload

Do not instantiate NotificationPayload directly. Use a concrete payload.

Common Fields

FieldPurpose
SubdomainTenant identifier. Required unless SourceSystem is used.
UserIdsTarget users. Required for push, optional for other channels.
SourceSystemSystem sender identity. Allows source-system configs with no tenant subdomain.
ModuleName, ModuleNameArMetadata used by Notification Center filtering and display.
ServiceName, ServiceNameArMetadata used by Notification Center filtering and display.
NotificationSettingTypeBusiness setting/category key.
DataAdditional 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:

TypeTemplate
VerificationTemplateDataVerificationTemplate
InvitationTemplateDataInvitationTemplate
ExistingUserInvitationTemplateDataExistingUserInvitationTemplate
InvoiceTemplateDataSendInvoiceTemplate
OfflineInvoiceTemplateDataAddOfflineInvoiceTemplate
WorkflowNotificationTemplateDataWorkFlowTemplate
DeviceRegistrationTemplateDataDeviceRegistration
MinimumQuantityTemplateDataMinimumQuantityTemplate
InvoicesPastDueDateTemplateDataInvoicesPastDueDateTemplate
CustomTemplateDataSelected 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:

  • Title
  • Body
  • ImageUrl
  • Category
  • Priority
  • TitleAr
  • BodyAr
  • RouteUrl

DeliveryOptions contains:

  • ScheduledTime
  • ExpireIfOffline
  • CollapseKey
  • Tag
  • RequireInteraction

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:

KeyConstantPurpose
__wa_template_nameTemplateNameKeyLocal template name to find in WhatsAppTemplate.
__wa_template_paramsTemplateParamsKeyJSON array of ordered template parameter values.
__wa_tmpl_media_typeTmplMediaTypeKeyTemplate media header type, for example document.
__wa_tmpl_media_urlTmplMediaUrlKeyMedia URL.
__wa_tmpl_media_nameTmplMediaNameKeyMedia display name.
EntityIdEntityIdOptional business entity id.
NotificationEntityTypeEntityTypeOptional 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:

  • NotificationRequestId
  • PhoneNumber
  • Status
  • FailureReason
  • NotificationEntityType
  • EntityId

Important Enums

EnumCurrent values
NotificationChannelTypePushNotification, Email, SMS, WhatsApp
DeliveryModeHttp, Queue
NotificationStatusPending, Scheduled, Processing, Sent, Delivered, Failed, Cancelled
DeliveryStatusPending, Sent, Delivered, Failed, Expired, Rejected, Bounced, Opened, Clicked
EmailProvidersSMTP, AzureGraph
SmsProvidersGenericHttpSms
PushProvidersFCM
WhatsAppProvidersMsegatWhatsApp
PlatformTypeMobile, Web, All
ApplicationTargetERP, POS, AdminPortal, All
WhatsAppProvisioningStatusNotStarted, 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 JsonDerivedType mappings 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 PayloadJson rows when changing constructors or required fields.
  • Add deserializer tests for retry whenever payload shapes change.

Internal Documentation — Microtec