Business Central Integration Events: How to Publish and Subscribe in AL
business central integration event
Also searched as
- business central integration event example
- how to subscribe to an event in business central al
- IntegrationEvent attribute business central
- business central EventSubscriber attribute
Short answer
An integration event is a procedure marked with the IntegrationEvent attribute that has an empty body. Code elsewhere subscribes to it with the EventSubscriber attribute, so extensions can change standard behavior without modifying base objects. You publish with IntegrationEvent, subscribe with EventSubscriber, and pass var parameters when the subscriber needs to alter data.
Applies to: Business Central online and on-premises, AL extensions (v2 extension model). Event signatures change between releases, always check the symbols of your target version.
Subscribe to an existing integration event
- 1Find the event. In VS Code, use the AL Explorer or search the base app symbols for procedures marked IntegrationEvent, usually named OnBefore... or OnAfter... on the codeunit you want to influence (for example the sales posting codeunit).
- 2Create a codeunit in your extension to hold subscribers. Subscribers can live in any codeunit, and a dedicated codeunit per feature keeps them easy to find.
- 3Add a procedure with the EventSubscriber attribute giving object type, object, event name, element name (empty for non-field events), SkipOnMissingLicense and SkipOnMissingPermission.
- 4Copy the parameter list from the publisher. Names must match the publisher parameter names, and you may omit trailing parameters you do not need. Add var where you intend to change the value.
- 5Keep the subscriber short. Put real logic in a separate codeunit so the subscriber stays a thin hook.
- 6Publish and test with the standard process (post a document, run a batch job) and use the debugger with a breakpoint in the subscriber to confirm it fires.
- 7If it never fires, check that the publisher name is spelled exactly, the extension is installed on the tenant or company, and no ManualBinding applies.
Declaring a publisher and a subscriber
A publisher is a procedure whose body is empty. The attribute takes two booleans: IncludeSender (pass the publishing object instance to subscribers, only meaningful for codeunits, tables and pages with an instance) and GlobalVarAccess (let subscribers read the publisher's global variables). Both should normally be false, because exposing globals ties subscribers to your internals.
A subscriber is any procedure carrying the EventSubscriber attribute. The compiler checks that the target event exists and that parameter names and types line up. Subscribers run synchronously inside the publisher's transaction, so an error in the subscriber rolls back the whole operation the user was doing.
// Publisher in your own codeunit
codeunit 50100 "Order Check Mgt"
{
procedure CheckOrder(var SalesHeader: Record "Sales Header")
var
IsHandled: Boolean;
begin
OnBeforeCheckOrder(SalesHeader, IsHandled);
if IsHandled then
exit;
// default behavior here
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeCheckOrder(var SalesHeader: Record "Sales Header"; var IsHandled: Boolean)
begin
end;
}// Subscriber in another extension
codeunit 50101 "My Order Subscribers"
{
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Order Check Mgt", 'OnBeforeCheckOrder', '', false, false)]
local procedure HandleOnBeforeCheckOrder(var SalesHeader: Record "Sales Header"; var IsHandled: Boolean)
begin
if SalesHeader."Sell-to Customer No." = 'CASH' then
IsHandled := true;
end;
}IsHandled, var parameters and what subscribers may change
Most Microsoft publishers follow the IsHandled pattern: an OnBefore event receives a Boolean by var. If any subscriber sets it to true, the base code skips its default logic and uses what the subscriber produced. This is the closest thing AL has to overriding a procedure, and it is why the same event may be called by several subscribers from different apps. Do not assume yours runs first or alone.
Parameters passed by var can be modified, parameters passed by value cannot. Record parameters passed by var are the live record, so changing a field changes what the base code later posts or modifies. Always check whether the base code calls Modify afterward, otherwise your change exists only in memory.
Order between subscribers from different extensions is not guaranteed. If two apps both set IsHandled or change the same field, the result depends on load order, so document that in the extension and keep subscribers idempotent.
Integration events vs business events vs internal events
IntegrationEvent is for other AL extensions. BusinessEvent is for external consumers (Power Automate, Power Apps and similar), is treated as a contract that must stay stable, and should not be used to alter behavior. InternalEvent is visible only inside the same extension and is useful for decoupling your own modules without exposing a public surface.
Because integration events are a public contract, Microsoft and good ISVs avoid changing their signatures, but it does happen between major versions. When a publisher is removed or its parameters change, subscribers fail to compile or stop firing after the upgrade, which is a common cause of broken extensions on a new release.
For events on fields and triggers, the standard OnAfterValidateEvent and OnBeforeValidateEvent subscribers (with the field name as element name) are database triggers, not integration events. They work the same way to subscribe to, but they fire only when the field is validated in code or the UI, not on direct assignment.
Manual binding and the Event Recorder
Set EventSubscriberInstance = Manual on the subscriber codeunit and the subscribers fire only after you call BindSubscription, and stop after UnbindSubscription. This is the right tool when a subscriber should be active only during one operation, such as one import run, because it avoids global side effects on every user and every posting.
To discover which events fire during a process you do not know, use the Event Recorder page, start recording, perform the action in the client, stop, and read the list of events with the calling object. It is the fastest way to find the right OnBefore or OnAfter hook for a business process without reading the base code line by line.
codeunit 50102 "Import Subscribers"
{
EventSubscriberInstance = Manual;
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Order Check Mgt", 'OnBeforeCheckOrder', '', false, false)]
local procedure Skip(var SalesHeader: Record "Sales Header"; var IsHandled: Boolean)
begin
IsHandled := true;
end;
}
// Caller
ImportSubs: Codeunit "Import Subscribers";
BindSubscription(ImportSubs);
// ... run import ...
UnbindSubscription(ImportSubs);Try it here, free
Business Central AL Extension Skeleton Generator
Fill in publisher, prefix and ID range to get app.json, a table extension, a page extension, an event subscriber codeunit and a permission set.
Common pitfalls
- !Putting heavy logic or a Commit inside a subscriber. It runs inside the caller's transaction and can break posting or leave partial data.
- !Relying on the order in which subscribers from different extensions run. It is not guaranteed.
- !Subscribing to a standard event and forgetting that the signature can change in the next major version. Pin and test against the preview before upgrading.
- !Changing a record in a by-value parameter and expecting the base code to see it. Only var parameters flow back.
- !Using IncludeSender or GlobalVarAccess true in your own publishers, which locks subscribers to your internal state.
- !Subscribing to a table trigger event and expecting it to fire for direct field assignment. Validate events fire only on Validate.
How an ERP-grounded AI assistant handles this
Finding the right event is mostly reading source and symbols. A private model that has indexed your extension code and the base app symbols (kept on your own servers for an on-prem Business Central) can suggest candidate OnBefore and OnAfter events, draft the subscriber, and flag signature differences between versions. It produces code for a developer to review and test in a sandbox, it does not deploy anything on its own.
Frequently asked questions
What is the difference between an integration event and a business event?
An integration event lets other AL extensions hook into code and can pass var parameters to change behavior. A business event is meant for external systems such as Power Automate, is treated as a stable contract, and should not change behavior in the publisher. Use integration events for extensibility and business events for outbound notifications.
Can an event subscriber stop the base code from running?
Only if the publisher supports it, usually through an IsHandled Boolean passed by var. If the subscriber sets it to true, the base code skips its default path. Without such a parameter a subscriber can raise an Error to abort, but it cannot silently skip the logic.
Why is my event subscriber not firing?
Typical causes are a misspelled event or object name, the extension not being installed for that company or environment, a Manual subscriber codeunit that was never bound, or the code path not actually raising the event. Put a breakpoint in the publisher and confirm the publishing procedure is reached.
Do events work the same in SaaS and on-premises?
Yes, the extension model is the same. The difference is deployment and which events your target version exposes. Online tenants move to new versions on Microsoft's schedule, so event signatures can change under you sooner than on an on-premises server you upgrade deliberately.
Related
Calling and extending the Business Central API v2.0
The Business Central API v2.0 is a REST/OData endpoint at api.businesscentral.dynamics.com/v2.0/{tenant}/{environment}/api/v2.0, authenticated with Azure AD OAuth 2.0. It exposes standard entities like customers and items, and lets you publish your own with an AL API page.
Error fixFixing "You do not have the following permissions on TableData (table): (permission)" in Business Central AL
This runtime error means the current user's assigned permission sets do not grant the required Insert, Modify, Delete, Read, or Execute right on that specific table. It is most common right after installing or updating a custom AL extension, because Business Central checks object-level permissions even for tables an extension owns.
How-toHow to call an external REST API from AL in Business Central
Use the HttpClient, HttpRequestMessage, HttpResponseMessage and HttpContent types in AL, send the request with Send, check IsSuccessStatusCode, and parse the body with JsonObject.ReadFrom. Make sure the extension has Allow HttpClient Requests turned on, and keep tokens out of source code. Keep calls short, because they run inside the AL session.
Error fixBusiness Central Error Messages: What They Mean and How Errors Are Handled
Most Business Central errors come from a few AL patterns: TestField and FieldError for missing or invalid field values, Error for rule violations, and permission or locking messages from the platform. Developers can customize them with Error and ErrorInfo, collect many errors at once, or catch them with TryFunction. If the whole service is unreachable, check service health and environment state first.
Error fixFixing "Cannot create a record in (table). The record already exists" in D365 F&SCM data entity imports
This is the standard kernel duplicate-key exception, thrown when the Data Management Framework tries to insert a staging row into a target table whose unique or alternate key already matches an existing record. It almost always means the entity's insert-vs-update logic did not recognize the target row as an update, not that you have a true accidental duplicate in your source file.
Error fixFixing "There are currently no batch servers available for processing" in D365 F&SCM
This message means the batch framework cannot find any AOS instance flagged as a batch server and available for the batch group the job is assigned to. The fix is almost always in server configuration (System administration > Servers) or batch group assignment, not in the batch job itself.
AI for ERPAI for Dynamics 365 Business Central, on-premises or SaaS, beyond Copilot
AI for Business Central beyond Copilot: grounded question answering over BC's data via OData and APIs, for on-premises and SaaS tenants alike.
Stuck on Microsoft Dynamics 365 Business Central?
Talk to engineers who work inside Microsoft Dynamics 365 Business Central every week, and who build private AI that answers these questions from your own ERP data.
Keep exploring
Free tools
- Business Central AL Extension Skeleton GeneratorFill in publisher, prefix and ID range to get app.json, a table extension, a page extension, an event subscriber codeunit and a permission set.
- Business Central AL Event Subscriber GeneratorBuilds an AL subscriber codeunit for any published event, with the correct attribute syntax and a procedure stub to fill in.
- Business Central On-Premises Extension Deploy PowerShell GeneratorCreates the PowerShell sequence to publish, sync, install or upgrade a Business Central extension on an on-premises server instance.
ERP fixes and how-tos
- Adding a Private AI Layer to Business Central On-PremisesAdd AI to Business Central on-prem without cloud: API v2.0, custom API pages, SQL replica, retrieval, local LLM, BC permission sets, approved write-back.
- How to call an external REST API from AL in Business CentralCall an external REST API from Business Central AL with HttpClient: JSON request, headers, bearer token, error handling, the Allow HttpClient Requests setting.
- Business Central Item Table (27), Table 6507 and Temporary Tables in ALBusiness Central Item table (27), related item tracking tables such as 6507, and how temporary tables work in AL: syntax, behavior and common mistakes.
AI on your ERP
- AI for Business Central manufacturing operations, beyond CopilotAI for Business Central manufacturing beyond Copilot: grounded answers on production orders, routings, and capacity via APIs v2.0, on-prem capable.
- AI for Dynamics 365 Business Central in Discrete ManufacturingGrounded AI for Dynamics 365 Business Central discrete manufacturers: production orders, planning worksheets, routings and costing, on a private LLM.
Integrations
- How to add WhatsApp to Microsoft Dynamics 365 Business CentralHow to connect WhatsApp to Dynamics 365 Business Central: API v2.0 or custom API pages, webhooks, template messages, and two-way replies that post back safely.
- How to add AI agents to Dynamics 365 Business CentralHow to add AI agents to Dynamics 365 Business Central: API v2.0 and custom API pages as the tool layer, approval gates, SaaS vs on-prem, and build options.
Software
- Microsoft Dynamics 365 Business CentralDynamics 365 Business Central explained for manufacturers: modules, APIs, AL extensions, deployment, strengths, limits and alternatives for small and mid-size firms.
- Microsoft Dynamics 365 Finance and Supply ChainDynamics 365 Finance and Supply Chain Management explained for manufacturers: modules, data entities, OData, deployment, strengths, limits and alternatives.