Shopify and NetSuite
Shopify NetSuite integration
Orders, customers and payments from Shopify into NetSuite. Items, prices, stock per location and tracking back. Built to your NetSuite account, its custom fields and its concurrency limit, then hosted and run for you.
What moves between Shopify and NetSuite
Shopify is where the order is captured. NetSuite is where it is fulfilled, billed and booked. An integration between the two carries eleven kinds of record, most of them in one direction.
Shopify to NetSuite
- Orders, as a Sales Order, a Cash Sale or an Invoice
- Customers, with billing and shipping address
- Payment transactions, as a Customer Deposit against the sales order
- Refunds, as a Credit Memo, Cash Refund or Customer Refund
- Return requests, as a Return Authorization
- Cancellations, which close the sales order
- Shopify Payments payouts, as a bank deposit that finance can reconcile
NetSuite to Shopify
- Items and matrix items, as products and variants
- Item fields, as metafields
- Stock per location, as inventory levels per Shopify location
- Item Fulfillments, as Shopify fulfillments with carrier and tracking number
The record type decides the rest of the flow. A Cash Sale records sale and payment in one transaction and takes the stock down at once, with no Item Fulfillment. That fits Shopify POS and digital goods. A Sales Order waits for a warehouse.
For B2B, Shopify companies map to NetSuite customers, company locations to subcustomers, and catalogs to price levels. Both systems have the same limit here: a Shopify company holds at most 10,000 locations, and a NetSuite customer hierarchy holds at most 10,000 customers and subcustomers.
Which system owns what
Each piece of data has one owner. Without that rule the two systems overwrite each other and nobody can say which value is right.
| Data | System of record | Direction | Sync behavior |
|---|---|---|---|
| Items, SKUs, variants | NetSuite | NetSuite to Shopify | changed items on a schedule |
| Titles, descriptions, images | Shopify | stays in Shopify | never overwritten from NetSuite |
| Prices and price levels | NetSuite | NetSuite to Shopify | scheduled, 250 prices per request |
| Stock per location | NetSuite | NetSuite to Shopify | scheduled, 250 quantities per call |
| Orders | Shopify until import, then NetSuite | Shopify to NetSuite | webhook plus reconciliation |
| Customers | Shopify for web, NetSuite for B2B accounts | both ways | matched on email or external ID |
| Payments and payouts | Shopify | Shopify to NetSuite | with the order, payouts daily |
| Fulfillment and tracking | NetSuite or the WMS | NetSuite to Shopify | minutes after the Item Fulfillment |
| Refunds and returns | where the refund starts | both ways | one record per event, with restock flag |
What Shopify and NetSuite store differently
Variants against matrix items. A Shopify product has up to three options and up to 2,048 variants. A NetSuite matrix has a parent item and child items, at most 2,000 combinations, and only the children appear on transactions. The link between the two is an item ID map: one row per Shopify variant ID and NetSuite internal ID. Shopify does not require a SKU to be unique, or to be filled at all. A variant without a row in the map makes its order line fail in NetSuite, which is why we check the map before every order write. More on this in variant mapping.
Discounts. A Shopify discount code is a string on the order. NetSuite needs a discount item to book it against. An order of two shirts at 40.00 with code FALL10 comes in as 80.00 minus 8.00. Without a discount item for FALL10, or a general web discount item, NetSuite cannot resolve the line and rejects the whole order.
Tax. Shopify calculates tax at checkout, per line. NetSuite recalculates tax on the sales order unless it is told to take the store's amount. Two calculations that round differently disagree by a cent on a share of orders, which blocks automatic matching of deposit and invoice. The mapping sets one side as the source: the Shopify amount written per line, or NetSuite's own calculation.
Subsidiary, location, department, class. Shopify has none of these. NetSuite wants them on the header and often on every line. They come from rules: the store decides the subsidiary, the Shopify location decides the NetSuite location, the sales channel decides the class.
Custom fields. Item data that Shopify has no field for goes into metafields. NetSuite holds it in fields such as custitem_material or custitem14. An app can define 256 metafields per resource type, and metafieldsSet writes 25 per request.
Stock states. Shopify has eight inventory states, among them available, committed, reserved and safety_stock. The API accepts writes to available and on_hand only. NetSuite has On Hand, Committed, Available and Back Ordered per location. We send NetSuite's Available, minus any buffer you set, and let Shopify keep its own committed. Which locations count is a decision per location, covered in multi-location inventory.
The technical reality of this pair
Both systems meter their APIs, in different units.
| Limit | Shopify | NetSuite |
|---|---|---|
| Unit | query cost points per second | concurrent requests per account |
| Lowest tier | 100 points per second | 5 (Standard) |
| Highest tier | 1,000 on Plus, 2,000 on enterprise | 20, plus 10 per SuiteCloud Plus license |
| Over the limit | THROTTLED inside an HTTP 200 |
HTTP 429 CONCURRENCY_LIMIT_EXCEEDED |
| Bulk route | bulk operations, JSONL file | SuiteQL, 1,000 rows per page |
| Release schedule | a version every quarter, supported 12 months | two releases a year |
Stock, worked through. A catalog of 12,000 variants across two locations is 24,000 quantities. Reading them from NetSuite with SuiteQL takes 24 pages of 1,000 rows in one concurrency slot. Writing them to Shopify with inventorySetQuantities takes 24,000 divided by 250, which is 96 mutations. Sent one item at a time the same update is 24,000 calls, and on a standard plan that runs into THROTTLED long before it finishes. We send only the quantities that changed since the last run, so a normal cycle is a handful of calls.
Since API version 2026-04 every inventory write carries changeFromQuantity: the quantity the integration believes Shopify has. When Shopify's number has moved in the meantime, the call fails with CHANGE_FROM_QUANTITY_STALE and the integration reads again before it writes. A sale that happened during the sync is not overwritten.
Orders, worked through. NetSuite is the slower side. A sales order save that triggers user event scripts and workflows takes several seconds. At 4 seconds per order and 2 of the 5 slots on a Standard account, the maximum is 30 orders a minute, or 1,800 an hour. The other 3 slots stay free for your 3PL, your reporting and your users' own scripts. The full calculation is in NetSuite concurrency limits.
Webhooks. Shopify waits five seconds for an answer to a webhook, retries 8 times over 4 hours, and then deletes a subscription that was made through the Admin API. It guarantees neither order nor a single delivery. So the webhook only puts the order ID in a queue and answers 200. A reconciliation run then compares Shopify's recent orders with the external IDs in NetSuite and picks up anything the webhooks missed. Without the read_all_orders scope an app sees the last 60 days of orders, which bounds how far back that run can look. The Shopify API rate limits note covers the cost model in detail.
Authentication. NetSuite access runs under a dedicated role, not Administrator. Oracle points new integrations to OAuth 2.0 and stops new token-based integrations with release 2027.1. A sandbox refresh deletes the sandbox tokens. Details are on the NetSuite page; the Shopify side is on the Shopify page.
Where standard connectors stop
Standard connectors and iPaaS templates cover the common case with fixed settings. Their own documentation shows where the settings stop.
- One price level. A typical template takes one NetSuite price level for the selling price and one for the compare-at price, in one currency per store. A third price level, or a price per customer, needs custom saved-search formulas and a script.
- B2B in a separate template. Company-specific catalogs run as a second set of flows next to the consumer flows, with a filter to keep B2B orders out of the first set.
- Locations are mapped, not allocated. NetSuite locations map to Shopify locations one to one or many to one. There is no rule for priority, splitting or a reserve per channel. An item without a map record is skipped without an error.
- Saved searches by internal ID. One widely used template installs 30 saved searches in NetSuite and refers to them by internal ID. Renaming or deleting one breaks every flow that uses it.
- Scheduled, with a lag. Order flows run on a schedule with a recommended lag of 10 to 15 minutes, so that the payment status has settled before the order is picked up.
A built integration has no fixed settings. Price levels, catalogs, allocation rules and timing follow how your account works. The comparison on technical grounds is in custom integration vs iPaaS.
When it goes wrong
| What fails | What the integration does | What you see |
|---|---|---|
| NetSuite answers 429 | keeps the order in the queue, retries after a growing pause | nothing, unless it lasts |
| SKU not in the item ID map | holds that order, continues with the rest | the order with the SKU that is missing |
| Discount code without a discount item | holds the order | the order with the code |
| Webhook never arrived | reconciliation run finds the order by ID | a log line: found by reconciliation |
CHANGE_FROM_QUANTITY_STALE on stock |
reads the current quantity, sends again | nothing |
| NetSuite release or maintenance window | queue fills, drains afterwards | queue length on the dashboard |
An order that still fails after its retries goes to a separate list with its original payload, so it can be sent again after the cause is fixed. Nothing is dropped without a trace. After a pause, the first run starts from the last order it confirmed, not from the clock: a sync that resumes from the wrong timestamp is the usual cause of missing records after a maintenance window.
Before go-live the integration runs as a dry run against your NetSuite sandbox and your live Shopify data, writing nothing, and you approve what it would do. From then on every run has a diff per record in the dashboard. This is part of every e-commerce ERP integration we build. Sibling pages: Magento NetSuite integration, WooCommerce NetSuite integration and BigCommerce NetSuite integration. Tell us how your NetSuite account is set up.
Frequently asked questions
Do I need an integration partner to connect Shopify and NetSuite?
Shopify and NetSuite have no direct link out of the box. The options are a packaged connector, an iPaaS template that your team configures and maintains, or an integration built for your account. We build it, host it and run it: you get a fixed build price and a monthly fee, and the monitoring and the fixes are ours.
How is this different from SuiteScript and RESTlets built in-house?
The code is the smaller part. A RESTlet written in-house has no queue in front of it, no retry when NetSuite answers 429, and nobody watching when Shopify retires an API version. Shopify ships a version every quarter and supports each one for at least 12 months. Oracle ships two NetSuite releases a year. We track both release schedules and do the monitoring.
Can it handle B2B pricing and high order volumes?
Yes. NetSuite price levels and quantity pricing are written to Shopify catalogs and price lists, 250 prices per request. For volume, the order flow is sized to your NetSuite concurrency limit: 2 slots at 2 seconds per order is 60 orders a minute, and the queue holds anything above that. See Shopify B2B NetSuite integration for companies, locations and catalogs.
Does it work with Shopify POS?
Yes. A POS order arrives through the same Admin API with a source name of pos and the retail location it was made at. We map that location to a NetSuite location and usually to a Cash Sale instead of a Sales Order, since the goods have already left the store.
What happens to orders placed during the switch from our current connector?
The new integration first runs next to the old one without writing: it reads the same Shopify orders and logs what it would create in NetSuite. Once both agree, flows are switched over one at a time. Orders carry an external ID, so an order that both the old and the new route touch is updated, not created twice.
Do we need Shopify Plus for this integration?
No. The Admin API is the same on every plan; what changes is the rate: 100 cost points per second on standard plans, 1,000 on Plus. Since April 2026 companies, catalogs and payment terms are on all plans, with at most 3 active catalogs outside Plus. Plus also raises the location limit from 10 to 200.
Tell us what you need
Tell us which systems you use and what needs to work better. We reply personally within one working day. We help you define the work, then agree the price and timing before you commit.
- You know the price and the timeline before you commit to anything
- We work out the connection that takes the work off your hands
- We handle the build, hosting, monitoring and maintenance
- Your team has less information to retype and fewer discrepancies to chase