title: User Message Types audience: developer keywords: notification, user, send, read, count, thread, message, Cloud Events Note

locale: en-us

User Message Types

Parent Document: API_Reference.md Implementation Folder: app/src/Message Type/Implementations/Notification/


Overview

User message types provide in-app notification capabilities for Cloud Events integrations. Notifications are stored in the Cloud Events Note table and scoped to individual users. Features include:

All read operations are automatically filtered to the current user (caller identity) via FilterGroup(2).

Message Type List

Message TypeDirectionPurpose
User.Notification.CountOutboundGet total, unread, and read notification counts
User.Notification.GetOutboundRetrieve paginated list of notifications
User.Notification.ReadInboundMark notifications as read or unread
User.Notification.SendInboundSend a new notification to a user
User.Notification.ThreadOutboundRetrieve all notifications in a thread
Email.Draft.SetInboundCreate an email draft in outbox (HTML + attachments, no send)

Common Notification Record Structure

All outbound message types return notification records with this JSON structure:

FieldTypeDescription
entryNoIntegerUnique entry number
threadIdGUIDThread identifier for grouped conversations
parentEntryNoIntegerParent notification entry number (0 if root)
recipientUserIdCode[50]Recipient user ID
senderUserIdCode[50]Sender user ID
relatedTableIdIntegerRelated BC table ID (0 if none)
relatedRecordSystemIdGUIDRelated BC record SystemId
approvalEntryNoIntegerRelated approval entry number (0 if none)
subjectText[250]Notification subject line
bodyTextNotification body text (from Blob field)
isReadBooleanWhether the notification has been read
sourceEntrySystemIdGUIDSystemId of the source notification entry
systemIdGUIDSystemId of the notification record
systemCreatedAtDateTimeWhen the notification was created
systemModifiedAtDateTimeWhen the notification was last modified
notificationTypeTextNotification type enum name

Table Reference

Table: Cloud Events Note (65327)

No.NameTypeIn PK
1Entry No.IntegerYes
2Thread IDGUIDNo
3Parent Entry No.IntegerNo
4Recipient User IDCode[50]No
5Sender User IDCode[50]No
6Related Table IDIntegerNo
7Related Record SystemIdGUIDNo
8Approval Entry No.IntegerNo
9SubjectText[250]No
10BodyBlob (UTF-8 text)No
11Is ReadBooleanNo
12Notification TypeEnumNo

Access Rules


User.Notification.Count

Direction: Outbound (Response to request)

Purpose: Returns the total, unread, and read notification counts for the current user.

Request Format

{
  "specversion": "1.0",
  "type": "User.Notification.Count",
  "source": "MyApp v1.0"
}

Request Data Parameters

No request data parameters. No subject or data body is required.

Response Format

FieldTypeDescription
statusString"Success" or "Error"
totalIntegerTotal notifications for the current user
unreadIntegerUnread notifications (Is Read = false)
readIntegerRead notifications (Is Read = true)

Example Response

{
  "status": "Success",
  "total": 25,
  "unread": 10,
  "read": 15
}

Notes


User.Notification.Get

Direction: Outbound (Response to request)

Purpose: Retrieves a paginated list of notifications for the current user. Supports skip/take paging and optional table view filtering.

Request Format

{
  "specversion": "1.0",
  "type": "User.Notification.Get",
  "source": "MyApp v1.0",
  "data": "{\"skip\":0,\"take\":20}"
}

Request Data Parameters

ParameterTypeRequiredDescription
skipIntegerNoNumber of records to skip. Default: 0.
takeIntegerNoMaximum records to return. Default: 50.
tableViewStringNoBC table view filter expression.

Example — Filter unread only

{
  "skip": 0,
  "take": 10,
  "tableView": "WHERE(Is Read=CONST(No))"
}

Response Format

FieldTypeDescription
statusString"Success" or "Error"
noOfRecordsIntegerTotal records matching filters
resultArrayArray of notification objects (see Common Structure)

Example Response

{
  "status": "Success",
  "noOfRecords": 2,
  "result": [
    {
      "entryNo": 1,
      "threadId": "00000000-0000-0000-0000-000000000000",
      "parentEntryNo": 0,
      "recipientUserId": "ADMIN",
      "senderUserId": "SYSTEM",
      "relatedTableId": 0,
      "relatedRecordSystemId": "00000000-0000-0000-0000-000000000000",
      "approvalEntryNo": 0,
      "subject": "New order received",
      "body": "Sales order SO-1001 has been created.",
      "isRead": false,
      "sourceEntrySystemId": "00000000-0000-0000-0000-000000000000",
      "systemId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "systemCreatedAt": "2024-01-15T10:30:00Z",
      "systemModifiedAt": "2024-01-15T10:30:00Z",
      "notificationType": "Message"
    }
  ]
}

Notes


User.Notification.Read

Direction: Inbound (Write operation)

