Skip to main content

Changelog

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

Component
Type

Import product videos in bulk over REST

A new REST endpoint imports product videos in bulk, mirroring the existing bulk image import. This makes it easy to attach many video links, such as YouTube URLs, to products at once.

A machine's spare part products are returned correctly

Querying a machine's spare part products could return an empty list even when the machine had parts. The parts are now returned as expected.

Search value set items by description

You can now search value set items by their localized description text, as a case-insensitive partial match across all languages, instead of only by the value code. Special characters such as %, _ and \ in a search term are matched literally.

Product search returns categories when expanded

On the REST product search endpoint, passing expands=categories had no effect. The parameter now correctly includes category information in the results.

Fixed structured data output

Fixed the JSON-LD structured data for products and clusters, correcting the type, the fallback image, the price formatting and the availability markup.

Attribute changes appear in search facets in near-realtime

Creating or updating a product attribute value did not always update the matching search facet filter, so faceted search could show stale values. Attribute changes now appear in the facets in near-realtime, without a manual reindex.

Per-item shipment status on the order detail page

The order detail page now shows each item's shipment status as a translated, color-coded badge, with a status column in the item overview and Unknown shown when a status is missing.

Order list REST endpoints no longer error on assign and add

Assigning users or companies to an order list, or adding items to it, through the REST order list endpoints could fail with a server error. These endpoints now work as documented.

ICS surcharge flag applies to contacts only

The ICS surcharge flag is now added to a cart address only for logged-in contacts, not for guests or other user types.

Search companies, contacts and customers by term

You can now search companies, contacts and customers by a free-text term. An empty term is handled gracefully instead of returning an error.

Fixed quick order prices for the logged-in customer

Quick order prices are now calculated from the logged-in customer's pricing instead of a fixed tax zone, so the listed prices match the customer.

Faster company queries

The GraphQL query for companies has been optimized. Fetching large pages of companies together with their contacts, addresses, sources and attributes is now significantly faster.

Fetching attribute values on cluster products works

Querying attributes on a cluster product could fail the entire query with a server error when an attribute had no value. The query now succeeds instead of erroring.

Product sitemap respects the catalog root

The generated XML product sitemap now includes only products within the configured catalog root.

Order address codes are no longer truncated

When an order moved from draft to new, the address code in the REST order response could be truncated, which could break downstream exports. Address codes are now returned in full throughout the order lifecycle.

The validateOrderList flag on tender items is deprecated

The validateOrderList flag on the tender item inputs (TenderAddItemsInput and TenderUpdateItemInput) is deprecated. It has no effect, because order lists are not enforced when adding or updating tender items regardless of the flag.

Fixed product and cluster pages returning a 404 for logged-in users

Product and cluster detail pages no longer return a 404 for logged-in B2B users, because the queries now include the user's company and contact context.

Attach bulk images by product source

The bulk image import endpoint can now match products by their external source and source id (productSource and productSourceId), so you no longer need to resolve an internal product id first.

Net and gross descriptions on product prices now match the API

The GraphQL schema descriptions for the net and gross price fields were reversed relative to the values the API returns. The descriptions now match the API, so the reference describes each field accurately. The returned values themselves are unchanged.

Language codes for localized fields are case-insensitive again

A regression made language codes on localized fields such as product names, short names, package descriptions and slugs case-sensitive, so mixing lowercase and uppercase codes could produce empty values on import. Language codes are treated case-insensitively again, so nl and NL are equivalent across stored data, display and API responses.

Search handles decimal value queries

Searching for a decimal value such as 130.1731005 could fail, and is now fixed. Single-character words and numbers in a search term are ignored and do not refine the search, because the minimum length for a search token is two letters or numbers.

Fixed adding a cluster combination to the cart

Adding a cluster combination to the cart now submits the correct bundle id, so the item is added successfully.

Fixed a cart error when the response was empty

Adding or updating a cart item no longer errors when the backend returns an empty response.

Guide users through a required password reset at login

When a login is rejected because the account must set a new password, the storefront now shows reset instructions and automatically triggers a password-reset email instead of a generic login error.

Reassigning a contact to a company works reliably

Removing a contact from a company and then adding it back could fail because the earlier link was retained internally. Contacts can now be removed from and re-added to a company reliably.

Category import handles HTML and long descriptions

Importing categories could fail silently when the description or short description contained HTML or was very long. These descriptions now import correctly.

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.

Fixed an error on products without bundles

The combo deals section on a product page no longer errors when the product has no bundles.

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.

Fixed the product specifications tab staying blurred

The product specifications tab no longer stays blurred after loading, and it can no longer be loaded twice while a request is in progress.

Fixed the no-image placeholder in the add-to-basket modal

The add-to-basket modal now shows the correct no-image placeholder when a product or bundle has no image.

Fixed order details breaking on a missing bonus item

Order details no longer break when a bonus product is missing. Such items are skipped or shown with a placeholder image and plain name.

Content outside the catalog root returns a 404

Categories, products and clusters whose category path falls outside the configured catalog root now return a 404 instead of rendering.

Fixed price and range filters

Active price and range filters now show removable chips, the slider remembers widened bounds and resets correctly when a filter is removed, and the range filter type and applied values are preserved.

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.

Restrict which countries are accepted

A new propeller_allowed_countries filter lets a shop restrict which countries are accepted in cart delivery and invoice addresses, address forms and registration. A rejected submission, such as a disallowed country, now shows an error and stops instead of a success message.

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.

Fixed the cluster page sticky sidebar

The sticky sidebar on a cluster page now positions correctly, pinning short sidebars below the header and tall ones to the bottom of the viewport.

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.

Fixed spare part rendering

Fixed an error that could break the display of spare parts on a product.

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.

Redirect to the cart when over the purchase authorization limit

At checkout, a logged-in purchaser whose cart requires authorization and exceeds their limit is now redirected back to the cart instead of continuing.

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.

Category pages resolve by slug

A category page now resolves by its slug instead of falling back to the base catalog category when no category id is supplied.

List view and quote overview display fixes

In list view the add-to-basket button now shows only its icon on small screens, and the quote overview no longer shows a stray dash before the payment method and shipping amounts.

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.

Prompt for a missing invoice address at checkout

At the first checkout step, a logged-in user with an empty invoice address is now prompted to fill it in instead of seeing the Continue button.

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.