Integrations
Building a B2B wholesale portal for an Australian brand: architecture patterns beyond Shopify B2B
Quick answer: Shopify B2B and the equivalent WooCommerce wholesale plugins cover the basic wholesale ordering experience well — logged-in buyers see their own pricing, place orders against a price list, get an invoice. They start to break for AU brands when the business shape adds tiered customer segments, freight-zone-specific surcharges, Net-30 credit limits, customer-specific catalogues, ERP-driven inventory across multiple warehouses, or sales rep-entered orders on behalf of customers. The architecture patterns for a portal that handles those cases sit alongside the off-the-shelf platform, not inside it. This piece walks through where the line is and the patterns that we deploy when building wholesale portals for AU brands at meaningful scale.
The wholesale portal is one of the most common custom-build conversations we have with Australian product brands. The default starting point is Shopify B2B (or an equivalent WooCommerce wholesale plugin) and for some brands that’s the right answer. For others — usually those with established wholesale channels, complex catalogue structures, or operational logic the off-the-shelf platform can’t express — the platform is the thing that’s holding the business back.
This piece is about the architectural patterns that show up when you build past what Shopify B2B reaches. None of it is exotic. All of it is the difference between a portal that scales with the wholesale business and one that the operations team works around.
Where the off-the-shelf platforms stop
Shopify B2B (the offering bundled into Shopify Plus) handles a defined set of B2B requirements well:
- Customer-specific price lists with per-customer pricing visibility
- Net payment terms (with a few preset windows)
- Volume-based quantity rules and minimums
- Tax-exempt and registered-customer purchasing
- Company hierarchies with multiple buyers per company
The equivalent WooCommerce path (Wholesale Suite, B2BKing, or similar plugin sets) covers similar ground with different UX trade-offs.
In our experience the AU brands that move past these platforms generally do so because of one or more of:
- Tiered customer pricing that the platform’s price-list model can’t express cleanly. Five-tier wholesale pricing (Standard / Volume / Distributor / Key Account / Owner) with quantity-break logic per tier, where the tier rule is “the better of these three calculations,” is past what most platforms support natively.
- Freight zone surcharges specific to Australian geography. A B2B order to a metro Sydney address ships differently from one to remote WA. The freight rules involve customer-specific contract rates, zone-specific surcharges, and minimum-order thresholds that vary by region. Most platforms model freight as “flat rate by weight” or “real-time carrier rate” and neither captures the wholesale freight model AU brands actually use.
- Net-30 (or Net-60) credit limits with available-credit logic. The platform shows a customer their pricing, but does it know they have $4,200 of unpaid invoices and a $5,000 credit limit? Most don’t. The customer places the order, the brand discovers the credit-limit issue at fulfilment, and the order has to be re-confirmed manually.
- Customer-specific catalogues. Not just “Customer X sees prices,” but “Customer X sees the 47 products they have a current contract for and nothing else.” The platform models this as price-list scope; in practice you need to model it as catalogue scope.
- ERP-driven inventory and pricing. The product catalogue lives in Cin7, Unleashed, NetSuite, Pronto, or another ERP that’s the source of truth. The portal’s job is to render the ERP’s data in a buyer-friendly way, not to be the system of record for product or pricing data.
- Multi-warehouse fulfilment with intelligent splitting. Order lines may need to ship from different warehouses based on stock, customer location, and freight cost. The platform either treats the order as one shipment or doesn’t handle the splitting decision.
- Sales rep order entry. Field sales reps place orders on behalf of customers, often during in-person visits. The portal needs to support “rep logs in as themselves, selects customer, sees customer’s pricing and catalogue, places order on customer’s account.”
Each of those, individually, is a feature that can sometimes be bolted onto Shopify B2B or WooCommerce via apps. The combination is where the platform stops being the right base and a custom portal starts making sense.
The architectural shape that scales
The architecture we deploy for AU brands past the off-the-shelf line has a consistent shape:
- Custom portal as the buyer-facing surface. The portal is a focused web application that the buyer logs into, browses their catalogue, places orders, sees invoices and payment status. It doesn’t try to do everything Shopify does — it does the wholesale buying flow specifically.
- ERP as the source of truth for product, pricing, inventory, and customers. Cin7 / Unleashed / NetSuite / Pronto holds the master data. The portal reads from the ERP and pushes orders back to it. Critically, the portal does not maintain its own copy of pricing or catalogue data; it queries the ERP in real time (with caching for performance).
- Accounting integration as a separate concern. Xero or MYOB is where invoices live and where payment status reconciles. The portal doesn’t replace the accounting integration; it integrates alongside it, reading customer credit data and pushing order data for invoicing.
- Freight engine as a discrete service. A small internal service handles freight calculation, applying customer-specific rates, zone surcharges, and minimum-order thresholds. The portal calls the freight engine; the ERP doesn’t model freight rules to the depth most AU brands need.
- Sales rep app or admin layer. Either a separate sales-rep view of the same portal (rep logs in, selects a customer, sees their catalogue and pricing) or a dedicated tablet-friendly app for in-person ordering.
This shape lets each system do what it’s best at: the ERP holds master data and inventory, accounting holds invoices and payment status, the portal handles the buyer experience, and a thin integration layer holds the business rules that bridge them.
The catalogue and pricing architecture
The most consequential architectural decision in a B2B portal build is where product catalogue and pricing data live, and how the portal accesses them.
In our experience, the failure mode that breaks more wholesale portals than any other is catalogue and pricing drift between the portal and the ERP. The portal’s product catalogue gets seeded from the ERP at launch. Over time, products get added or discontinued in the ERP. Prices get updated. Customer-specific pricing gets renegotiated. If the portal maintains its own copy of any of this, it drifts. Buyers place orders at prices that no longer reflect the agreement. Sales reps quote prices that don’t match invoiced prices.
The robust pattern is to keep the ERP as the single source of truth and have the portal query it. In practice:
- Product catalogue: the portal pulls the catalogue from the ERP, caches it for 5–15 minutes, and renders it. New products appear in the portal within the cache window. Discontinued products disappear cleanly.
- Pricing: the portal calculates the price for a logged-in customer by pulling their price-list assignment from the ERP and applying it to the product. Cached at a per-customer level with short TTLs.
- Inventory: real-time read from the ERP for the customer’s assigned warehouse. Cached briefly to avoid hammering the ERP API but invalidated aggressively on the buyer’s product detail page so the buyer sees current stock when they’re actively considering a purchase.
The caching design matters. Too aggressive and you serve stale inventory; too conservative and the portal feels slow and you burn through the ERP’s API rate limits. The right design is per-resource: catalogue can cache for 15 minutes; pricing for 5 minutes; inventory for 30 seconds on hot pages and longer on cold pages. Each cache layer needs a clear invalidation strategy when the source data changes.
The freight engine
For AU wholesale brands, freight calculation is consistently underestimated as an architectural concern. The platform-default approach — flat rates by weight, or real-time carrier rates — doesn’t capture the wholesale freight model most AU brands use.
The model that does:
- Customer-specific contract rates. Customer A has negotiated a flat $25 per-pallet freight to anywhere in metro Sydney. Customer B has the standard contracted rates. The freight engine looks up the customer’s rate card before calculating.
- Zone-specific surcharges. A delivery to remote WA has a regional surcharge on top of the standard rate. The zone is determined from the postcode; the surcharge varies by carrier and service.
- Minimum-order freight rules. Orders below a freight-free threshold attract a freight charge. The threshold may vary by customer tier.
- Pallet-vs-carton logic. Above a certain order size the freight pricing switches from per-carton to per-pallet, and the carton consolidation logic determines how many pallets the order requires.
- Service-level selection. Some customers want next-day; others accept 5-day economy. The freight engine offers selectable service levels and surfaces the cost difference at order entry.
None of this is impossible in Shopify B2B’s freight model, but expressing all of it in the platform’s rule language is brittle. A dedicated freight engine (a few hundred lines of code, in our experience) handles it cleanly and is the natural place to add carrier integration if the brand wants live carrier rates on top of the contract rate logic.
This is the same shape as the carrier-agnostic shipping layer we describe in after Sendle: architecting Shopify and WooCommerce shipping — a thin internal abstraction that holds the business rules and talks to whatever carriers you’ve integrated to.
Net-30 credit and available-credit logic
The B2B feature that most often blocks an off-the-shelf platform is real-time credit-limit enforcement.
The pattern that works:
- The portal reads the customer’s credit limit and current outstanding invoice balance from the accounting system (Xero, MYOB) on session load.
- As the buyer builds their order, the running total updates the “available credit” figure displayed in the cart.
- When the buyer places the order, the portal does a final available-credit check against the current outstanding (re-querying the accounting system to catch any payments received between session start and order placement).
- If the order exceeds available credit, the portal flags it. Some brands block the order entirely until payment is received; others auto-route to the AR team for manual review; others let the order through with a credit-hold flag that the fulfilment team sees before picking.
The key architectural decision is what counts as “outstanding.” Most brands use invoiced-but-unpaid as the base, with policies on how to handle invoices that are due-but-not-yet-overdue versus invoices that are past due. The credit-check service holds the policy; the portal renders the result.
This is also where the integration to accounting becomes load-bearing rather than incidental. The portal can’t enforce credit limits without real-time visibility into the customer’s actual position; the accounting system holds that position. The integration pattern is the same as we discuss in ecommerce accounting integrations — webhook-driven where the accounting platform supports it, polling-based with reconciliation where it doesn’t.
Sales rep order entry
The sales rep flow is the single most common request we hear when starting a wholesale portal project and the single most common feature that’s skipped at launch because the buyer-facing portal is enough work on its own.
The right shape, when it’s built:
- Rep authentication separate from customer authentication. The rep logs in as themselves and picks the customer they’re ordering for. This matters for audit trail and for showing the rep’s commission attribution.
- Customer search and selection. The rep types the customer name and picks from results. The portal then shows the customer’s catalogue, pricing, and credit position.
- Order on behalf of the customer. The order is placed in the customer’s account, with the rep stamped as the order’s creator. The customer receives order confirmation as normal.
- Tablet-friendly layout for in-person ordering. Most rep order entry happens with the rep on site at the customer’s premises. The interface needs to work on iPad in landscape, with large tap targets and offline-tolerant behaviour for sites with patchy internet.
In larger brands, sales rep entry justifies a dedicated app rather than a view of the same web portal. The crossover point is roughly “more than five reps regularly placing orders.” Below that, a tablet-friendly view of the portal is sufficient and far cheaper to maintain.
Reporting that the existing ERP doesn’t produce
The reporting layer is often the deciding factor in whether a wholesale portal feels like a step forward or a step sideways. The ERP holds the data but rarely surfaces it in the ways the sales and operations teams need.
The reports that usually justify the portal:
- Per-customer ordering trends. Frequency, average order value, product mix, seasonal patterns. Sales reps use this to identify customers who are reordering less than expected.
- Catalogue performance. Which products are reordering, which are stocked but rarely sold, which are growing month-on-month.
- Credit and AR exposure. Outstanding by customer, days-outstanding analysis, credit-utilisation across the customer base.
- Sales rep performance. Orders per rep, value per rep, customer counts and attrition.
- Order channel attribution. Portal vs phone vs email vs rep-entered orders, with trends.
Each of these is buildable directly into the portal’s admin layer or pushed out as scheduled reports. The build cost is small once the data plumbing for the portal itself is in place — the portal is already reading the data, the reporting layer just needs to render it differently.
When the build is justified
The cost of a custom B2B wholesale portal for an Australian brand, in our experience, lands in the $40,000–$120,000 range for a first-version build, depending on the complexity of pricing logic, the number of integrations (ERP, accounting, freight, payment), and whether sales-rep entry is in scope.
The conditions where that’s worth the spend:
- Wholesale revenue is above $1m annually and growing. Below that, the off-the-shelf platforms cover most needs and the operational workaround for the gaps is cheaper than the build.
- The brand has named accounts with bespoke commercial arrangements (custom catalogues, contract pricing, contract freight) that the platforms can’t express.
- The buyer experience matters as a competitive position — particularly true in categories where wholesale buyers also have direct relationships with multiple suppliers and the portal experience influences which supplier gets the order.
- The operations team is currently spending 20+ hours a week handling order entry, pricing corrections, or credit holds that a portal would handle natively. The portal’s ongoing operational saving needs to amortise against its build cost.
Outside those conditions, the off-the-shelf B2B platforms are the right answer and the brand should focus on getting more value out of them rather than rebuilding from scratch.
Common questions
How long does a wholesale portal build take? First-version build for a brand with one ERP integration, one accounting integration, contract freight rules, and buyer-facing ordering: typically 12–20 weeks. Adding sales rep entry, multi-warehouse fulfilment logic, or complex tiered pricing extends that by 4–8 weeks each. The longest part of the project is rarely the development — it’s the data alignment between the ERP, accounting system, and the brand’s actual commercial rules, which are often less consistent than the brand realises.
Can’t we just use Shopify B2B? For brands with simple pricing tiers, flat freight rules, and no real Net-30 requirement, yes. The line moves once you have customer-specific catalogues, contract-rate freight, real-time credit-limit enforcement, or ERP-driven inventory at meaningful complexity. The honest test: list the commercial rules your wholesale business actually runs on. Can Shopify B2B express each one in its configuration without business-logic workarounds? If yes, stay on Shopify B2B.
What ERP integrations do you handle? The common AU wholesale ERPs we integrate to: Cin7, Unleashed, NetSuite, Pronto, MYOB Advanced, SAP Business One, and several industry-specific ERPs. The integration pattern is similar across them — the specifics of the API surface and authentication vary. We cover this in more depth in best practice software API integrations and the per-platform integration articles.
Should the portal hold product images, or should the ERP? Both, in practice. The ERP holds the product master record (SKU, description, attributes, pricing data). Product images, marketing copy, and merchandising data typically live in a dedicated PIM (Product Information Management) layer or in the portal’s own content store. The boundary is the merchandising data — anything that’s about how the product is presented to a buyer belongs in the portal’s control; anything that’s about what the product is belongs in the ERP.
What about wholesale-specific features like price approval workflows? For brands where reps quote special pricing that needs management approval before the order ships, the workflow lives in the portal: rep enters the price, the portal flags it as needing approval, an approver receives a notification, approves or rejects, the order moves accordingly. This is a common addition in larger brands and is the kind of business-logic feature the off-the-shelf platforms typically can’t express cleanly.
How does payment work in a B2B portal? Net terms are the dominant payment model in AU wholesale — the portal places the order, the brand invoices, the customer pays on terms. Some portals also support credit-card-at-checkout for customers without credit terms, which uses the same payment processing as a B2C ecommerce flow. The credit and accounting integration is what makes the Net terms flow work correctly.
If you’re scoping a wholesale portal build for your AU brand and want the architecture mapped against your specific ERP, freight model, and customer commercial rules, start a project and we’ll work through it.
More reading
Cliniko API integrations: practitioner's guide for AU clinics
A practitioner's view of the Cliniko API surface — what it covers, where it stops, and the integration patterns Australian allied-health practices use to build the layer Cliniko doesn't ship natively.
IntegrationsMindbody to Cliniko migration: technical realities for AU clinics
The technical realities of moving an Australian wellness, recovery or multi-modality clinic off Mindbody and onto Cliniko — what transfers cleanly, what doesn't, where the workarounds live, and what timeline to plan against.
IntegrationssimPRO API integrations: connecting AU trades to the stack
A practical view of the simPRO API surface — what it covers, where it stops, and the integration patterns Australian commercial trades operators use to build the layer simPRO doesn't ship natively.