ml-connector
Microsoft Dynamics 365 F&OStripe

Microsoft Dynamics 365 F&O and Stripe integration

Microsoft Dynamics 365 F&O runs financials, receivables, and the general ledger. Stripe processes online payments, invoices, refunds, and payouts. Connecting the two brings settled payment activity into Dynamics without re-keying, so customer payments, refunds, and the fees taken out of each payout are recorded against the correct accounts. ml-connector handles the very different APIs on each side, reads Stripe on its webhooks and a backfill poll, and writes into Dynamics through its OData payment journals. Because Stripe has no GL accounts or chart of accounts, the ledger stays in Dynamics where it belongs.

How Microsoft Dynamics 365 F&O works

Microsoft Dynamics 365 F&O exposes customers, vendor invoices, payment journal lines, main accounts, posted general journal entries, and financial dimensions through an OData v4 REST service at a tenant-specific URL such as contoso.operations.dynamics.com/data. Authentication is OAuth 2.0 client credentials through Microsoft Entra ID, returning a one-hour bearer token. Reads use server-driven paging up to 10,000 records with an odata.nextLink cursor, and service protection limits return HTTP 429 with a Retry-After header. Dynamics can push outbound Business Events such as customer payment posted, but those payloads are lightweight stubs that carry identifiers and require a follow-up OData read for full detail.

How Stripe works

Stripe exposes customers, invoices, charges, payment intents, refunds, payouts, and balance transactions through its v1 REST API at api.stripe.com/v1, with form-encoded bodies and JSON responses. Authentication is a secret API key sent over HTTP Basic auth, with restricted keys available for least-privilege read access. Stripe pushes events over HTTPS to a registered endpoint, signed with HMAC-SHA256 in the Stripe-Signature header and verified against the raw request body; delivery is at-least-once and unordered, so events are deduplicated on event.id. List endpoints use cursor pagination, POST writes accept an Idempotency-Key, and all amounts are in the smallest currency unit such as cents.

What moves between them

The main flow runs from Stripe into Microsoft Dynamics 365 F&O. ml-connector consumes Stripe payment, refund, and payout activity and posts it into Dynamics as customer payment journal lines and reconciliation entries, mapped to the matching customer accounts, main accounts, and financial dimensions. Customer records can flow the other direction so a Stripe customer aligns with an existing Dynamics customer account, keyed on email or an external reference. Balance transactions and payout reports drive the fee and net-settlement entries so the bank deposit ties out. Stripe has no GL chart of accounts, so the ledger stays in Dynamics and ml-connector never writes accounting entries back into Stripe.

How ml-connector handles it

ml-connector stores both credential sets encrypted. On the Stripe side it sends the secret API key over HTTP Basic auth and verifies every inbound webhook against the raw body and the endpoint secret before doing any work, deduplicating on event.id because Stripe delivers at-least-once and out of order. On the Dynamics side it requests an Entra ID client-credentials bearer token, refreshes it before the one-hour expiry, and targets the customer's tenant-specific OData host, which is captured as a credential since there is no shared base URL. Stripe amounts arrive in the smallest currency unit, so each value is converted to a Dynamics currency amount before posting. Customer accounts, main accounts, and financial dimensions are mapped first, with dimensions passed as the formatted display string Dynamics requires, so every payment journal line lands on a valid account and dimension. Because a Stripe event is unordered, the connector re-fetches the charge, payment intent, or payout from Stripe to get current state rather than trusting the event payload, then posts to a Dynamics payment journal. Dynamics returns HTTP 429 under service protection limits, so writes honor the Retry-After header and back off, and OData natural keys mean a re-read payment is deduplicated on a BullMQ jobId to avoid double-posting. A scheduled poll backfills anything a webhook missed, and posted journal entries are read-only in Dynamics, so corrections post as new entries. Every record carries a full audit trail and can be replayed if a downstream call fails.

A real-world example

A mid-sized software company with roughly 200 employees bills its subscription customers through Stripe and runs Microsoft Dynamics 365 F&O for financials and the general ledger. Before the integration, an accountant exported the Stripe payout report each week and keyed the gross payments, refunds, and Stripe fees into Dynamics by hand, then spent the first days of month-end close reconciling the bank deposit against the receivables it was meant to cover. With Microsoft Dynamics 365 F&O and Stripe connected, each settled payment and refund posts into Dynamics as a customer payment journal line within the webhook window, the payout report drives the fee and net entries, and customers stay aligned across both systems. The weekly re-keying step is gone and close starts from reconciled numbers.

What you can do

  • Post settled Stripe payments and refunds into Microsoft Dynamics 365 F&O as customer payment journal lines against the right accounts.
  • Record Stripe payout fees and net settlement so the bank deposit reconciles in the Dynamics general ledger.
  • Keep the Dynamics customer master aligned with Stripe customers, keyed on email or an external reference.
  • Bridge the Stripe secret API key and the Microsoft Entra ID client-credentials token, with HMAC-SHA256 webhook verification.
  • Verify and deduplicate Stripe events on event.id, honor Dynamics 429 Retry-After backoff, and keep a full audit trail with replay.

Questions

Which direction does data move between Microsoft Dynamics 365 F&O and Stripe?
The main flow is Stripe into Microsoft Dynamics 365 F&O. Settled payments, refunds, and payout activity move from Stripe into Dynamics as customer payment journal lines and reconciliation entries, while customer records can flow back so a Stripe customer aligns with a Dynamics account. Stripe has no GL chart of accounts, so the ledger stays in Dynamics and ml-connector does not write accounting entries back into Stripe.
How does the integration bridge Stripe API keys and the Dynamics Entra ID login?
ml-connector stores both credential sets encrypted. It sends the Stripe secret key over HTTP Basic auth on every Stripe call, and it requests an OAuth 2.0 client-credentials bearer token from Microsoft Entra ID for Dynamics, refreshing it before the one-hour expiry. The Dynamics tenant URL is captured as a credential because the platform publishes no shared base address.
Does the integration use Stripe webhooks, and how are duplicates handled?
Yes. Stripe pushes events signed with HMAC-SHA256, which ml-connector verifies against the raw request body before processing. Because delivery is at-least-once and unordered, events are deduplicated on event.id and the connector re-fetches the charge, payment intent, or payout from Stripe to get current state, and a scheduled poll backfills anything a webhook missed.

Related integrations

Connect Microsoft Dynamics 365 F&O and Stripe

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

Get started