Implementing Business Events in D365FO

Implementing Business Events in D365FO​

Business Events in Dynamics 365 Finance and Operations (D365FO) provide a powerful, event-driven integration mechanism that allows external systems to react to business processes in near real time. They enable D365FO to publish meaningful business signals, such as order confirmations or approvals.

In this article, we’ll explore:

  • What Business Events are and when to use them

  • How are they triggered in D365FO

  • How to implement a custom Business Event using X++

  • How to consume Business Events using Azure Logic Apps

  • Real-world integration considerations and best practices

This guide is written for D365FO developers, architects, and technical decision-makers looking to build scalable, modern integrations.

What Are Business Events in D365FO?

Business Events allow D365FO to notify external systems when specific business processes or user actions occur. These events can then be consumed by services such as:

  • Microsoft Power Automate

  • Azure Logic Apps

  • Azure Service Bus

  • Azure Event Grid

This enables event-driven integrations, reducing the need for polling, batch jobs, or custom APIs.

Examples of Business Event Triggers :

Business events can be raised from:

  • Workflow-based actions

    • Approving a purchase requisition

    • Approving a vendor invoice

  • Non-workflow business processes

    • Confirming a sales order

    • Posting a packing slip

    • Posting an invoice

Both types can generate Business Events that downstream systems can react to immediately.

⚠️ Important: To consume Business Events, customers must have valid subscriptions to Azure services or Power Platform components such as Logic Apps or Power Automate.

Out-of-the-Box vs Custom Business Events

D365FO provides several Business Events out of the box, especially around workflows and core processes. However, real-world projects often require:

  • Publishing events for custom processes

  • Extending existing processes with additional payload data

  • Aligning events with specific integration contracts

In these cases, custom Business Events must be implemented using X++.

How Business Events Are Implemented in D365FO

At a high level, implementing a Business Event involves three steps:

  1. Build the Business Event contract

  2. Build the Business Event class

  3. Trigger the event from a business process

Technically, this requires implementing two core classes and extending the relevant business process.

Step 1: Business Event Class (Event Definition)

The Business Event class:

  • Extends BusinessEventsBase

  • Defines metadata (name, description, module)

  • Builds and sends the payload

Example: Packing Slip Posted Business Event


[BusinessEvents(classStr(FTDPackingSlipBusinessEventContract),
    'Packing Slip Posted BE',
    'Triggered when packing slip is posted',
    ModuleAxapta::SalesOrder)]
public final class FTDPackSlipPostedBusinessEvent extends BusinessEventsBase
{
    private SalesTable salesTable;

    private SalesTable parmSalesTable(SalesTable _salesTable = salesTable)
    {
        salesTable = _salesTable;
        return salesTable;
    }

    public static FTDPackSlipPostedBusinessEvent newFromSalesTable(SalesTable _salesTable)
    {
        FTDPackSlipPostedBusinessEvent businessEvent = new FTDPackSlipPostedBusinessEvent();
        businessEvent.parmSalesTable(_salesTable);
        return businessEvent;
    }

    private void new()
    {
    }

    [Wrappable(true), Replaceable(true)]
    public BusinessEventsContract buildContract()
    {
        return FTDPackingSlipBusinessEventContract::newFromSalesTable(salesTable);
    }
}

Key Architectural Notes

  • BusinessEventsBase handles publishing and lifecycle management

  • The [BusinessEvents] attribute registers the event in D365FO

  • buildContract() defines the payload structure

Step 2: Business Event Contract (Payload Definition)

The contract:

  • Extends BusinessEventsContract

  • Defines the event payload

  • Is serialized and sent to external systems

Example: Packing Slip Business Event Contract

[DataContract]
public final class FTDPackingSlipBusinessEventContract extends BusinessEventsContract
{
    private SalesIdBase          salesId;
    private LegalEntityDataAreaId legalEntity;
    private String50             salesStatus;

