← All posts Insights 11 min read

Shopify B2B and NetSuite: Integration Architecture for Wholesale in 2026

Quick Summary Shopify B2B and NetSuite — Integration Architecture for Wholesale in 2026 Shopify B2B (Shopify Plus only, launched 2022 and significantly expanded through 2026) provides company accounts, customer-specific price lists, net payment terms, and draft orders — all requiring distinct NetSuite integration handling. The correct NetSuite mapping grain is the location, not the company.…

Shopify B2B CompanyLocation to NetSuite Customer mapping architecture diagram
Quick Summary

Shopify B2B and NetSuite — Integration Architecture for Wholesale in 2026

  • Shopify B2B (Shopify Plus only, launched 2022 and significantly expanded through 2026) provides company accounts, customer-specific price lists, net payment terms, and draft orders — all requiring distinct NetSuite integration handling.
  • The correct NetSuite mapping grain is the location, not the company. Shopify’s own B2B object model treats CompanyLocation as the unit that holds billing/shipping addresses, catalogs, tax exemptions, and payment terms — map that to NetSuite, not the parent Company.
  • Customer-specific price lists in Shopify B2B must sync bidirectionally: NetSuite price levels drive the Shopify B2B catalog assignment per location, not the other way.
  • Net 30/60/90 terms in Shopify B2B create Invoice records in NetSuite, not Cash Sales — a fundamental difference from retail order sync.
Plus only
Shopify B2B requires a Shopify Plus plan — the Company and CompanyLocation objects don’t exist on lower tiers
CompanyLocation
The correct NetSuite mapping grain — not Company; each location keeps its own billing, tax, and terms
Price Level
NetSuite’s B2B pricing mechanism — must drive Shopify B2B catalogs, not the other way
Invoice
The NetSuite record created for net-terms B2B orders — not the Cash Sale used for retail

Shopify B2B is now a credible wholesale channel — Shopify Plus merchants run self-service portals for wholesale buyers alongside their retail DTC storefront. Integrating it with NetSuite is more complex than retail Shopify integration because B2B introduces concepts — company accounts, per-location catalogs, payment terms, draft orders — that require different NetSuite record types and sync logic. The mistake that costs the most shows up on the second wholesale buyer with two branches: map the Shopify Company straight to one NetSuite Customer and both branches’ billing addresses, tax exemptions, and payment terms collapse into a single record. This architecture specifies the grain that avoids it, plus the order sync, price-list direction, and version-pinning decisions that go with it.

Object model: Company, CompanyLocation, CompanyContact

Shopify’s B2B object model (GraphQL Admin API) has three layers, and the integration decision that determines everything downstream is which layer you sync to NetSuite as the customer entity.

Shopify object Role NetSuite integration note
Company The buying business; holds locations and contacts Top-level record for consolidated reporting only — not the sync target for orders
CompanyLocation A branch with its own billing/shipping address, catalog, tax exemptions, payment terms The correct grain — map one NetSuite Customer per location
CompanyContact A person acting for the company, linked to a retail customer record Sync as a contact linked to the location-level customer — never as a standalone NetSuite customer

Shopify’s own documentation is explicit that catalogs, tax exemptions, and payment terms are assigned per CompanyLocation, not per Company. A wholesale buyer with an East Coast warehouse and a West Coast warehouse has one Shopify Company and two CompanyLocation records — each with its own tax nexus and negotiated terms. That structure is the article; the rest of this guide is what breaks when an integration ignores it, covered in depth in the Shopify + NetSuite integration guide library.

Company-level mapping vs. location-level mapping to NetSuite
Company-level mapping collapses branch data; location-level mapping preserves it Top row: mapping the Shopify Company directly to one NetSuite Customer collapses two branches’ billing, tax, and terms into a single record. Bottom row: mapping each CompanyLocation to its own NetSuite Customer keeps each branch’s billing, tax, and terms distinct. Where the Shopify B2B → NetSuite sync grain goes Wrong grain — company-level mapping Shopify Company Acme Corp One NetSuite Customer both branches share it East and West branch billing, tax exemption, and terms collapse into one record. Correct grain — location-level mapping Shopify Company Acme Corp CompanyLocation East Region NetSuite Customer Acme Corp — East CompanyLocation West Region NetSuite Customer Acme Corp — West Each location keeps its own billing address, tax exemption, and payment terms.

