A NetSuite Shopify integration has to move six things reliably: items, inventory, orders, fulfillments, refunds and payouts. Each one needs a single owner and a single direction, and each one becomes a specific NetSuite record that finance will later have to reconcile. At #10, we work on the Shopify store side of these connections and review how the handoffs to the ERP behind the store actually behave. Our hands-on ERP work has been with Fishbowl and QuickBooks Online rather than NetSuite, so this article is about the integration patterns we know well and how they map onto NetSuite. We are not a NetSuite implementer, and we don’t sell connectors.
That distinction matters because most NetSuite and Shopify problems are not NetSuite problems. They are decisions nobody made when they chose to integrate Shopify with NetSuite: which system owns the price, what happens to a partial refund, how a payout gets matched to the orders inside it. Those decisions are the same whichever ERP sits behind the store.
Why “it syncs” is not the same as “it reconciles”
Oracle NetSuite is a cloud ERP. For an ecommerce brand it usually holds the items, inventory, purchasing, order fulfillment records and the general ledger, while Shopify holds the storefront, checkout and customer experience. Most connector demos stop when a Shopify order appears in NetSuite as a sales order. That’s one handoff out of several. A brand can have every order importing cleanly and still have a finance team rebuilding month end by hand, because refunds, fees and payouts take a different path from the original sale.
Take a premium California olive oil and wine brand we’ve supported for years. Its Shopify Plus store connects to Fishbowl for inventory and QuickBooks Online for accounting. Shopify POS runs in several retail locations, with a B2B wholesale portal on top. We’ve worked on stalled order imports and wrong prices on imported orders there. We’ve mapped subscription line items, POS locations, partial refunds and partial fulfillments. We’ve also traced gifting orders into accounting to see whether they posted as invoices or sales receipts. The ERP is different from NetSuite. The list of things that broke would look familiar to any NetSuite team.
If you run Fishbowl, our Fishbowl and Shopify guide covers that connection in detail. For the general case, our Shopify ERP integration guide has an interactive ownership map.
Which system owns which record in a NetSuite Shopify integration
Start with a written ownership table. Every row should be confirmed by the person who’d be blamed if it were wrong: operations for stock and shipments, finance for money and tax.
| Record | Usually owned by | Becomes in NetSuite | Decide up front |
|---|---|---|---|
| Items and SKUs | NetSuite | Inventory, kit or assembly item | How Shopify variants map to NetSuite items |
| Product content | Shopify | (often not synced) | Whether NetSuite needs titles and images at all |
| Inventory | NetSuite | Quantity by location | On hand or available, and how often it syncs |
| Retail prices | Shopify or NetSuite | Price level | One owner, so a sync never undoes a fix |
| Wholesale prices | NetSuite or Shopify B2B | Price level or customer pricing | Which one the order should import at |
| Customers | Shopify | Customer record | How to avoid a new duplicate on every order |
| Orders | Shopify | Sales order | Which channels and order types import |
| Fulfillments | NetSuite or 3PL | Item fulfillment | How partial shipments return to Shopify |
| Billing | NetSuite | Cash sale or invoice | Which one, per channel |
| Refunds | Shopify | Cash refund or credit memo | Restock or not, and partial amounts |
| Payouts | Payment processor | Deposit | How fees and refunds are recorded |
The NetSuite record names in that table are the standard ones, but how a connector uses them is configurable. Some create a cash sale as soon as an order ships. Some create an invoice and apply a payment. Some record a customer deposit at checkout. Each choice changes how finance reconciles later. Make it on purpose, not by accepting the connector’s default.
The five flows that have to work
Every NetSuite Shopify integration is really five or six separate syncs sharing one connector, plus customer data riding along with orders. This is how they usually run:
<figure class=“ar-fig”>
<svg viewBox=“0 0 640 520” role=“img” aria-labelledby=“nsi-flow-t nsi-flow-d”>
<title id=“nsi-flow-t”>Five flows between Shopify and NetSuite</title>
<desc id=“nsi-flow-d”>Order: Shopify to NetSuite sales order. Inventory: NetSuite to Shopify, quantity by location. Fulfillment: NetSuite item fulfillment to Shopify tracking. Refund: Shopify to NetSuite cash refund or credit memo. Payout: payment processor to a NetSuite deposit.</desc>
<text x=“110” y=“34” text-anchor=“middle” style=“font-size:18px;font-weight:700”>Shopify</text>
<text x=“530” y=“34” text-anchor=“middle” style=“font-size:18px;font-weight:700”>NetSuite</text>
<line x1=“20” y1=“50” x2=“620” y2=“50” style=“stroke:var(–line);stroke-width:1”/>
<defs><marker id=“nsi-ah” viewBox=“0 0 10 10” refX=“9” refY=“5” markerWidth=“7” markerHeight=“7” orient=“auto-start-reverse”><path d=“M0,0 L10,5 L0,10 z” style=“fill:var(–ink)”/></marker></defs>
<rect x=“20” y=“70” width=“180” height=“56” rx=“10” style=“fill:none;stroke:var(–ar-c1);stroke-width:2”/><text x=“110” y=“104” text-anchor=“middle” style=“font-size:18px”>Order placed</text>
<rect x=“440” y=“70” width=“180” height=“56” rx=“10” style=“fill:none;stroke:var(–ar-c2);stroke-width:2”/><text x=“530” y=“104” text-anchor=“middle” style=“font-size:18px”>Sales order</text>
<line x1=“206” y1=“98” x2=“432” y2=“98” style=“stroke:var(–ink);stroke-width:2” marker-end=“url(#nsi-ah)”/><text x=“320” y=“88” text-anchor=“middle” style=“font-size:15px;fill:var(–muted)”>1 order</text>
<rect x=“20” y=“160” width=“180” height=“56” rx=“10” style=“fill:none;stroke:var(–ar-c1);stroke-width:2”/><text x=“110” y=“194” text-anchor=“middle” style=“font-size:18px”>Stock shown</text>
<rect x=“440” y=“160” width=“180” height=“56” rx=“10” style=“fill:none;stroke:var(–ar-c2);stroke-width:2”/><text x=“530” y=“194” text-anchor=“middle” style=“font-size:18px”>Qty by location</text>
<line x1=“432” y1=“188” x2=“206” y2=“188” style=“stroke:var(–ink);stroke-width:2” marker-end=“url(#nsi-ah)”/><text x=“320” y=“178” text-anchor=“middle” style=“font-size:15px;fill:var(–muted)”>2 inventory</text>
<rect x=“20” y=“250” width=“180” height=“56” rx=“10” style=“fill:none;stroke:var(–ar-c1);stroke-width:2”/><text x=“110” y=“284” text-anchor=“middle” style=“font-size:18px”>Tracking sent</text>
<rect x=“440” y=“250” width=“180” height=“56” rx=“10” style=“fill:none;stroke:var(–ar-c2);stroke-width:2”/><text x=“530” y=“284” text-anchor=“middle” style=“font-size:18px”>Item fulfillment</text>
<line x1=“432” y1=“278” x2=“206” y2=“278” style=“stroke:var(–ink);stroke-width:2” marker-end=“url(#nsi-ah)”/><text x=“320” y=“268” text-anchor=“middle” style=“font-size:15px;fill:var(–muted)”>3 fulfillment</text>
<rect x=“20” y=“340” width=“180” height=“56” rx=“10” style=“fill:none;stroke:var(–ar-c1);stroke-width:2”/><text x=“110” y=“374” text-anchor=“middle” style=“font-size:18px”>Refund issued</text>
<rect x=“440” y=“340” width=“180” height=“56” rx=“10” style=“fill:none;stroke:var(–ar-c2);stroke-width:2”/><text x=“530” y=“374” text-anchor=“middle” style=“font-size:18px”>Refund or credit</text>
<line x1=“206” y1=“368” x2=“432” y2=“368” style=“stroke:var(–ink);stroke-width:2” marker-end=“url(#nsi-ah)”/><text x=“320” y=“358” text-anchor=“middle” style=“font-size:15px;fill:var(–muted)”>4 refund</text>
<rect x=“20” y=“430” width=“180” height=“56” rx=“10” style=“fill:none;stroke:var(–ar-c3);stroke-width:2;stroke-dasharray:6 4”/><text x=“110” y=“456” text-anchor=“middle” style=“font-size:16px”>Payment</text><text x=“110” y=“476” text-anchor=“middle” style=“font-size:16px”>processor</text>
<rect x=“440” y=“430” width=“180” height=“56” rx=“10” style=“fill:none;stroke:var(–ar-c2);stroke-width:2”/><text x=“530” y=“464” text-anchor=“middle” style=“font-size:18px”>Deposit</text>
<line x1=“206” y1=“458” x2=“432” y2=“458” style=“stroke:var(–ink);stroke-width:2” marker-end=“url(#nsi-ah)”/><text x=“320” y=“448” text-anchor=“middle” style=“font-size:15px;fill:var(–muted)”>5 payout</text>
</svg>
<figcaption>Orders and refunds flow from Shopify to NetSuite. Inventory and fulfillments flow back. The payout comes from the payment processor (dashed box), not from Shopify’s order data, and is the flow most often left to a spreadsheet.</figcaption>
</figure>
1. Orders
A Shopify order becomes a NetSuite sales order. The questions are which orders import (online only, or POS and B2B too), when (on payment, on a schedule), and what they carry. This is where order processing starts, so it gets the most scrutiny. Line items need to land on the right NetSuite items. Discounts, shipping, tax, gift messages and subscription details all need a field to go to. A discount Shopify applies to the whole cart may have to become a discount line or adjusted line prices, and finance should agree which.
On the olive oil and wine brand’s Fishbowl connection, POS orders marked to ship needed Shopify Flow to tag them and set their location before the ERP routed them correctly. NetSuite connectors have their own filters and conditions, and the same kind of gap appears when an order type falls outside them.
2. Inventory
NetSuite usually owns quantity, by location, because receiving, transfers and the rest of inventory management happen there. Shopify also tracks inventory by location, so the mapping between Shopify locations and NetSuite locations has to be exact. Decide whether Shopify should show quantity on hand or quantity available after open orders, and how often that number is pushed. Few connectors are truly real-time. One that syncs on a schedule will oversell during a busy promotion if the interval is long.
Kits and bundles need a deliberate rule. If a gift set is a kit item in NetSuite, its availability depends on its components, and Shopify needs to show the right number for it.
3. Fulfillments
When the warehouse ships, NetSuite records an item fulfillment, and the tracking needs to come back to Shopify so the customer is notified. If you use a 3PL, the shipment may come from the 3PL into NetSuite first, or straight to Shopify. Either is fine. Having both is how orders end up marked fulfilled twice, or not at all. Test a partial shipment and an order split across two locations.
4. Refunds and returns
Refunds usually start in Shopify or at a POS register. NetSuite needs a record of the money (a cash refund or credit memo, depending on how the sale was billed) and, if the item came back, a return that puts it back in stock. Partial refunds are where this goes wrong most often. In our own work, partial refunds and partial fulfillments on POS orders each needed their own mapping before the ERP handled them properly.
5. Payouts
Shopify Payments, PayPal and other processors deposit money in batches, net of fees, refunds and chargebacks. A deposit in the bank doesn’t equal any one order. Someone has to match it to the orders inside it and record the fees. Oracle’s own connector documentation, for example, describes a payout sync that adds Shopify payments and fees to NetSuite deposits, and it depends on how orders are billed (cash sales rather than invoices) and how refunds are recorded. That’s why the billing decision in the ownership table matters. It decides whether payouts can be matched automatically at all.
Tax sits across all five. Decide where it’s calculated (Shopify, a tax service or NetSuite) and make sure the amount NetSuite records matches what the customer was charged. For our olive oil and wine client, we automated tax imports for order types that didn’t follow the standard path, such as wholesale marketplace orders. The unusual order types are the ones that skip a workflow.
Connector, middleware or custom code
There are three common ways to connect NetSuite and Shopify:
- A prebuilt Shopify connector. Oracle offers its own NetSuite Connector, and other NetSuite connectors are listed in the Shopify App Store. NetSuite was one of the launch partners in Shopify’s Global ERP Program in 2021. Fast to start, with mappings you configure rather than write.
- An integration platform (iPaaS). Integration solutions such as Celigo run flows between Shopify, NetSuite and other systems, with more room for custom rules and its own error dashboard.
- Custom integration. Code written against the Shopify API and NetSuite’s APIs or SuiteScript. The most flexible, and the most dependent on whoever wrote it.
We don’t recommend one over the others in general. It depends on how many order types you have, how much custom logic they need and who will maintain the connection in two years. What we do recommend: write down the ownership table and the five flows before anyone configures anything. Every option asks the same questions in a different interface.
What we check on the Shopify side
Our work is on the Shopify and Shopify Plus side of the connection, and that’s where a lot of the decisions live. Before blaming the connector, we look at:
- Variant and SKU hygiene. Duplicate SKUs, blank SKUs and variants that were replaced but not remapped.
- Locations. Whether every Shopify location, including each POS register’s location, has a clear NetSuite counterpart.
- B2B setup. On Shopify Plus, company accounts, catalogs and payment terms for wholesale buyers, and whether those orders import at the wholesale price. On our olive oil and wine client’s wholesale portal, we fixed a price that reverted to retail on B2B orders. We also built a custom app that marks B2B companies as tax exempt.
- Apps that create orders. Subscription apps, membership apps and wholesale marketplaces all create orders that look slightly different from a checkout order. Each needs a test.
- Shopify Flow and tags. Any automation that tags, holds or reroutes orders before the connector picks them up.
If you’re moving onto Shopify Plus from another platform with NetSuite already in place, the same checks belong in the replatforming plan. The NetSuite connection is often the last part of a migration to settle. The replatform check in our Labs is a quick way to see what else is on that list.
How to test a NetSuite Shopify integration before you trust it
Put one real order of each type through the whole path, from checkout to the bank deposit:
- A standard online order.
- A POS sale, and a POS sale shipped to the customer.
- A wholesale order at wholesale pricing.
- A subscription order, if you sell subscriptions.
- A bundle or kit.
- An order with a partial shipment.
- An order with a partial refund, with and without restocking.
Do it in a sandbox or with test orders you can reverse, and export what each system recorded so you can compare them side by side. For each one, compare Shopify and NetSuite at every step: line items, prices, tax, shipping, status and location. Then have finance find the payout that contains it and confirm it reconciles. Record which differences are intentional.
When something fails, keep the evidence before anyone fixes it by hand. A manually corrected order is useful to finance and useless to whoever is trying to find out why it failed.
Questions finance and operations teams ask
Does #10 do NetSuite implementations?
No. We don’t implement or configure NetSuite, and we’re not a NetSuite partner. We work on the Shopify and Shopify Plus side of the connection and review how orders, stock, refunds and payouts move between systems. Our hands-on ERP experience is Fishbowl and QuickBooks Online. If you need a NetSuite specialist, we’ll say so before you pay for anything.
Should NetSuite or Shopify be the source of truth for inventory?
Usually NetSuite, because it’s where receiving, transfers and fulfillment are recorded. Shopify then shows a quantity per location. The two things to settle are which quantity to publish (on hand or available) and how often it updates.
Why do our Shopify payouts never match NetSuite?
Because a payout is a batch, net of fees, refunds and chargebacks, often spanning several days. Matching it needs the orders to be billed in a way the payout sync can link to, and refunds recorded the same way. If finance is reconciling payouts by hand, start with how sales and refunds are billed in NetSuite.
Can one NetSuite Shopify integration handle DTC, POS and wholesale?
Usually, with configuration. Each channel needs its own rules for which orders import, at what price, from which location and with what tax. Test one real order per channel before assuming it works. Wholesale pricing and POS locations are where we most often find gaps.
What should we ask a Shopify ERP integration agency?
Ask them to trace a real order from checkout to the bank deposit, including a partial refund. Ask which ERPs they’ve actually maintained, and where their scope ends. A clear answer about what they don’t do is a good sign.
Bring us the order that doesn’t add up
If your NetSuite Shopify integration is importing orders but finance still doesn’t trust the numbers, start with one order, refund or payout that doesn’t reconcile. We’ll look at the Shopify side and map who owns each record with your team. Then we’ll tell you plainly which parts are ours to fix and which belong with your NetSuite partner.
Talk to #10, or read more about our Shopify ERP and inventory integration service.
