# Shopify ERP Integration: Connecting Inventory, Orders and Fulfillment

> How a Shopify ERP integration should move products, stock, orders, fulfillment, refunds and payouts, and how #10 reviews one that has started to drift.

Human version: https://nr10.com/shopify-erp-integration/
Published: November 4, 2026

---

Reading Time:   11 min.

A Shopify ERP integration works when every record has one owner and one direction: the ERP usually owns items and physical stock, Shopify owns the sale, the warehouse owns the shipment, and accounting owns the money once it lands. At #10, we review and repair existing connections between Shopify or Shopify Plus and the systems behind the store. We also maintain and extend them. Most of the problems we see are not bugs in the connector. They come from a record that two systems both think they own, or that neither does.

This guide is for ecommerce, operations and finance leads who already run a Shopify store alongside an ERP system, or are about to integrate one. It covers what has to move, which way it should move, and where the handoffs usually break. If you run Fishbowl specifically, our [Fishbowl and Shopify guide](https://nr10.com/fishbowl-inventory-shopify-for-multi-channel-brands/) goes deeper on diagnosing an existing connection. Running NetSuite? The sibling article on [NetSuite and Shopify integration](https://nr10.com/netsuite-shopify-integration/) maps the same ideas to NetSuite’s record types.

## What a Shopify ERP integration actually connects

An ERP (enterprise resource planning) system is where a business keeps its items, stock, purchasing and often its accounting. Cloud ERPs such as NetSuite and Microsoft Dynamics, along with SAP, Acumatica, Odoo and inventory systems like Fishbowl, all fill some or all of that role. Whichever one you run, “the integration” sounds like one pipe. In practice it is a set of separate syncs that happen to share a connector, and each one has its own timing and failure modes:

- **Items.** Which ERP item a Shopify product variant represents, matched on SKU or another shared key.
- **Inventory.** How much of each item can be sold, at each location, and how often that number is refreshed.
- **Orders.** How a Shopify sale, POS sale or wholesale order becomes a sales order in the ERP, ready for order processing.
- **Fulfillment.** How shipment status and tracking get back to Shopify so the customer is notified.
- **Customers.** How customer data, including B2B company accounts, reaches the ERP (and your CRM, if you run one) without duplicates.
- **Refunds and returns.** How money going back to a customer, and stock coming back to a shelf, reach the ERP and the books.
- **Payments and payouts.** How the cash the payment processor deposits is matched to the orders it covers.

A brand can have a healthy order sync and a broken refund sync at the same time. That is why we never treat “is the integration working?” as one question. We ask it once per record.

Our longest-running example is a premium California olive oil and wine brand. It runs Shopify Plus with Fishbowl for inventory and QuickBooks Online for accounting. On top of that sit Shopify POS in several retail locations, a B2B wholesale portal and subscriptions. The work there has touched every item on that list. We’ve fixed stalled order imports and wrong prices on downloaded orders. We’ve mapped subscription line items, POS locations, partial refunds and partial fulfillments, and traced payments into accounting. None of those were the same problem, even when they arrived in the same support ticket.

## Who owns each record, and which way it flows

The single most useful document in any Shopify ERP integration is a short map: for each record, where it starts, where it goes, and how often. Click a record type below to see the pattern we most often find, and what tends to go wrong with it.

<div class=“shopify-erp-integration-syncmap” data-explainer=“shopify-erp-integration-syncmap”>

| Record | Usually starts in | Flows to | Watch for |
| --- | --- | --- | --- |
| Products and SKUs | ERP (item master) | Shopify, warehouse | SKUs that don’t match, seasonal replacements, bundles |
| Inventory | ERP or warehouse | Shopify, per location | On hand vs. available, sync timing, POS locations |
| Prices | Shopify (retail), ERP (wholesale) | Each other, by channel | Wholesale orders importing at retail price |
| Customers | Shopify | ERP, accounting | Duplicate customers, B2B companies vs. buyers |
| Orders | Shopify (online, POS, B2B) | ERP, then warehouse | Stalled imports, subscription and bundle lines |
| Fulfillment and tracking | Warehouse or ERP | Shopify | Partial shipments, orders split across locations |
| Refunds and returns | Shopify | ERP, accounting | Partial refunds, restock vs. no restock |
| Tax | Shopify or tax service | Accounting, tax filing | Order types that skip the tax workflow |
| Payouts | Payment processor | Accounting | Fees, refunds and chargebacks netted out |

</div>

That table is a common default, not a rule. Some brands manage product content and retail prices in Shopify and only push SKUs to the ERP. Some run the warehouse directly in the ERP, so fulfillment comes from there rather than a separate 3PL. What matters is that your team can write the map down, and that the connector’s settings agree with it.

This is the part of ERP integration for Shopify that no connector can decide for you. When two systems can both edit the same field, decide which one wins. The usual symptom of an undecided owner is a value that changes back. Someone fixes a price in Shopify. The next sync overwrites it from the ERP. The fix looks like it never happened.

## How orders move from checkout to the warehouse

The order sync carries the most weight, so it gets the most attention. A typical path looks like this:

<figure class=“ar-fig”>
<svg viewBox=“0 0 640 560” role=“img” aria-labelledby=“sei-flow-t sei-flow-d”>
<title id=“sei-flow-t”>One order’s path through a Shopify ERP integration</title>
<desc id=“sei-flow-d”>Six steps. Shopify records the sale. The ERP creates a sales order. The warehouse picks and ships. Shopify receives tracking and notifies the customer. A refund starts in Shopify and is passed to the ERP. Accounting matches the payout to the orders it covers.</desc>
<g>
<line x1=“44” y1=“60” x2=“44” y2=“500” style=“stroke:var(–line);stroke-width:2”/>
<circle cx=“44” cy=“60” r=“18” style=“fill:var(–ar-c1)”/><text x=“44” y=“66” text-anchor=“middle” style=“font-size:16px;fill:#fff”>1</text>
<text x=“80” y=“55” style=“font-size:20px”>Sale recorded</text><text x=“80” y=“80” style=“font-size:15px;fill:var(–muted)”>online, POS or wholesale</text>
<rect x=“470” y=“38” width=“150” height=“40” rx=“20” style=“fill:none;stroke:var(–ar-c1);stroke-width:2”/><text x=“545” y=“64” text-anchor=“middle” style=“font-size:16px”>Shopify</text>
<circle cx=“44” cy=“148” r=“18” style=“fill:var(–ar-c2)”/><text x=“44” y=“154” text-anchor=“middle” style=“font-size:16px;fill:#fff”>2</text>
<text x=“80” y=“143” style=“font-size:20px”>Sales order created</text><text x=“80” y=“168” style=“font-size:15px;fill:var(–muted)”>items, prices, ship-from</text>
<rect x=“470” y=“126” width=“150” height=“40” rx=“20” style=“fill:none;stroke:var(–ar-c2);stroke-width:2”/><text x=“545” y=“152” text-anchor=“middle” style=“font-size:16px”>ERP</text>
<circle cx=“44” cy=“236” r=“18” style=“fill:var(–ar-c0)”/><text x=“44” y=“242” text-anchor=“middle” style=“font-size:16px;fill:#fff”>3</text>
<text x=“80” y=“231” style=“font-size:20px”>Picked and shipped</text><text x=“80” y=“256” style=“font-size:15px;fill:var(–muted)”>stock drops, tracking issued</text>
<rect x=“470” y=“214” width=“150” height=“40” rx=“20” style=“fill:none;stroke:var(–ar-c0);stroke-width:2”/><text x=“545” y=“240” text-anchor=“middle” style=“font-size:16px”>Warehouse</text>
<circle cx=“44” cy=“324” r=“18” style=“fill:var(–ar-c1)”/><text x=“44” y=“330” text-anchor=“middle” style=“font-size:16px;fill:#fff”>4</text>
<text x=“80” y=“319” style=“font-size:20px”>Customer notified</text><text x=“80” y=“344” style=“font-size:15px;fill:var(–muted)”>fulfillment and tracking</text>
<rect x=“470” y=“302” width=“150” height=“40” rx=“20” style=“fill:none;stroke:var(–ar-c1);stroke-width:2”/><text x=“545” y=“328” text-anchor=“middle” style=“font-size:16px”>Shopify</text>
<circle cx=“44” cy=“412” r=“18” style=“fill:var(–ar-c1)”/><text x=“44” y=“418” text-anchor=“middle” style=“font-size:16px;fill:#fff”>5</text>
<text x=“80” y=“407” style=“font-size:20px”>Refund issued</text><text x=“80” y=“432” style=“font-size:15px;fill:var(–muted)”>then passed to the ERP</text>
<rect x=“470” y=“390” width=“150” height=“40” rx=“20” style=“fill:none;stroke:var(–ar-c1);stroke-width:2”/><text x=“545” y=“416” text-anchor=“middle” style=“font-size:16px”>Shopify</text>
<circle cx=“44” cy=“500” r=“18” style=“fill:var(–ar-c3)”/><text x=“44” y=“506” text-anchor=“middle” style=“font-size:16px;fill:#fff”>6</text>
<text x=“80” y=“495” style=“font-size:20px”>Payout matched</text><text x=“80” y=“520” style=“font-size:15px;fill:var(–muted)”>deposit tied to its orders</text>
<rect x=“470” y=“478” width=“150” height=“40” rx=“20” style=“fill:none;stroke:var(–ar-c3);stroke-width:2”/><text x=“545” y=“504” text-anchor=“middle” style=“font-size:16px”>Accounting</text>
</g>
</svg>
<figcaption>One order, six handoffs. Each step is a separate sync with its own owner, and a failure at any one of them can look like “the integration is broken.”</figcaption></figure>

Three things decide whether that path holds up.

**What triggers the import.** Some connectors import every paid order. Others filter by tag, location, sales channel or fulfillment status. For the olive oil and wine brand, POS orders marked to ship needed Shopify Flow to tag them and map their location groups before the ERP would route them correctly. If an order type never arrives, check the trigger first.

**What the order carries.** Line items, prices, discounts, shipping method, tax, gift messages, subscription details and the ship-from location all have to land in the right ERP fields. A discount that Shopify applies at the cart level may need to become a line-level price in the ERP. A bundle sold as one Shopify product may need to break into its components so the right stock is reserved.

**What happens when it fails.** Every connector will eventually fail to import an order. The question is whether anyone notices before the customer does. Agree who checks the error queue. Then agree how they check for a partial order already in the ERP, and how they retry without creating a duplicate.

## Inventory sync: the number on the product page

Inventory is the sync customers see. When stock levels are wrong, they either buy something that isn’t there or can’t buy something that is.

Shopify tracks inventory per location. Your ERP probably tracks it per warehouse, bin or site. The integration has to agree on three things:

Good inventory management on Shopify depends on the integration agreeing three things:

1. **Which number to publish.** Stock on hand, stock available to sell after open orders, or something adjusted by a buffer. These are different numbers. The right one depends on how fast you sell and how often the sync runs.
2. **Which locations map to which.** A retail shop, an outlet and a warehouse might each be a Shopify location. If the ERP has one site for all three, or three sites that don’t line up with Shopify’s, counts will drift in ways that look random.
3. **How often it runs.** Few connectors are truly real-time. A sync every few minutes behaves very differently from a nightly batch, especially during a promotion or holiday peak.

Bundles and kits deserve their own test. If a gift set is a product in Shopify but a list of components in the ERP, decide whether Shopify should show the gift set’s own count or a count calculated from its components. Then check that selling one actually reduces the components.

## Fulfillment, refunds and payouts: the return trip

Most teams spend their integration budget on the outbound trip (order to warehouse) and very little on the return trip. That is where we find a lot of the long-running problems.

**Fulfillment.** When the warehouse ships, Shopify needs to know, with tracking, so the customer gets their notification. Partial shipments are where it breaks: two boxes on different days, or one item backordered. Test a partial shipment on purpose. Shopify should show the order as partially fulfilled, not closed or untouched.

**Refunds and returns.** A refund issued in Shopify has to reach the ERP, and the ERP has to know whether the item came back to stock. Partial refunds are the usual gap. For the olive oil and wine brand, partial refunds and partial fulfillments on POS orders each needed their own mapping before the ERP handled them correctly. A refund that never reaches the ERP leaves the sales order looking fully paid. Finance finds it at month end.

**Invoices and payouts.** Some ERPs bill a Shopify order as an invoice, others as a cash sale or sales receipt. Either way, your payment processor doesn’t deposit order totals. It deposits a batch, net of fees, refunds, chargebacks and adjustments, sometimes covering several days. Matching that deposit to the orders inside it is an accounting job, and it’s the step most integrations leave out. If finance is reconciling payouts by hand in a spreadsheet, that is a real cost, even when every other sync is working.

Tax sits alongside all three. Where it’s calculated (Shopify, a tax service or the ERP) and where it’s reported have to agree. For the same brand, we automated tax imports for order types that didn’t follow the standard path, such as wholesale marketplace orders and certain fee orders. Tax rates by retail location were part of the POS setup too.

## Choosing how the connection is built

There are three common integration options for connecting Shopify to an ERP. Each one moves the same records. They differ in who maintains the logic and how much customization you can add. Shopify also runs a [Global ERP Program](https://www.shopify.com/news/the-best-in-commerce-joins-the-best-in-enterprise-shopify-launches-global-erp-program), launched in 2021 with ERP vendors including Oracle NetSuite, Microsoft Dynamics 365 Business Central, Infor, Acumatica and Brightpearl, so that their own connectors are available in the Shopify App Store. A vendor-built connector is a sensible place to start if your ERP has one.

| Approach | What it is | Good fit when | Watch for |
| --- | --- | --- | --- |
| Prebuilt connector app | A Shopify app or ERP add-on with fixed mappings | Your flows are close to standard | Limited room for custom order types |
| Integration platform (iPaaS) | Middleware with configurable flows between systems | Several systems, some custom rules | Another subscription, and its own error queue |
| Custom API integration | Code written against the Shopify and ERP APIs | Unusual flows nothing else handles | Someone has to own and maintain it |

We don’t sell any of these, and we don’t build ERP integrations from scratch. Our work starts where the connection already exists: reviewing how it’s configured, fixing what’s broken and extending it when the business adds a channel, a location or a new order type. If a review shows you’ve outgrown the connector, we’ll say so plainly. We also don’t recommend one ERP over another. Still choosing the right ERP software? Ask each vendor how it handles every record in the map above.

## Wholesale, POS and subscriptions: where the defaults stop working

Automation in most connectors assumes one kind of order: an online retail sale shipped from one warehouse. Every channel you add stretches that assumption.

**Wholesale.** A wholesale order may share a SKU with a retail order but carry a different price, a minimum, different shipping rules and different tax treatment. Shopify B2B on Shopify Plus supports company accounts, catalogs and payment terms. The ERP needs to receive those orders at the wholesale price, not have a sync push the retail price back onto them. For the olive oil and wine brand, we fixed a wholesale price that reverted to retail on B2B orders. We also set up an order minimum and hid some shipping options from wholesale buyers. A custom app we built marks B2B companies as tax exempt.

**POS.** Each retail location needs to map to the right ERP location, with the right tax. Sales taken in the shop and sales taken in the shop but shipped later need different routing. Gratuities, if you take them, need somewhere to go.

**Subscriptions.** Subscription orders are created by an app, not a shopper, and they often carry extra line-item properties. Make sure the connector imports them like any other order, and that a product swap (a new vintage or harvest, say) doesn’t leave the ERP expecting an item that no longer sells.

Before you add a channel, put one real order of that type through the whole path in a test, from checkout to payout. It’s much cheaper than finding out from the warehouse.

## How we review an existing Shopify ERP integration

When a brand brings us an integration that has started to drift, we follow the same order every time:

1. **Start from a record that doesn’t match.** A specific order, SKU or location, with what each system currently shows and what it should show.
2. **Write the ownership map.** Every record type, its owner, its direction and its timing, confirmed with operations and finance rather than guessed from the settings.
3. **Trace real orders end to end.** At least one per order type: online, POS, POS shipped, wholesale, subscription, and one with a partial refund.
4. **Separate findings from questions.** A confirmed mapping error is a scoped fix. An assumption about how a bundle should deduct needs investigating first.
5. **Fix, test, document.** Each fix gets a test order and a short note for the staff who run imports, so the next exception has an owner. For the olive oil and wine brand, we wrote staff procedures for imports and Shopify workflows alongside the ongoing sync work.

That review is the starting point of our [Shopify ERP and inventory integration service](https://nr10.com/what-we-do/shopify-erp-integration/). We use it on [Shopify migrations](https://nr10.com/what-we-do/replatforming-to-shopify/) too. The connection from the ERP to Shopify is often the slowest part of a move to settle.

## Questions operations teams ask

### What does a Shopify ERP integration agency actually do?

It should look past the storefront to the systems behind it. Ask any agency to trace a real order from checkout through the ERP, the warehouse, the refund and the payout, and to tell you which of those steps they’ve maintained before. Our hands-on work is Shopify Plus with Fishbowl, Shopify POS, B2B wholesale and QuickBooks Online for a premium DTC brand.

### Why does our Shopify inventory keep drifting from the ERP?

Usually it’s one of four things. A variant is mapped to the wrong item. A location is mapped to the wrong site. The sync runs less often than you sell. Or someone edits one side and the other side overwrites it. Bundles that don’t deduct their components cause it too. Pick one SKU that’s wrong and trace it, rather than adjusting counts by hand.

### Should Shopify or the ERP be the system of record?

For most records, the ERP owns items and physical stock, and Shopify owns the sale and the customer’s interaction. The split for prices and product content varies. The important part is that each field has exactly one owner, written down, so a sync never overwrites a deliberate change.

### When does a Shopify store need an ERP?

Usually when stock lives in more than one place, when you sell through more than one channel (retail, POS, wholesale), or when finance is re-keying orders into accounting by hand. Shopify handles a single-warehouse retail store well on its own. Once purchasing, multiple locations and wholesale terms enter the picture, the ERP becomes the record for items and stock, and the integration becomes the thing to get right.

### Can one integration handle retail, POS and wholesale orders?

Usually, yes, but not on default settings. Each order type needs its own trigger, routing, pricing and tax rules confirmed, and each needs a test order. Wholesale pricing and POS location mapping are the two areas where we most often find gaps.

### Do you work with NetSuite?

Our hands-on ERP work is with Fishbowl and QuickBooks Online. The review method is the same for any ERP: ownership, direction, timing, and a real order traced end to end. The [NetSuite and Shopify article](https://nr10.com/netsuite-shopify-integration/) covers what that looks like with NetSuite’s record types. Send us your stack and we’ll tell you honestly whether we’re a fit before you pay for anything.

## Start with the order that doesn’t reconcile

You don’t need a full diagnosis before you get in touch. Bring one order, SKU or payout that doesn’t match, tell us which systems are involved, and who on your team can speak for the warehouse and for finance.

[Talk to #10](https://nr10.com/contact/) about your Shopify ERP integration. We’ll start with that one record and work outward from there. You can also see the rest of our [Shopify and Shopify Plus work](https://nr10.com/what-we-do/shopify/).
