Skip to content
SyncMyShop

Integrations

Stock and availability: your store shows what you can actually ship

Your ERP or warehouse system knows what is on the shelf. The store has to show what can ship: on hand minus open orders and safety stock, per location, with a date when the item is on its way. We build that integration to your rules, host it and run it.

Which system owns the quantity?

One system owns each number and every other system receives it. For stock, the owner is the system where goods are received and picked: the ERP, the warehouse management system or the 3PL. The store does not own a count. It contributes the orders it accepted since the last update.

Data Owner Direction When it has to arrive
On-hand quantity per location ERP or WMS to the store after every receipt, pick and adjustment
Open order quantity store at capture, ERP after import both ways within minutes of the order
Safety stock per item ERP, or a rule in the integration to the store when the rule changes
Expected receipt date purchase order or supplier feed to the store daily, and when the purchase order changes
Supplier stock the supplier's file or API to the store and the ERP as often as the supplier publishes

When two systems disagree, the owner's value is written and the difference is logged. A store count of 14 against an ERP count of 11 becomes 11, and the run records that 3 units were removed and which transaction caused it. Without an owner per field, each system overwrites the other in turn and neither number can be trusted.

Stock is one of the five flows described on the integrations overview.

Which stock counts?

On hand is not available to sell. Shopify splits the on-hand quantity of a location into six states: available, committed, reserved, damaged, safety_stock and quality_control. A seventh, incoming, holds goods that are on their way and is not part of on hand. The definitions are in Shopify's inventory states documentation. NetSuite makes the same split per location under its own names: On Hand, Committed, Available, On Order and Back Ordered, where On Hand includes the committed quantity.

A worked example for one item at one location:

on hand                 120
committed (open orders) -18
safety stock             -6
quality control          -4
damaged                  -2
available to sell        90
From 120 units on hand to 90 available to sell Of 120 units on hand at one location, 18 are committed to open orders, 6 are safety stock, 4 are in quality control and 2 are damaged. 90 are available to sell. After a new order of 12 units, committed rises to 30 and available drops to 78. On hand at the Reno warehouse: 120 units 120 on hand Committed 18 Available 90 Safety stock 6 Quality control 4 Damaged 2 Available quantity sent to the store 90 After a new order of 12 units, before it ships 120 on hand Committed 30 Available 78 Safety stock 6 Quality control 4 Damaged 2 Available quantity sent to the store 78
120 on hand is 90 available to sell. A new order of 12 moves units from available to committed; on hand only changes when the order ships.

An integration that sends 120 to the store oversells by up to 30 units. An integration that sends 90 and updates on every order is correct.

The second decision is which locations count. A distributor holds 100 units in the Reno warehouse and 10 on the showroom floor in Sacramento. An integration that adds up every location sends 110. A customer orders 105 online, the warehouse ships 100, and the remaining 5 are display units in another city. The rule that prevents this is set per location: whether its stock counts for the web store, and for which sales channel. Standard connectors and iPaaS platforms map locations one to one or add several ERP locations into one store location. A rule that says which location fulfills first, or that reserves part of a location for a channel, is outside their settings. The multi-location inventory page covers those rules.

The third decision is what zero means. Sold out, discontinued and unknown are three states, and most feeds deliver all three as the number 0. The integration keeps them apart: a status field next to the quantity, and a rule per state for what the product page shows. The notes page on which stock counts goes through each state.

What actually moves

No black box: these are the fields in a stock flow, with the form they take on the way.

Field Example What is done with it
SKU or item ID 00123456 matching key, kept as text so leading zeros and case survive
Location Reno to location 124656943 mapped per location, with a flag: counts for the store or not
Available quantity 90 calculated from on hand, committed and safety stock
Committed quantity 18 open orders that have not shipped
Incoming quantity 240 on purchase order, not yet received
Expected date 2026-11-30 ISO 8601, converted from the source format
Item status active, discontinued keeps zero apart from gone
Backorder rule allow, deny whether the store sells at zero

A stock write to Shopify sets the available quantity per inventory item and location. The call carries the quantity the integration last saw, so Shopify can refuse the write when an order came in between:

{
  "input": {
    "name": "available",
    "reason": "correction",
    "referenceDocumentUri": "erp://item-receipt/IR-20418",
    "quantities": [
      {
        "inventoryItemId": "gid://shopify/InventoryItem/30322695",
        "locationId": "gid://shopify/Location/124656943",
        "quantity": 90,
        "changeFromQuantity": 96
      }
    ]
  }
}