Company account sync: map to the location, not the company

1
Create a top-level NetSuite Customer on Shopify company creation

When a Shopify B2B company is created, create a parent NetSuite Customer record for consolidated reporting: Company name → Customer name, primary contact → Contact record. This record is a grouping node — it should not receive orders or invoices directly.

2
Create one child NetSuite Customer per Shopify CompanyLocation

For every CompanyLocation under the company, create a child Customer record under the parent: Location name → Customer name, billing/shipping address → billing/shipping address, payment terms → Terms field (Net 30 → the account’s Net 30 term record), tax exemption → tax item or exempt flag. This is the record every order, invoice, and payment posts against.

3
Assign the NetSuite price level to the location, not the parent

NetSuite Customer records have a priceLevel field. Set it on each location-level child Customer based on the catalog assigned to that specific CompanyLocation in Shopify — two locations under the same company can legitimately sit on different price lists.

4
Store both Shopify IDs in custom NetSuite fields

Add custentity_shopify_company_id on the parent Customer and custentity_shopify_location_id on each child Customer. The location ID is the primary key your integration matches orders against — a B2B order carries a location, not just a company, and matching on the wrong key re-introduces the collapse this section exists to prevent.

Skip step 2 and map every order straight to the parent-level Customer created in step 1, and you get the failure this guide opened with: two branches’ billing addresses, tax exemptions, and payment terms compete for the same fields, and whichever synced last wins silently. NetSuite’s parent/child customer relationship exists to let the East and West records above roll up into one AR balance for the company while keeping each location’s fields independent — use it for that, not as a reason to skip location-level records.

Price lists and catalogs: NetSuite is the source of truth

Shopify B2B assigns catalogs — a product selection plus a price list — to a CompanyLocation, not to the company as a whole. NetSuite’s price levels are the correct source of truth for those prices: a price change made in NetSuite for a customer’s negotiated tier should push to that location’s Shopify catalog, never the reverse.

The anti-pattern is bidirectional price editing — letting a merchandiser update a wholesale price directly in the Shopify catalog and letting that value flow back into NetSuite. The two systems then race on the next sync, and whichever wrote last determines the price a buyer sees, with no record of which number is authoritative. Lock catalog price fields against manual edits in Shopify for any location tied to a NetSuite price level, and treat every price discrepancy as a NetSuite-side correction, not a Shopify-side one.

B2B order sync: draft orders and net terms

Shopify B2B scenario NetSuite record to create Key differences from retail
Immediate payment order (credit card) Sales Order → Invoice → Payment Same as retail — Cash Sale or SO+payment
Net 30/60/90 order Sales Order → Invoice (open) No payment at order time — Invoice left open until paid
Draft order (pending approval) Sales Order in “Pending Approval” status Do not create an invoice until the Shopify draft is approved
Partial payment order Invoice with Deposit applied Record the deposit against the invoice, leave the balance open

Every row above posts against the location-level Customer from the previous section, using its Terms field as the default — never a value re-typed per order. That single change removes the most common B2B order-sync bug: an order with the buyer’s contracted Net 30 terms landing in NetSuite on the account’s default terms because the integration reads terms off the parent company instead of the location.

Net terms in NetSuiteDo not create Cash Sales for B2B orders with payment terms:

A Cash Sale in NetSuite assumes immediate payment and posts directly to the revenue account. A B2B order with Net 30 terms should be: Sales Order (on Shopify B2B placement) → converted to Invoice on fulfilment → Payment applied when the customer pays. Creating a Cash Sale for a Net 30 order incorrectly recognizes revenue before payment and misrepresents the AR balance.

Payment terms drift: the silent AR break

