ml-connector
Microsoft Dynamics 365 Business CentralMicrosoft Teams

Microsoft Dynamics 365 Business Central and Microsoft Teams integration

Microsoft Dynamics 365 Business Central runs finance, purchasing, and sales. Microsoft Teams is where the people who approve and act on those events already work. Connecting the two turns ERP activity into Teams messages: when a purchase invoice is posted, a vendor is created, or a sales invoice goes out, ml-connector posts a message to the right Teams channel or chat with the key details from Business Central. Teams holds no invoice, purchase order, or GL records, so it serves as a notification and human-in-the-loop approval surface rather than a second copy of the ledger. Both systems authenticate through Microsoft Entra ID, so a single Azure app registration drives both sides.

How Microsoft Dynamics 365 Business Central works

Microsoft Dynamics 365 Business Central exposes vendors, customers, purchase invoices, sales invoices, purchase orders, GL accounts, general ledger entries, dimensions, items, and employees through its REST API v2.0, built on OData v4 against a tenant and environment specific base URL where every company-scoped resource nests under /companies({id})/. It authenticates with OAuth 2.0 client credentials from Microsoft Entra ID using the https://api.businesscentral.dynamics.com/.default scope. It supports push webhooks through a subscription API for entities such as vendors, customers, purchase invoices, and sales invoices, but each subscription expires after 3 days, the notification carries only a change signal and not the changed data, and purchase orders are not webhook-enabled so they need polling.

How Microsoft Teams works

Microsoft Teams has no standalone API; all access goes through the Microsoft Graph REST API at https://graph.microsoft.com/v1.0/, which uses standard HTTP verbs with JSON and OData-style paging. It exposes teams, channels, channel messages, chats, chat messages, and users, and supports writing messages through POST to a channel or chat. For an unattended connector it authenticates with OAuth 2.0 client credentials from Microsoft Entra ID using the https://graph.microsoft.com/.default scope, which requires an Azure AD admin to consent to application permissions such as ChannelMessage.Send and User.Read.All. Teams holds no invoice, purchase order, GL account, or vendor objects, so it is a notification and approval surface, not a finance data source.

What moves between them

The flow runs from Microsoft Dynamics 365 Business Central into Microsoft Teams. ml-connector watches Business Central finance events such as posted purchase invoices, new or changed vendors, sales invoices, and GL-relevant changes, then posts a Teams channel message or chat message that carries the document number, vendor or customer name, amount, and status read from Business Central. Vendor and employee records in Business Central are matched to Teams users so the message can mention or direct message the responsible person. Cadence is event-driven where Business Central webhooks are enabled, with a scheduled poll covering purchase orders and any window a webhook missed. Teams holds no ledger data, so nothing financial is written back from Teams into Business Central.

How ml-connector handles it

ml-connector stores one set of Microsoft Entra ID client credentials and requests two tokens from the same Azure app: one for the https://api.businesscentral.dynamics.com/.default scope and one for the https://graph.microsoft.com/.default scope, refreshing each roughly hourly token before it expires. On the Business Central side it builds the base URL from the tenant and environment name and reads the changed document after a notification arrives, because Business Central webhook payloads are change signals only and never include the record. Those subscriptions expire after 3 days, so a cron job renews them before expiry and re-runs the mandatory validationToken handshake, and the connector verifies the clientState shared secret on every notification since neither Business Central nor Graph sends an HMAC signature. Purchase orders are not webhook-enabled, so they are polled with $filter=lastModifiedDateTime gt to catch only new changes. On the Teams side it resolves the target team and channel, maps Business Central vendors and employees to Graph users by email, and posts the message. Graph exposes no idempotency key, so ml-connector dedupes on the Business Central document number plus a BullMQ jobId to avoid posting the same alert twice when a document is re-read. Throttling is handled by honoring the Retry-After header on HTTP 429 from Graph and backing off on Business Central 429s, and every message carries a full audit trail with replay if a post fails.

A real-world example

A mid-sized construction supplier with about 200 staff runs Microsoft Dynamics 365 Business Central for accounts payable and sales, and the whole back office lives in Microsoft Teams all day. Before the integration, the AP lead checked Business Central by hand for newly posted vendor invoices, then pasted details into a Teams chat to ask a manager for sign-off, which meant high-value bills sometimes sat for a day before anyone noticed. With Business Central and Teams connected, each posted purchase invoice fires a message into the approvals channel within the polling and webhook window, carrying the vendor, amount, due date, and status straight from Business Central, and the manager is mentioned directly. Approvals happen in minutes where they used to take a day, and no one has to watch the ERP for new work.

What you can do

  • Post Microsoft Dynamics 365 Business Central finance events into Microsoft Teams channels and chats as readable messages.
  • Carry document number, vendor or customer, amount, due date, and status from Business Central into each Teams message.
  • Map Business Central vendors and employees to Teams users by email for direct mentions and chat messages.
  • Drive both systems from one Microsoft Entra ID app, with separate Business Central and Graph .default scope tokens.
  • Renew 3-day Business Central subscriptions, re-read the changed document, and dedupe on document number with retries and a full audit trail.

Questions

Which direction does data move between Microsoft Dynamics 365 Business Central and Microsoft Teams?
The flow is one-way, from Business Central into Teams. Finance events such as posted purchase invoices, new vendors, and sales invoices are read from Business Central and posted as messages into Teams channels or chats. Microsoft Teams holds no invoice, purchase order, or GL records, so it acts as a notification and approval surface and nothing financial is written back into Business Central.
Do the two systems share authentication?
Yes. Both Microsoft Dynamics 365 Business Central and Microsoft Teams authenticate through Microsoft Entra ID using OAuth 2.0 client credentials, so a single Azure app registration drives both sides. ml-connector requests one token for the Business Central .default scope and a separate token for the Microsoft Graph .default scope, since each API has its own scope and consented application permissions.
How does the integration know when something changed in Business Central?
ml-connector subscribes to Business Central webhooks for supported entities like purchase invoices, vendors, and sales invoices, but those notifications carry only a change signal, so it re-reads the document from the API before composing the Teams message. Subscriptions expire after 3 days, so a cron job renews them and re-runs the validationToken handshake. Purchase orders are not webhook-enabled, so they are polled on a schedule using a lastModifiedDateTime filter.

Related integrations

Connect Microsoft Dynamics 365 Business Central and Microsoft Teams

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

Get started