Connecting Shopify Plus to NetSuite, SAP or Dynamics 365 is rarely blocked by the API itself. Both ends publish full API references, both speak JSON over HTTPS, and both publish most of their limits. What breaks a Shopify ERP integration is everything the reference docs don’t put in one place: which system owns a given field, what happens when a webhook never lands, and who upgrades the connector when Shopify retires the API version it’s pinned to.
This is written for the operator or technical lead scoping a Shopify ERP integration, or trying to rescue one that’s already syncing bad data. The awkward part of any ecommerce integration with ERP software on the far end is that both systems were built to be the authority, and neither one will tell you when it’s been overruled.
Every figure below links to the document it came from. Vendor capability claims are labeled as vendor claims and never restated as neutral fact. Shopify App Store ratings, review counts and connector prices were observed on August 24, 2026, and all of those move, so re-pull anything you’re about to put in a business case. Pricing is as of August 2026 and vendors change it without notice.
A Shopify ERP Integration Is an Agreement About Which System Is Allowed to Be Wrong
Shopify frames this decision in its own documentation, which is useful because it means the API branches on your answer rather than assuming one. The product model migration guide splits integrations into two cases: “Shopify is your source of truth,” where you use targeted mutations to change specific fields, and “An external system is your source of truth,” where you use a declarative sync mutation to “replace complete product state in one operation.” Shopify names ERPs and PIMs explicitly in the second branch.
That second path has a sharp edge. The same guide describes productSet as a mutation that “Creates or updates entire product state” and “Replaces all data (not a merge).” The productSet reference page is more precise about where that bites: for list fields such as collections, metafields and variants it “deletes existing entries that aren’t included in the mutation’s input,” while for every other field type it “Updates only the included fields.” So if your merchandising team adds a metafield or a collection in the Shopify admin and the nightly ERP job runs productSet without it, that entry is gone the next morning with no error anywhere.
So the system-of-record decision isn’t per object. It’s per field. Product title might belong to the ERP while product description, images and SEO fields belong to Shopify, and the only way to hold that line is to make the sync job write a field subset rather than a whole object.
The Inventory State Your Shopify ERP Integration Can't Write
Shopify tracks eight inventory states, and its inventory quantities and states guide lists them as incoming, on hand, available, committed, reserved, damaged, safety stock and quality control. On hand is the sum of the other six local states, not an independent number you can set.
One of those states is closed to you. The same page states that you “can’t use the Admin API to adjust or move inventory quantities in the committed state,” because Shopify manages committed stock itself through order creation, fulfillment, draft order reservations and transfers marked ready to ship. An ERP that thinks in a single quantity-on-hand figure and pushes it straight to Shopify is overwriting a number that already had open orders subtracted from it.
That mechanism is the ordinary cause of overselling in a Shopify ERP integration, and it doesn’t announce itself. The ERP is correct about the warehouse, Shopify is correct about the open orders, and the sync job is the only thing in the system that’s wrong.
Compare and Swap, and Why Shopify Asks You Who's in Charge
Shopify publishes the lost-update problem as a worked example on that same page: you read 100 units, another process sells 20 while you’re deciding, you write 90 based on your stale read, and the true figure should have been 70. The fix is the changeFromQuantity field, which lets you declare the quantity you expect to find before your change applies, and returns a CHANGE_FROM_QUANTITY_STALE error when the current value doesn’t match. It’s implemented on four mutations: inventoryAdjustQuantities, inventoryMoveQuantities, inventorySetQuantities and productVariantsBulkUpdate. Shopify introduced it in the concurrency protection changelog effective in API version 2026-01.
Then Shopify says the quiet part in one sentence: “If you don’t care about the current quantity because you’re the source of truth, then you don’t need to implement compare and swap and should opt out.” Read “opt out” literally. The same changelog makes changeFromQuantity required in 2026-04, “with explicit opt-out,” and flags it as a breaking change, so declining to use it is now something you have to say in the request rather than something you get by omission.
Your answer to the system-of-record question determines which code you write, so you can’t defer it to build time.
While you’re in there, set referenceDocumentUri on inventory adjustments. Shopify’s documentation says it “transforms inventory adjustments from a ‘black box’ into a transparent system where you can trace every change back to its source,” and it accepts a GID-style value pointing at the ERP document that caused the change. Skipping it costs nothing on day one and costs an afternoon every time finance asks why a location is off by eleven units.
Every Shopify ERP Integration Runs on an Expiring API Version Pin
Shopify’s versioning policy releases a new API version every three months at the start of the quarter and supports each stable version for a minimum of 12 months, with at least nine months of overlap between consecutive versions. Release candidates “may include backwards-incompatible changes, so not recommended for production.” Here’s the current support table from that page.
| Version | Release date | Support ends |
|---|---|---|
| 2025-07 | July 1, 2025 | July 16, 2026 15:00 UTC |
| 2025-10 | October 1, 2025 | October 16, 2026 15:00 UTC |
| 2026-01 | January 1, 2026 | January 16, 2027 15:00 UTC |
| 2026-04 | April 1, 2026 | April 16, 2027 15:00 UTC |
| 2026-07 | July 1, 2026 | July 16, 2027 15:00 UTC |
| 2026-10 | October 1, 2026 | October 16, 2027 15:00 UTC |
| 2027-01 | January 1, 2027 | January 16, 2028 15:00 UTC |
Microsoft documents what that cadence does to a connector more plainly than anyone else in the market. The Business Central Shopify connector FAQ says the connector “is built on the Shopify GraphQL Admin API, which Shopify versions every three months and aggressively deprecates fields between versions,” that “The connector pins a specific API version (adopted at each Business Central major release) and must uptake to the next version before support ends,” and then, in Microsoft’s own words: “Fall behind, and the integration stops working.”
The pin also runs behind current by design. The same FAQ explains that “the Shopify Connector released in April 2025 uses the Admin API version from January 2025, while the October release uses the API version released in July,” and that the Shopify support timeline “doesn’t align with the Business Central update period.” Microsoft’s worked example is now retrospective: it warned that the 2025 wave 2 connector relies on API version 2025-07, “supported until July 1, 2026,” and Shopify’s own table puts that version’s end at July 16, 2026. Both dates are behind us, which makes it a clean illustration of the pattern rather than a live deadline.
Every connector has this property. Workato’s Shopify connector documentation states the connector uses Shopify REST Admin API version 2026-01 and GraphQL Admin API version 2026-01, and Shopify’s table retires 2026-01 on January 16, 2027. MuleSoft’s Anypoint Connector for Shopify is at version 1.1 and, per its own docs, “exposes operations provided by the Shopify REST Admin API,” while Shopify’s REST Admin API page has labeled REST “a legacy API as of October 1, 2024” and required all new public apps to be GraphQL-only since April 1, 2025.
Neither of those is a defect. Vendors update connectors continuously and a published doc page is a snapshot. They’re both good due-diligence questions: which Shopify API version is your connector on today, what’s your committed lag behind current, and what happens to my store if you miss an uptake.
Who Owns the Quarterly Upgrade
That turns a maintenance detail into a contract question, and it needs answering before signature rather than at the first failed sync. Whoever owns the upgrade owns a recurring quarterly obligation for the life of the integration.
Put four things in writing. Which party performs the API version uptake, how many days before end of support it’s committed to happen, whether the work is inside a retainer or billed as change requests, and what the remedy is when a sync outage is caused by a missed uptake rather than by your code. We build these stacks, and the version pin is the line item most often absent from a scope of work.
What Mandatory Idempotency Breaks in an Existing Shopify ERP Integration
On December 12, 2025, Shopify published a breaking change notice making the idempotency directive mandatory for a set of inventory and refund mutations in API version 2026-04. Seventeen mutations are named, including refundCreate, inventoryAdjustQuantities, inventorySetQuantities, inventoryMoveQuantities, inventoryActivate, the inventory transfer and shipment mutations, and locationActivate and locationDeactivate.
Shopify’s notice says that “Even though the idempotency directive doesn’t show up as mandatory at the schema level, calling these mutations without an idempotency directive will result in an error at runtime.” Schema introspection won’t warn you, codegen won’t warn you, and your type checker won’t warn you. It surfaces the first time you post a refund on the new version.
The mechanics have a deadline built in too. The idempotency implementation guide says Shopify tracks idempotency keys for 24 hours from the original request, after which “retries that occur beyond this window (such as long-delayed job retries), will not have idempotency protection, and will be treated as separate operations.” Duplicates arriving while the first request is still in flight get IDEMPOTENCY_CONCURRENT_REQUEST instead of being processed.
If your architecture has a dead-letter queue that a human drains on Monday, that’s the design constraint to work around. A failed inventory adjustment replayed 48 hours later applies twice, and a replayed refundCreate refunds twice. Anything that can be retried outside the 24-hour window needs its own dedupe record on your side, keyed to the ERP document rather than to Shopify’s key.
Webhook Delivery: Why Every Shopify ERP Integration Needs a Reconciliation Job
Shopify’s HTTPS webhook documentation gives the numbers: your endpoint acknowledges with a 200, “Any response outside the 200 range, including 3XX codes, is treated as an error,” and Shopify enforces “a one-second connection timeout and a five-second timeout for the entire request.” On failure, “it retries 8 times over the next 4 hours,” and after eight consecutive failures the subscription is deleted automatically if it was configured through the Admin API, with warning emails to the app’s emergency developer address.
Eight retries over four hours is the current figure. The older nineteen-retries-over-forty-eight-hours number still circulates widely in integration write-ups and in a lot of institutional memory, and building a recovery window around it gives you a margin that doesn’t exist. Four hours of endpoint downtime and the subscription is gone, not just the events.
Shopify also disclaims both ordering and delivery. Its webhooks overview states that Shopify “doesn’t guarantee ordering within a topic, or across different topics for the same resource,” offering the example that a products/update webhook might arrive before a products/create, and recommends ordering off the X-Shopify-Triggered-At header or the payload’s updated_at. Then it says outright: “Your app shouldn’t rely on receiving data from Shopify webhooks. Webhook delivery isn’t always guaranteed.”
So the reconciliation job isn’t a hardening task for phase two. Shopify’s own guidance is to “use reconciliation jobs to periodically fetch data from Shopify so that your app stays consistent with Shopify’s data,” and it points at the implementation: many queries support updated_at filters, so a job can fetch everything changed since its last successful run. In our experience this is the component most often cut to hit a launch date and rebuilt after the first bad week.
Deduplication has two headers and they do different jobs. Shopify says duplicate deliveries happen after network timeouts and retries, that X-Shopify-Webhook-Id identifies an individual delivery, and that X-Shopify-Event-Id correlates deliveries originating from the same merchant action, so multiple subscriptions on one topic produce different webhook IDs sharing one event ID. Dedupe on the webhook ID and correlate on the event ID. And because you have five seconds total, queue the payload and acknowledge immediately, which Shopify calls out as “a useful pattern for handling bursts of traffic.”
Should you build on Shopify’s newer Events API instead? Not for production ERP work yet. The Events documentation says Events “is in developer preview, available today for a subset of topics,” and the page itself carries an unstable API version. Shopify says it will become the primary subscription mechanism as topic coverage expands, which makes it worth tracking and not worth pinning revenue to.
The other end of the wire disclaims ordering too. Microsoft’s business events documentation for finance and operations apps states that “the order in which the apps emit the events isn’t guaranteed to preserve the order in which they’re delivered,” with defaults of three retries a second apart, ten endpoints per event and a ten-second HTTP timeout. The same page warns against using business events for data export because “They aren’t intended to carry large payloads.” Two event systems, two ordering disclaimers, one reconciliation job that has to be the actual source of consistency.
Throughput: The ERP Side Is the Bottleneck in Most Shopify ERP Integrations
Teams scoping a Shopify ERP integration usually assume Shopify is the constraint. Shopify’s rate limit documentation gives the GraphQL Admin API 100 points per second on Standard, 200 on Advanced, 1,000 on Shopify Plus and 2,000 on Shopify for enterprise. Plus gets ten times the Standard throughput, which is one of the few places where the plan tier genuinely changes the engineering.
Shopify’s model is a leaky bucket with a calculated query cost, where every field carries an integer cost, a mutation defaults to 10 points, and a single query can’t exceed 1,000 points regardless of plan. At 1,000 points per second restore and 10 points per mutation, a Plus store sustains roughly 100 default-cost mutations per second. That arithmetic is ours, off Shopify’s published cost model, not a figure Shopify states.
Rate limits are scoped to the combination of app and store, so “calls from one app don’t affect the rate limits of another app, even on the same store,” and every response carries extensions.cost.throttleStatus with maximumAvailable, currentlyAvailable and restoreRate. Shopify recommends using that metadata “to manage your app’s behavior dynamically,” with a recommended backoff of one second. Your integration can read its remaining budget from the response instead of guessing.
NetSuite Concurrency Is One Shared Pool
Now the other end. Oracle’s concurrency governance documentation governs at the account level and says “The account governance limit covers the total number of web services and RESTlet requests combined.” SOAP, REST and RESTlets all draw from one budget, so your Shopify sync competes with the 3PL feed, the tax integration and every internal script.
The base numbers are small. Oracle’s service tier table gives Standard 5 concurrent requests, Premium 15, and Enterprise and Ultimate 20 each, with development and partner accounts fixed at 5. Each SuiteCloud Plus license adds 10, and Oracle’s own example works out a Tier 1 account with five licenses to 65. You can also allocate concurrency to a specific integration, which Oracle notes “reduces the available limit for other integrations without a specific limit.”
Set that against Shopify Plus at 1,000 points per second and the asymmetry is the whole capacity plan. Shopify will accept work far faster than a Standard-tier NetSuite account can absorb it, so queues, batching and backpressure belong on the ERP side of the middleware, not in front of Shopify.
SuiteScript governance tightens it further. Oracle’s usage unit costs price record.load() on a standard transaction at 10 units and Record.save() at 20, and the script type limits cap a RESTlet at 5,000 units and a scheduled script at 10,000. A sales order load plus save is 30 units, so a single RESTlet invocation tops out around 166 order saves before it runs out of governance. That last figure is our arithmetic off Oracle’s published unit costs, not an Oracle claim.
When you exceed it you get specific errors, which Oracle documents: a RESTlet returns HTTP 400 with SuiteScript code SSS_REQUEST_LIMIT_EXCEEDED, request-level SOAP credentials produce ExceededRequestLimitFault with WS_CONCUR_SESSION_DISALLWD, and token-based SOAP auth produces ExceededConcurrentRequestLimitFault with WS_REQUEST_BLOCKED.
NetSuite also runs its own optimistic locking, with the user-facing strings “Record has been changed.” and “Unable to save record. Record was changed by a different user. Please reload and try again.” in the record locking documentation. Both platforms independently landed on optimistic locking, which tells you how often both were losing updates.
Business Central and Finance and Operations Throttle Differently
Microsoft’s operational limits for Business Central online publish a per-environment OData rate of 600 requests per minute in production and 300 in sandbox, a maximum of 5 concurrent requests, a maximum batch size of 100, a maximum page size of 20,000 and a cap of 200 webhook subscriptions. Separately, per user, OData and SOAP allow 6,000 requests within a five-minute sliding window. Those two figures get conflated constantly and they measure different things.
Throttling returns HTTP 429, and Microsoft’s rate limit page adds that request execution is limited to 10 minutes before the service returns a 504. The workaround on Microsoft’s operational limits page is to spread “your workload in smaller batches across multiple users or service principals.” Note also that Microsoft’s API reference states extending APIs with additional fields “isn’t currently possible in Business Central,” and that if you need it “you must copy the AL code for the API and create a custom API based on that.” Custom fields are a build, not a config toggle.
Finance and operations carries a published limit that is no longer enforced. Microsoft’s service protection API limits page documents 6,000 requests, 1,200 seconds of execution time and 52 concurrent requests per five-minute sliding window, and then states that “As of March 31, 2023, user-based service protection API limits are no longer being implemented in finance and operations apps environments,” with the limits disabled on all environments and the enabling option removed in version 10.0.36. What’s actually enforced is resource-based throttling on CPU and memory, surfacing as a high resource utilization error, plus priority-based throttling with Low, Medium and High levels and no published numeric thresholds.
The same page lists nine integration paths exempt from service protection limits, including the data management framework, recurring integrations, Data Integrator and the finance and operations apps connector. That exemption list is the batch lane, and it’s the reason bulk ERP loads go through the data management framework rather than through OData.
SAP is the outlier here. SAP publishes no rate limit or throttling figures for S/4HANA Cloud OData APIs or for SAP Integration Suite, while it does publish rate-limit documentation for other BTP services, so the absence isn’t a search artifact. The closest published material describes tenant resource boundaries for integration flows rather than requests per second. Sizing a sync against SAP means load testing your own tenant, because there’s no published number to design against.
SKUs, Variants and Matrix Items: Where Shopify ERP Integration Mapping Breaks
Start with the cheapest trap. Shopify’s fulfillment service documentation states that “SKU strings are case-sensitive at Shopify” and that SKUs returned from the stock endpoint are matched respecting case. Plenty of ERPs treat item codes as case-insensitive, so ABC-123 and abc-123 are one item on one side and two on the other. Normalize case at the boundary and log every mismatch rather than silently coercing.
The object model matters for where the SKU lives. Per Shopify’s inventory documentation, a ProductVariant carries merchandising data and has a one-to-one relationship with an InventoryItem, the InventoryItem holds the SKU and physical product information, and an InventoryLevel connects one inventory item to one location. Mapping an ERP item to a Shopify product is the wrong join. The join is ERP item to inventory item.
Then the ceilings, which don’t line up. Shopify raised the variant limit to 2,048 per product in an October 15, 2025 changelog, up from a historical limit of 100, and warned that “merchants using apps that are not using the in-support GraphQL product APIs may have a downgraded or broken experience when creating or viewing products with more than 100 variants.” NetSuite’s matrix item documentation says “The maximum number of the total combinations of matrix options is 2000,” and that the parent item doesn’t appear on transactions, only child items do. Two different models with two different ceilings, and the NetSuite figure counts option combinations rather than children.
Oracle publishes an escape hatch called Virtual Variations, described as a way to avoid rebuilding parent-child relationships in NetSuite when they already exist in the storefront. It requires every Shopify variant SKU to have a corresponding standalone NetSuite item, which is a real trade: less matrix maintenance, more items in the item master.
Cross-Reference IDs in Both Directions
Never let the two systems find each other by string-matching SKUs at runtime. Shopify’s metafields documentation uses precisely this scenario as its example, describing an app that creates an app-owned metafield to track internal SKU codes, in the reserved app namespace. App-owned metafields are view-only in the admin by default and app-data metafields are hidden from it entirely.
The pattern is symmetric. Store the ERP’s internal record ID on the Shopify object in an app-owned metafield, store the Shopify GID on the ERP record, and make every lookup use an ID rather than a business key. SAP does the same thing: its own Shopify integration package ships an iFlow named “Create Shopify Metafield Definitions.”
Default field mappings deserve a review pass for the same reason. Oracle’s shipped Shopify mappings send sku to itemId, order_number to tranid, the Shopify order id to a custbody_fa_channel_order field, and inventory_management to isdropshipitem. That last pair takes a Shopify inventory-tracking flag and lands it on a NetSuite drop-ship boolean, which is a semantic decision you’re inheriting rather than making. Read the default map line by line before go-live.
Customer Merges Invalidate Your Foreign Key
If the ERP stores a Shopify customer ID as its key, a merge can break it without an error anywhere. The customerMerge documentation states that the two ID arguments “don’t guarantee which customer is kept” and lays out Shopify’s selection order: an explicit overrideFields.customerIdOfEmailToKeep wins if it’s provided and valid, otherwise a single customer with an email address wins, otherwise account state and email marketing consent decide with an enabled account beating other states, and customerTwoId is kept as the fallback. The mutation is asynchronous and returns a job, and it requires the write_customer_merge scope.
Shopify provides customerMergePreview and a resultingCustomerId so you can find out which record survives before you commit. Subscribe to customer update events, resolve the surviving ID, and repoint the ERP key rather than letting a dead ID sit in your customer master.
Multi-Location Inventory and Split Shipments in a Shopify ERP Integration
Most ERPs model a sales order with one ship-from location and one fulfillment event. Shopify doesn’t. Its order management documentation defines a fulfillment order as “the strategy for how an order will be fulfilled” and states that “There can be more than one fulfillment order for an order at a given location.”
Shopify’s split carts guide names four split-shipping triggers plus ship-and-pickup in one order: preorder items mixed with one-time purchases, subscription items mixed with one-time purchases, products shipping from different locations, and products in different shipping profiles, with a mixed shipping-and-pickup order treated as its own scenario. Its instruction to app developers is direct: if your app “assumes a one-to-one mapping between an order, location, and fulfillment order, then update it to read fulfillment order data and the fulfillment order deliveryMethod.”
Cancellation reshapes the graph again. Shopify’s fulfillment service guidance states that after a fulfillment is canceled, a new fulfillment order is created from the canceled line items, and if those items can’t all be sourced from one location, the new fulfillment order is assigned by the shop’s fulfillment priority settings, “which might result in multiple newly opened fulfillment orders for different locations.” Your ERP integration has to handle a sales order whose shipment structure changed after it was already booked.
Location modeling is the other half. Shopify’s fulfillment service documentation says each fulfillment service corresponds to an inventory location and that each physical warehouse should have its own fulfillment service, and it notes that Shopify requests all inventory data from a remote fulfillment service once every hour. Oracle’s connector documentation instructs admins to “set different NetSuite locations to sync to different Shopify locations” when multiple locations are enabled, and Microsoft’s Business Central connector overview describes pushing inventory levels from selected Business Central locations to multiple Shopify locations. The retail side of this problem is the same argument in a different context, which we covered in how Shopify POS changes unified commerce inventory.
Oracle also states that “NetSuite Connector does not support transfer orders in Shopify.” If inter-location transfers are part of your operating model, that’s a requirement the first-party connector doesn’t cover.
Refunds, Returns and Financial Write-Back in a Shopify ERP Integration
Refund write-back is where duplicates cost real money, and it’s now covered by the mandatory idempotency change since refundCreate is on that list of seventeen mutations. Returns have their own migration: Shopify’s returns apps documentation carries a caution that API version 2025-07 introduced return processing, which “confirms return items, releases exchange items, and updates a merchant’s financial reports,” and that existing return apps “should migrate to use returnProcess to avoid disruptions and unexpected outcomes.”
Oracle forces a direction here, which is a clean illustration of the system-of-record principle in vendor form. Its refund documentation states that “You can’t sync refunds both ways for a single account under one connector,” so “you must choose which way you want to sync your refunds,” and Oracle’s Shopify best practice is to issue the refund in NetSuite and sync it out. The same documentation explains that an exchange “is essentially a return and a new sale of the returned item,” and that return records themselves don’t sync, only the refund component.
Transaction type mapping follows payment state: Oracle’s connector creates cash sales for orders with payment and invoices for orders with terms, with refunds routing to cash refunds and credit memos respectively. If your finance team expects every Shopify order to land as the same document type, that assumption breaks the first time a B2B order comes through on terms. The B2B side has its own order shape, which we walked through in when to move B2B operations onto Shopify Plus.
Order amendments have hard boundaries if the ERP is the master. Shopify’s order editing documentation requires the order to be in your store currency unless you’ve upgraded to Shopify Extensions in Checkout, blocks editing of archived orders and orders placed before January 1, 2019, and blocks line item quantity changes on prepaid subscriptions with multiple scheduled fulfillments. It also notes that editing an order “doesn’t modify the subscription contract itself.”
Currency and timing are where a Shopify ERP integration produces month-end variances instead of errors. Every money field is a MoneyBag with presentmentMoney in the customer’s currency and shopMoney in the shop’s base currency, so posting the wrong one to the general ledger is a silent, compounding error. The Order object carries createdAt, set at checkout completion, and processedAt, which Shopify says “might not match the date and time when the order was created,” plus updatedAt for change tracking.
Pick one field for period cutoff, document the choice, and filter reconciliation jobs on updatedAt while never using it for financial periods. A store selling into several regions compounds all of it, because every one of those fields now varies by market.
Reconciling to the bank needs an object most integrations skip. The ShopifyPaymentsPayout object includes a summary that “breaks down fees and gross amounts by transaction type, such as charges, refunds, and adjustments,” with a transaction type indicating whether funds move to the bank account or back to Shopify Payments. A deposit is net of fees and spans many orders, so order totals alone will never tie to the statement. Microsoft lists “Receive payout information from Shopify Payments” as a connector capability, which is a fair yardstick to hold any connector against.
Backfill and Steady State Are Two Architectures in One Shopify ERP Integration
Loading history and running daily sync are different problems, and trying to serve both with one code path is how projects lose a month. Historical backfill is a bulk, order-insensitive, throughput-bound job. Steady state is an event-driven, ordering-sensitive, latency-bound one.
Backfill also has a gate people discover late. Shopify’s access scopes documentation says that by default “you have access to the last 60 days’ worth of orders for a store,” and that reaching further back requires the read_all_orders scope, which you request from Shopify with a justification and which Shopify has to approve before you can add it alongside read_orders or write_orders. That’s an approval process with lead time, not a configuration flag, and it belongs on the project plan at kickoff.
For the extract side, bulk operations allow five concurrent operations per app per shop as of API version 2026-01, up from one, give a bulk query 10 days to complete, and produce a signed result URL that expires after one week. A bulk query supports five total connections nested no more than two levels deep. On the write side, bulk imports allow five concurrent operations, require completion within 24 hours, cap the JSONL input at 100MB, and are limited to one connection field. Shopify states that bulkOperationRunMutation isn’t subject to the rate limits that single queries face.
Two constraints shape how you write the JSONL. Shopify says the API “doesn’t serially process the contents of the JSONL file” and warns you to “Avoid relying on a particular sequence of lines and object order to achieve a desired result,” so you can’t express create-then-update dependencies inside one file. And idempotency in bulk “is applied per row in your JSONL input file, not per the entire bulk operation,” with Shopify warning that reusing a single key across rows causes every row after the first to be treated as a duplicate.
That gives you a clean architectural fork. Backfill runs as staged bulk operations, one object type per pass, ordered by dependency across passes rather than within a file, with per-row idempotency keys generated from the ERP document ID. Steady state runs on webhooks with a queue, an idempotent handler, and the reconciliation job filtering on updated_at. On the ERP side the same split exists: the data management framework and recurring integrations are the exempt batch lane in finance and operations, while OData carries the transactional traffic.
Peak season is when the two paths collide, because a catalog refresh and Black Friday order volume want the same budget. We wrote about stress-testing a Shopify store before peak season, and the ERP sync belongs in that test plan alongside the storefront.
Sandbox and UAT: Where a Shopify ERP Integration Actually Gets Tested
Client transfer stores and development stores get confused constantly, and they have opposite rules for this use case. Shopify’s documentation for client transfer stores lists among its limitations that “You can only install free apps and partner-friendly apps. Custom and draft apps can’t be installed,” and that “Real transactions aren’t supported.” A bespoke connector app is a custom app, so the store you hand to a client can’t host it during the build.
Development stores can be created on a Plus plan with enterprise features like Flow and Launchpad, and they’ll take a custom app, which makes them the right UAT environment for a bespoke build. Their limitations are different: testing runs through the Bogus gateway or your provider’s test mode, “Real transactions through active payment providers, Store Credit, and Gift Cards aren’t supported,” dev stores can’t be converted to production stores, and they can’t be transferred to a client.
The practical consequence is worth planning around rather than discovering in week ten. You can’t fully test payment-to-payout reconciliation before go-live, because payouts require real transactions. Sequence the financial sync last, run a parallel period where Shopify and the ERP both produce numbers and someone compares them, and don’t sign off the general ledger posting on synthetic data.
Non-production environments can also be a paid line item on the middleware side. Alumio’s pricing page lists a “Full OTAP street (production, UAT, sandbox)” under its Connect Core tier rather than its entry tier, which is a vendor claim about their packaging and a reasonable question to ask any iPaaS vendor before you assume UAT is free. Note too that Business Central’s sandbox rate is 300 requests per minute against production’s 600, so a load test result from sandbox doesn’t transfer directly.
What Each ERP Vendor Actually Ships for Shopify Integration
So what’s the best ERP for ecommerce? There’s no vendor-neutral answer, and no sourced basis for crowning one. The decision is usually settled before you start, because the ERP is already running your finance and supply chain. What you actually have to establish is what your specific ERP and edition ships for Shopify, what it doesn’t, and what that gap costs you in middleware or custom development. Coverage is uneven in ways you can verify yourself in an afternoon.
Shopify’s Global ERP Program collection, described as “A suite of certified enterprise resource planning apps to directly integrate with your Shopify store,” contains five apps as of August 24, 2026, and the broader inventory and ERP category lists 189. The European ERP Program holds a further 13. Here’s the Global program with ratings and review counts as observed.
| App | Developer | Rating | Reviews | Listed pricing |
|---|---|---|---|---|
| NetSuite ERP Connector | Oracle NetSuite | 4.4 | 6 | From $199.92/month |
| Dynamics 365 Business Central | Microsoft | 2.3 | 23 | Free to install |
| Brightpearl by Sage | Sage | 4.6 | 53 | Free to install |
| Acumatica Cloud ERP | Acumatica | 5.0 | 1 | Free to install |
| Infor eCommerce Connector | Infor | unrated | 0 | Free |
Read those counts before the stars. Microsoft’s Business Central listing sits at 2.3 across 23 reviews, and 23 reviews describes the experience of 23 merchants over the years since the app launched on April 29, 2022. It’s not a rate, it isn’t weighted for how many of those merchants had a Business Central partner doing the configuration, and it can move materially on a handful of new reviews. What a small base does support is a narrower conclusion: a program badge tells you a connector exists, not that it covers your record set, so test it against your own objects before you commit.
Third-party connectors on the same platform carry heavier review bases than the first-party one. Against Oracle’s 4.4 across 6 reviews, WebBee’s Robust NetSuite Integrator shows 4.2 across 76 reviews with published tiers at $80, $199.99, $300 and $500 per month, and TechMarbles’ NetSuite Integration – TM shows 5.0 across 29 reviews with tiers at free for the first 50 orders or 30 days, $99 and $199 per month.
Oracle NetSuite
Oracle’s connector is the oldest of the first-party options, launched on the App Store on December 2, 2014, and its published tiers are B2C Standard at $199.92, POS at $249.92, B2C Premium at $249.92 and B2B at $916.58 per month, billed in USD on a 30-day recurring basis. The FarApp lineage is still visible in the product: Oracle’s setup documentation instructs admins to log in at app.farapp.com, and shipped custom fields carry names like custitem_farapp_parent and custitem_fa_shopify_handle.
The documented limits decide scope. One store per connector, refunds syncing in one direction only, no transfer order support, and metafields that are add and update only with deletion handled manually in Shopify.
None of those are defects. They’re published boundaries, and if your requirements sit inside them, this is the cheapest path with the clearest price.
Watch the transport timeline on the NetSuite side. Oracle’s SuiteTalk documentation says new integrations should be built on REST web services starting with the 2026.1 release, that from 2027.1 “it will no longer be possible to build new integrations using SOAP web services,” that from 2027.2 only the last endpoint stays supported, and that with 2028.2 “all endpoints will be disabled, and SOAP-based integrations will stop working.” SOAP isn’t deprecated today, and it remains buildable until 2027.1, but a middleware vendor offering a SOAP-based NetSuite connector is offering a transport with a published shutdown date.
SuiteScript 2.1 is current, and Oracle notes the 2.x API version tag still resolves to 2.0 unless the account preference for executing 2.x server scripts is changed. And SuiteCommerce is Oracle’s own storefront product, not a Shopify connector, so a SuiteCommerce deck arriving mid-evaluation is answering a different question.
Dynamics 365 Business Central, and Not Finance and Operations
Business Central has a genuine first-party connector, preinstalled for new online environments, installable from Marketplace for existing ones, and published as open source in Microsoft’s BCApps repository. The FAQ is explicit about where it doesn’t run: online only, not on-premises, not on Embed App deployments where the client URL uses the bc.dynamics.com format, and it requires both a Business Central and a Shopify license.
Keep the sync directions straight, because “bidirectional” isn’t accurate as a blanket description. Per Microsoft’s connector overview, products and items sync both ways including images, variants, barcodes, vendor item numbers, tags and metafields, and customers and companies sync both ways with smart mapping on phone and email and B2B companies matched on tax or registration numbers. Inventory levels and posted sales invoices go from Business Central to Shopify. Orders come from Shopify to Business Central, from online stores, POS and B2B, carrying shipping costs, gift cards, tips, payment terms and transactions, PO numbers, fraud risk and return, refund or cancellation information, along with Shopify Payments payout data.
Finance and Operations is the harder sentence. Microsoft’s own FAQ states that “The Shopify connector doesn’t work with other Dynamics 365 applications, like Dynamics 365 Sales or Dynamics 365 Supply Chain Management.” There’s no Microsoft first-party Shopify connector for finance and operations apps, so that project is middleware or custom, built against OData, custom SOAP or JSON services, and a read-only REST metadata service, with business events for near-real-time push.
Dual-write is a bidirectional integration between finance and operations apps and Dataverse, and it has no role in a Shopify integration. And the Shopify connector in Power Platform is titled “Shopify (Independent Publisher) (Preview)”, published by an independent publisher rather than shipped as a Microsoft first-party connector, throttled at 100 API calls per connection per 60 seconds, with four actions covering orders and customers and zero triggers. It’s not a product or inventory sync path.
SAP S/4HANA and SAP Business One Are Two Different Shopify Stories
SAP publishes Shopify integration content on its Business Accelerator Hub, and the catalog holds five Shopify packages: two published by SAP, plus packages from Incture Technologies, Flexso and PROCLANE. Every one of the five returns CertifiedBySap: false in the Hub’s own catalog data, SAP’s two included. That’s a field value from SAP’s catalog service, not an assessment. For a buyer running diligence it means one thing precisely: “published by SAP” and “certified by SAP” are different statements, and neither the packages nor the Hub expose a certification you can cite.
Edition coverage is the finding that changes scope. SAP’s own package, S/4HANA Cloud Public Edition Integration with Shopify at version 1.1.3, is the substantial one, with eight documented business processes covering product, stock, price and discount replication out to Shopify, and B2C customers, orders, cancellations and returns coming back, plus delivery details outbound. It ships eleven integration flow artifacts. It targets S/4HANA Cloud public edition.
Private edition gets a different, thinner story. The private edition package is published by Incture Technologies and its catalog returns a single artifact, for pulling incremental data from Shopify into S/4HANA Cloud private edition, with Incture’s own configuration guide stating that writing data back to Shopify means reaching out to them. The Flexso package states in its own description that only the S/4HANA-to-Shopify stock from MRP area flow “has been made publicly available,” with the rest available by contacting Flexso. Check what’s downloadable rather than reading a package’s advertised scenario list as shipped functionality, and apply that check to every vendor, not just these.
SAP also publishes a Shopify Adapter for SAP Integration Suite at version 1.4.0, described as facilitating connectivity to Shopify APIs and supporting both the REST and GraphQL Admin APIs. And Flexso’s package description says its integration “leverages webhooks for real-time data synchronization,” which means it inherits every delivery and ordering guarantee problem covered above. The reconciliation job is as mandatory on an SAP stack as it is on a custom build.
SAP Business One is a separate product with a separate answer, and the answer is that no Shopify package exists for it in the Hub catalog at all. A Business One merchant connecting Shopify is on a third-party connector or on custom work against the Service Layer or the integration framework. The SAP Business One app on the Shopify App Store is published by eShopSync, a third party, and syncs products and categories from Business One to Shopify in one direction. Note also that the DI API isn’t deprecated, and SAP publishes a page on functional limitations of the Service Layer versus the DI API, so “just use the Service Layer” deserves a read of that page first.
One timing factor drives a lot of these projects. Per SAP’s maintenance strategy page, mainstream maintenance for Business Suite 7 core applications, which includes SAP ERP 6.0, runs to the end of 2027, with extended maintenance available for three years from the beginning of 2028 to the end of 2030 at a premium of two percentage points on the maintenance basis, and customer-specific maintenance after that. SAP has also committed to at least one S/4HANA release being in maintenance until 2040. A brand on ECC is making an ERP decision and an ecommerce integration decision inside the same budget cycle, which is a reason to design the Shopify side to survive the ERP migration underneath it.
Native Connector or Middleware for Your Shopify ERP Integration
An ERP integration is usually a purchase decision before it’s a build decision: install a first-party app, hire an agency to build flows on an iPaaS, or write the connector yourself. The honest way to choose is by scope rather than by philosophy.
If your ERP has a first-party connector, the record set matches what you need, and the documented limits are acceptable, the native connector is the cheapest path with the clearest published price. The moment your requirements exceed those limits, and multiple stores, bidirectional refunds, transfer orders, an unsupported record type or an ERP with no first-party connector all qualify, you’re buying middleware or building. Here’s the coverage picture as published.
| ERP | First-party Shopify connector | Coverage note |
|---|---|---|
| Oracle NetSuite | Yes, on the Shopify App Store | One store per connector, refunds one direction, no transfer orders |
| Dynamics 365 Business Central | Yes, first-party and open source | Business Central online only, not on-premises, not Embed App |
| Dynamics 365 Finance and Operations | No | Microsoft states the connector doesn’t work with other D365 apps |
| SAP S/4HANA Cloud public edition | SAP-published Hub package, not SAP-certified | Eight business processes, eleven integration flows |
| SAP S/4HANA Cloud private edition | Partner package, not SAP-certified | One artifact, one direction |
| SAP Business One | No package in the Hub catalog | Third-party connector or custom Service Layer work |
Price transparency runs the other way from what you’d expect. The native connectors publish numbers on the App Store, while most iPaaS vendors publish none: Celigo names Standard, Professional and Enterprise editions with no currency figures, Workato’s pricing page carries no plan names and no amounts at all, MuleSoft lists every tier as contact for pricing, and Patchworks marks Growth, Professional and Enterprise as enquire for pricing. Two publish something: Boomi lists Pay-As-You-Go at $99 per month plus usage, with every named subscription tier quote-only, and Alumio lists Connect Lite at EUR 499 per month, qualified on its own page as a starting price that scales by capacity.
The metering model prices your architecture rather than your revenue, which is why two brands at identical order volume get different invoices. Patchworks defines an operation as counted when “Patchworks sends or receives a data payload, regardless of how many items that payload contains,” with its tiers set at up to 150,000, 400,000 and 1,000,000 operations and three, four and eight connectors respectively. Under that model, a chatty sync that pushes one product per call costs several times what a batched one does at identical order volume, so batching design has a direct line to the invoice.
Four product facts to have straight before vendor calls. Celigo ships two distinct Shopify and NetSuite products, a managed Integration App and a template, both on the Celigo platform, and its published flow list on the Integration App page names thirteen prebuilt flows, covering orders, customers, customer deposits, items, item inventory, billing, fulfillment in both directions, cancellations, refunds and a payout-report add-on. Boomi’s current platform name is the Boomi Enterprise Platform and it markets a NetSuite and Shopify Integration Accelerator. Workato documents both a NetSuite SOAP and a NetSuite REST connector plus SAP RFC and OData.
Alumio’s integration list names SAP, S/4HANA, Business One, Business byDesign, ECC and Dynamics 365 Finance and Operations, and doesn’t list NetSuite. Every one of those is a vendor claim from a vendor page, and every one should be confirmed against your record set in a trial.
Marketplace presence varies too. Patchworks has a Shopify App Store listing, free to install and showing no reviews yet as of August 24, 2026, while the Celigo and Workato partner pages both show zero apps. That’s a distribution choice rather than a capability signal, but it changes how billing, permissions and installation work.
What to Settle Before You Sign a Shopify ERP Integration Contract
None of the following is exotic. All of it is cheaper to answer in a scoping call than in a war room, and most of it never appears in a statement of work unless someone puts it there.
- Which system owns each object, and for the product record, which system owns each field
- Who performs the Shopify API version uptake, on what schedule, and under whose budget
- Whether the reconciliation job is in scope for launch or deferred, and what its cadence and alerting look like
- How your retry path stays inside Shopify's idempotency key retention window, and what happens to anything replayed later
- Whether your ERP tier's concurrency budget is shared with other integrations, and who arbitrates when they collide
- Which direction refunds flow, and what the process is when a refund is issued on the wrong side
- How historical order access is obtained, and when that request goes in
- Which environment hosts UAT, whether it can install a custom app, and which financial flows can't be tested there
- What the middleware meter counts, and what your projected sync volume does to it at peak
Answer those and the build is mostly mechanical. Skip them and the integration ships, syncs, and quietly disagrees with itself until someone in finance finds it.
If you’re scoping a Shopify ERP integration and want a partner who’ll put the version-pin question in the contract instead of the change log, that’s the kind of Shopify integration services work we do. Take a look at how BLKDG works as a Shopify Partner, then tell us about your Shopify and ERP stack and we’ll tell you where the gaps are before you spend anything.
Not sure where the gap is? That's exactly what the Digital Marketing Growth Audit is for.
A free, no-obligation look at where your site can win more traffic and conversions, with a clear digital marketing roadmap to get there. Just a straight read on where your digital presence stands and where it's headed.
