Microsoft Dynamics 365 Business Central and Coupa integration
Microsoft Dynamics 365 Business Central runs your finance, accounts payable, and general ledger. Coupa runs procurement and the supplier-facing invoice approval workflow. Connecting the two means an invoice that suppliers submit and your buyers approve in Coupa lands in Business Central accounts payable without re-keying, matched to its purchase order and vendor. Approved supplier invoices and purchase orders flow from Coupa into Business Central as draft purchase invoices and purchase orders, and once Business Central posts and pays them the paid status returns to Coupa so buyers see settlement. ml-connector handles the different auth and APIs on each side and moves records on a schedule you control.
What moves between them
The main flow runs from Coupa into Microsoft Dynamics 365 Business Central. ml-connector reads approved supplier invoices from Coupa and posts them into Business Central as purchase invoices against the matching vendor, carrying the vendor reference, currency, amounts, and line detail, and it brings Coupa purchase orders into Business Central as purchase orders so receipts and bills can match. Suppliers are aligned so every Coupa invoice resolves to an existing Business Central vendor, and GL accounts and dimensions are mapped so each line codes to a valid account and cost dimension. After Business Central posts and pays a purchase invoice, the paid status returns to Coupa as a supplier invoice payment so buyers see settlement. Business Central stays the system of record for AP and the general ledger, so ml-connector posts financial documents only into Business Central and never writes GL entries into Coupa.
How ml-connector handles it
ml-connector stores both credential sets encrypted. On the Business Central side it requests an Entra ID OAuth 2.0 client-credentials token for the api.businesscentral.dynamics.com/.default scope, builds the base URL from the configured tenant and environment name, scopes every call under the right company, and refreshes the token before expiry. On the Coupa side it requests a client-credentials token from the instance oauth2/token endpoint, caches it per instance and client until shortly before expiry, refreshes once on a 401, and sends the X-Coupa-API-Version header on every call. It reads the Coupa invoices endpoint filtered to approved status so unapproved documents never reach AP. Suppliers, GL accounts, and dimensions are mapped first so each invoice posts to an existing vendor and valid account. A Coupa invoice arrives as a draft purchase invoice in Business Central, then the Microsoft.NAV.post bound action posts it, since a plain POST never auto-posts. Inbound Coupa webhooks are accepted only after the X-Coupa-Signature HMAC is verified, and because Business Central notifications carry no data and purchaseOrders is not webhook-supported, the connector polls Business Central on lastModifiedDateTime with a stored high-water mark and pages through @odata.nextLink continuation tokens. Business Central has no idempotency-key header, so ml-connector dedupes on the vendor and document number plus a BullMQ jobId, while Coupa rate-limits with HTTP 429 and Business Central caps at 600 requests per minute and returns 429 when throttled, so ml-connector backs off with jitter and retries, and every record carries a full audit trail and can be replayed if a downstream call fails.
A real-world example
A mid-sized facilities services company with roughly 400 employees runs Microsoft Dynamics 365 Business Central for finance and accounts payable and uses Coupa for procurement and invoice approvals across several regional branches. Before the integration, the AP team pulled approved invoices out of Coupa and keyed them into Business Central as draft purchase invoices one by one, then later went back into Coupa to mark which ones had been paid, which delayed month-end close and left suppliers asking about payment status. With Microsoft Dynamics 365 Business Central and Coupa connected, each approved Coupa invoice posts into Business Central AP automatically against its vendor and purchase order, gets posted through the Microsoft.NAV.post action, and the paid status flows back to Coupa once Business Central settles the payment. The double entry is gone, invoices reach the ledger the same day they clear approval, and buyers see settlement without asking AP.
What you can do
- Post approved Coupa supplier invoices into Microsoft Dynamics 365 Business Central as purchase invoices against the matching vendor and purchase order.
- Bring Coupa purchase orders into Business Central so receipts and bills can match against them.
- Return Business Central purchase invoice payment status to Coupa as supplier invoice payments so buyers see settlement.
- Keep Coupa suppliers aligned with Business Central vendors and map GL accounts and dimensions so each line codes to a valid account.
- Bridge Coupa OAuth client-credentials with Microsoft Entra ID client credentials, verify signed webhooks, and poll with retries and a full audit trail.
Questions
- Which direction does data move between Microsoft Dynamics 365 Business Central and Coupa?
- The main flow is Coupa into Business Central. Approved supplier invoices and purchase orders move from Coupa into Business Central as draft purchase invoices and purchase orders, while paid status returns to Coupa as supplier invoice payments. Business Central stays the system of record for accounts payable and the general ledger, so ml-connector writes financial documents only into Business Central and never posts GL entries into Coupa.
- How does ml-connector handle Coupa OAuth and Business Central authentication?
- It requests an OAuth 2.0 client-credentials token from the Coupa oauth2/token endpoint, caches it per instance until shortly before expiry, refreshes once on a 401, and sends the X-Coupa-API-Version header on every call. On the Business Central side it requests a Microsoft Entra ID client-credentials token for the api.businesscentral.dynamics.com/.default scope and builds the tenant-specific base URL from the stored environment name, since that name is part of the URL and differs per customer. Both tokens are refreshed before expiry.
- Does the integration use webhooks or polling?
- It uses both, matched to each system. ml-connector verifies the X-Coupa-Signature HMAC on inbound Coupa invoice, purchase order, and payment webhooks before acting. Business Central change notifications carry no payload and expire every three days, and purchaseOrders is not webhook-supported, so ml-connector polls Business Central on a lastModifiedDateTime filter with @odata.nextLink paging and dedupes on the document number and a jobId so a retried read never posts a duplicate purchase invoice.
Related integrations
More Microsoft Dynamics 365 Business Central integrations
Other systems that connect to Coupa
Connect Microsoft Dynamics 365 Business Central and Coupa
Free to use. Add your credentials, ping your real systems, and see if we fit.
Get started