LUCENTCOMMERCEGET A FREE STORE AUDITFREE AUDIT

ERP · INTEGRATIONS · SHOPIFY PLUS · 15 APRIL 2025 · 8 MIN READ

SAP and Dynamics: integrating Shopify with enterprise ERP

At this size the hard part is not the API. It is that you do not control the ERP, its release calendar, or the people who change it.

An order moving from storefront to ERP through a queue

Put a middleware layer you own between Shopify and the ERP, define your own message format in the middle, and have both ends map into it. Then choose the ERP’s interface style — OData or REST for record-level work, file or queue-based recurring jobs for volume — and accept that most objects will move on a schedule rather than in real time. What makes SAP and Dynamics different from a mid-market ERP is not the technology. It is that you cannot iterate against them: changes go through a release calendar and a change board owned by someone else, so any design needing frequent ERP-side change will not survive contact with the organisation.

IN SHORT

  • Name the exact product before scoping. Dynamics 365 Business Central and Dynamics 365 Finance and Operations are different products with different integration models, and so are SAP ECC and S/4HANA.
  • A middleware layer with its own message format is not optional at this size — it is what stops an ERP upgrade becoming a Shopify project.
  • Business Central exposes a REST API, enabled by default online; Microsoft documents that its standard APIs cannot be extended with extra fields, so anything non-standard needs a custom API.
  • Finance and Operations exposes data entities over OData for synchronous work, and a data management pipeline with staging tables for file, queue and recurring integrations at volume.
  • Batch is a legitimate answer for products, prices and master data. Orders are the exception and should be event-driven.
  • Never call the ERP synchronously from a storefront request. Replicate contract pricing and availability into Shopify instead.

First, establish which product you are integrating

This sounds like pedantry and it is the most common cause of a mis-scoped statement of work.

Dynamics is two products sharing a brand. Business Central is the mid-market ERP, descended from NAV, and exposes a documented REST API — version 2.0 at the time of writing — which Microsoft states is enabled by default for Business Central online, with on-premises deployments needing it turned on. Finance and Operations is the enterprise product, descended from AX, and its integration model is built on *data entities*: de-normalised abstractions over the physical tables, which Microsoft describes as insulating "application code from the inevitable churn of the physical tables between versions". A team quoted for "a Dynamics 365 integration" has been given almost no information.

SAP is at least two, and probably four. ECC and S/4HANA are different generations, each existing in on-premise and cloud editions with materially different interface inventories. We are not going to list which interfaces your release exposes, and the reason is worth stating: SAP’s documentation portal requires a session, so we cannot verify a current inventory from public sources, and a list from memory is exactly what gets a project scoped wrongly. Get it from your SAP team, for your release. What you can plan around is the shape — a record-level synchronous interface, a document-oriented asynchronous one, and a middleware product SAP sells to sit between them — and the shape is stable even when the names are not.

Ask three questions before writing a line of scope: which product and version, on-premise or cloud, and who is allowed to approve a change to it. The third answer shapes your architecture more than the first two.

The constraint is the release calendar

A mid-market ERP integration is a technical project with organisational bits. An enterprise one is an organisational project with technical bits, and the difference shows up in week three.

On a Shopify build we deploy several times a week. The ERP next to it may deploy quarterly, into a window agreed months ago, gated by a change board that will ask about regression risk to financial reporting. That is not obstruction; it is correct behaviour for a system that closes the books. It does mean any design whose iteration loop runs through the ERP iterates in months.

So the goal is to need as few ERP-side changes as possible, and to front-load the ones you need into one agreed set. Read from standard interfaces wherever a standard interface will do, even when a custom one would be tidier; keep transformation logic on your side of the boundary; and when you do need a custom entity, ask once, early, with its fields agreed in writing.

The corollary is about who is in the room. If the answer to "who owns the ERP end of this" is a team you raise tickets with, the timeline should reflect ticket latency — and saying so at the start is cheaper than discovering it at the second milestone.

Put something you own in the middle

Two systems talking directly is the design that seems simplest and ages worst. At this scale we would treat middleware as a requirement rather than an option, and the argument is not about traffic volume.

Define your own message format for each object — order, product, price, inventory, customer, fulfilment — and have both ends map into and out of it. The ERP’s payload shape becomes one adapter; Shopify’s GraphQL becomes another. That is what lets you survive change on either side: when the ERP upgrades and a field moves, you change one adapter and the Shopify side never knows.

It also buys the operational things neither end provides — a record of every message sent, the ability to replay one, a queue that absorbs an ERP outage instead of dropping orders into it, and somewhere for reconciliation jobs to live. "Replay yesterday afternoon" is a feature you need on a specific afternoon, and it has to exist beforehand.

What we would not build is that logic inside a Shopify app or inside the ERP. In an app it becomes a thing with ERP access deployed on the storefront team’s cadence, which the ERP team will rightly not accept. In the ERP it is subject to the release calendar and can only be tested in an ERP environment — the scarcest resource on the project.

Batch is not a failure state

There is a tendency, coming from API-first work, to treat a nightly file drop as something to apologise for. Here it is often the right answer, and the vendors design for it.

Microsoft’s Finance and Operations documentation is the clear example: alongside synchronous OData services it describes asynchronous integration through a data management pipeline, explicitly supporting file-based import and export and "recurring integrations (file, queue, and so on)", with a staging table per entity for asynchronous and high-volume scenarios. That is a supported, high-throughput path, not a compromise.

The decision is per object. Products, prices, master data and financial postings are fine on a schedule; nobody’s experience of your store depends on a description arriving twelve hours sooner. Inventory wants a fast delta feed with a nightly full reconciliation. Orders are the exception: the warehouse is waiting, so an order should leave Shopify as an event, land in your middleware’s queue, and be created in the ERP from there — idempotently, keyed on the Shopify order id, because Shopify webhooks are delivered at least once and, by Shopify’s own documentation, not in guaranteed order.