changeFromQuantity says: set 90, provided the store still shows 96. If a customer bought 2 units a second earlier, the store shows 94, the write is rejected and the integration recalculates from the new state. A write without that check overwrites the sale. From API version 2026-04 the inventorySetQuantities mutation also requires an idempotency key, so a call that is retried after a timeout is applied once.

What goes wrong quietly

A product is missing from the supplier file. This file arrived this morning:

sku;description;qty;eta
00123456;Torque wrench 1/2 in;14;
00123457;Torque wrench 3/4 in;0;11/30/2026
00123459;Socket set 24 pc;> 10;

Item 00123458 was in yesterday's file and is absent today. Treating absence as zero takes a product offline that the supplier has in stock. Treating it as unchanged leaves yesterday's quantity up for a product that is gone. Neither is right by default, so the rule is set per feed: absent means zero, absent means unchanged, or absent means unpublished after three files in a row. The same file has two more problems: > 10 is not a number, and 11/30/2026 is a US date that a European parser reads as invalid or, for a date like 03/04/2026, as the wrong day.

An item has no mapping. Standard connectors keep a mapping record per item. An item without one is skipped by the inventory sync, and no error is raised. The store keeps showing the last quantity it had. In our runs an unmatched item goes on a list in the run report, with the SKU and the reason, and the count of unmatched items is a number on the dashboard.

Today's export did not arrive. The supplier's server was down or the export job failed. Nothing errors, because there is nothing to process. The integration checks the age of the last file: a feed that normally arrives at 06:00 and is still missing at 08:00 raises an alert, and the store shows the age of the data it is running on.

A product drop oversells. At 10:00 the ERP and the store both show 12 units of a limited item. At 10:02 a sales rep enters a wholesale order for 8 in the ERP, which leaves 4. The store syncs every 15 minutes and still shows 12. It takes an order for 2 units at 10:04, 3 units at 10:07 and 2 units at 10:11. At 10:15 the sync runs: 4 minus 7 is minus 3. Three customers have a confirmation for units that do not exist.

A 15-minute sync oversells 3 units during a product drop At 10:00 the ERP and the store both show 12 units. At 10:02 a wholesale order for 8 units is entered in the ERP, leaving 4. The store keeps selling from 12 until the 10:15 sync and takes orders for 2, 3 and 2 units. 4 minus 7 is minus 3. With an event-driven update the store shows 4 from 10:03. ERP: 12 available at 10:00 wholesale order: 8, leaves 4 Store orders 2 units 3 units 2 units Store count with a sync every 15 minutes store still counts down from 12 4 - 7 = -3 Store count with an event-driven update sold out after 4 units store shows 4 10:00 10:05 10:10 10:15 The store took orders for 7 units against 4 that existed. With the count at 4, the 10:07 order is limited to 2 units and the 10:11 order is refused.
The same thirteen minutes with a 15-minute sync and with an update sent when the ERP quantity changes.

With an update sent when the ERP quantity changes, the store shows 4 at 10:03. The first order takes 2, the second is limited to the 2 that are left, and the third sees a sold-out page.

A kit shows stock that cannot be assembled. A kit contains 2 of component A and 1 of component B. With 9 of A and 7 of B on the shelf, the kit quantity is the lower of 9 divided by 2, rounded down, and 7: that is 4. After one loose unit of A is sold the kit quantity is still 4; after two it is 3. The kit has to be recalculated on every component change. See kits and bundles.

Throughput and limits

A catalog of 50,000 variants, written to Shopify one variant per call, is 50,000 calls. A mutation costs at least 10 points and a store on a standard plan restores 100 points a second, so the ceiling is 10 calls a second: 50,000 divided by 10 is 5,000 seconds, or 83 minutes. During those 83 minutes the integration has no budget left for orders or prices.

Shopify accepts up to 250 items in an array input. Sent in batches of 250, the same catalog is 50,000 divided by 250: 200 calls. Sent as changes only, it is smaller again: if 1,200 variants changed since the last run, that is 5 calls.

