Skip to main content

Changelog

All platform changes in one place. Filter by component or type to find what matters to you.

Component
Type

Bulk shipment import upserts by source

The bulk shipments endpoint now upserts on the source and sourceId combination. A shipment with a known combination is updated and a new one is created when it does not exist yet.

Product bulk upsert updates EAN code, package and package unit

Updating a product through the bulk upsert by source id did not save changes to eanCode, package and packageUnit. These fields are now updated as expected.

Order search returns the expected results

Searching orders through the API could return incorrect or incomplete results for some filter combinations. Order search now returns the orders that match the query.

Supplier changes on order items are saved

Changing the supplier on an order item while editing a quote or order was lost once the order was processed. The updated supplier is now stored on the order.

Correct created and modified timestamps on media

Media items returned incorrect values for their created and last modified timestamps. These now reflect the actual creation and modification times.

Bonus items discounts apply consistently

Bonus item discounts were not always applied correctly. Incentive results are now calculated and stored consistently on the order.

Company name available on the orders query

The orders and quote queries now return the name of the company an order belongs to. This is the company itself, not the company name stored on the order address, which can differ.

Clearer error when a category parent does not exist

Creating a category with a parent that cannot be found returned a confusing message with a second, unrelated line about root categories. The endpoint now returns a single clear message that names the missing parent.

Bulk prices accept productSource as an array

Sending productSource as an array on the bulk prices endpoint failed with a not-found error, while a single object worked. The endpoint now accepts productSource as an array as well.

Validity dates on bulk cost prices

Bulk cost prices now support a from and to validity date, the same way bulk prices do. Use them to schedule a cost price change ahead of time.

Import attributes together with companies, contacts and customers

The bulk import for companies, contacts and customers now accepts attributes in the same nested payload. You can set attribute values during the import instead of sending a separate request.

Default value is optional when creating an attribute description

Creating an attribute description no longer requires a default value. Leave it out for attributes that do not need one. This applies to both the GraphQL and REST APIs.

Products can belong to multiple clusters as options

Clusters (product variants) have options, the extra products you offer alongside the configured cluster product. A product can now be linked to any number of clusters as an option instead of exactly one, which helps when the same product fits several clusters. The same product can still be sold on its own alongside those cluster offerings.

Validation and consistency improvements on the product, category and cluster APIs

The product, category and cluster endpoints (including cluster configs, cluster options and cluster products) now have stricter, more consistent validation across REST and GraphQL, with clearer error messages. Lookup keys are case sensitive (use sourceId, not sourceid), and bulk requests reject duplicate identifiers and empty arrays, with each batch rolled back if an item fails validation. Categories, products and clusters created without a parent are kept as root or floating items rather than placed under a default category.

The price fields that were deprecated earlier have now been removed from the product and cluster-product endpoints (price, taxCode, taxPercentage, costPrice, suggestedPrice, discountPrice, discountPriceFrom, discountPriceTo, costprices, surcharges and priceDisplay); use the pricing endpoints instead. Cluster options also have their own dedicated input and response types.

Pricesheet CSV import accepts localized name and description columns

The pricesheet CSV import treated localized name and description columns with the wrong type, causing valid rows to fail mapping. The import now accepts these columns as expected.

Order and hide categories and products in your storefront catalog

You can now set the order of categories, and of the products inside a category, per storefront. Categories and individual products can also be hidden without unpublishing them, which keeps seasonal or less relevant items out of view while preserving their data.

Favorite lists reject mixed id and source inputs

Favorite list mutations accepted both productIds and productSources (or clusterIds and clusterSources) in the same call, which led to ambiguous behavior. These combinations now return a validation error.

Channel-level default language settings

Channels now support two new settings, defaultAppLanguage and defaultDataLanguage. These give a per-channel fallback when a request does not specify a language, so regional channels serve the correct locale by default without every client call passing an explicit language.

Dedicated catalog per sales channel

If you run multiple sales channels, for example a B2B portal alongside a spare-parts webshop, each channel can now have its own dedicated catalog. Products and categories are fully separated per channel, so a product surfaces only in the channels it belongs to and nothing appears in the wrong storefront.

Consistent pagination metadata from attributeResultByClusterId

attributeResultByClusterId could return a response.page that did not match the requested page and exceeded response.pages, breaking pagination logic built on that metadata. The returned page now matches the page actually served and stays within bounds.

Filter category product search by orderlist

CategoryProductSearchInput now accepts applyOrderlists: Boolean and orderlistIds: [Int!]. Category queries can be scoped to one or more orderlists, so browsing a category returns only the products that belong to the selected orderlists. This makes it easier to render category pages that respect a customer's assigned orderlists.

