NetSuite BigCommerce Integration: Why Your Inventory Numbers Don't Match
BigCommerce says an item is in stock. NetSuite says there's nothing left. Or it goes the other way — NetSuite shows plenty on hand, and the storefront marks the item out of stock and won't let anyone buy it. Either version of this problem shows up the same way: a customer places an order the warehouse can't fulfill, or a product sits unsellable for no reason anyone can point to, and someone finally asks why the two systems don't agree.
This is a common complaint about NetSuite-to-BigCommerce setups, and it's rarely one bug. It's usually two or three small, individually reasonable decisions stacking up until the numbers quietly diverge. A distributor running NetSuite as the ERP and BigCommerce as the storefront, selling out of more than one warehouse, is the textbook case — the sync works fine until a backorder, a vendor-direct shipment, or a second location enters the picture, and then it doesn't.
This article goes deep on BigCommerce specifically — variant-level tracking, the Locations API, and where connectors diverge in what they actually support. If you're also running (or evaluating) a different cart against the same NetSuite instance, the platform-neutral version of this problem — on hand vs. committed vs. available, event-driven vs. batch sync, build-vs-buy on the connector — is covered in NetSuite ecommerce inventory sync.
What's actually being compared
The short version: NetSuite tracks Quantity On Hand, Quantity Committed, and Quantity Available (on-hand minus committed) per item, per location — and it's Quantity Available, summed across every location flagged to make inventory available for sale, that a storefront should be showing. Oracle's NetSuite Connector and Celigo's integration app both document that they sync Quantity Available rather than Quantity On Hand. That's the correct number to expose — it's also the number most likely to look "wrong" to someone checking the warehouse floor, because on-hand and available are legitimately different numbers, not a sync error. (The full breakdown of this part is identical on every cart; it's in NetSuite ecommerce inventory sync.)
What's BigCommerce-specific is what happens on the other side of that number once it arrives.
The common causes
Each of the three causes below gets in at a different step of the sync.
The BigCommerce tracking field isn't actually set to track from NetSuite. This is a common
root cause and an easy one to miss. If a product's inventory_tracking is set to none,
BigCommerce doesn't track inventory for it at all, so the item stays purchasable regardless of
what NetSuite says. If variants exist but tracking is set at the product level instead of the
variant level, the per-variant numbers aren't the ones BigCommerce sells against. Oracle's own NetSuite help center has a troubleshooting article for exactly this symptom: an
item with no inventory that customers can still order.
Multi-location math. A distributor with two or three warehouses has inventory spread across locations, and NetSuite sums "available" across the locations flagged to make inventory available. A location with "Make Inventory Available" cleared has its on-hand stock excluded from the available count, and a location that holds stock that shouldn't count toward sellable (a quarantine location, a returns bin) but is still flagged will inflate it. Either way, stock disappears from or sneaks into the total — and the drift shows up exactly where multi-location setups usually break: backorders, inter-location transfers, and anything routed through a location nobody remembered to check.
Vendor drop-ships and non-standard transaction types. The standard connector flows are built around ordinary purchase-and-fulfill transactions. A vendor-direct shipment, a special order that never actually touches the warehouse, or a bill-only transaction from a drop-ship vendor can move real inventory without going through the transaction type the connector is watching. The inventory number is technically correct in NetSuite and never reaches BigCommerce at all for that unit.
A deliberate safety buffer and plain sync-interval lag also move the numbers, but they're identical on every cart, not BigCommerce-specific. (On timing, Oracle's documentation lists scheduled sync intervals anywhere from 20 to 90 minutes depending on the connector and the type of sync.) What's worth your time here is the BigCommerce-specific layer underneath: how variant-level tracking and the Locations API actually represent that data once it arrives.
Variant-level inventory: where misconfiguration actually lives
BigCommerce's inventory_tracking field is set per product, but the decision that matters is
whether it's set to variant when the product genuinely has variants. Each variant/option
combination carries its own inventory_level and inventory_warning_level — its own number,
independent of the parent product record. If tracking is left at product while variants exist,
BigCommerce doesn't use the variant-level numbers and sells against the product-level figure,
which means a connector faithfully writing correct per-SKU quantities from NetSuite can still
produce a storefront that oversells one variant and shows another perpetually out of stock.
This is a common failure mode specifically at product-creation time: a product gets built with
variants in BigCommerce, but whoever set it up (or whatever import script created it) left
inventory_tracking at the product default instead of flipping it to variant. The connector
isn't wrong. The product configuration is.
Multi-location: the Locations API, and whether your connector actually uses it
BigCommerce's multi-location support lives behind the V3 REST Inventory and Locations APIs.
Every store starts with one default location (id 1); additional locations are created through
the /locations endpoint. The API allows up to 100 active locations, but the number your plan
allows is lower on the smaller plans. Inventory updates against these APIs come in two flavors —
absolute adjustments, which overwrite a location's quantity with a new count (BigCommerce
recommends these as the default method), and relative adjustments, which increment or
decrement against whatever's already there. A relative adjustment applies on top of the current
number, so a replayed request applies it again unless your integration guards against that;
BigCommerce's documentation doesn't describe built-in retry protection for these endpoints. A
storefront can also surface location-level stock to shoppers, for example for click-and-collect
flows, through the GraphQL Storefront API's per-location inventory fields, though BigCommerce says
that has to be enabled on request.
The part worth checking before you assume this API is in play: some NetSuite-to-BigCommerce integrations take NetSuite's multi-location sum and write one flattened number to BigCommerce. Celigo's BigCommerce app, for instance, documents that it sums quantity available across the configured NetSuite locations and sends the combined total. BigCommerce's own Catalog API likewise returns inventory for only the default location. A flattened number works fine for availability, but it means true per-location data (what you'd need for in-store pickup, location-specific fulfillment routing, or showing shoppers which warehouse has stock) never makes it to BigCommerce. "We have multi-location inventory" in NetSuite and "we have multi-location inventory" in BigCommerce are not automatically the same claim.
Connector behavior, in practice
Oracle's NetSuite Connector, Celigo's BigCommerce integration app, and custom middleware built directly against the V3 Inventory API differ in exactly the ways that matter for this problem: what they write (a single aggregate number vs. true per-location records), how they're triggered (scheduled job vs. a NetSuite-side event firing a webhook or RESTlet call), and how visible their failures are (whether a failed sync shows up anywhere besides "the numbers are wrong again"). A packaged connector is the right starting point for most setups — someone else maintains the BigCommerce API version churn — but it only covers the field mappings and transaction types its authors built for. The gap often shows up years after setup, when nobody left on the team remembers which inventory model the connector was actually configured against.
How to diagnose it yourself
Work through these roughly in order — each one rules out a cheaper explanation before you go looking for a harder one:
- Check the BigCommerce product's
inventory_trackingsetting. Confirm it's set tovariantfor any product that actually has variants — notproduct, and notnone. This single check resolves a surprising share of "the sync is broken" tickets before anything else gets looked at. - Pick one disputed SKU and do the arithmetic by hand. Pull NetSuite's Quantity On Hand, Quantity Committed, and Quantity Available for that item at every location configured to make inventory available. Add up Quantity Available across those locations. Compare that sum — not Quantity On Hand — to what BigCommerce is showing.
- Confirm whether your connector writes to the Locations API or the old aggregate field. If you have more than one NetSuite location feeding inventory, check whether BigCommerce actually has more than one Location configured, or whether everything's landing as one flattened number against the default location.
- Check when the integration last actually ran. Look at your connector's sync job history and its timestamps. If the last successful run was hours ago, you're looking at a timing or failure problem, not a logic problem.
- Confirm which field the connector is actually mapped to. It's worth explicitly verifying the integration is mapped to Quantity Available and not Quantity On Hand — a misconfigured mapping made at setup time, years ago, is a real and common cause.
- Trace one non-standard order type end to end. Take one vendor drop-ship or special order and follow exactly how it affects NetSuite's inventory record, and whether that transaction type is one the sync job is watching at all.
Questions to ask about your current setup
- Is
inventory_trackingactually set tovarianton every product that has variants, or was that decided once at import time and never audited since? - Does your connector write to BigCommerce's Locations API, or does it flatten every NetSuite location into one aggregate number? Do you actually know which, right now, without checking?
- Is your connector using absolute or relative inventory adjustments — and if a sync job retries after a timeout, is that retry idempotent, or does it double-count?
- What transaction types does your connector not watch, and who decided that was an acceptable gap — or did nobody decide, and it's just never come up yet?
- If the sync silently failed for a day, would anything alert you, or would the first signal be a customer order you can't fulfill?
How we'd think about fixing it
The fix depends entirely on which of the causes above is actually in play, and treating all of them as the same kind of problem is how distributors end up rebuilding an integration that wasn't actually broken.
The first real decision isn't technical — it's which inventory concept the business actually wants exposed to customers. Available-to-promise, strict on-hand, or on-hand minus a deliberate safety buffer are all defensible choices, and they produce different numbers on the storefront by design. That decision should be made on purpose and documented, not discovered by comparing a spreadsheet to a screenshot.
From there, it's a matter of mapping every path a unit of stock can move through that the standard connector doesn't natively watch — drop-ships, transfers, backorder holds — and deciding per gap what kind of fix it actually needs. Some gaps are a configuration change (a location flag, a tracking-field correction). Some need a scheduled reconciliation job that catches drift the real-time sync misses. Some genuinely need a purpose-built sync step for a transaction type the off-the-shelf connector was never built to handle. The trade-off in each case is between how much custom logic you're willing to maintain and how much drift you're willing to tolerate before someone notices — and that trade-off is different for a company running two locations than one running twelve.
We're not going to hand you the specific reconciliation query or the exact saved-search logic here — that part genuinely depends on your warehouse setup, your connector, and which NetSuite features you have enabled. That's the actual integration work, not a template.
When to call someone
If the checklist above gets you to "the tracking field was wrong" or "the sync job had been failing silently for two days," you've probably fixed it yourself. If you've confirmed the field mapping, the Locations API question, and the sync timing are all correct and the numbers still don't agree — or if the gap is a transaction type your business runs regularly and the standard connector was never built to watch — that's usually the point where it's worth a second set of eyes before you build something custom on top of a connector you don't fully trust yet.
That's the kind of integration work we do, and the conversation is a plain technical one — you'd be talking to an engineer, not a salesperson. Send us your connector's field mapping or your integration diagram and we'll tell you where we think the drift is actually coming from. Start that conversation.