On the Shopify side, anything touching the whole catalogue belongs in a bulk operation rather than a paginated loop. The documented envelope is a 100MB JSONL input file and a 24-hour operation timeout, with up to five bulk mutation operations per shop running simultaneously from API version 2026-01, and each output row carrying a __lineNumber so a failure traces back to its input line.

Contract pricing decides your architecture

If you sell B2B — and most businesses running SAP or Dynamics next to Shopify do — this decision has the widest consequences, and it is made too late on most projects.

The ERP holds negotiated pricing: customer-specific price lists, volume breaks, contract terms, sometimes logic rather than data. Shopify has its own model. B2B is built around a Company, its CompanyLocations and CompanyContacts, with catalogs associated with company locations to offer, in Shopify’s words, "exclusive product selections and negotiated pricing levels to contacts at different company locations". So the question is whether contract pricing is *replicated* into Shopify catalogs or *looked up* live from the ERP at render time.

Replicate, almost always. A live lookup puts the ERP in the critical path of a page load: your storefront’s availability becomes the ERP’s availability, your product page is as fast as a synchronous ERP call on its worst day, and a maintenance slot becomes a storefront outage. Replicating into catalogs is more work up front and you do it once.

The honest exception is pricing that cannot be enumerated — configured products priced by a rules engine, or availability confirmed against live allocation before a commitment. Even then, keep it out of browsing: quote at the point of quotation, confirm at the point of order, show an indicative price in the catalogue. Never call the ERP inside add-to-cart. And check one Shopify constraint early, because it has ended requirements we have seen written into briefs: the B2B documentation states that B2B does not support purchase options such as subscriptions, pre-orders and try before you buy.

Where the schedule actually goes

The code is rarely what overruns. Four things reliably are, and three can be started before any development begins.

  • Environments. You need an ERP environment that is not production, refreshed with realistic data, that you are allowed to write to. Getting one is a governance and procurement exercise, and it is the longest lead item on most of these projects.
  • Test data that matches reality. A sandbox seeded with demo customers will not exercise your contract pricing, tax cases or unit-of-measure conversions. Ask for an anonymised extract, and expect the request to take longer than you think.
  • Extensibility limits on standard interfaces. Microsoft documents that extending Business Central APIs with additional fields is not currently possible, and that the way round it is to copy the AL code for the API and build a custom one. In Finance and Operations, configuration keys can render an entity or an individual field non-functional regardless of your mapping, and the entity list must be refreshed after code or configuration changes. Validate the entities you depend on in the target environment early.
  • Returns, credit notes and cancellations. Always descoped, always required. Decide where a refund is authored, how a credit note reaches the customer, and what happens to an order cancelled after it reached the ERP — before the first order flows.

What we would tell you not to build

Do not mirror the ERP’s data model into Shopify. Shopify is a sales channel, not a second ERP. It needs enough of the product to sell it and enough of the customer to serve them. Every extra field you replicate is a field that can disagree, and one somebody will eventually edit in the wrong system.

Do not build bidirectional sync on anything. One owner per object, one direction per object. Two writers without an arbiter produces values that oscillate, and the diagnosis is expensive because both logs say success.

Do not put the storefront in front of the ERP. No synchronous ERP calls in a page render, an add-to-cart, or a checkout step. Everything the shopper sees should already be in Shopify, put there by your middleware on a cadence you chose. This is the rule that keeps the store trading on the day the ERP does not.

Questions this raises

How do you integrate SAP or Dynamics with Shopify?

Through a middleware layer you own, which defines its own message format for each object and maps both ends into it. Products, prices and master data move on a schedule via the ERP’s file, queue or OData interfaces; orders move as events from Shopify webhooks into a queue and are created in the ERP idempotently. No storefront request should ever call the ERP directly.

Which Dynamics 365 product are we talking about?

Establish this before scoping anything. Business Central is the mid-market ERP with a documented REST API, enabled by default for online deployments. Finance and Operations is the enterprise product, integrated through data entities exposed over OData for synchronous work and a data management pipeline with staging tables for high-volume file and recurring integrations. They are different projects with different costs.

Should Shopify look up contract prices from the ERP in real time?

No, in almost every case. A live lookup makes your storefront’s speed and availability dependent on the ERP’s, including during its maintenance windows. Replicate negotiated pricing into Shopify B2B catalogs attached to company locations, and reserve live ERP calls for quotation and order confirmation — never browsing or add-to-cart.

Is a nightly batch integration acceptable for an enterprise ERP?

Yes, for most objects, and the vendors design for it — Microsoft documents recurring file and queue-based integrations with per-entity staging tables as the high-volume path for Finance and Operations. Keep orders event-driven, because the warehouse is waiting on them, and give inventory a fast delta feed with a nightly full reconciliation.

Why not connect Shopify directly to the ERP and skip the middleware?

Because the two sides change on incompatible cadences and neither gives you the operational tools you will need. Middleware absorbs an ERP outage instead of dropping orders into it, lets you replay a specific afternoon, isolates an ERP upgrade to a single adapter, and gives reconciliation jobs somewhere to live. It is also the only place both teams can agree the contract sits.

What takes the longest on an enterprise ERP integration?

Getting a non-production ERP environment with realistic data that you are permitted to write to. It is a governance and procurement exercise rather than a technical one, and it should be started on day one. After that: agreeing custom interfaces inside a release window, and the returns and credit-note flow that was descoped at the start.

NEXT STEP

Free store audit

A senior Shopify engineer reviews your storefront, theme performance and checkout, then sends a prioritised list of fixes.