Fix removing language entries from localized media fields

Media update mutations did not remove a language entry from localized arrays such as name, description, alt text, image and video when that language was left out of the input. The existing value stayed in place instead of the array being replaced. Update mutations now replace localized arrays with the provided input, so dropping a language entry from the call removes it from the stored value.

Pricesheet category discounts apply only to products in the category

In rare cases, a pricesheet discount that targets a category could apply to a product outside that category, returning a lower customer price than the price sheet defined. Category discounts now apply only to products that are actually in the targeted category.

More reliable bulk inventory updates and cleanup

Bulk inventory updates now succeed or fail as a whole, so a single bad record no longer leaves the rest of the update in an unknown state. Inventory is also cleaned up when its parent is removed: deleting a company removes its inventory, and deleting a warehouse unlinks it from any inventory that referenced it.

Payment method and carrier logos returned by cart queries

Cart queries now include logo URLs for payment methods and carriers. The payment method logo field was previously missing from the response and the carrier logo field returned null, so frontends can drop any local asset map keyed by method or carrier name and render the logos straight from the cart response.

Improvements to managing inventories

Inventory records now support a companyId field, making it easier to reserve stock for a specific company in multi-tenant setups. This release also includes further performance improvements across inventory queries and mutations.

More detailed REST validation error responses

Validation errors on REST endpoints now return more detailed information in the response body, making it easier to identify which field failed validation and why.

Use company, contact and customer attributes as a condition in business rules

Business rules can now evaluate attributes on companies, contacts and customers when determining payment methods, carriers and incentives. This works the same way as order item attribute conditions and applies to both tender and cart evaluation. Company, contact and customer data is now passed through during rule evaluation so attribute-based conditions resolve correctly at checkout.

Self-service API keys

Partners and Backoffice users can now create and manage both GraphQL and REST API keys directly from the platform or through GraphQL. A dedicated user role has been introduced for API key access control.

Fix empty shipments array for authenticated users

The order query was returning an empty shipments array for authenticated users in certain cases. Shipment data is now consistently returned when querying orders.

Fix error response for invalid pagination parameters on attribute descriptions

Using negative values for page or offset when retrieving attribute descriptions returned an internal server error instead of a proper validation error. The API now returns a 400 response with a clear message.

Fix order search not matching on address fields

Searching for orders by recipient first name, city, postal code or other delivery address fields was returning zero results. Only email-based searches produced matches. Order search now correctly matches against all supported search fields.

Fix CSV import of attributes across multiple entities

Importing attribute values via CSV for multiple entities (companies, products, contacts) was only updating the first entity in the file. The import logic has been corrected so that the same attribute can be set on multiple entities in a single CSV import.

Fix products query returning wrong results with class: PRODUCT filter

Fixed the products query returning incorrect results when filtering with class: PRODUCT inside a category. Cluster products were incorrectly indexed with category IDs from their parent cluster, causing them to appear in unrelated category results.

Fix error when setting keywords on cluster products via REST

Fixed an error when setting keywords on products within clusters via the REST API. The clusterProductUpdate operation previously returned a 500 Internal Server Error when keywords were included in the update payload.

Embedded Workflows and AI Agents

The platform now supports embedding external workflows and AI agents directly in the Sales Hub and Backoffice. Agents appear inline on quotes, orders, the PIM and other pages. They are triggered by a button click or chat input and execute against external webhook endpoints.

Embedded workflow demo

How it works. Each agent is configured with a webhook URL. When triggered, Propeller sends a POST request containing the current page context (order data, company details, product list) and the user's message. The external endpoint processes the request and returns a response that is displayed inline. Any system that can handle HTTP POST and return JSON works: n8n, custom APIs, LLM services.

What this enables. Partners can build and connect their own logic: margin validation on quotes, reorder suggestions based on order history, conversational assistants for pricing or product selection, automated churn detection. The full commercial dataset (customers, orders, products, prices) is available in the webhook payload. Business rules like discount limits and catalog restrictions apply to agent interactions the same way they apply to manual actions.

Agent types control where the agent appears. Built-in types include SALES_HUB_ORDER_EDITOR, SALES_HUB_QUOTE_EDITOR and SALES_HUB_COMPANY. Custom types can be registered for frontend pages like product detail or customer portal.

GraphQL API. Agents are managed through agentCreate, agentUpdate and agentDelete mutations. Conversations use agentConversationCreate and agentMessageCreate. The agents query lists available agents filtered by type and trigger.

See the full documentation at Workflows and AI Agents.

Improved change detection for user management bulk imports