Purpose: Marks one or more notifications as read or unread for the current user. Only modifies records where the read status actually changes.

Request Format

{
  "specversion": "1.0",
  "type": "User.Notification.Read",
  "source": "MyApp v1.0",
  "data": "{\"entryNos\":[5,8,12]}"
}

Request Data Parameters

ParameterTypeRequiredDescription
entryNosInteger[]YesArray of notification entry numbers to mark
isReadBooleanNoTarget read status. Default: true

Example — Mark as unread

{
  "entryNos": [5],
  "isRead": false
}

Response Format

FieldTypeDescription
statusString"Success" or "Error"
noOfRecordsIntegerNumber of records that were actually modified
resultArrayArray of modified notification objects (see Common Structure)

Example Response

{
  "status": "Success",
  "noOfRecords": 2,
  "result": [
    {
      "entryNo": 5,
      "threadId": "00000000-0000-0000-0000-000000000000",
      "parentEntryNo": 0,
      "recipientUserId": "ADMIN",
      "senderUserId": "SYSTEM",
      "relatedTableId": 0,
      "relatedRecordSystemId": "00000000-0000-0000-0000-000000000000",
      "approvalEntryNo": 0,
      "subject": "Approval required",
      "body": "Purchase order PO-2001 requires your approval.",
      "isRead": true,
      "sourceEntrySystemId": "00000000-0000-0000-0000-000000000000",
      "systemId": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
      "systemCreatedAt": "2024-01-15T09:00:00Z",
      "systemModifiedAt": "2024-01-15T11:45:00Z",
      "notificationType": "Approval"
    }
  ]
}

Error Response

{
  "status": "Error",
  "error": "Missing required field 'entryNos' (array of integers) in request."
}

Notes


User.Notification.Send

Direction: Inbound (Write operation)

Purpose: Sends a new notification to a specified user. The sender is automatically set to the current user (caller identity). Supports threading via threadId and parentEntryNo.

Request Format

{
  "specversion": "1.0",
  "type": "User.Notification.Send",
  "source": "MyApp v1.0",
  "data": "{\"recipientUserId\":\"JOHN\",\"subject\":\"Task completed\",\"body\":\"The report has been generated.\"}"
}

Request Data Parameters

ParameterTypeRequiredDescription
recipientUserIdTextYesUser ID of the recipient
subjectTextYesNotification subject line
bodyTextNoNotification body text
threadIdGUIDNoThread identifier to group related notifications
parentEntryNoIntegerNoParent notification entry number. Required if threadId is set
relatedTableIdIntegerNoTable ID of the related BC record
relatedRecordSystemIdGUIDNoSystemId of the related BC record
notificationTypeTextNoNotification type enum name (e.g., "Approval")

Example — Threaded notification with related record

{
  "recipientUserId": "JOHN",
  "subject": "Approval required",
  "body": "PO-2001 needs your approval.",
  "threadId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "parentEntryNo": 10,
  "relatedTableId": 38,
  "relatedRecordSystemId": "c4d5e6f7-a8b9-0123-cdef-456789012345",
  "notificationType": "Approval"
}

Response Format

Returns the created notification record:

FieldTypeDescription
statusString"Success" or "Error"
noOfRecordsIntegerAlways 1 on success
resultArrayArray containing the created notification object (see Common Structure)

Example Response

{
  "status": "Success",
  "noOfRecords": 1,
  "result": [
    {
      "entryNo": 15,
      "threadId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "parentEntryNo": 10,
      "recipientUserId": "JOHN",
      "senderUserId": "ADMIN",
      "relatedTableId": 38,
      "relatedRecordSystemId": "c4d5e6f7-a8b9-0123-cdef-456789012345",
      "approvalEntryNo": 0,
      "subject": "Purchase order PO-2001 requires approval",
      "body": "Please review and approve purchase order PO-2001 for vendor 10000.",
      "isRead": false,
      "sourceEntrySystemId": "00000000-0000-0000-0000-000000000000",
      "systemId": "d5e6f7a8-b9c0-1234-def0-567890123456",
      "systemCreatedAt": "2024-01-15T14:30:00Z",
      "systemModifiedAt": "2024-01-15T14:30:00Z",
      "notificationType": "Approval"
    }
  ]
}

Error Responses

{
  "status": "Error",
  "error": "Missing required field 'recipientUserId' in request."
}
{
  "status": "Error",
  "error": "Missing required field 'parentEntryNo' when 'threadId' is specified."
}

Notes


User.Notification.Thread

Direction: Outbound (Read operation)

Purpose: Retrieves all notifications belonging to a specific thread. The current user must be a recipient of at least one notification in the thread.

Request Format

