Business Central (Part 8)

Neil Haddley β€’ December 18, 2025

External Business Events

Business CentralMicrosoft Dynamicsexternal-business-eventsal-languageintegrationbusiness-central

project files

TEXT
1businesscentralbusinessevents/
2β”œβ”€β”€ .vscode/
3β”œβ”€β”€ .alpackages/
4β”œβ”€β”€ .snapshots/
5β”œβ”€β”€ app.json
6β”œβ”€β”€ EventCategoryExt.enumext.al
7β”œβ”€β”€ JobManagerAssigned.codeunit.al
8β”œβ”€β”€ UserSetupsAPI.page.al
9└── Neil Haddley_businesscentralbusinessevents_1.0.0.0.app

ExternalBusinessEvent Attribute

The [ExternalBusinessEvent] decorator attribute in Business Central enables developers to expose custom business events that can be consumed by external systems. This attribute marks a business event as available for external integration through the Business Central API.

Key Characteristics
  • External Integration: Events are exposed through the Business Central API and can be subscribed to by external applications
  • Real-time Notifications: Provides near real-time event notifications to external systems
I updated the Project Manager

I updated the Project Manager

External Business Event Code ran

External Business Event Code ran

Flow ran successfully

Flow ran successfully

Under the hood: Two small pieces work together

One procedure declares the event, and a second procedure subscribes to the Project Manager field's OnAfterValidate event on the Job table. When the field changes, the subscriber raises the external event with the job's id, number, description, the user's id and the user's email. A flow on the outside then receives it, which is what the last two screenshots show.

EventCategoryExt.enumext.al

AL
1enumextension 50100 EventCategoryExt extends EventCategory
2{
3    value(50100; Jobs)
4    {
5        Caption = 'Jobs';
6    }
7}

JobManagerAssigned.codeunit.al

AL
1codeunit 50100 JobManagerAssigned
2{
3    [ExternalBusinessEvent('ProjectManagerAssigned', 'Project Manager Assigned', 'Event raised when a project manager is assigned to a job', EventCategory::Jobs)]
4    local procedure ProjectManagerAssigned(JobId: Guid; NoCode: Code[20];Description: Text[100]; UserSetupId: Guid; UserEmail: Text[100])
5    begin
6    end;
7
8    [EventSubscriber(ObjectType::Table, Database::Job, 'OnAfterValidateEvent', 'Project Manager', false, false)]
9    local procedure JobOnAfterValidateProjectManager(var Rec: Record Job; var xRec: Record Job;CurrFieldNo: Integer)
10    var
11        UserSetupRec: Record "User Setup";
12    begin
13        if Rec."Project Manager" <> xRec."Project Manager" then begin
14            if Rec."Project Manager" <> '' then begin
15                if UserSetupRec.Get(Rec."Project Manager") then begin
16                    ProjectManagerAssigned(Rec.SystemId, Rec."No.", Rec.Description, UserSetupRec.SystemId, UserSetupRec."E-Mail");
17                end;
18            end;
19        end;
20    end;
21}

UserSetupsAPI.page.al

AL
1page 50101 "User Setups API"
2{
3    PageType = API;
4    APIPublisher = 'neilhaddley';
5    APIGroup = 'admin';
6    APIVersion = 'v1.0';
7    EntityName = 'userSetup';
8    EntitySetName = 'userSetups';
9    SourceTable = "User Setup";
10    DelayedInsert = true;
11    ODataKeyFields = SystemId;
12
13    layout
14    {
15        area(Content)
16        {
17            repeater(GroupName)
18            {
19                field(id; Rec.SystemId)
20                {
21                    Caption = 'Id';
22                    Editable = false;
23                }
24                field(userId; Rec."User ID")
25                {
26                    Caption = 'User ID';
27                }
28                field(salesPersonCode; Rec."Salespers./Purch. Code")
29                {
30                    Caption = 'Salesperson Code';
31                }
32                field(allowPostingFrom; Rec."Allow Posting From")
33                {
34                    Caption = 'Allow Posting From';
35                }
36                field(allowPostingTo; Rec."Allow Posting To")
37                {
38                    Caption = 'Allow Posting To';
39                }
40                field(registerTime; Rec."Register Time")
41                {
42                    Caption = 'Register Time';
43                }
44                field(email; Rec."E-Mail")
45                {
46                    Caption = 'Email';
47                }
48            }
49        }
50    }
51}

Part of the Business Central series

✍️ This is the latest part β€” more may follow