Microsoft Dynamics 365 F&O and Brex integration
Microsoft Dynamics 365 F&O runs financials, procurement, and the general ledger. Brex runs corporate cards, expense management, and bill pay. Connecting the two brings coded card spend into the ledger without re-keying. After Brex finishes coding a transaction, ml-connector posts it into D365 F&O against the correct main account and financial dimensions, and keeps the Brex vendor directory aligned with D365 vendors. Because Brex card and cash transactions are read-only, the connector treats Brex as the spend source and Microsoft Dynamics 365 F&O as the ledger of record.
What moves between them
The main flow runs from Brex into Microsoft Dynamics 365 F&O. ml-connector reads coded accounting records and card transactions from Brex and posts them into D365 F&O as general journal entries or vendor invoices, mapped to the matching main accounts and financial dimensions, then calls Brex back to set export_status to EXPORTED. Vendor records flow the same direction so each Brex bill-pay vendor maps to a real D365 vendor account. Custom fields and Brex GL accounts are aligned with D365 financial dimensions so every posted line lands on a valid combination. Brex transactions are read-only and D365 posted journal entries are not directly writable, so ml-connector never writes ledger postings back into Brex.
How ml-connector handles it
ml-connector stores both credential sets encrypted. On the Brex side it sends the Bearer token on every request and switches between the v2 api.brex.com base and the v1 platform.brexapis.com base depending on the sub-API, since expenses and vendors still use v1. On the D365 side it accepts the tenant environment host per customer, requests an Entra ID client-credentials token scoped to that host, and refreshes it before the roughly one-hour expiry. Brex pushes ACCOUNTING_RECORD_READY_FOR_EXPORT as a Svix-signed webhook, so each event is verified by HMAC-SHA256 over the webhook-id, webhook-timestamp, and raw body before the connector pulls the full record and posts it. Main accounts and financial dimensions are mapped first, so every journal line resolves to a valid D365 combination, and the dimension display string must follow the format configured in D365 for integrating applications. Merchant names from Brex rarely match D365 vendor names exactly, so the connector keeps a fuzzy-match and caching layer. D365 OData has no idempotency key and rejects duplicate natural keys, so ml-connector dedupes on the Brex record id and a BullMQ jobId before posting, and it sets export_status to EXPORTED only after D365 confirms. It honors the Brex Idempotency-Key on any transfer it creates, backs off on HTTP 429 from either side using Retry-After where present, tracks the 90-day Brex token inactivity expiry, and replays any record whose downstream post fails.
A real-world example
A venture-backed software company with about 250 employees runs Microsoft Dynamics 365 F&O for financials and uses Brex for corporate cards and expense management across engineering, sales, and operations. Before the integration, an accountant exported a Brex spend report at the end of each week and keyed the card transactions into the D365 general ledger by hand, guessing at the department and project dimensions and matching merchant names to vendors one at a time. With Microsoft Dynamics 365 F&O and Brex connected, each coded Brex accounting record posts into D365 against the right main account and financial dimensions as soon as it is ready for export, and merchant-to-vendor matching is handled by a cached fuzzy match. The weekly re-keying disappears and month-end close starts with card spend already in the ledger.
What you can do
- Post coded Brex accounting records and card transactions into the Microsoft Dynamics 365 F&O general ledger as journal entries.
- Map Brex GL accounts and custom fields to D365 main accounts and financial dimensions so every line is valid.
- Keep Brex bill-pay vendors aligned with Microsoft Dynamics 365 F&O vendor accounts using a fuzzy merchant match.
- Bridge the Brex Bearer token and the Microsoft Entra ID client-credentials token for the tenant environment host.
- React to the Brex ACCOUNTING_RECORD_READY_FOR_EXPORT webhook, verified by HMAC-SHA256, and mark records exported after posting.
Questions
- Which direction does data move between Microsoft Dynamics 365 F&O and Brex?
- The main flow is Brex into Microsoft Dynamics 365 F&O. Coded accounting records, card transactions, and vendors move from Brex into D365 as journal entries, vendor invoices, and vendor accounts. Brex card and cash transactions are read-only and D365 posted journal entries are not directly writable, so ml-connector treats Brex as the spend source and never writes ledger postings back into it.
- How does the integration react to a Brex transaction being ready to post?
- Brex pushes an ACCOUNTING_RECORD_READY_FOR_EXPORT webhook signed through Svix once it has finished coding a transaction. ml-connector verifies the HMAC-SHA256 signature over the webhook-id, webhook-timestamp, and raw body, then pulls the full accounting record, posts it into D365 F&O, and calls Brex back to set export_status to EXPORTED. A scheduled poll backfills any record a webhook missed.
- How does the integration avoid posting the same Brex spend twice in D365?
- Microsoft Dynamics 365 F&O OData has no idempotency key and rejects duplicate natural keys with an error. ml-connector dedupes on the Brex record id and a BullMQ jobId before it posts, and it sets the Brex export_status to EXPORTED only after D365 confirms the write. If a downstream call fails, the record is retried with backoff and can be replayed from a full audit trail.
Related integrations
More Microsoft Dynamics 365 F&O integrations
Other systems that connect to Brex
Connect Microsoft Dynamics 365 F&O and Brex
Free to use. Add your credentials, ping your real systems, and see if we fit.
Get started