Fixed an issue where bulk import endpoints for companies, contacts and customers would detect false changes when email addresses contained mixed case characters. The comparison now correctly accounts for case sensitivity, preventing unnecessary updates.

Fixed nested addresses and attributes in bulk user imports

Fixed an issue where addresses and attributes provided as nested payload in the company, contact and customer bulk endpoints could be incorrectly assigned across records in the same batch.

Media upload mutations accept array input

The uploadImage input property on the mediaImageCreate mutation now accepts an array, allowing multiple files to be uploaded in a single request. The same change applies to other media type mutations.

Updated account page to dashboard

Replaced the account details page with a dashboard layout featuring recent orders, quotes and a customizable content block.

Sorting improvements

Added support for secondary sorting options in the catalog and relevance-based sorting for search results with configurable field boosting.

Redesigned product list layout

Redesigned the catalog search results page to use a row-based list layout, better suited for B2B catalogs with technical products.

Migrated to localized short names

Migrated product short names to use localized values for proper multi-language support.

Improved cluster scrolling

Improved scrolling behavior on cluster detail pages so the specification list no longer blocks access to the cluster configuration.

Fixed visual issue with headers

Fixed a visual display issue with page headers.

Fixed shipments not appearing in order detail

Fixed an issue where shipment information was not displayed on the order detail page.

Fixed quote expiry date mismatch

Fixed a mismatch between the quote expiry date shown in the backoffice and the date displayed on the frontend.

Fixed quantity input digit limit

Fixed an error that occurred when entering more than 10 digits in the quantity input field.

Fixed product specifications not displaying

Fixed an issue where the specifications section was not showing on the product detail page.

Fixed product image overlay centering

Fixed an issue where the enlarged product image overlay was not centered on the page and appeared cut off at the bottom.

Fixed PHP 8.2+ deprecation errors

Fixed PHP deprecation errors that appeared when running on PHP 8.2 or higher.

Fixed out of stock products added to basket

Fixed an issue where out of stock products could still be added to the basket despite stock validation being enabled.

Fixed missing payment and carrier costs on quote

Fixed missing payment method costs, carrier and shipping costs on the quote overview page.

Fixed missing bulk prices on cluster page

Fixed an issue where bulk prices added to products in a cluster were not visible on the frontend cluster detail page.

Fixed missing address abbreviation in checkout

Fixed a missing gender field in the checkout address form, which could cause incorrect salutations in order confirmation emails.

Fixed favorite list rename visibility

Fixed an issue where renaming a favorite list was not immediately reflected in the add to favorites button.

Fixed duplicate delivery address display

Fixed an issue where the default delivery address was displayed twice on the addresses page.

Fixed default address change visibility

Fixed an issue where changes to the default delivery or invoice address were not immediately visible on the account overview page.

Fixed company switch addresses not visible

Fixed an issue where delivery addresses from the selected company were not displayed after switching companies.

Fixed column headers CSS

Fixed broken CSS styling on column headers.

Fixed cluster product favorites

Fixed an issue where cluster products could not be added to a favorites list.

Fixed catalogue filters

Fixed incorrect behavior of filters on the catalogue page.

Fixed cart visible after company switch

Fixed an issue where a cart created for one company remained visible after switching to another company.

Fixed cart buttons mobile alignment

Fixed misaligned buttons in the cart view on mobile devices.

Fixed cart and checkout summary

Fixed incorrect totals in the cart summary and checkout summary pages, including missing carrier and payment method line items.

Fixed basket mini account border radius

Fixed the basket item count badge border radius to maintain a circular shape regardless of the number of digits.

Fixed add to basket loader

Fixed an issue where the loading indicator remained visible after adding a product to the basket.

Expanded dashboard with favorites, authorization requests and invoices tiles

Added three new tiles to the contact dashboard: favorites, authorization requests and invoices.

Spare parts product filters now support input arguments

The sparePartProducts.filters field in the machine query now accepts an input argument, matching the behavior of product search filters elsewhere. Previously, the field returned all product attributes regardless of whether they were marked as searchable. You can now pass input: { isSearchable: true } to return only filterable attributes.

Order REST endpoint now returns sources for all items

Fixed an issue where GET /v2/orders/{id} with expands=SOURCES only returned sources for the first 12 order items. Orders with more than 12 items now correctly include source data for every item.

Fixed priority field error when applying incentives

Fixed an issue where tenderApplyIncentives returned an error when bonus items did not have a priority value set. The mutation no longer fails with "Cannot return null for non-nullable field TenderMainItem.priority" when incentive bonus items lack a priority.

