Microsoft Dynamics 365 Business Central and Expensify integration
Microsoft Dynamics 365 Business Central runs your finance and chart of accounts. Expensify runs employee expense capture, approvals, and corporate card reconciliation. Connecting the two moves approved expense reports out of Expensify and into the Business Central general ledger without re-keying. Employees, GL account codes, and accounting dimensions stay aligned across both systems so every expense lands on a valid account. ml-connector handles the very different APIs on each side and runs the sync on a schedule you control.
What moves between them
The main flow runs from Expensify into Microsoft Dynamics 365 Business Central. ml-connector polls Expensify on a schedule for newly approved expense reports, then posts each one into Business Central as a draft purchase invoice or as journal lines against the mapped GL accounts, allocated to the right dimensions. Employee records flow from Business Central into Expensify so the connector provisions and de-provisions staff into the correct policies with their approver chains. Reference data is aligned so Business Central GL accounts populate the Expensify categoryGLCodeMap and Business Central dimensions map to Expensify tags. Business Central GL accounts and ledger entries are read-only, so ml-connector reads them for mapping but never writes ledger entries back into Expensify. Cadence is poll-driven, typically every 15 to 60 minutes for expenses, with employee and reference syncs on a slower schedule.
How ml-connector handles it
ml-connector stores both credential sets encrypted. On the Business Central side it requests a fresh Microsoft Entra ID bearer token, refreshing on a 401, and builds the base URL from the stored environmentName and company. On the Expensify side it sends the static partnerUserID and partnerUserSecret inline in the job description on every call. Because Expensify offers no push webhooks, the connector polls with approvedAfter set to the last processed timestamp, then calls the markAsExported onReceive action so the same report is not ingested twice; expense amounts arrive in cents and are converted on the way in. Each Expensify category resolves to a Business Central GL account through the categoryGLCodeMap, and each tag resolves to a dimension, so posted lines reference accounts and dimensions that already exist. Posting is two steps in Business Central: create the draft purchase invoice, then call Microsoft.NAV.post to commit it. Employee provisioning matches on the stable Expensify employeeID so an email change updates the existing record rather than creating a duplicate, and a domain group update requires a non-null domainGroupID on every employee in the batch. Expensify rate limits at 20 requests per minute and Business Central at 600 per environment, so the connector backs off and retries on 429, and every record carries a full audit trail and can be replayed if a downstream call fails.
A real-world example
A 250-person professional services firm runs Microsoft Dynamics 365 Business Central for finance and uses Expensify for travel and card expenses across three offices. Before the integration, an accountant exported approved reports from Expensify each week, hand-keyed the totals into Business Central as purchase invoices, and re-typed the GL code for every category, which produced miscoded lines and a slow month-end close. With the two systems connected, each approved report flows into Business Central as a draft invoice with category-to-account and tag-to-dimension mapping already applied, then posts automatically. New hires provisioned in Business Central appear in the right Expensify policy with their manager as approver, and the weekly re-keying step is gone.
What you can do
- Post approved Expensify expense reports into Microsoft Dynamics 365 Business Central as draft purchase invoices, then commit them with the post action.
- Map each Expensify category to a Business Central GL account and each tag to a dimension so every line lands on a valid account.
- Provision and de-provision Business Central employees into Expensify policies with their approver chains, matched on a stable employee ID.
- Poll Expensify for newly approved reports on a schedule, marking each as exported to prevent duplicate ingestion.
- Bridge Expensify static partner credentials with the rotating Microsoft Entra ID token, backing off and retrying on rate limits with a full audit trail.
Questions
- Which direction does data move between Microsoft Dynamics 365 Business Central and Expensify?
- Approved expense reports move from Expensify into Business Central, where they post as draft purchase invoices or journal lines against the mapped GL accounts. Employees move the other way, from Business Central into Expensify policies. Business Central GL accounts and ledger entries are read-only, so ml-connector reads them for mapping but never writes ledger entries back into Expensify.
- How does the integration handle Expensify having no webhooks or sandbox?
- Expensify is pull-only with no push notifications, so ml-connector polls the Integration Server endpoint on a schedule, using approvedAfter to fetch only newly approved reports since the last run. After a successful ingest it calls the markAsExported action so the same report is not processed twice. Because Expensify has no sandbox, testing uses a dedicated test policy in a separate account to avoid touching production data.
- How are Expensify expense categories matched to Business Central accounts?
- Expensify stores GL codes as a categoryGLCodeMap on each policy, and tags act as accounting dimensions such as project or department. ml-connector maps each category to a Business Central GL account and each tag to a Business Central dimension, so posted lines reference accounts and dimensions that already exist. Amounts arrive from Expensify in cents and are converted before posting.
Related integrations
More Microsoft Dynamics 365 Business Central integrations
Other systems that connect to Expensify
Connect Microsoft Dynamics 365 Business Central and Expensify
Free to use. Add your credentials, ping your real systems, and see if we fit.
Get started