System Limit Number
Shopify GraphQL Admin API points restored per second 100 standard, 200 Advanced, 1,000 Plus, 2,000 enterprise
Shopify GraphQL Admin API cost of a single query 1,000 points at most
Shopify, every API items in an array input 250
NetSuite concurrent requests per account 5 Standard, 15 Premium, 20 Enterprise and Ultimate, plus 10 per SuiteCloud Plus license
Business Central online OData requests per user 6,000 per 5 minutes, 5 processed at once
Business Central online entities per response 20,000

Sources: Shopify API rate limits and NetSuite concurrency governance, checked on October 3, 2026.

The NetSuite number is shared by every integration on the account. A Standard-tier account with 5 concurrent requests that already runs a shipping tool and a reporting export has less than 5 left. A request over the limit gets HTTP 429 with the code CONCURRENCY_LIMIT_EXCEEDED.

How this is handled: large reads go through bulk operations, changes arrive as events, writes go out in batches of changed records only, and every call runs through a queue that slows down on a 429 and retries with growing pauses. A nightly comparison of the full catalog catches what an event missed. The notes on Shopify API rate limits, NetSuite concurrency limits and real time versus batch work through the numbers.

Buffers

A buffer is the number of units held back from the store to cover the time between a sale elsewhere and the next update. It follows from two numbers: how fast the item sells and how old the store's count can be.

An item that sells 36 units an hour during a drop, with an update that is at most 5 minutes behind: 36 times 5 divided by 60 is 3 units. A buffer of 3 covers it. An item that sells 2 a day needs none.

Standard connectors apply one flat quantity to every item. A flat buffer of 5 on a catalog of 4,000 SKUs holds 20,000 units back from sale, most of them on items that sell once a week. We set the buffer per item or per item group, and per channel: a marketplace that penalizes cancellations gets a higher one than your own store. On Shopify the held-back units are written to the safety_stock state, so the admin shows where they went. The safety stock page has the rules.

Delivery dates and backorder dates

Two items with zero on the shelf are not the same. One arrives tomorrow and the other in six weeks. The date that tells them apart exists in the ERP as the expected receipt date on a purchase order line, and in most supplier feeds as a column. Standard connectors carry the quantity; their inventory flows have no field for an expected or promised date.

Carrying the date takes three conversions:

  • Format. 11/30/2026, 30-11-2026 and 2026-11-30 are the same day. 03/04/2026 is March 4 in a US file and April 3 in a European one. The source format is set per feed and stored as ISO 8601.
  • Lead time to date. "5 business days" is a duration. An order placed on Monday, November 23, 2026 counts Tuesday and Wednesday, skips Thanksgiving on Thursday the 26th, counts Friday, Monday and Tuesday, and lands on December 1. Without the holiday calendar the answer is November 30.
  • Receipt to ship date. Goods received on November 30 ship after your own handling time and before the carrier's cut-off, in the warehouse's time zone.

The result is written to the product, and the store shows a date on an item with zero stock. The delivery dates page covers the fields and the cases where a supplier moves the date.

Supplier stock next to your own

A supplier feed fills gaps. It does not overwrite the count of what is in your own warehouse. The rule is set per connection and per field.

Your available Supplier available Store shows
6 40 6, ships today
0 40, lead time 3 business days orderable, with the later ship date
0 0, expected 11/30/2026 backorder with a date
0 absent from today's file the absence rule of that feed decides

When two suppliers carry the same item, the order between them is a setting. Each product belongs to one connection, so a second supplier sending the same SKU does not overwrite the first.

A file exchange fails in four known ways: a filename that is reused so an old file is read twice, a processed file that is not archived, a file that is read while the supplier is still writing it, and an export that does not arrive. The supplier feeds page covers each one, and supported sources lists the formats and transports. Trading partners that send availability as an X12 document use the EDI 846 inventory advice.

You stay in control

Every run is compared with what it is about to change before anything is written.

  • Dry run. The integration runs against live data and writes nothing. You see what it would have changed.
  • Approval. Per connection, changes wait for your approval or go through automatically.
  • Exclusions. Products with a manual arrangement are left out. The integration cannot overwrite them.
  • Overrides. A pinned ship date or a pinned quantity for one product, with an end date.
  • Diff per run. Which products changed, from which value to which, and from which file or transaction.

A run that would set most of the catalog to zero is held:

run 2026-10-02 06:00   feed: stock_20261002.csv   rows: 4,160
held: 3,910 of 4,160 rows set available to 0 (94%)
last run: 212 of 4,158 rows at 0 (5%)
action: waiting for release