    public static FTDPackingSlipBusinessEventContract newFromSalesTable(SalesTable _salesTable)
    {
        var contract = new FTDPackingSlipBusinessEventContract();
        contract.initialize(_salesTable);
        return contract;
    }

    private void new()
    {
    }

    private void initialize(SalesTable _salesTable)
    {
        salesId     = _salesTable.SalesId;
        salesStatus = enum2Symbol(enumNum(SalesStatus), _salesTable.SalesStatus);
    }

    [DataMember('SalesOrderId'), BusinessEventsDataMember("@AccountsReceivable:SalesOrderId")]
    public SalesIdBase parmSaleOrderId(SalesIdBase _salesId = salesId)
    {
        salesId = _salesId;
        return salesId;
    }

    [DataMember('SalesStatus'), BusinessEventsDataMember("@AccountsReceivable:SalesStatus")]
    public String50 parmSalesStatus(String50 _salesStatus = salesStatus)
    {
        salesStatus = _salesStatus;
        return salesStatus;
    }

    [DataMember('LegalEntity'), BusinessEventsDataMember("@AccountsReceivable:LegalEntity")]
    public LegalEntityDataAreaId parmLegalEntity(LegalEntityDataAreaId _legalEntity = legalEntity)
    {
        legalEntity = _legalEntity;
        return legalEntity;
    }
}

Best Practices for Contracts

  • Keep payloads small and meaningful

  • Avoid sensitive data unless strictly required

  • Use stable identifiers (e.g., SalesId, RecId)

  • Treat contracts as public APIs

Step 3: Trigger the Business Event from the Business Process

The final step is extending the relevant business logic and sending the event at the correct point in the process.

Example: Extend Packing Slip Posting

[ExtensionOf(classStr(SalesPackingSlipJournalPost))]
public final class FTDSalesPackingSlipJournalPost_Extension
{
    protected void endPost()
    {
        next endPost();

        if (chainFormLetterContract.parmVersioningUpdateType() == VersioningUpdateType::Initial)
        {
            FTDPackSlipPostedBusinessEvent::newFromSalesTable(salesTable).send();
        }
    }
}

Why This Matters

  • Ensures the event is sent only after successful posting

  • Prevents duplicate or invalid messages

  • Aligns with D365FO extensibility best practices

Consuming Business Events Using Azure Logic Apps

One of the most common and powerful patterns is consuming D365FO Business Events in Azure Logic Apps.

High-Level Integration Flow

  1. D365FO publishes a Business Event

  2. Logic App is triggered

  3. Payload is parsed to JSON

  4. Message is forwarded to Azure services (Queue, Service Bus, Event Grid)

Step-by-Step: Logic App Configuration

1. Create a Logic App

  • Go to Azure Portal → Logic Apps → Create

  • Select subscription, resource group, and region

  • Choose Consumption or Standard based on scale needs

2. Add the Business Event Trigger

  • Open Logic App Designer

  • Search for “When a business event occurs”

  • Configure:

    • D365FO environment

    • Legal entity

    • Business Event name (your custom event)

3. Parse JSON Payload

  • Add Parse JSON action

  • Use the trigger body as content

  • Generate schema using a sample payload from D365FO

4. Store the Message in Azure Queue

  • Add Put a message on a queue

  • Select:

    • Azure Storage Account

    • Target Queue

  • Use parsed JSON as message content

This pattern is ideal for decoupled, scalable integrations.

Logic App Configuration​

Testing and Troubleshooting

To test the integration:

  1. Execute the business process in D365FO (e.g., post packing slip)

  2. Check Logic App Run History

  3. Validate payload structure and queue message

  4. Monitor failures and retries in Azure

Final Thoughts: Why Business Events Matter

Business Events are a strategic integration feature in D365FO:

  • Promote event-driven architecture

  • Reduce tight coupling

  • Improve responsiveness

  • Align perfectly with Azure-native services

For customers and partners building modern D365FO solutions, Business Events are no longer optional; they are a best practice.

Share this post

Found this useful? Help others discover it.

Leave a Comment

Your email address will not be published. Required fields are marked *