ml-connector
Microsoft Dynamics 365 Business CentralBILL

Microsoft Dynamics 365 Business Central and BILL integration

Microsoft Dynamics 365 Business Central runs finance, purchasing, and the general ledger. BILL runs accounts payable: bill capture, approval routing, and vendor payment by check, ACH, or virtual card. Connecting the two keeps the vendor master and chart of accounts aligned across both systems and moves approved purchase invoices into BILL for payment without re-keying. Once BILL pays a bill, the payment detail posts back into Business Central as a vendor payment journal line applied to the matching invoice. ml-connector handles the very different authentication on each side and uses BILL webhooks to react as soon as a payment settles.

How Microsoft Dynamics 365 Business Central works

Microsoft Dynamics 365 Business Central exposes vendors, purchase invoices, purchase orders, GL accounts, general ledger entries, dimensions, and payment journals through the Business Central API v2.0, a REST API built on OData v4 with JSON payloads. Authentication uses Microsoft Entra ID OAuth 2.0 client credentials in the service-to-service flow, scoped to a tenant and a named environment such as production, so the base URL is tenant-specific. The chart of accounts and general ledger entries are read-only, while vendors and purchase invoices support writes; a purchase invoice is created as a draft and posted with the Microsoft.NAV.post bound action. Business Central can push change notifications by subscription, but a notification carries no record data and subscriptions expire every three days, so finance records are read by polling with a lastModifiedDateTime filter for delta sync.

How BILL works

BILL exposes its data through the BILL API Platform v3, a REST API over JSON. It is not OAuth: a call to the login endpoint with a developer key plus the org email, password, and organization ID returns a session token that is sent on every subsequent request, and a standard session expires after 35 minutes of inactivity. The API covers vendors, bills (AP invoices), payments, customers, invoices, and a writable chart of accounts, plus accounting classifications such as departments, locations, and jobs for line-item tagging. Purchase orders are not supported in BILL, which is by design since BILL is AP and AR focused and POs live in the ERP. BILL pushes events such as bill.created, bill.updated, and payment.updated by webhook, signed HMAC-SHA256 in the x-bill-sha-signature header.

What moves between them

The flow runs in both directions, split by system of record. From Microsoft Dynamics 365 Business Central into BILL, ml-connector pushes vendor master records and approved purchase invoices as BILL vendors and bills, mapping each Business Central GL account and dimension to the BILL chart of accounts and accounting classifications so every bill line is coded correctly. From BILL back into Business Central, ml-connector reads payment records after BILL pays a bill and records them as vendor payment journal lines applied to the matching vendor and invoice. Vendors flow before bills, because BILL cannot accept a bill for a payee that does not exist yet. Purchase orders stay in Business Central, since BILL has no purchase order object, and the Business Central chart of accounts stays the source of truth.

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, scopes every call to the tenant and the configured environment name, and refreshes the token before expiry. On the BILL side it logs in with the developer key and org credentials to get a session token, and because BILL returns a plain auth error rather than a clear expiry code, it treats any 401 as a signal to re-login and retry the call. Vendors and GL accounts are synced first, because BILL cannot code or pay a bill against a payee or account that does not exist; each Business Central dimension maps to a BILL classification (department, location, or job). The write-back is event-driven: ml-connector subscribes to BILL bill and payment webhooks, verifies the HMAC-SHA256 signature in x-bill-sha-signature against the minified JSON body before processing, and posts the payment into Business Central. Because a BILL subscription auto-disables after repeated delivery failures and its security key is shown only once at creation, ml-connector stores that key immediately, monitors subscription health, and falls back to polling BILL on a schedule so nothing is missed. Neither system offers an idempotency-key header, so ml-connector dedupes on the BILL bill or payment ID and a BullMQ jobId before posting to Business Central. BILL allows only three concurrent calls per org, so requests are queued rather than fanned out, and Business Central returns HTTP 429 when throttled, so the connector backs off with jitter. Every record carries a full audit trail and can be replayed if a downstream call fails.

A real-world example

A mid-market professional services firm with roughly 200 employees runs Microsoft Dynamics 365 Business Central for finance and the general ledger and uses BILL to capture and pay its vendor invoices. Before the integration, the AP team re-keyed vendor details and GL coding from Business Central into BILL by hand, then typed each payment back into the ledger after BILL cut the check or sent the ACH, which slowed month-end close and let vendor records drift apart between the two systems. With Microsoft Dynamics 365 Business Central and BILL connected, vendors and GL accounts stay aligned automatically, approved purchase invoices land in BILL as bills coded to the right accounts, and each payment posts back into Business Central as a vendor payment journal line applied to the right invoice the moment the BILL webhook fires. The manual re-keying step disappears and the AP ledger reconciles against both systems.

What you can do

  • Push Microsoft Dynamics 365 Business Central vendor records into BILL so every bill is coded against a valid payee.
  • Send approved Business Central purchase invoices into BILL as payable bills, with GL accounts and dimensions mapped to the BILL chart of accounts and classifications.
  • Record BILL payments back into Business Central as vendor payment journal lines applied to the right invoice.
  • Bridge Microsoft Entra ID OAuth 2.0 client credentials on the ERP side and the BILL session token, re-logging in automatically on a 401.
  • Trigger the write-back from BILL bill and payment webhooks verified by HMAC-SHA256, with polling fallback, dedup, retries, and a full audit trail.

Questions

Which direction does data move between Microsoft Dynamics 365 Business Central and BILL?
It moves both ways, split by system of record. Vendor records and approved purchase invoices push from Business Central into BILL as vendors and bills, with GL accounts and dimensions mapped to the BILL chart of accounts and classifications. Payment detail is pulled back from BILL into Business Central as vendor payment journal lines applied to the matching invoice. Purchase orders stay in Business Central because BILL has no purchase order object, and the Business Central chart of accounts stays authoritative.
How does the integration handle BILL session tokens versus Business Central OAuth?
ml-connector stores both credential sets encrypted and presents the right one to each system. Business Central uses Microsoft Entra ID OAuth 2.0 client credentials scoped to the tenant and a named environment, and the connector refreshes that token before it expires. BILL uses a session token from a developer-key login that expires after about 35 minutes of inactivity, and because BILL signals expiry only as a generic auth error, the connector treats any 401 as a cue to re-login and retry.
Does BILL push events, or does ml-connector poll for payment status?
BILL supports both, and ml-connector uses webhooks as the primary trigger. It subscribes to BILL bill and payment events and verifies the HMAC-SHA256 signature in the x-bill-sha-signature header before acting. Because a BILL subscription auto-disables after repeated delivery failures, the connector monitors subscription health and falls back to scheduled polling so no payment is missed. On the Business Central side, change notifications carry no payload and expire every three days, so finance records are read by polling with a lastModifiedDateTime filter.

Related integrations

Connect Microsoft Dynamics 365 Business Central and BILL

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

Get started