Bulk attribute imports now upsert translations instead of replacing them

Bulk attribute text value imports (via REST and GraphQL CSV import) now upsert translation values instead of replacing all existing ones. Previously, importing attribute values for one language would overwrite values in other languages. Each language is now updated independently.

Fixed stock validation

Fixed an issue where stock validation showed incorrect popups on the product detail page.

Fixed portal login

Fixed an issue preventing users from logging into the portal.

Fixed unauthorized error when switching companies

Fixed an issue where switching companies returned Unauthorized use of companyId errors. This affected category page queries, the cartStart mutation and addressesByCompanyId queries when using an API key with an access token.

Fixed shopping cart accessories

Fixed an issue where clicking to add accessories in the shopping cart had no effect.

Fixed recaptcha configuration

Fixed an issue preventing recaptcha from being enabled in the plugin settings.

Fixed dropshipment shipping costs

Fixed incorrect shipping costs displayed when choosing dropshipment as the order type.

Fixed catalog page access

Fixed an issue where catalog pages could not be accessed on the frontend.

Fixed closed portal search leak

Fixed an issue where products were visible in the search bar even when closed portal mode was enabled and the user was not logged in.

Fixed carrier not displayed in order editor

Fixed an issue where newly created carriers were not displayed in the backoffice order editor.

Fixed product image overlay positioning

Fixed an issue where the product image overlay was not centered on the page and appeared cut off at the bottom.

Fixed add to cart failing for clusters with options

Fixed an issue where adding a cluster with options to the cart failed with a pricing error. The cart now correctly handles clusters that include option products.

CSV company import now correctly imports email and phone

Fixed an issue where importing companies via CSV did not populate the email and phone fields. These fields are now correctly imported from the CSV data.

Fixed cluster search filters

Fixed an issue where search filters did not take into account searchable attributes for products within clusters.

Fixed failing to fetch prices

Fixed an error that occurred when fetching prices for products and clusters added to the cart.

Fixed duplicate specifications on PDP

Fixed an issue where product specifications appeared twice on the product detail page.

Priority field for tender and order item reordering

Added a new priority field to TenderMainItem and OrderItem types. This field allows you to control the display order of line items within a tender or order, enabling custom sorting of items beyond the default insertion order.

Partial text search for attribute descriptions

Attribute description search now supports partial text matching on names and descriptions. Previously, searches required exact or prefix matches. You can now find attribute descriptions by searching for any part of their name or description text.

Image variants now created for all language images

Fixed an issue where uploading images for multiple languages only generated image variants (thumbnails and resized versions) for the last language processed. Image variants are now correctly created for all language versions of an image.

Fixed spare part products query for universal KType lookups

Fixed an issue where the sparePartProducts query returned null when looking up parts using a universal KType value. The query now correctly resolves spare parts for universal KType lookups.

Fixed company search validation for short IDs

Fixed an issue where searching for companies by a single-digit ID failed due to a minimum character validation constraint. Company search now correctly handles short search terms including single-character values.

Carts query now supports channel ID filtering

The carts query now accepts a channelId filter parameter. This allows you to retrieve only carts associated with a specific channel, which is useful for multi-channel setups where you need to manage carts per storefront or sales channel.

Localized short names for products

Products now support localized short names through a new shortNames field, similar to how names and descriptions already work. This allows you to define short product names per language.

The existing shortName field is now deprecated but continues to work. When creating or updating products, you can use either shortName or shortNames. If both are provided, shortNames takes precedence.

Fixed discount calculations on clusters with options

Fixed an issue where percentage discounts on clusters with options were incorrectly applied as absolute amounts on child items. This caused wrong totals when a percentage discount was active on a cluster that included option products. Discount calculations now correctly apply the percentage to each child item.

Implemented channel ID

Added channel ID support so carts, orders, quote requests and quotes are created with the correct channel assignment.

Quote status changes no longer create duplicate versions

Fixed an issue where changing a quote status to a non-public status (for example from "Quote" to "Draft quote") incorrectly created multiple additional quote versions. This occurred when products with surcharges were included in the order. Status changes now correctly create only the expected single version entry.

Order address code, quote versioning and channel filter fixes

Fixed an issue where creating orders or quotes failed when the address code exceeded 30 characters. The address code field now supports up to 64 characters, aligning with the allowed length in user and order address data. Also fixed an issue where the channelIds filter parameter in the orders query had no effect. Orders and quotes can now be correctly filtered by channel ID.

Fixed company switching

Fixed an issue where the company switch popup would keep spinning without completing the switch.

Fixed downloads section cut off

Fixed an issue where the downloads section on the product detail page was cut off.