{
  "specversion": "1.0",
  "type": "User.Notification.Thread",
  "source": "NotificationUI v3.0",
  "subject": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

Request Parameters

ParameterTypeRequiredDescription
subjectGUIDYesThread ID as a GUID string
skipIntegerNoNumber of records to skip. Default: 0.
takeIntegerNoMaximum records to return. Default: all.

Example — Thread with paging

{
  "specversion": "1.0",
  "type": "User.Notification.Thread",
  "source": "NotificationUI v3.0",
  "subject": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "data": "{\"skip\":0,\"take\":10}"
}

Response Format

FieldTypeDescription
statusString"Success" or "Error"
noOfRecordsIntegerTotal records in the thread
resultArrayArray of notification objects (see Common Structure)

Example Response

{
  "status": "Success",
  "noOfRecords": 2,
  "result": [
    {
      "entryNo": 10,
      "threadId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "parentEntryNo": 0,
      "recipientUserId": "JOHN",
      "senderUserId": "ADMIN",
      "relatedTableId": 38,
      "relatedRecordSystemId": "c4d5e6f7-a8b9-0123-cdef-456789012345",
      "approvalEntryNo": 0,
      "subject": "Purchase order PO-2001 requires approval",
      "body": "Please review and approve.",
      "isRead": true,
      "sourceEntrySystemId": "00000000-0000-0000-0000-000000000000",
      "systemId": "d5e6f7a8-b9c0-1234-def0-567890123456",
      "systemCreatedAt": "2024-01-15T09:00:00Z",
      "systemModifiedAt": "2024-01-15T10:00:00Z",
      "notificationType": "Approval"
    },
    {
      "entryNo": 12,
      "threadId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "parentEntryNo": 10,
      "recipientUserId": "ADMIN",
      "senderUserId": "JOHN",
      "relatedTableId": 38,
      "relatedRecordSystemId": "c4d5e6f7-a8b9-0123-cdef-456789012345",
      "approvalEntryNo": 0,
      "subject": "Re: Purchase order PO-2001",
      "body": "Approved. Looks good.",
      "isRead": false,
      "sourceEntrySystemId": "00000000-0000-0000-0000-000000000000",
      "systemId": "e6f7a8b9-c0d1-2345-ef01-678901234567",
      "systemCreatedAt": "2024-01-15T10:15:00Z",
      "systemModifiedAt": "2024-01-15T10:15:00Z",
      "notificationType": "Approval"
    }
  ]
}

Error Responses

{
  "status": "Error",
  "error": "The subject must contain the Thread ID (GUID) to retrieve."
}
{
  "status": "Error",
  "error": "No notifications found for the specified Thread ID and current user."
}

Notes


Email.Draft.Set

Direction: Inbound (Write operation)

Purpose: Creates an email draft in Business Central outbox without sending it. Supports HTML body and URL-based attachments.

Request Format

{
  "specversion": "1.0",
  "type": "Email.Draft.Set",
  "source": "MyApp v1.0",
  "data": "{\"to\":[\"buyer@contoso.com\"],\"subject\":\"PO 1005\",\"htmlBody\":\"<p>Please review.</p>\",\"relatedTableId\":38,\"attachments\":[{\"fileName\":\"spec.pdf\",\"contentType\":\"application/pdf\",\"url\":\"https://example.com/spec.pdf\"}]}"
}

Request Data Parameters

ParameterTypeRequiredDescription
toText or Text[]YesRecipient email address(es). Supports ;/, delimited string or array.
subjectTextYesEmail subject line.
htmlBodyTextNoHTML body content.
bodyTextNoFallback body when htmlBody is omitted.
ccText or Text[]NoCC recipient email address(es).
bccText or Text[]NoBCC recipient email address(es).
emailScenarioTextNoExplicit Email Scenario enum name.
relatedTableIdIntegerNoUsed for best-guess scenario selection when emailScenario is omitted.
attachmentsObject[]NoURL-based attachments. Each object requires fileName + (url or contentUrl).

Response Format

FieldTypeDescription
statusString"Success" or "Error"
messageIdGUIDDraft email message ID
outboxSystemIdGUIDSystemId of created Email Outbox entry
outboxUrlStringWeb client URL to open the created outbox draft/card context
emailScenarioResolvedStringResolved Email Scenario name from request/context

Example Response

{
  "status": "Success",
  "messageId": "d8f0f4d7-2f8b-4a4c-90e2-9f5c2d9d0f42",
  "outboxSystemId": "26d55e6d-8b76-4d96-9f8c-2fb0fcf7e6a5",
  "outboxUrl": "https://businesscentral...",
  "emailScenarioResolved": "Purchasing"
}

Scenario Resolution

Resolution order:

  1. Explicit emailScenario from request
  2. Best-guess from relatedTableId
  3. Default
  4. First available enum value in Email Scenario

Notes


Webhook Notifications

For asynchronous processing (Queue API), subscribe to External Business Events:

Webhook payload: { MessageId, MessageType: "User.Notification.*", ResponseContentLink, Timestamp }

Use ResponseContentLink to directly download the response, or use MessageId to fetch via Data API. See Events_and_Webhooks.md for setup.


© Origo – Cloud Events Base Extension