{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-release-notes/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":[]},"type":"markdown","redocly_category":"Release-notes","owner":"MB"},"seo":{"title":"Release notes April 2026","description":"Release notes April 2026","keywords":"release-notes, product-update, features"},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"release-notes-april-2026"},"children":["Release notes April 2026"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"notable-features"},"children":["Notable features"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"norce-commerce-query-api-v2.0-is-deprecated"},"children":["Norce Commerce Query API v2.0 is deprecated"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Norce Commerce Query API v3.0 is live and runs in parallel with Query API v2.0 under the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/3.0"]}," path. Query API v2.0 is deprecated, and all integrations using Query API v2.0 should plan their migration to Query API v3.0."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Timeline for Norce Commerce Query API v2.0:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["April 10, 2026:"]}," Deprecation in effect."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["August 31, 2026:"]}," End of Support. No more bug fixes or patches for Query API v2.0."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["October 31, 2026:"]}," End of Life. Query API v2.0 is taken offline."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The changes in Query API v3.0 are mostly structural: format, metadata, and data model alignment. No core functionality has been removed, so most integrations only need minor updates. Do not start new implementations on Query API v2.0."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Read more in ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"/solution-portal/functional-change-upgrade-query-v2-v3"},"children":["Upgrade Norce Commerce Query from v2 to v3"]}," and in the ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"/api-reference/query/openapi"},"children":["Query API reference"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"norce-checkout-transaction-insights-released"},"children":["Norce Checkout Transaction Insights released"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["All transactions between Norce Checkout components and adapters are now visible in Norce Checkout Admin. You can find the transactions either by browsing from a specific order or by filtering under ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Events > Transactions"]},". Transactions are also accessible from the order detail view."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The following Norce Checkout adapters now support Transaction Insights: Norce adapter, Svea, Walley, Adyen, Avarda, Awardit, Ingrid, nShift, PayPal, and the Non-PSP adapter."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"new-norce-checkout-endpoint-for-fetching-order-ids-by-date-and-status"},"children":["New Norce Checkout endpoint for fetching order IDs by date and status"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The Norce Checkout order service has a new endpoint, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GET /api/v{version}/checkout/orders/ids"]},", where you filter by date and status and receive all order IDs matching the filter. The endpoint is useful for integrations that fetch orders and need to make sure that all orders have been received."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The endpoint takes either ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["order_statuses"]}," or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["current_statuses"]},", and exactly one of them must be provided. ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["current_statuses"]}," returns orders whose current status matches one of the provided values and that transitioned to that status within the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["from"]},"/",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["to"]}," range."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"external-discount-codes-in-norce-commerce"},"children":["External discount codes in Norce Commerce"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Norce Commerce baskets can now carry external discount codes, for example from Voyado. Commerce Admin supports External Discount Code as a new promotion requirement type."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"other-patches-and-fixes"},"children":["Other patches and fixes"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"norce-checkout"},"children":["Norce Checkout"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Order"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Added the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["UpdateCustomerLoyalty"]}," endpoint to the V0 CheckoutController."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Performance improvements on order listing and filtering in Checkout Admin."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Loyalty updates are now allowed in the Accepted and Completed order states."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["PayPal adapter"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Added a per-merchant/channel setting, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CopyBillingEmailToShipping"]},", to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PaypalOptions"]},". When enabled, the billing email is copied to the shipping email address during the PayPal authorize, capture, and capture-authorized-payment flows."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The PayPal adapter now returns a clear ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["paypal-amount-not-positive"]}," error (HTTP 400) when an order's remaining amount is zero or negative, instead of a generic ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["paypal-error"]},"."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Walley adapter"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The Walley adapter model now uses the new Loyalty object from checkout-order."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The Walley adapter now skips redundant payment updates when the cart and shipping have not meaningfully changed, preventing lock conflicts during checkout completion."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Walley ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GetOrder"]}," 404 NotFound is now handled gracefully."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Fixed the update-payment callback incorrectly rejecting valid updates by comparing against the callback body instead of the persisted payment state."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The Walley adapter now rejects order modifications once the payment has moved past Intent, preventing Norce order totals from silently diverging from the Walley payment."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The Walley session is now refreshed on update-payment callbacks when another payment on the order changes the amount to cover (for example, a voucher added by another adapter), even if cart and shipping are unchanged."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The error \"Walley payment already exists for this order\" now returns HTTP 409 Conflict instead of HTTP 400 Bad Request."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Checkout Admin"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Timeouts when rendering the order or cart view no longer occur."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Fixed the \"no schema with key or ref\" error that prevented validation."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Norce adapter"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Cart references (Norce Commerce ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["BasketId"]},") now return a conflict for all statuses except \"Removed\". An existing order in a non-removed state blocks new orders from being created with the same Norce Commerce ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["BasketId"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Fixed loyalty notification failures where Qliro sends ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["LOYALTY_PROVIDER_MEMBER_CREATE"]}," after order completion, which triggered a customer-changed hook that failed on a finalized basket."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Adyen adapter"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Fixed a JSON deserialization crash when Adyen returns non-JSON error responses (for example, \"000 Resource not found\"). The actual Adyen error message is now passed through to API consumers."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["NotFoundException"]}," in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CompleteAuthorizationWebhook"]}," is now handled gracefully."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Awardit adapter"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["When reverting an order from processing back to checkout, the Awardit adapter now handles the case where the Awardit payment reservation has already expired."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Ingrid adapter"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The Ingrid adapter now returns a configuration error instead of an unhandled exception when receiving configuration errors from Ingrid."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Fixed an issue where an attempt to reduce error logs caused idempotent recovery to stop working, which could cause orders to get stuck and not move to the completed state."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Kustom adapter"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Fixed a possible error when removing a Kustom Checkout payment because of a null value in shipping."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Svea adapter"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Shipping attributes are no longer overwritten when updating ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["shippingData"]}," or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["shippingCreatedWebhookData"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["When cart contents change, the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ShouldRejectShippingSession"]}," flag is now set in the Svea update call, so Svea cancels the previously confirmed shipping session and prompts the customer to re-select shipping."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Svea Checkout order row names are now truncated to 40 characters, which is the limit in Svea Checkout."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["UpdatePayment"]}," no longer sends unnecessary ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["UpdateOrder"]}," calls when only non-mapped shipping fields change (for example, State, Reference, TmsReference, Addons, Attributes)."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["When scope is Cart, the Svea adapter now compares Svea's current order with the shipping-relevant cart fields and only suppresses shipping rejection when all fields provably match. This fixes false-positive shipping re-selection caused by non-cart hook cascades, such as billing address updates."]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"commerce-admin"},"children":["Commerce Admin"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Promotions"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Added support for External Discount Code as a new promotion requirement type."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Fixed an issue where changes to the promotion requirement order sum type were occasionally not saved."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Fixed an issue where searching for products in promotions could return an incorrect number of variants."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Category"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Fixed an issue where VAT codes did not appear when selecting a sales area on a category."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Company and Customer"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Fixed an issue where searching for companies in the \"Add company\" dialog on a customer returned incorrect results due to a case-sensitive filter comparison."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Export"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Fixed an issue where exporting large datasets to Excel failed because of the maximum number of cell styles."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["General"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Dragging items in sortable lists (for example, category parametrics) now auto-scrolls the page when the list is longer than the screen."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Import"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Currency must now be selected manually on the import page to ensure the correct currency is used."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Pricelist Warehouse"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Fixed an issue where connected warehouses showed the wrong type icon in the price list warehouse view."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Product"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Added a confirmation dialog when requesting a translation, to prevent accidental triggers of third-party integrations."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Fixed an issue where the client price rules filter on the product list showed no options."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Suppliers"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Fixed an issue where updating a supplier SKU's supplier or part number could fail."]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"commerce-service"},"children":["Commerce Service"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["External discount codes"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Baskets can now carry external discount codes, for example from Voyado."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Performance"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Faster product loading, since product variant details are looked up more efficiently for products with many parametrics."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Improved performance for payment and checkout endpoints (buyer, payer, and shipTo reads) and for customer and company reads during price calculation."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Fixed an issue where the Basket ID could be missing from the purchase response when using the new payment service."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Fixed an issue where flag promotions interfered with product requirement effects."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Fixed basic authentication on the optional validation URL in legacy payment services."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Fixed an issue where baskets containing certain non-standard items could cause errors during delivery method selection."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Fixed an issue where removing items from the basket (for example, invoice fee lines) did not always take effect."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["When a promotion is marked ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ExcludeFromTotalPrice"]},", the full discount including VAT is now restored before evaluating other promotions. This prevents lower-tier tiered promotions from triggering on a basket that only qualifies for the higher tier."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Corrected a formatting issue in the API specification where some parameter descriptions were not rendered."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"commerce-query"},"children":["Commerce Query"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Fixed a sometimes empty ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PriceLists"]}," array when using ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["$expand=PriceLists"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Added the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Popularities"]}," navigation on Product, so ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GET /Product/Products({id})?$expand=Popularities"]}," now works and mirrors Query API v2.0."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"product-feed"},"children":["Product Feed"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The fallback culture is now applied to product image entries when a requested culture has no translation in the source data. File culture entries are emitted for every requested culture, falling back to the configured fallback culture when available."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Performance improvements to lower database load during Product Feed execution."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"commerce-connect"},"children":["Commerce Connect"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Price no longer defaults to 0 on rule-only imports."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Fixed an issue where importing new variants to products with product-to-product relations sometimes failed."]}]}]},"headings":[{"value":"Release notes April 2026","id":"release-notes-april-2026","depth":1},{"value":"Notable features","id":"notable-features","depth":2},{"value":"Norce Commerce Query API v2.0 is deprecated","id":"norce-commerce-query-api-v2.0-is-deprecated","depth":3},{"value":"Norce Checkout Transaction Insights released","id":"norce-checkout-transaction-insights-released","depth":3},{"value":"New Norce Checkout endpoint for fetching order IDs by date and status","id":"new-norce-checkout-endpoint-for-fetching-order-ids-by-date-and-status","depth":3},{"value":"External discount codes in Norce Commerce","id":"external-discount-codes-in-norce-commerce","depth":3},{"value":"Other patches and fixes","id":"other-patches-and-fixes","depth":2},{"value":"Norce Checkout","id":"norce-checkout","depth":3},{"value":"Commerce Admin","id":"commerce-admin","depth":3},{"value":"Commerce Service","id":"commerce-service","depth":3},{"value":"Commerce Query","id":"commerce-query","depth":3},{"value":"Product Feed","id":"product-feed","depth":3},{"value":"Commerce Connect","id":"commerce-connect","depth":3}],"frontmatter":{"seo":{"description":"Release notes April 2026","keywords":"release-notes, product-update, features","title":"Release notes April 2026"},"metadata":{"redocly_category":"Release-notes","owner":"MB"}},"lastModified":"2026-10-07T12:26:01.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/release-notes/2026/release-notes-april-2026","userData":{"isAuthenticated":false,"teams":["anonymous"]}}