ml-connector
Microsoft Dynamics 365 F&OMicrosoft Teams

Microsoft Dynamics 365 F&O and Microsoft Teams integration

Microsoft Dynamics 365 F&O runs financials, procurement, and supply chain. Microsoft Teams is where the same staff already work, so it is the natural place to see and act on finance events. Connecting the two means a posted vendor invoice, a confirmed purchase order, or a workflow step awaiting approval shows up as a message in the right Teams channel instead of sitting in an inbox or going unseen. Because Teams holds no invoice, PO, or GL records, it is treated as a notification and approval surface, and Dynamics stays the system of record. ml-connector listens for Dynamics Business Events and posts them into Teams, fetching the full detail over OData because the event itself carries only identifiers.

How Microsoft Dynamics 365 F&O works

Microsoft Dynamics 365 F&O exposes vendors, vendor invoices, purchase orders, customers, main accounts, and general journal entries through an OData v4 REST API at a tenant-specific host such as contoso.operations.dynamics.com/data. It authenticates with OAuth 2.0 client credentials issued by Microsoft Entra ID against an environment-scoped resource. For outbound push it uses the Business Events framework, where an admin activates events like vendor invoice posted, purchase order confirmed, or workflow step completed and routes them to an HTTPS endpoint. Each event payload is a lightweight stub with a BusinessEventId, a ControlNumber for deduplication, and the legal entity, so the full record is retrieved with a follow-up OData call. Reads that are not event-driven are done by polling OData.

How Microsoft Teams works

Microsoft Teams has no standalone API; all programmatic access goes through the Microsoft Graph REST API at graph.microsoft.com/v1.0 over HTTPS and JSON. It authenticates with OAuth 2.0 client credentials from Microsoft Entra ID using the scope graph.microsoft.com/.default, and the application permissions, including ChannelMessage.Send, must be granted by an admin. The relevant entities are teams, channels, users, and chatMessage, which is used to post notifications and adaptive cards into a channel or a direct chat. Teams is a communications platform, not an ERP, so it exposes no invoice, purchase order, vendor, or GL objects. Graph supports change notifications by subscription for inbound triggers such as a reply on an approval card.

What moves between them

The flow runs from Microsoft Dynamics 365 F&O into Microsoft Teams. As Dynamics emits Business Events for posted vendor invoices, confirmed purchase orders, posted payments, and completed workflow steps, ml-connector posts a corresponding message or adaptive card into the mapped Teams channel, with the full invoice or PO detail read back over OData and rendered on the card. User records from Graph are read to map a Dynamics approver or vendor contact to a Teams user for an @mention or a direct chat. No financial records move back into Dynamics, because Teams holds none; the only return path is an approval reply captured from a channel that can act as a trigger.

How ml-connector handles it

ml-connector stores both credential sets encrypted and requests a separate Entra ID client-credentials token for each side, one scoped to the Dynamics environment host and one to graph.microsoft.com/.default, so a single identity model is bridged to two scopes and each token is refreshed on expiry. Dynamics Business Events are received on an HTTPS endpoint that has no signature header, so the endpoint is locked to HTTPS with TLS 1.2 and the BusinessEventId and ControlNumber are validated, with the ControlNumber used as the dedup key because delivery order is not guaranteed and the same event can arrive twice. Since the event payload is only a stub, the connector calls back to OData for the full record, honoring the legal entity scope with cross-company where multiple entities exist. The record is mapped to an adaptive card and posted with ChannelMessage.Send to the channel configured for that event type. Graph throttles with HTTP 429 and a Retry-After header, which the connector honors with backoff; Dynamics service protection returns 429 the same way on OData reads. Where an inbound Graph subscription is used for approval replies, the connector renews it before its three-day expiry and verifies the clientState on every notification.

A real-world example

A mid-sized distributor with about 400 staff runs Microsoft Dynamics 365 F&O for purchasing and accounts payable, and the whole company already lives in Microsoft Teams. Before the integration, buyers and approvers had to open Dynamics and hunt through the workflow queue to learn that a purchase order was confirmed or an invoice was waiting on a sign-off, so approvals stalled for days and vendors chased for status. With Microsoft Dynamics 365 F&O and Microsoft Teams connected, every confirmed PO and every invoice pending approval drops into the procurement channel as an adaptive card with the vendor, amount, and document number pulled live from OData. Approvers see the event the moment it fires, the right person is @mentioned, and the bottleneck of people not knowing there was anything to act on disappears.

What you can do

  • Post Microsoft Dynamics 365 F&O Business Events such as invoice posted and PO confirmed into Teams channels as adaptive cards.
  • Read the full Dynamics record over OData and render it on the card, since the event payload carries only identifiers.
  • Map Dynamics approvers and vendor contacts to Teams users for @mentions and direct chat notifications.
  • Bridge one Microsoft Entra ID identity to a Dynamics environment scope and a Microsoft Graph scope, refreshing each token on expiry.
  • Deduplicate on the Business Event ControlNumber and honor Retry-After backoff so notifications post once with a full audit trail.

Questions

Which direction does data move between Microsoft Dynamics 365 F&O and Microsoft Teams?
The flow is Dynamics into Teams. Business Events for invoices, purchase orders, payments, and workflow steps move from Microsoft Dynamics 365 F&O into Microsoft Teams as channel messages and adaptive cards. Teams has no invoice, PO, or GL objects, so no financial records move back, and Dynamics stays the system of record. The only return path is an approval reply on a card, which can act as a trigger.
How does the integration authenticate to both systems?
Both sides use OAuth 2.0 client credentials from Microsoft Entra ID, so the connector bridges one identity model to two scopes. One token is scoped to the Dynamics environment host for OData, and a separate token uses the graph.microsoft.com/.default scope for Teams. The Graph application permissions, including ChannelMessage.Send, must be granted by an admin, and the connector refreshes each token on expiry.
Why does the connector call back to Dynamics after a Business Event fires?
Dynamics Business Event payloads are lightweight stubs that carry only a BusinessEventId, a ControlNumber, and the legal entity, not the full record. ml-connector uses the ControlNumber to deduplicate, since delivery order is not guaranteed and an event can arrive twice, then calls back to the OData API to retrieve the full invoice or PO detail before it builds the Teams card.

Related integrations

Connect Microsoft Dynamics 365 F&O and Microsoft Teams

Free to use. Add your credentials, ping your real systems, and see if we fit.

Get started