Professional B2B System for Magento 2 Open Source
- SKU
- M2-B2B
Description / Professional B2B System for Magento 2 Open Source
MAGENTO 2 · MAGENTO OPEN SOURCE · COMPANIES · B2B COMMERCE
Combine B2B and B2C sales in one Magento installation.
Kowal B2B Suite
Build a contractor portal with companies, roles, pricing, catalogs, RFQ, limits, documents, and integrations. Activate B2B logic for selected websites and adapt the process to your commercial rules.
16 modules and a theme · Website scope · REST and GraphQL
HOW IT WORKS IN PRACTICE
01 · Define your sales model
You define companies, channels, prices, and data sources.
02 · Configure the B2B process
You assign roles, catalog, terms, and approvals.
03 · Connect systems and deploy
You select adapters and verify complete scenarios.
What does your store gain?
Explore the module features, use cases, and settings.
Explore the module
KOWAL B2B SUITE · MAGENTO 2 OPEN SOURCE
A professional B2B system without moving to Adobe Commerce
Kowal B2B Suite extends Magento 2 Open Source with the features needed for wholesale and contract sales.
Manage companies, users, custom pricing, quick orders, trade credit limits, approvals, quotes, documents, and integrations — all in one Magento environment.
Companies and roles · Prices and catalogs · RFQ · Trade credit · Documents · Integrations
B2B sales tailored to your commercial rules
Each contractor can receive its own prices, catalog, payment terms, limits, and users with different permissions.
The system supports both a simple wholesale model and advanced purchasing processes with multi-step approval and integration with ERP, PIM, WMS, or CRM.
Key areas of the B2B platform
Move daily contractor service from emails, spreadsheets, and manual arrangements directly into Magento.
Companies, users, and purchasing roles
One company can have multiple users, addresses, and people responsible for purchasing. Roles define who can place orders, approve them, or view data.
Custom pricing and catalogs
Each contractor can receive its own catalog, contract prices, quantity tiers, and purchasing rules. The customer sees the offer intended for their company.
Quick orders and shopping lists
Customers can efficiently place large orders by SKU, use shopping lists, and import items instead of searching for each product separately.
RFQ, quotes, and approvals
The quoting process can include negotiated prices, an expiration date, and individual terms. Orders can go through approval based on value or user role.
Financial control without spreadsheet work
Trade credit limits, credit utilization, and payment terms help control sales with deferred payment.
The customer has access to documents, while the team sees commercial terms and process status in one place.
Documents in the customer portal
- invoices and credit memos,
- delivery documents and confirmations,
- PDF quotes,
- documents from Magento or the ERP system.
What does implementation look like?
The platform can be implemented in stages. First, we organize commercial rules, then map them in Magento and integrate them with company systems.
1. Sales model
We define customers, channels, price lists, payments, restrictions, and data sources.
2. Company rules
We configure users, prices, catalog, addresses, limits, and purchasing roles.
3. Purchasing process
We implement quick orders, quotes, approvals, documents, and checkout rules.
4. Integrations and testing
We connect ERP, PIM, WMS, or CRM, test scenarios, and prepare the team for daily work.
Integrations with company systems
Data about customers, prices, products, orders, and documents can be exchanged with ERP, PIM, WMS, CRM, EDI, and contractor purchasing systems.
Synchronization can include trade credit limits, payment terms, order statuses, and documents. Task and error history makes it easier to control the process.
B2B that grows with your business
Kowal B2B Suite is a solution for wholesalers, distributors, manufacturers, and companies running contract sales.
You can start with companies, pricing, and catalog, then extend the platform with quick orders, RFQ, limits, approvals, documents, and integrations.
One Magento. One catalog. One B2C and B2B sales process.
One package, modular architecture
kowal/metapackage-b2b-suite provides the files for 16 B2B modules and the frontend/Kowal/b2b theme. The main package registers them in autoload and replaces subpackage names, so installing the suite does not require a separate repository for each module.
The implementation is designed for Magento Open Source 2.4.9 and PHP 8.3. The scope of activated modules, theme compatibility, and process scenarios must be verified in the target installation.
Website and company access model
B2B features operate in the context of the selected website_id. A company must have an active relationship with that channel, and roles define access to purchasing, users, quotes, and documents.
The first company model assumes one assigned website. B2C sales can use the same installation, but B2B activation and access to companies remain separated by channel configuration.
Quick Order, approvals, and staged implementation
Quick order checks SKU, quantity, website assignment, company visibility, and B2B price. Shopping lists and import logs help handle repeat orders.
Approval rules take company, website, currency, and threshold into account. The current pending request is closed with an approve, reject, or cancel decision. A multi-step workflow must be agreed and verified as a specific implementation scope.
Documents and secure access
Documents are assigned to a company and website. PDF files are stored in var/kowal_b2b_documents and downloaded through a controller that verifies access.
The source can be Magento Sales or a hybrid Magento + API mode. The package includes order, invoice, shipment, and credit memo documents, as well as a shared PDF renderer; synchronizing documents from an external system requires the appropriate adapter.
Integrations require adapters and data sources
The Integration layer provides profiles, identifier mapping, jobs, retry, logs, and a dead letter queue. A specific ERP, PIM, WMS, or CRM is connected with an adapter implementing SyncAdapterInterface.
Before launch, define the source of truth for companies, prices, inventory, orders, and documents. REST and GraphQL are integration points; installing the package does not automatically connect all company systems.
Installation via Composer
Package kowal/metapackage-b2b-suite, module Kowal_B2BBase. After configuring access to the Kowal repository, install the package, enable the module, update Magento, and clear cache. In production, include compilation and static content deployment according to the store process.
From configuration to results
1. Define your sales model
You define companies, channels, prices, and data sources.
2. Configure the B2B process
You assign roles, catalog, terms, and approvals.
3. Connect systems and deploy
You select adapters and verify complete scenarios.
Order portal for contractors
The company is assigned to an active B2B website. Its user works with the catalog and price defined by the agreed terms, adds items by SKU, and places the order.
Depending on configuration, the process includes a limit and approval. Documents and integrations remain linked to the company and the correct sales channel.
Plan a B2B implementation tailored to your company
Want to adapt the module to your store? Ask about implementing Kowal B2B Suite and discuss the configuration or required extensions.
More Information
| Theme compatibility | Luma / Blank, KOWAL |
|---|
Integration Configuration
Kowal B2B API — Complete REST Documentation
Contract version:
V1· Source of truth:Kowal_B2BApi/etc/webapi.xml· Audience: store administrators, implementation partners, and teams integrating ERP, PIM, WMS, or purchasing systems.
1. API purpose and boundaries
Kowal B2B API exposes B2B data and processes operating in Magento 2: companies, catalog and individual prices, quick purchasing, documents, trade credit limit, approvals, RFQ, and integration queues. It is a REST API for system integrations; it does not replace standard Magento endpoints for catalog, cart, checkout, and customer account.
The document describes only the endpoints currently exposed by the module. It does not promise operations not made available by the V1 contract, such as order creation via REST, price list CRUD, or website configuration editing.
2. Obtaining access and collaboration rules
2.1. Integration launch process
- The integrator provides the store administrator with the integration goal, environment (test/production), source system, data scope, and list of required API areas.
- The administrator creates or configures the Magento integration, assigns minimal ACL permissions, and securely provides:
baseUrl, token,websiteId,companyIdwhen applicable, currency, and test data. - The integrator runs the
GET /V1/kowal-b2b/websites/:websiteId/configtest, followed by functional tests in the test environment. - Before production, both parties agree on the synchronization schedule, maximum data size, retry, data owner, and error reporting method.
- Tokens are stored only in a secrets vault; the administrator rotates or revokes them when the vendor, user, or integration scope changes.
2.2. Responsibilities
| Party | Responsibility |
|---|---|
| Store administrator | Configuration of B2B website, company and company relationship with website, token, and ACL; provision of test data; decision on data access. |
| Integrator | Secure token storage, correct use of websiteId/companyId context, data validation, error and retry handling, and not disclosing data of other companies. |
| Business process owner | Agreement on the source of truth for prices, documents, RFQ, limits, and synchronization statuses. |
Do not use an administrator token in a client application or share one token across independent systems. Each integration should have its own token and only the required ACL.
2.3. Permissions
Magento verifies the Bearer token and ACL assigned to the administrative user or integration. B2B endpoints require one of the following permission groups:
| ACL | Scope |
|---|---|
config | Websites and feature flags |
companies, company_save, company_users, batch | Companies, their users, and batch company import |
products, prices, catalog_permissions | Catalog, availability, prices, and visibility |
import_export, quick_order, documents | Import/export profiles, shopping lists, and documents |
credit_limits, approvals, orders, quotes | Limit, approval workflow, order context, and RFQ |
system_integrations | Profiles, mappings, and integration jobs |
The scope should result from the purpose of the integration. Example: a purchasing system usually needs products, prices, catalog_permissions, quick_order, and quotes; an ERP handling documents — documents and, if it owns synchronization, system_integrations.
3. Technical conventions
Address, headers, and parameters
The base address has the form https://b2b.example.com/rest/V1. All paths later in this document are provided from /V1; the full endpoint address is BASE_URL + path.
Authorization: Bearer Accept: application/jsonContent-Type: application/json The API uses JSON. Names in URLs are camelCase (websiteId, companyId), and JSON fields correspond to Magento contract parameter names. :companyId, :quoteId, :sku, etc. are path parameters. In examples, ? indicates an optional parameter.
websiteId is required for sales channel-dependent operations. It must point to an existing website with B2B enabled. companyId points to a company that must have an active relationship with this website when the operation runs in its context. The API does not select a default website or company.
Request body and idempotency
Magento serializes the DTO object under the method parameter name: most write operations accept {'request': {...}}; company creation uses {'company': {...}}; company batch — {'companies': [...]}. Endpoints with simple arguments accept fields without a wrapper, e.g. {'websiteId': 1, 'currency': 'PLN', 'items': [...]}.
The Idempotency-Key header, max. 128 characters, is currently supported by POST /companies: retrying with the same key will return the previously created company. For an integration job, use the request.idempotencyKey field. Do not assume automatic idempotency of other write endpoints; retry them only after determining the operation status.
Responses and errors
Successful responses are Magento contract objects or arrays. Fields returned by objects may be extended in a compatible way; the integration should ignore unknown fields. A business error may contain:
{ 'code': 'b2b.company.not_assigned_to_website', 'message': 'B2B company is not assigned to website.', 'website_id': 1, 'trace_id': 'request-correlation-id', 'details': {'company_id': 10}, 'field_errors': []}| HTTP | Meaning | Integrator response |
|---|---|---|
400 / 422 | Invalid data or domain validation | Correct the data; do not retry without changing the payload. |
401 / 403 | Missing or insufficient token/ACL | Do not retry; report the token scope to the administrator. |
404 | The resource or relationship does not exist in the given context | Verify identifiers and website context. |
409 | Status conflict or duplicate | Read the current state before deciding to retry. |
5xx / timeout | Technical error | Use limited retry with backoff and keep the trace_id. |
Do not log tokens, full personal data, or configuration secrets. A report to the store team should include time, method, path without secrets, HTTP status, trace_id, and anonymized payload.
4. Input data schemas
The schemas below are common to the reference endpoints. A field without ? is required by the contract; ? means an optional value. The metadata, config, configuration, and payload fields are JSON objects.
| DTO / wrapper | Fields |
|---|---|
company | websiteId, name, taxId, externalId?, status?, salesRepresentativeId?, customerGroupId?, websiteActive? |
companyUser | websiteId, roleId, active |
request — RFQ | websiteId, companyId, customerId?, externalId?, title, currency, validUntil?, customerNote?, salesNote?, metadata? |
request — RFQ item | quoteId, sku, productId?, name?, qty, requestedPrice?, offeredPrice?, comment?, metadata? |
request — RFQ decision | customerId?, adminUserId?, message? |
request — RFQ comment | quoteId, customerId?, adminUserId?, authorType, message, visibleForCustomer |
request — document | websiteId, companyId, orderId?, orderIncrementId?, invoiceId?, invoiceIncrementId?, creditmemoId?, creditmemoIncrementId?, externalId?, documentNumber, documentType, status, issueDate?, dueDate?, grandTotal?, currency?, metadata? |
request — document file | documentId, fileName, filePath, mimeType, fileSize, checksum?, primary |
request — limit | websiteId, companyId, termsId?, creditLimit, currency, active, status, metadata? |
request — limit exposure | websiteId, companyId, sourceType, sourceId, sourceIncrementId?, amount, currency, dueDate?, metadata? |
request — payment terms | websiteId, code, name, daysDue, active, description? |
request — approval rule | websiteId, companyId, name, thresholdAmount, currency?, priority, active, metadata? |
request — approver | ruleId, customerId, sortOrder, active |
request — approval decision | approverCustomerId?, comment? |
request — approval request | websiteId, companyId, orderId?, orderIncrementId?, requesterCustomerId?, grandTotal, currency, comment?, metadata? |
request — import/export profile | websiteId, code, name, direction, entityType, format, behavior, active, configuration? |
request — integration profile | websiteId, code, name, systemType, adapterCode, direction, active, maxAttempts, config? |
request — mapping | websiteId, systemType, entityType, localId, externalId, metadata? |
request — integration job | profileId, direction?, entityType, operation, idempotencyKey?, maxAttempts?, payload?, scheduledAt? |
5. Endpoint reference
In the tables, ACL means the minimum Magento permission resource. Result defines the successful response type.
5.1. Websites and configuration
| Method and endpoint | ACL | Input | Result and use |
|---|---|---|---|
GET /V1/kowal-b2b/websites | config | — | Array of websites (websiteId, code, name, B2B flag). Retrieve before integration configuration. |
GET /V1/kowal-b2b/websites/:websiteId/config | config | path: websiteId | B2B website configuration, including enabled/debug/log retention. Run as an access test. |
GET /V1/kowal-b2b/websites/:websiteId/features | config | path: websiteId | Feature flags active for the website; use for conditional client feature enabling. |
5.2. Companies and company users
| Method and endpoint | ACL | Input | Result and use |
|---|---|---|---|
GET /companies?websiteId= | companies | query: websiteId | Array of companies assigned to the website. |
POST /companies | company_save | body: company | Creates a company and relationship with the website; use Idempotency-Key on retries. Returns the company. |
POST /companies/batch | batch | body: companies — array of company | Creates multiple companies and returns a result per item, including errors. |
GET /companies/:companyId?websiteId= | companies | path: companyId; query: websiteId | Company verified in website context. |
PUT /companies/:companyId | company_save | path: companyId; body: company | Updates company data and relationship for company.websiteId. |
POST /companies/:companyId/activate?websiteId= | company_save | path: companyId; query: websiteId | Activates the company in the indicated website and returns it. |
POST /companies/:companyId/block?websiteId= | company_save | path: companyId; query: websiteId | Blocks the company in the indicated website and returns it. |
GET /companies/:companyId/users?websiteId= | company_users | path: companyId; query: websiteId | Array of customer assignments to the company. |
PUT /companies/:companyId/users/:customerId | company_users | path: companyId, customerId; body: companyUser | Grants/updates the customer role and activity in the company; returns the assignment. |
5.3. Products, price, and catalog visibility
| Method and endpoint | ACL | Input | Result and use |
|---|---|---|---|
GET /products?websiteId= | products | query: websiteId | Array of basic Magento products for the website. |
GET /products/:sku?websiteId= | products | path: encoded sku; query: websiteId | Product (id, sku, name, type, status, websites). |
GET /products/:sku/availability?websiteId= | products | path: sku; query: websiteId | MSI availability and salable quantity for SKU. |
GET /products/:sku/b2b-status?websiteId= | products | path: sku; query: websiteId | B2B status: website assignment, translations, and stock data. |
GET /reports/products/missing-translations?websiteId= | products | query: websiteId | Report of SKUs without required translations, with reason/details. |
GET /reports/products/missing-stock?websiteId= | products | query: websiteId | Report of SKUs without required stock data. |
GET /companies/:companyId/products/:sku/price?websiteId=¤cy=&qty= | prices | path: companyId, sku; query: websiteId, currency, optional qty (default 1) | Explanation of the price applicable to the company, currency, and quantity; read before purchase. |
GET /companies/:companyId/products/:sku/visibility?websiteId= | catalog_permissions | path: companyId, sku; query: websiteId | SKU visibility/purchase result for the company. |
GET /companies/:companyId/catalog-visibility?websiteId= | catalog_permissions | path: companyId; query: websiteId | Array of company visible catalog index items. |
POST /companies/:companyId/catalog-visibility/reindex?websiteId= | catalog_permissions | path: companyId; query: websiteId | Rebuilds the index and returns the number of indexed items. Administrative operation. |
5.4. File import and export
| Method and endpoint | ACL | Input | Result and use |
|---|---|---|---|
GET /import-export/profiles?websiteId= | import_export | query: websiteId | Array of website import/export profiles. |
POST /import-export/profiles | import_export | body: request — import/export profile | Saves the profile and returns its data. |
POST /import-export/import/:profileId?sourceFile=&dryRun= | import_export | path: profileId; query: sourceFile, optional dryRun=false | Starts import of a file indicated on the Magento environment side; returns a job. Does not send multipart. |
POST /import-export/export/:profileId?resultFile= | import_export | path: profileId; optional query: resultFile | Creates an export job, optionally with a target file path. |
GET /import-export/jobs?websiteId= | import_export | query: websiteId | Array of import/export jobs for the website. |
GET /import-export/jobs/:jobId | import_export | path: jobId | Status, result, and data of a single job. |
GET /import-export/jobs/:jobId/logs | import_export | path: jobId | Diagnostic logs of the job. |
5.5. Quick order and shopping lists
| Method and endpoint | ACL | Input | Result and use |
|---|---|---|---|
POST /companies/:companyId/quick-order/validate | quick_order | path: companyId; body: websiteId, currency, items (sku, qty) | Validates multiple SKUs in company context: availability, visibility, and price; returns a summary result. |
GET /companies/:companyId/shopping-lists?websiteId= | quick_order | path: companyId; query: websiteId | Array of company shopping lists. |
POST /companies/:companyId/shopping-lists | quick_order | path: companyId; body: websiteId, name, optional customerId, isDefault=false | Creates and returns a shopping list. |
GET /shopping-lists/:listId/items | quick_order | path: listId | Array of items on the indicated list. |
POST /shopping-lists/:listId/items | quick_order | path: listId; body: currency, items (sku, qty) | Adds items to the list and returns the saved items. |
5.6. Documents and files
| Method and endpoint | ACL | Input | Result and use |
|---|---|---|---|
GET /companies/:companyId/documents?websiteId=&documentType= | documents | path: companyId; query: websiteId, optional documentType | Company documents, optionally filtered by type. |
GET /documents/:documentId?companyId=&websiteId= | documents | path: documentId; query: companyId, websiteId | Document details after company ownership verification. |
POST /documents | documents | body: request — document | Creates or saves document metadata and returns the document. |
POST /documents/files | documents | body: request — document file | Registers an existing file in Magento storage (name, path, MIME, size); does not upload binaries. |
GET /documents/:documentId/files?companyId=&websiteId= | documents | path: documentId; query: companyId, websiteId | Array of document file metadata. |
GET /documents/:documentId/sync-logs | documents | path: documentId | Document synchronization logs; intended for administrative integration. |
5.7. Trade credit limit and payment terms
| Method and endpoint | ACL | Input | Result and use |
|---|---|---|---|
GET /companies/:companyId/credit/status?websiteId=¤cy= | credit_limits | path: companyId; query: websiteId, currency | Limit status, utilization, and available company amount. |
POST /credit-limits | credit_limits | body: request — limit | Creates/updates the company limit and returns the limit. |
POST /credit/exposures | credit_limits | body: request — exposure | Reserves limit exposure for a source, such as an order, and returns it. |
POST /credit/exposures/:exposureId/release | credit_limits | path: exposureId; optional body: message | Releases exposure; returns its state. |
GET /payment-terms?websiteId= | credit_limits | query: websiteId | Array of active/known website payment terms. |
POST /payment-terms | credit_limits | body: request — payment terms | Saves payment terms and returns them. |
5.8. Approval workflow
| Method and endpoint | ACL | Input | Result and use |
|---|---|---|---|
GET /companies/:companyId/approval/rules?websiteId=¤cy= | approvals | path: companyId; query: websiteId, optional currency | Company approval rules for the channel/currency. |
POST /approval/rules | approvals | body: request — rule | Creates/updates a threshold rule and returns it. |
GET /approval/rules/:ruleId/approvers | approvals | path: ruleId | Array of assigned approvers, in sortOrder. |
POST /approval/approvers | approvals | body: request — approver | Saves the customer assignment as an approver. |
GET /companies/:companyId/approval/required?websiteId=&grandTotal=¤cy= | approvals | path: companyId; query: websiteId, grandTotal, currency | Boolean: whether the amount requires approval. |
POST /approval/requests | approvals | body: request — approval request | Creates a request for the order and returns it. |
GET /companies/:companyId/approval/requests?websiteId=&status= | approvals | path: companyId; query: websiteId, optional status | Array of company approval requests. |
POST /approval/requests/:requestId/approve | approvals | path: requestId; body: request — decision | Approves the request; returns its current state. |
POST /approval/requests/:requestId/reject | approvals | path: requestId; body: request — decision | Rejects the request; returns its current state. |
POST /approval/requests/:requestId/cancel | approvals | path: requestId; body: request — decision | Cancels the request; returns its current state. |
GET /approval/requests/:requestId/decisions | approvals | path: requestId | Decision history for the request. |
5.9. B2B order context
| Method and endpoint | ACL | Input | Result and use |
|---|---|---|---|
GET /orders/:orderId/b2b-context | orders | path: orderId | B2B context of a single native Magento order, e.g. company, approval status, limit, export. |
GET /companies/:companyId/orders/b2b-context?websiteId=&approvalStatus= | orders | path: companyId; query: websiteId, optional approvalStatus | Array of company order contexts, optionally filtered by approval status. |
5.10. RFQ and commercial offers
| Method and endpoint | ACL | Input | Result and use |
|---|---|---|---|
GET /companies/:companyId/quotes?websiteId=&status= | quotes | path: companyId; query: websiteId, optional status | Company RFQs and quotes, optionally by status. |
POST /quotes | quotes | body: request — RFQ | Creates a draft RFQ and returns it. Add items with a separate endpoint. |
GET /quotes/:quoteId | quotes | path: quoteId | RFQ/quote details. |
GET /quotes/:quoteId/items | quotes | path: quoteId | Array of RFQ items. |
POST /quotes/items | quotes | body: request — RFQ item | Adds SKU and quantity, optional requested/offered price, and comment. |
GET /quotes/:quoteId/comments | quotes | path: quoteId | RFQ comments. The customer sees only comments marked as visible. |
POST /quotes/comments | quotes | body: request — RFQ comment | Adds a message; authorType and visibleForCustomer define the author and visibility. |
GET /quotes/:quoteId/history | quotes | path: quoteId | RFQ status change and event history. |
POST /quotes/:quoteId/submit | quotes | path: quoteId; body: request — RFQ decision | Submits the draft RFQ for pricing. |
POST /quotes/:quoteId/make-offer | quotes | path: quoteId; body: request — RFQ decision | The salesperson creates/submits an offer; define item prices before calling. |
POST /quotes/:quoteId/accept | quotes | path: quoteId; body: request — RFQ decision | Accepts the current offer. This contract does not create a REST order. |
POST /quotes/:quoteId/reject | quotes | path: quoteId; body: request — RFQ decision | Rejects the offer/RFQ. |
POST /quotes/:quoteId/cancel | quotes | path: quoteId; body: request — RFQ decision | Cancels the RFQ if the current status allows it. |
5.11. Integration profiles and jobs
| Method and endpoint | ACL | Input | Result and use |
|---|---|---|---|
GET /integrations/profiles?websiteId=&systemType= | system_integrations | query: websiteId, optional systemType | Integration profiles for the website. |
POST /integrations/profiles | system_integrations | body: request — integration profile | Saves an ERP/PIM/WMS, etc. profile and returns it. |
POST /integrations/mappings | system_integrations | body: request — mapping | Saves a local ID ↔ external ID pair. |
GET /integrations/mappings/local?websiteId=&systemType=&entityType=&localId= | system_integrations | query: all parameters required | Finds a mapping by Magento identifier. |
GET /integrations/mappings/external?websiteId=&systemType=&entityType=&externalId= | system_integrations | query: all parameters required | Finds a mapping by external system identifier. |
POST /integrations/jobs | system_integrations | body: request — job | Publishes a job for execution; idempotencyKey identifies the business operation. |
GET /integrations/jobs?websiteId=&status= | system_integrations | query: websiteId, optional status | Array of integration jobs. |
GET /integrations/jobs/:jobId | system_integrations | path: jobId | Status and details of a single job. |
POST /integrations/jobs/:jobId/process | system_integrations | path: jobId | Processes the job and returns its current state. |
POST /integrations/jobs/:jobId/retry | system_integrations | path: jobId | Retries the job after an error, according to its attempt limit. |
GET /integrations/jobs/:jobId/logs | system_integrations | path: jobId | Job execution logs. |
GET /integrations/jobs/:jobId/errors | system_integrations | path: jobId | Domain/technical job errors. |
6. Example calls
export BASE_URL='https://b2b.example.com/rest/V1'export TOKEN='token-przekazany-przez-administratora'export WEBSITE_ID=1 COMPANY_ID=10 SKU='B2B-SKU-001' CURRENCY='PLN'# Test dostępu i konfiguracji kanałucurl -sS '$BASE_URL/kowal-b2b/websites/$WEBSITE_ID/config' \ -H 'Authorization: Bearer $TOKEN' -H 'Accept: application/json'# Cena kontraktowa firmy dla konkretnej ilościcurl -sS '$BASE_URL/kowal-b2b/companies/$COMPANY_ID/products/$SKU/price?websiteId=$WEBSITE_ID¤cy=$CURRENCY&qty=5' \ -H 'Authorization: Bearer $TOKEN' -H 'Accept: application/json'# Walidacja koszyka po SKUcurl -sS -X POST '$BASE_URL/kowal-b2b/companies/$COMPANY_ID/quick-order/validate' \ -H 'Authorization: Bearer $TOKEN' -H 'Content-Type: application/json' \ --data '{'websiteId':1,'currency':'PLN','items':[{'sku':'B2B-SKU-001','qty':5}]}'# Utworzenie RFQcurl -sS -X POST '$BASE_URL/kowal-b2b/quotes' \ -H 'Authorization: Bearer $TOKEN' -H 'Content-Type: application/json' \ --data '{'request':{'websiteId':1,'companyId':10,'customerId':25,'title':'Dostawa kwartalna','currency':'PLN','externalId':'ERP-RFQ-2026-001'}}'7. Recommended integration scenarios
Purchase by SKU
- Read the website configuration and save the provided
websiteId,companyId, and currency. - Use quick order for batch validation of SKU, quantity, visibility, and availability.
- For accepted items, retrieve the price from
pricewith the correctqty. - Create an RFQ, add items, and send them via
submitif the purchase requires a quote. - Track RFQ status and history; after acceptance, follow the agreed Magento order process because
V1does not expose an order creation endpoint.
Documents and billing
- Retrieve the company document list, optionally filtering by
documentType. - For the selected document, retrieve metadata and the file list; the file path is not automatically a public URL — agree on the binary download method with the store administrator.
- Read the limit status before the purchasing process; only an integration with
credit_limitsACL can manage it.
Asynchronous operations
- Save the integration profile and identifier mappings.
- Publish a job with a business
idempotencyKeyand keep thejobId. - Read the job and logs/errors; call
retryonly after analyzing the error and removing its cause.
8. Pre-production acceptance list
- The token has only the required ACL and is not an administrator token used by the UI.
- The integrator correctly handles
401,403,404,422validation,409conflict, and timeouts. - Each request in the B2B context provides the correct
websiteId, and company data uses the correctcompanyId. - Prices, visibility, and availability are checked before creating the purchasing process.
- Company creation uses
Idempotency-Key; integration jobs have a stableidempotencyKeyin the body. - Logs do not contain tokens or sensitive data, and the support procedure provides
trace_id. - Tests were performed in a test environment on a company that has an active relationship with the B2B website.
9. Compatibility
The contract is versioned by /V1. Extending responses with new fields is compatible; the integrator should tolerate unknown fields. A change that removes a field, field meaning, or endpoint requires a new API version. If there is a discrepancy between the document and the running installation, the active webapi.xml contract of the given module version is binding.
Module Installation Instructions
Kowal B2B Suite Installation and Configuration
This manual is intended for the person who purchased Kowal B2B Suite and needs to launch it in an existing Magento Open Source installation. It guides you through two stages:
- technical installation — performed by a developer or server administrator;
- business configuration — performed in the Magento panel by the store administrator.
Before you begin, create a backup of the Magento database and files. We recommend performing the first launch in a test environment and only then deploying to production.
1. What you receive and what you need
Kowal B2B Suite is delivered as the Composer package kowal/metapackage-b2b-suite. It includes B2B modules and the frontend/Kowal/b2b theme.
Requirements
| Element | Requirement |
|---|---|
| Magento | Magento Open Source 2.4.9 |
| PHP | 8.3 |
| Composer | Composer 2 |
| Server access | SSH and the ability to run bin/magento |
| Magento | working catalog, customers, checkout, Sales, MSI, and cron |
write access to var/ for the PHP process |
From Kowal, you will receive:
- private Composer repository address — referred to below as
REPOSITORY_URL; - user name or access identifier —
USERNAME; - access token —
ACCESS_TOKEN; - allowed package version range.
Do not store the token in the Git repository, tickets, or shell history shared with other people.
2. Technical installation
Run all commands in the root directory of the existing Magento installation, as a user with access to the files and to the bin/magento command.
2.1. Preparation
- Make sure Magento works correctly before the change.
- Save the deployment state and back up the database and the
app/etc,pub/media, andvardirectories. - In production, enable maintenance mode for the update:
bin/magento maintenance:enable2.2. Adding the private repository
Add the Kowal Composer repository and configure the access credentials you received.
You will receive Composer repository access credentials, the customer email address and license token, by email after purchase. They are also available in the customer panel after logging in at kowal.store. Replace TWOJ_EMAIL_KLIENTA with your account email address and TWOJ_TOKEN with the token you received. Run the commands in the Magento root directory.
composer config repositories.kowal composer https://repo.kowal.store
composer config http-basic.repo.kowal.store 'TWOJ_EMAIL_KLIENTA' 'TWOJ_TOKEN'Composer usually stores credentials in the local auth.json; do not add this file to Git.
2.3. Package installation
Install the version provided with the license. For the current package line, an example command is:
composer require kowal/metapackage-b2b-suite:^0.2 --with-all-dependenciesAfter downloading dependencies, update the Magento schema and configuration:
bin/magento setup:upgrade
bin/magento cache:cleanIn production mode, also run:
bin/magento setup:di:compile
bin/magento setup:static-content:deploy -f pl_PL en_US
bin/magento cache:flushUse only the locales that are active in the store. If the installation uses a different deployment process, add the above commands to its standard procedure.
2.4. Installation verification
bin/magento module:status | grep Kowal
bin/magento indexer:statusThe admin panel should show the B2B menu and the Stores > Configuration > Kowal > B2B tab. If they are missing, check the setup:upgrade result, cache, and the ACL roles of the administrator user.
2.5. PDF file permissions
PDFs generated by B2B use mPDF and directories under var/, including var/tmp/kowal_b2b_mpdf and var/kowal_b2b_documents. The PHP process must be able to create and write to them. Missing permissions result in document or PDF generation errors.
After completing the production deployment, disable maintenance mode:
bin/magento maintenance:disable3. Configuring the B2B store structure
3.1. Website and store view
The suite operates at the website scope, not globally. You can run B2C and B2B in the same Magento installation, but B2B should operate on a separate website or on a deliberately selected business sales website.
- In Stores > Settings > All Stores, create or select the B2B website, its store, and store view.
- Note the
website_id— it is used by companies, prices, documents, API, and integrations. - In Content > Design > Configuration, assign the
frontend/Kowal/b2btheme only to the B2B store view. - Verify that active currencies, taxes, shipping methods, and payment methods are configured for the same scope.
Do not assign the B2B theme to a B2C store view if you do not want to change its presentation layer. Installing the modules alone does not enable B2B logic for all websites.
3.2. Activating B2B
- Open Stores > Configuration > Kowal > B2B.
- In the scope switcher, select the correct Website.
- In the General section, set Enable B2B to
Yes. - During implementation, you can enable Debug Mode; disable it after testing.
- In the Default Config scope, set the log retention period.
- Save the configuration and clear cache.
After activation, all store views belonging to this website are treated as B2B. A company without an active relationship with this website will not gain access to it.
3.3. Seller data
Complete the selling company data in Stores > Configuration > General > Store Information: name, address, phone, and tax ID. They are used in documents and RFQ PDFs. Also complete the general sender email address in Sales Emails configuration and the email logo if it should appear in PDFs.
4. Configuring the first B2B customer
Use the following order for each company. It helps avoid a situation where the customer has an account but cannot see the offer or proceed through checkout.
4.1. Company, people, and addresses
- Open B2B > Companies and create a company.
- Enter the name, tax ID, external identifier if the company is synchronized with ERP,
Activestatus, and assignment to the B2B website. - Add a company user or assign an existing Magento customer. Assign the correct role and activate the assignment.
- In B2B > Company Addresses, add company addresses; mark the default billing and shipping address for the B2B website.
- In B2B > Company Contacts, add an active primary contact with email and phone.
The billing address and primary contact are also used in RFQ PDFs. Missing data does not block the PDF, but the document will be less complete.
4.2. Company roles
Grant users only the permissions they need. A typical division is:
| Role | Example tasks |
|---|---|
| Company administrator | users, roles, addresses, documents, and company history |
| Buyer | catalog, quick order, cart, RFQ, and orders |
| Approver | decisions in the approval workflow |
| Accounting | documents and billing information |
Test an account of each type, especially permission to place orders and approve them. Do not use one shared account for the entire company.
5. Offer, pricing, and checkout
5.1. Catalog and prices
- Make sure Magento products are assigned to the B2B website, active, and have correct MSI data.
- Configure price lists or contract prices for the company in B2B > Pricing (Price Lists, Price List Assignments, or Contract Prices).
- Configure catalog visibility rules for the company according to the implemented permission model, then verify visibility on the customer account.
- Test on the company account: SKU search, product visibility, and price for quantity
1and for the quantity tier.
The B2B price depends on company, website, currency, and quantity. A product visible in B2C does not have to be available to a B2B customer.
5.2. Shipping and payment
- Enable the required shipping and payment methods in the standard Magento configuration for the B2B store view.
- In B2B > Checkout, add rules for available methods for the company/website if you want to restrict selection.
- Run a cart test using the company default addresses.
If order creation from RFQ is expected to work automatically on the administrator side, the company must have unambiguous default addresses and active payment and shipping methods. Otherwise, the Suite will load the data into native Backend Order Create, where the administrator completes missing elements.
5.3. Limits and approvals
These features are optional, but they should be configured before enabling them for customers.
- In B2B > Credit > Payment Terms, add payment terms.
- In B2B > Credit > Credit Limits, assign a limit, currency, status, and payment term to the company.
- In B2B > Approvals > Rules, create an amount threshold rule for the company and website.
- In B2B > Approvals > Approvers, assign approvers.
- Test the cart below and above the threshold and verify whether the approver decision changes the next step of the process.
6. Documents, PDF, and RFQ
6.1. Magento documents
In Stores > Configuration > Kowal > B2B > Documents, select the document source and decide which documents should be generated automatically: order confirmations, invoices, delivery documents, and credit memos. Also set the target document status.
In B2B > Documents > PDF Templates:
- check the active template for each type and website;
- preview it;
- adjust HTML/CSS only if you have someone familiar with Magento templates and mPDF CSS;
- generate a test invoice or confirmation and verify download from the company account.
6.2. RFQ and quote PDF
- In B2B > Quotes > RFQ, create a test RFQ for an active company and user.
- Add SKUs visible to the company, quantity, and quoted price.
- Set the expiration date, send the quote to the customer, and generate the PDF.
- Check the customer variant: seller/buyer data, items, price, total, and expiration date.
- Check the administrator variant: additionally sales notes, comments, history, and internal item information.
The customer PDF must not contain salesperson notes or internal status history.
7. Quick orders, imports, and integrations
Quick orders
In B2B > Quick Order > Debug SKU, check the SKU,qty list for the company, website, and currency. Then create a shopping list and test its use by the customer on the storefront.
Import and export
In B2B > Import/Export, define a profile only after establishing the data source. Profile configuration is a JSON object and must contain file paths available on the Magento server. First run the import in test mode and analyze the job and logs.
API integrations
Before creating an integration token, define the data scope and synchronization owner. Use a separate Magento integration for each ERP, PIM, WMS, or middleware and grant only the required B2B ACL. The full list of endpoints, tokens, and security rules is available in the API documentation for integrators (request the current integration documentation from Kowal).
8. Acceptance checklist
Before production launch, confirm:
- ☐Kowal modules are active, cron works, and cache and indexes are correct.
- ☐B2B is enabled only for the correct website.
- ☐The B2B theme is assigned only to the B2B store view.
- ☐The test company has Active status, a user, role, contact, and default addresses.
- ☐The test product is active, assigned to the website, visible to the company, and has the correct B2B price.
- ☐The customer can log in, search for SKU, use quick order, and add a product to the cart.
- ☐Checkout shows only permitted shipping and payment methods.
- ☐The limit and approval rule work according to company policy if these features are used.
- ☐The document and RFQ PDF generate and are available only to the correct company.
- ☐RFQ can be sent, accepted, and passed to the order creation process.
- ☐Integrations have separate tokens and restricted ACL if they are used.
9. Most common issues
| Symptom | What to check |
|---|---|
| No B2B menu | setup:upgrade, module status, cache, and administrator ACL. |
| Company or customer does not see B2B | Whether B2B is active for the correct website and whether the company has an active relationship with that website. |
| Product is not visible or has no price | Product assignment to website, SKU activity, MSI data, catalog rules, company price, currency, and quantity. |
| No shipping or payment method | Standard Magento configuration, B2B store view scope, and B2B Checkout rules. |
| PDF is not created | Active PDF template, mPDF package, permissions for var/, seller data, and Magento logs. |
| RFQ does not create an order automatically | Default company addresses, unambiguous payment and shipping; in other cases, use Backend Order Create. |
API returns 403 | The integration token does not have the required ACL; do not use an administrator token in an external application. |
When contacting support, provide the Magento version, package version, reproduction steps, event time, safely anonymized logs, and any trace_id. Do not send tokens or passwords.
10. Package update
- Review the release information provided by Kowal.
- Perform the update first in a test environment.
- Create a backup, run
composer update kowal/metapackage-b2b-suite --with-all-dependencies,bin/magento setup:upgrade, and in production also DI compilation and static asset deployment. - Repeat the acceptance checklist, with special attention to prices, checkout, documents, and integrations.
Do not update the package by manually copying files to app/code; this causes Composer issues and makes future support more difficult.