A truncated export causes this more often than a real stock-out. If it is real, you release the run. Failed calls are retried from a queue, and what still fails after the retries stays in the queue with its original payload and shows in the dashboard. The dry run and approval page describes the controls, and how an integration works shows a run from source to store.

In depth

  • Multi-location inventory: which locations count, which one fulfills first, and the 100 plus 10 case.
  • Delivery dates: expected receipt dates, business-day calendars and cut-off times.
  • Supplier feeds: CSV, Excel and XML from suppliers, and the four file-exchange failures.
  • Safety stock: buffers per item and per channel, calculated from sales rate and update delay.
  • Kits and bundles: kit availability recalculated from component stock.

Stock connects to two other flows. An accepted order turns available stock into committed stock, which is part of orders, customers and shipping. Which products a buyer sees at all is part of pricing and customer terms.

Systems and platforms

ERP and warehouse systems. NetSuite, Business Central, SAP Business One and Acumatica. Each reports quantity per location and each has its own limit: account concurrency at NetSuite, 6,000 requests per 5 minutes per user at Business Central online.

Store platforms. Shopify, Magento, WooCommerce and BigCommerce. Magento with Inventory Management calculates a salable quantity per stock: the quantity of each assigned source minus its out-of-stock threshold, added up, minus open reservations. Three sources with 20, 25 and 10 units and reservations for 15 give 55 minus 15: 40 salable.

Combinations. Shopify and NetSuite, Magento and NetSuite and Shopify and Business Central each have their own page with the limits of that pair.

A system that is not listed can be integrated when its data can be read and written in a controlled way: an API, a database view, or a scheduled export of at least one file a day. Tell us what you run.

Frequently asked questions

How often should inventory sync between the ERP and the store?

It differs per item. Items that sell several units an hour get an update on every change in the ERP, so the store is at most a minute or two behind. The rest of the catalog goes in a scheduled round, every 15 or 60 minutes, and the full catalog is compared once a night to catch whatever an event missed. The API limits of both systems set the ceiling: a Shopify store on a standard plan restores 100 points a second, which is the budget all stock, price and order calls of the integration share.

Which system should own inventory quantity?

The system where goods are received and picked: the ERP, the warehouse management system or the 3PL. The store receives the available quantity and never sends a count back. The one thing the store contributes is the orders it accepted since the last update. Those reduce the available number until the ERP has imported them and reports them as committed.

What happens when two customers buy the last unit at the same time?

The store accepts the first checkout that completes and its own count drops to zero for the second. The risk is the unit that was already sold somewhere else: in the ERP by a sales rep, or on a marketplace. That is covered by updating the store when the ERP quantity changes and by a buffer on fast-moving items. An order that still arrives for stock that is gone is flagged in the dashboard with the item, the two orders and the time of each.

Does the integration remove products from my store?

Only when you set that rule. A product that disappears from a feed can be left alone, set to zero, unpublished or marked as discontinued, and the choice is made per connection. Deleting is the one action that cannot be undone by the next run, so the default is to unpublish and report it in the run diff.

Can the store keep selling while the ERP is unreachable?

Yes. The store keeps the last available quantity it received and keeps counting its own orders down from it. Orders wait in the queue and are delivered to the ERP in the order they were placed once it responds again. For items with a buffer the store stops selling a few units early, which is the purpose of the buffer. The dashboard shows how old the last successful update is.

Can stock go negative?

In the ERP it can, when backorders are allowed or when a pick is booked before the receipt. For the store you choose per item what a negative or zero quantity means: sold out, orderable with a later ship date, or orderable without limit. A negative number is never sent to the store as a quantity; it is sent as zero plus the backorder rule.

Do you sync stock from suppliers that only send a spreadsheet?

Yes. A CSV on SFTP, an Excel file that arrives by email every morning and an XML feed at a URL are all read the same way: the file is checked, each row is matched to your SKU, and the quantity and expected date are written to the store and the ERP. The supplier feeds page covers formats and the four ways a file exchange fails.

What does the store show when an item is out of stock but on order?

A date. The expected receipt date from the purchase order or the supplier feed is converted to a ship date with your handling time and business-day calendar and written to the product. A customer sees "ships November 30" on an item with zero on the shelf. When no date is known the page says so, with the text you choose.

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

Suppliers, products, orders per day, a rough estimate is fine.

Or email directly: carsten@syncmyshop.com