# Business Central Integration Events: How to Publish and Subscribe in AL

> Source: https://netray.co/erp-help/business-central-integration-event-publisher-subscriber-al
> Publisher: Netray (netray.co), AI and integration engineering for ERP and manufacturing systems.
> Section: ERP Help

## 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.

## Kind

how-to

## System

dynamics

## Erp

Microsoft Dynamics 365 Business Central

## Module

AL development / events

## Query

business central integration event

## Alternate Queries

- business central integration event example
- how to subscribe to an event in business central al
- IntegrationEvent attribute business central
- business central EventSubscriber attribute

## 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.

## Steps

### Subscribe to an existing integration event

**Items:**

Find 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).

Create 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.

Add a procedure with the EventSubscriber attribute giving object type, object, event name, element name (empty for non-field events), SkipOnMissingLicense and SkipOnMissingPermission.

Copy 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.

Keep the subscriber short. Put real logic in a separate codeunit so the subscriber stays a thin hook.

Publish 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.

If it never fires, check that the publisher name is spelled exactly, the extension is installed on the tenant or company, and no ManualBinding applies.

## Sections

### Declaring a publisher and a subscriber

**Body:**

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.

**Code:**

// 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

**Body:**

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

**Body:**

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

**Body:**

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.

**Code:**

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);

## 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.

## Ai Angle

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.

## Faq

### What is the difference between an integration event and a business event?

**Answer:** 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?

**Answer:** 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?

**Answer:** 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?

**Answer:** 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.

## Search terms

business central integration event, IntegrationEvent attribute, EventSubscriber AL, business central events, IsHandled pattern, AL event publisher, BindSubscription, Event Recorder business central, business central business event, AL extension events

---
Talk to an engineer: https://netray.co/contact?intent=erp_ai | Machine catalog: https://netray.co/agent/catalog.json