Payment terms drift happens when a buyer’s negotiated terms change in one system and not the other — a sales rep grants Net 60 in Shopify for a promotional quarter, but the location-level NetSuite Customer keeps its default Net 30. Every order syncs correctly on the mechanics above and still generates an invoice with the wrong due date, because the terms value itself was never reconciled. This is a checklist item on every B2B integration, not an edge case to handle later:

  • Verify the Shopify CompanyLocation payment terms match the NetSuite location-level Customer’s Terms field before the first order syncs.
  • Re-check terms on every Shopify company/location update webhook, not only on order creation — terms changes don’t always coincide with an order.
  • Alert when an order’s Shopify-side terms and the matched NetSuite Customer’s Terms field disagree, instead of silently applying the NetSuite default.
  • Run a monthly reconciliation: every active B2B location’s Shopify terms against its NetSuite Terms field, flagging any mismatch for manual review.
  • Log every terms change with a timestamp and source system, so a disputed invoice due date can be traced to the record that actually changed.

What Shopify B2B still can’t do (as of 2026-08)

Shopify B2B does not support purchase options — subscriptions, pre-orders, or try-before-you-buy — for wholesale buyers. A merchant that needs recurring wholesale orders has to build that logic outside Shopify’s native purchase-options system, typically as a scheduled draft-order creation job rather than a subscription object. Shopify has moved this surface quickly in past release cycles; re-verify against the current B2B documentation before scoping a project that depends on it.

Pin the API version before you build

Every request in this architecture — company, location, catalog, and order writes — goes through the GraphQL Admin API, and Shopify ships a new stable version every quarter with a minimum 12-month support window and at least nine months of overlap between consecutive versions. Requesting a version past its support window does not error; Shopify silently falls forward to the oldest version still supported, which can change field availability on B2B objects without warning. Pin an explicit version in every request path, record it in one place in your integration’s config rather than scattered across code, and review each quarterly release’s breaking-changes list within 30 days of publication — B2B objects are newer surface area than order and product APIs and change faster.

None of this is a build-vs-buy argument — the mechanics above apply identically whether the integration is custom or packaged. If you cannot tell from a vendor’s documentation which grain it maps Shopify B2B companies to, that is a question worth asking before the contract; it is the kind of thing SoftXone’s NetSuite integration work for Shopify stores specifies up front, alongside the location-level mapping this guide describes.

Get the working checklists

The runbooks and decision checklists from these guides, as printable PDFs — free in the SoftXone guide library.

Browse the guide library →

Sources & Further Reading

References

  1. Shopify B2B Object ModelShopify dev docs — Company, CompanyLocation, and CompanyContact roles, per-location catalog/tax/terms assignment, and the current purchase-options limitation.
  2. Shopify B2B Company APIShopify GraphQL Admin API — Company object reference including price lists, contacts, and payment terms.
  3. Shopify API VersioningShopify dev docs — quarterly release cadence, support windows, and fall-forward behavior for unsupported versions.
  4. NetSuite Customer Record ReferenceOracle NetSuite Help — Customer record fields including price level, terms, subsidiary, and parent/child customer relationships.
  5. Shopify B2B DocumentationShopify Help — company management, price lists, and payment terms in Shopify B2B.

Frequently asked questions

How do Shopify B2B companies map to NetSuite?

Not directly to one Customer record. Map each Shopify CompanyLocation to its own NetSuite Customer, with those location-level records rolled up under a parent Customer for the company. Mapping the company straight to a single Customer collapses per-branch billing, tax, and terms into one record.

How are net terms handled?

Through Sales Orders that convert to open Invoices on fulfilment, using the Terms field on the location-level NetSuite Customer — never a Cash Sale, which assumes immediate payment and would misstate the AR balance.

What about price lists?

NetSuite price levels are the source of truth and drive the catalog assigned to each Shopify CompanyLocation. Letting merchandisers edit prices directly in the Shopify catalog creates a race the next sync can’t resolve correctly.

Does a CompanyContact need its own NetSuite customer record?

No. A CompanyContact is a person acting for the company, not a separate buyer. Sync it as a contact linked to the location-level Customer; creating a standalone NetSuite customer for a contact fragments order history when that person changes roles or leaves.

Is Shopify B2B available on every Shopify plan?

No. Shopify B2B requires Shopify Plus — the Company and CompanyLocation objects don’t exist on Basic, Grow, or Advanced plans, so this architecture only applies once a merchant is on Plus.

Related guides

Discussion

Leave a Reply

Your email address will not be published. Required fields are marked *


Ship it

Need this in your stack?

We build, integrate, and ship — no calls, just delivery.

Start a project →