Building B2B Storefronts
This guide covers the patterns and APIs needed to build a business-to-business (B2B) storefront with Norce Commerce. It picks up where the general customer login guide leaves off and focuses on the company context that makes B2B different from B2C.
For basket management once company context is established, see Working with B2B Baskets.
The B2B Model in Brief
A B2B order in Norce Commerce always involves two entities:
- Customer — the individual placing the order (the contact person)
- Company — the organization buying on behalf of which the order is placed
A customer can be linked to multiple companies. The active company context determines which prices, price lists, assortment restrictions, and company discounts apply during the session.
A B2C order has only a Customer and no Company. The same person can place both B2C and B2B orders — Norce does not require separate accounts.
Login and Company Resolution
Step 1 — Authenticate the customer
B2B login uses the same mechanism as B2C. Call LoginPost with the customer's credentials. A full Customer object is returned, including a Companies list.
If you use a third-party identity provider, authenticate externally and then look up the customer in Norce by email address or
CustomerCodeusingGetCustomerByEmailorGetCustomerByCode.
Step 2 — Resolve the active company
After login, check the Companies list on the returned Customer object:
- No companies: The customer is B2C only. Proceed with a standard session.
- One company: Set that company as the active context automatically.
- Multiple companies: Present a company selector and let the customer choose which company to buy for. Store the selected
CompanyIdin the session.
// Customer object after login — Companies list
"Companies": [
{
"Id": 334815,
"Code": "test0043",
"Name": "Acme Corp",
"PricelistIds": [4521, 4654]
},
{
"Id": 334816,
"Code": "test0044",
"Name": "Acme Nordic AB",
"PricelistIds": [4521]
}
]Store both CustomerId and the selected CompanyId in the session — you will need both for all subsequent product, pricing, and basket calls.
Step 3 — Fetch full company details (optional)
For rich B2B UIs (showing company address, flags, available price lists), fetch the full company object:
GET customer/1.1/GetCompany?companyId=334815This returns the complete company including delivery addresses, flags, info types, and price list associations.
Company-Specific Pricing
How pricing works
When a CompanyId is set in the session, Norce Commerce automatically selects the best available price from the price lists connected to that company. This happens both in product listing and in the basket.
Pass both customerId and companyId as context parameters when fetching products or price data:
GET product/1.1/GetProduct?partNo=PRD001&customerId=12345&companyId=334815The returned price reflects the company's best available price across all connected price lists.
Company discounts
Company discounts are category- or flag-based discount rules configured on the company. They are applied on top of the price list price and calculated in real time. They are not stored as explicit prices and do not appear in standard price exports — the discounted price is only visible when products are fetched in an authenticated company context.
Note: Company discounts are applied automatically when
companyIdis passed in context. No extra API calls are required.
Fetching available price lists
To let the customer explicitly choose which agreement (price list) to use for their purchase, fetch the company's available price lists:
GET customer/1.1/ListCompanyPricelists?companyId=334815See Working with B2B Baskets for how to use these in the basket.
Company-Specific Assortment
Some products are restricted to specific companies — they are invisible or unbuyable for customers without the right company context. This is configured in Norce via company-specific price lists that control assortment visibility.
When fetching product lists with companyId in context, Norce automatically filters to show only products available to that company. No special handling is required in the frontend beyond passing the correct companyId.
Tip: If a product appears in one company context but not another for the same customer, it is likely an assortment restriction rather than a data issue.
The B2B Purchase Flow
Creating the basket
Always create the basket with both CustomerId and CompanyId set from the start. This ensures company pricing and business rules apply to every item added:
{
"CustomerId": 12345,
"CompanyId": 334815
}See Working with B2B Baskets for full basket management, pricing scenarios, approval workflows, and procurement fields (PO number, cost centre, invoice mark).
Checkout
The checkout object in a B2B session populates Buyer, Payer, and ShipTo from the customer and company data. Common patterns:
- Payer is typically the company (company invoice address)
- ShipTo can be one of the company's delivery addresses, selected by the customer
- Buyer is the individual customer (the contact person)
Populate the checkout with the company's invoice address as the default payer address, and offer the company's delivery addresses as options for ShipTo.
New Company Registration
Some B2B storefronts allow companies to self-register. The typical flow:
- Collect company details (name, organization number, contact person) from the registration form.
- Create the company in Norce using
UpdateCompanyfrom the Customer Service API.UpdateCompanycreates a new company when no matching company exists, making it the standard call for storefront-driven company creation. - Send the new company to the ERP for approval (credit check, contract setup).
- ERP returns a
CompanyCodeand optionally a verification flag (e.g. "approved for contract purchasing"). - Update the company in Norce with the ERP code and linked price lists using
UpdateCompanyagain.
Until the company is approved and has a CompanyCode set, the customer can still browse — but restrict B2B checkout to approved companies. Use a company flag (e.g. IsApproved) to gate access.
For the integration side of this flow, see Customer and Company Integrations.
Common Patterns and Pitfalls
| Pattern | Notes |
|---|---|
Always pass both customerId and companyId | Both are required for any call where company pricing or assortment should apply — passing only companyId is not enough. Without customerId, Norce cannot resolve customer-specific entitlements; without companyId, prices and assortment restrictions fall back to B2C rules |
| Company selector on login | If a customer has multiple companies, present a picker before loading any prices — fetching prices without companyId and then re-fetching after selection doubles API calls |
| Clone the basket on context change | When a customer logs in after browsing anonymously, or switches active company mid-session, create a new basket based on the existing one rather than modifying it in place. Norce can carry over items while starting a clean session — this avoids stale anonymous-session data affecting pricing and order history, and preserves the old basket in history |
| Checking company approval state | Use a company flag to prevent unapproved companies from completing checkout |
| Company discounts not in list prices | Don't cache prices fetched without companyId and apply them in a company session — the discount won't be included |
Further Reading
- Customer Accounts and Login — authentication, account creation, password management
- Working with B2B Baskets — basket creation, pricing scenarios, approval workflows, procurement fields
- The Customer and Company Model — entity model, identification keys, import behavior
- Customer and Company Integrations — integration patterns for keeping company data in sync